1 // FGAIAircraft - FGAIBase-derived class creates an AI airplane
3 // Written by David Culp, started October 2003.
5 // Copyright (C) 2003 David P. Culp - davidculp2@comcast.net
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License as
9 // published by the Free Software Foundation; either version 2 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 // General Public License for more details.
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 #include <simgear/math/point3d.hxx>
26 #include <Main/fg_props.hxx>
27 #include <Main/globals.hxx>
28 #include <Scenery/scenery.hxx>
34 #include "AIAircraft.hxx"
36 FGAIAircraft::FGAIAircraft() {
38 // set heading and altitude locks
44 FGAIAircraft::~FGAIAircraft() {
48 bool FGAIAircraft::init() {
49 return FGAIBase::init();
53 void FGAIAircraft::update(double dt) {
60 void FGAIAircraft::SetPerformance(PERF_STRUCT ps) {
66 void FGAIAircraft::Run(double dt) {
68 FGAIAircraft::dt = dt;
70 double turn_radius_ft;
71 double turn_circum_ft;
72 double speed_north_deg_sec;
73 double speed_east_deg_sec;
74 double ft_per_deg_lon;
75 double ft_per_deg_lat;
76 double dist_covered_ft;
79 // get size of a degree at this latitude
80 ft_per_deg_lat = 366468.96 - 3717.12 * cos(pos.lat() / 57.2958 );
81 ft_per_deg_lon = 365228.16 * cos(pos.lat() / 57.2958);
84 double speed_diff = tgt_speed - speed;
85 if (fabs(speed_diff) > 0.2) {
86 if (speed_diff > 0.0) speed += performance.accel * dt;
87 if (speed_diff < 0.0) speed -= performance.decel * dt;
90 // convert speed to degrees per second
91 speed_north_deg_sec = cos( hdg / 57.29577951 ) * speed * 1.686 / ft_per_deg_lat;
92 speed_east_deg_sec = sin( hdg / 57.29577951 ) * speed * 1.686 / ft_per_deg_lon;
95 pos.setlat( pos.lat() + speed_north_deg_sec * dt);
96 pos.setlon( pos.lon() + speed_east_deg_sec * dt);
98 // adjust heading based on current bank angle
100 turn_radius_ft = 0.088362 * speed * speed / tan( fabs(roll) / 57.2958 );
101 turn_circum_ft = 6.2831853 * turn_radius_ft;
102 dist_covered_ft = speed * 1.686 * dt;
103 alpha = dist_covered_ft / turn_circum_ft * 360.0;
104 hdg += alpha * sign( roll );
105 if ( hdg > 360.0 ) hdg -= 360.0;
106 if ( hdg < 0.0) hdg += 360.0;
109 // adjust target bank angle if heading lock engaged
111 double bank_sense = 0.0;
112 double diff = fabs(hdg - tgt_heading);
113 if (diff > 180) diff = fabs(diff - 360);
114 double sum = hdg + diff;
115 if (sum > 360.0) sum -= 360.0;
116 if (fabs(sum - tgt_heading) < 1.0) {
121 if (diff < 30) tgt_roll = diff * bank_sense;
125 double bank_diff = tgt_roll - roll;
126 if (fabs(bank_diff) > 0.2) {
127 if (bank_diff > 0.0) roll += 5.0 * dt;
128 if (bank_diff < 0.0) roll -= 5.0 * dt;
131 // adjust altitude (meters) based on current vertical speed (fpm)
132 altitude += vs * 0.0166667 * dt * 0.3048;
134 // find target vertical speed if altitude lock engaged
136 double altitude_ft = altitude * 3.28084;
137 if (altitude_ft < tgt_altitude) {
138 tgt_vs = tgt_altitude - altitude_ft;
139 if (tgt_vs > performance.climb_rate) tgt_vs = performance.climb_rate;
141 tgt_vs = tgt_altitude - altitude_ft;
142 if (tgt_vs < (-performance.descent_rate)) tgt_vs = -performance.descent_rate;
146 // adjust vertical speed
147 double vs_diff = tgt_vs - vs;
148 if (fabs(vs_diff) > 1.0) {
151 if (vs > tgt_vs) vs = tgt_vs;
154 if (vs < tgt_vs) vs = tgt_vs;
158 // match pitch angle to vertical speed
164 void FGAIAircraft::AccelTo(double speed) {
169 void FGAIAircraft::PitchTo(double angle) {
175 void FGAIAircraft::RollTo(double angle) {
181 void FGAIAircraft::YawTo(double angle) {
186 void FGAIAircraft::ClimbTo(double altitude) {
187 tgt_altitude = altitude;
192 void FGAIAircraft::TurnTo(double heading) {
193 tgt_heading = heading;
198 double FGAIAircraft::sign(double x) {
200 if ( x < 0.0 ) { return -1.0; }