+double FGAIBallistic::getRelBrgHitchToUser() const {
+ //calculate the relative bearing
+ double az1, az2, distance;
+
+ geo_inverse_wgs_84(_offsetpos, globals->get_aircraft_position(), &az1, &az2, &distance);
+
+ double rel_brg = az1 - hdg;
+
+ SG_NORMALIZE_RANGE(rel_brg, -180.0, 180.0);
+
+ return rel_brg;
+}
+
+double FGAIBallistic::getElevHitchToUser() const {
+ // Calculate the distance from the user position
+ SGVec3d carthitchPos = getCartHitchPos();
+ SGVec3d cartuserPos = globals->get_aircraft_position_cart();
+
+ SGVec3d diff = cartuserPos - carthitchPos;
+
+ double distance = norm(diff);
+ double angle = 0;
+
+ double daltM = globals->get_aircraft_position().getElevationM() - _offsetpos.getElevationM();
+
+ // Now the angle, positive angles are upwards
+ if (fabs(distance) < SGLimits<float>::min()) {
+ angle = 0;
+ }
+ else {
+ double sAngle = daltM/distance;
+ sAngle = SGMiscd::min(1, SGMiscd::max(-1, sAngle));
+ angle = SGMiscd::rad2deg(asin(sAngle));
+ }
+
+ return angle;
+}
+
+void FGAIBallistic::setTgtOffsets(double dt, double coeff) {
+ double c = dt / (coeff + dt);
+
+ _x_offset = (_tgt_x_offset * c) + (_x_offset * (1 - c));
+ _y_offset = (_tgt_y_offset * c) + (_y_offset * (1 - c));
+ _z_offset = (_tgt_z_offset * c) + (_z_offset * (1 - c));
+}
+
+void FGAIBallistic::calcVSHS() {
+ // Calculate vertical and horizontal speed components
+ double speed_fps = speed * SG_KT_TO_FPS;
+
+ if (speed == 0.0) {
+ hs = vs = 0.0;
+ }
+ else {
+ vs = sin( _elevation * SG_DEGREES_TO_RADIANS ) * speed_fps;
+ hs = cos( _elevation * SG_DEGREES_TO_RADIANS ) * speed_fps;
+ }
+}
+
+void FGAIBallistic::calcNE() {
+ // Resolve horizontal speed into north and east components:
+ _speed_north_fps = cos(_azimuth / SG_RADIANS_TO_DEGREES) * hs;
+ _speed_east_fps = sin(_azimuth / SG_RADIANS_TO_DEGREES) * hs;
+
+ // Convert horizontal speed (fps) to degrees per second
+ speed_north_deg_sec = _speed_north_fps / ft_per_deg_lat;
+ speed_east_deg_sec = _speed_east_fps / ft_per_deg_lon;
+}
+
+SGVec3d FGAIBallistic::getCartOffsetPos(SGGeod inpos, double user_heading,
+ double user_pitch, double user_roll
+ ) const {
+ // Convert geodetic positions to geocentered
+ SGVec3d cartuserPos = SGVec3d::fromGeod(inpos);
+
+ // Transform to the right coordinate frame, configuration is done in
+ // the x-forward, y-right, z-up coordinates (feet), computation
+ // in the simulation usual body x-forward, y-right, z-down coordinates
+ // (meters) )
+ SGVec3d _off(_x_offset * SG_FEET_TO_METER,
+ _y_offset * SG_FEET_TO_METER,
+ -_z_offset * SG_FEET_TO_METER);
+
+ // Transform the user position to the horizontal local coordinate system.
+ SGQuatd hlTrans = SGQuatd::fromLonLat(inpos);
+
+ // And postrotate the orientation of the user model wrt the horizontal
+ // local frame
+ hlTrans *= SGQuatd::fromYawPitchRollDeg(
+ user_heading,
+ user_pitch,
+ user_roll);
+
+ // The offset converted to the usual body fixed coordinate system
+ // rotated to the earth-fixed coordinates axis
+ SGVec3d off = hlTrans.backTransform(_off);
+
+ // Add the position offset of the user model to get the geocentered position
+ SGVec3d offsetPos = cartuserPos + off;
+
+ return offsetPos;
+}
+
+void FGAIBallistic::setOffsetVelocity(double dt, SGGeod offsetpos) {
+ // Calculate the distance from the previous offset position
+ SGVec3d cartoffsetPos = SGVec3d::fromGeod(offsetpos);
+ SGVec3d diff = cartoffsetPos - _oldcartoffsetPos;
+
+ double distance = norm(diff);
+ // Calculate speed knots
+ speed = (distance / dt) * SG_MPS_TO_KT;
+
+ // Now calulate the angle between the old and current postion positions (degrees)
+ double angle = 0;
+ double daltM = offsetpos.getElevationM() - _oldoffsetpos.getElevationM();
+
+ if (fabs(distance) < SGLimits<float>::min()) {
+ angle = 0;
+ }
+ else {
+ double sAngle = daltM / distance;
+ sAngle = SGMiscd::min(1, SGMiscd::max(-1, sAngle));
+ angle = SGMiscd::rad2deg(asin(sAngle));
+ }
+
+ _elevation = angle;
+
+ // Calculate vertical and horizontal speed components
+ calcVSHS();
+
+ // Calculate the bearing of the new offset position from the old
+ // Don't do this if speed is low
+ //cout << "speed " << speed << endl;
+ if (speed > 0.1) {
+ double az1, az2, dist;
+ geo_inverse_wgs_84(_oldoffsetpos, offsetpos, &az1, &az2, &dist);
+ _azimuth = az1;
+ //cout << "offset az " << _azimuth << endl;
+ }
+ else {
+ _azimuth = hdg;
+ //cout << " slow offset az " << _azimuth << endl;
+ }
+
+ // Resolve horizontal speed into north and east components
+ calcNE();
+
+ // And finally store the new values
+ _oldcartoffsetPos = cartoffsetPos;
+ _oldoffsetpos = offsetpos;
+}