// move to the +l end/center of the runway
//cout << "Runway center is at " << runway._lon << ", " << runway._lat << '\n';
- double tshlon, tshlat, tshr;
- double tolon, tolat, tor;
+ double tshlon = 0.0, tshlat = 0.0, tshr;
+ double tolon = 0.0, tolat = 0.0, tor;
rwy.length = runway->lengthM();
rwy.width = runway->widthM();
geo_direct_wgs_84 ( aptElev, runway->latitude(), runway->longitude(), other_way,
// TODO - At hot 'n high airports this may be 500ft AGL though - need to make this a variable.
if((_pos.getElevationM() - rwy.threshold_pos.getElevationM()) * SG_METER_TO_FEET > 700) {
double cc = 0.0;
- if(tower->GetCrosswindConstraint(cc)) {
+ if(_controlled && tower->GetCrosswindConstraint(cc)) {
if(orthopos.y() > cc) {
//cout << "Turning to crosswind, distance from threshold = " << orthopos.y() << '\n';
leg = TURN1;
// turn 1000m out for now, taking other traffic into accout
if(fabs(orthopos.x()) > 900) {
double dd = 0.0;
- if(tower->GetDownwindConstraint(dd)) {
+ if(_controlled && tower->GetDownwindConstraint(dd)) {
if(fabs(orthopos.x()) > fabs(dd)) {
//cout << "Turning to downwind, distance from centerline = " << fabs(orthopos.x()) << '\n';
leg = TURN2;
// For now we're assuming that we aim to follow the same glidepath regardless of wind.
double d1;
double d2;
- CalculateSoD((tower->GetBaseConstraint(d1) ? d1 : -1000.0), (tower->GetDownwindConstraint(d2) ? d2 : 1000.0 * patternDirection), (patternDirection ? true : false));
+ CalculateSoD(((_controlled && tower->GetBaseConstraint(d1)) ? d1 : -1000.0), ((_controlled && tower->GetDownwindConstraint(d2)) ? d2 : 1000.0 * patternDirection), (patternDirection ? true : false));
if(SoD.leg == DOWNWIND) {
descending = (orthopos.y() < SoD.y ? true : false);
}
if(orthopos.y() < -1000.0 + turn_radius) {
//if(orthopos.y() < -980) {
double bb = 0.0;
- if(tower->GetBaseConstraint(bb)) {
+ if(_controlled && tower->GetBaseConstraint(bb)) {
if(fabs(orthopos.y()) > fabs(bb)) {
//cout << "Turning to base, distance from threshold = " << fabs(orthopos.y()) << '\n';
leg = TURN3;
double d1;
// Make downwind leg position artifically large to avoid any chance of SoD being returned as
// on downwind when we are already on base.
- CalculateSoD((tower->GetBaseConstraint(d1) ? d1 : -1000.0), (10000.0 * patternDirection), (patternDirection ? true : false));
+ CalculateSoD(((_controlled && tower->GetBaseConstraint(d1)) ? d1 : -1000.0), (10000.0 * patternDirection), (patternDirection ? true : false));
if(SoD.leg == BASE) {
descending = (fabs(orthopos.y()) < fabs(SoD.y) ? true : false);
}
}
if(inAir) {
- // FIXME - at the moment this is a bit screwy
- // The velocity correction is applied based on the relative headings.
- // Then the heading is changed based on the velocity.
- // Which comes first, the chicken or the egg?
- // Does it really matter?
-
- // Apply wind to ground-relative velocity if in the air
- vel = IAS - (cos((_hdg - wind_from) * DCL_DEGREES_TO_RADIANS) * wind_speed);
- //crab = f(track, wind, vel);
- // The vector we need to fly is our desired vector minus the wind vector
- // TODO - we probably ought to use plib's built in vector types and operations for this
- // ie. There's almost *certainly* a better way to do this!
- double gxx = vel * sin(track * DCL_DEGREES_TO_RADIANS); // Plane desired velocity x component wrt ground
- double gyy = vel * cos(track * DCL_DEGREES_TO_RADIANS); // Plane desired velocity y component wrt ground
- double wxx = wind_speed * sin((wind_from + 180.0) * DCL_DEGREES_TO_RADIANS); // Wind velocity x component
- double wyy = wind_speed * cos((wind_from + 180.0) * DCL_DEGREES_TO_RADIANS); // Wind velocity y component
- double axx = gxx - wxx; // Plane in-air velocity x component
- double ayy = gyy - wyy; // Plane in-air velocity y component
- // Now we want the angle between gxx and axx (which is the crab)
- double maga = sqrt(axx*axx + ayy*ayy);
- double magg = sqrt(gxx*gxx + gyy*gyy);
- crab = acos((axx*gxx + ayy*gyy) / (maga * magg));
- // At this point this works except we're getting the modulus of the angle
- //cout << "crab = " << crab << '\n';
-
- // Make sure both headings are in the 0->360 circle in order to get sane differences
- dclBoundHeading(wind_from);
- dclBoundHeading(track);
- if(track > wind_from) {
- if((track - wind_from) <= 180) {
- crab *= -1.0;
- }
+ // calculate ground speed and crab from the wind triangle
+ double wind_angle = GetAngleDiff_deg(wind_from + 180, track);
+ double wind_side = (wind_angle < 0) ? -1.0 : 1.0;
+
+ double sine_of_crab = wind_speed / IAS * sin(fabs(wind_angle) * DCL_DEGREES_TO_RADIANS);
+ if (sine_of_crab >= 1.0) {
+ // The crosswind component is greater than the IAS,
+ // we can't keep the aircraft on track.
+ // Assume increased IAS such that it cancels lateral speed.
+ // This is unrealistic, but not sure how the rest of the sim
+ // would react to the aircraft going off course.
+ // Should be a rare case anyway.
+ crab = wind_side * 90.0;
} else {
- if((wind_from - track) >= 180) {
- crab *= -1.0;
- }
+ crab = asin(sine_of_crab) * DCL_RADIANS_TO_DEGREES * wind_side;
}
+ vel = cos(wind_angle * DCL_DEGREES_TO_RADIANS) * wind_speed
+ + cos(crab * DCL_DEGREES_TO_RADIANS) * IAS;
} else { // on the ground - crab dosen't apply
crab = 0.0;
}
//cout << "X " << orthopos.x() << " Y " << orthopos.y() << " SLOPE " << slope << " elev " << _pos.elev() * SG_METER_TO_FEET << '\n';
_hdg = track + crab;
+ dclBoundHeading(_hdg);
dist = vel * 0.514444 * dt;
_pos = dclUpdatePosition(_pos, track, slope, dist);
}
void FGAILocalTraffic::TransmitPatternPositionReport(void) {
// airport name + "traffic" + airplane callsign + pattern direction + pattern leg + rwy + ?
- string trns = "";
+ string trns;
int code = 0;
-
- trns += tower->get_name();
+ const string& apt_name = _controlled ? tower->get_name() : airportID;
+
+ trns += apt_name;
trns += " Traffic ";
trns += plane.callsign;
if(patternDirection == 1) {
}
trns += ConvertRwyNumToSpokenString(rwy.rwyID);
- trns += " ";
+ trns += ' ';
// And add the airport name again
- trns += tower->get_name();
+ trns += apt_name;
pending_transmission = trns;
ConditionalTransmit(60.0, code); // Assume a report of this leg will be invalid if we can't transmit within a minute.