1
0
Fork 0
flightgear/src/AIModel/AIBase.hxx

297 lines
9.4 KiB
C++
Raw Normal View History

// FGAIBase.hxx - abstract base class for AI objects
// Written by David Culp, started Nov 2003, based on
// David Luff's FGAIEntity class.
// - davidculp2@comcast.net
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#ifndef _FG_AIBASE_HXX
#define _FG_AIBASE_HXX
#include <string>
#include <list>
#include <simgear/constants.h>
#include <simgear/math/point3d.hxx>
#include <simgear/scene/model/placement.hxx>
#include <simgear/misc/sg_path.hxx>
#include <simgear/structure/ssgSharedPtr.hxx>
#include <Main/fg_props.hxx>
SG_USING_STD(string);
SG_USING_STD(list);
David Culp: Here's a new batch of AI code which includes a working radar instrument. I put the radar calculations into the existing AIAircraft class. It was easier that way, and it can always be migrated out later if we have to. Every tenth sim cycle the AIManager makes a copy of the current user state information. When the AIAircraft updates it uses this information to calculate the radar numbers. It calculates: 1) bearing from user to target 2) range to target in nautical miles 3) "horizontal offset" to target. This is the angle from the nose to the target, in degrees, from -180 to 180. This will be useful later for a HUD. 4) elevation, in degrees (vertical angle from user's position to target position) 5) vertical offset, in degrees (this is elevation corrected for user's pitch) 6) rdot (range rate in knots, note: not working yet, so I commented it out) and three items used by the radar instrument to place the "blip" 7) y_shift, in nautical miles 8) x_shift, in nautical miles 9) rotation, in degrees The radar instrument uses the above three items, and applies a scale factor to the x-shift and y-shift in order to match the instrument's scale. Changing the display scale can be done entirely in the XML code for the instrument. Right now it's set up only to display a 40 mile scale. The radar is an AWACS view, which is not very realistic, but it is useful and demonstrates the technology. With just a little more work I can get a HUD marker. All I need to do there is make a bank angle adjustment to the current values.
2004-02-27 10:20:17 +00:00
class FGAIManager;
class FGAIFlightPlan;
Mathias Fröhlich: I have introduced the posibility to start directly on the carrier. With that patch you will have a --carrrier=id argument where id can either be the pennant number configured in the nimitz scenario or the carriers name also configured in the carriers scenario. Additionaly you can use --parkpos=id to select different positions on the carrier. They are also configured in the scenario file. That includes the switch of the whole FGInterface class to make use of the groundcache. That means that an aircraft no longer uses the current elevation value from the scenery class. It rather has its own local cache of the aircrafts environment which is setup in the common_init method of FGInterface and updated either manually by calling FGInterface::get_groundlevel_m(lat, lon, alt_m); or implicitly by calling the above method in the FGInterface::_updateGeo*Position(lat, lon, alt); methods. A call get_groundlevel_m rebuilds the groundcache if the request is outside the range of the cache. Note that for the real usage of the groundcache including the correct information about the movement of objects and the velocity information, you still need to set up the groundcache in the usual way like YASim and JSBSim currently does. If you use the native interface, you will get only static objects correctly. But for FDM's only using one single ground level for a whole step this is IMO sufficient. The AIManager gets a way to return the location of a object which is placed wrt an AI Object. At the moment it only honours AICarriers for that. That method is a static one, which loads the scenario file for that reason and throws it away afterwards. This looked like the aprioriate way, because the AIManager is initialized much later in flightgears bootstrap, and I did not find an easy way to reorder that for my needs. Since this additional load is very small and does only happen if such a relative location is required, I think that this is ok. Note that moving on the carrier will only work correctly for JSBSim and YASim, but you should now be able to start and move on every not itself moving object with any FDM.
2005-07-03 09:39:14 +00:00
struct ParkPosition {
ParkPosition(const ParkPosition& pp)
: name(pp.name), offset(pp.offset), heading_deg(pp.heading_deg)
{}
ParkPosition(const string& n, const Point3D& off = Point3D(), double heading = 0)
: name(n), offset(off), heading_deg(heading)
{}
string name;
Point3D offset;
double heading_deg;
};
typedef struct {
string callsign;
// can be aircraft, ship, storm, thermal, static or ballistic
string m_type;
string m_class;
string path;
string flightplan;
FGAIFlightPlan *fp;
double repeat; // in seconds
double latitude; // used if no flightplan defined
double longitude; // used if no flightplan defined
double altitude; // used if no flightplan defined
double speed; // used if no flightplan defined
double heading; // used if no flightplan defined
double roll; // used if no flightplan defined
double azimuth; // used by ballistic objects
double elevation; // used by ballistic objects
double rudder; // used by ship objects
double strength; // used by thermal
double turb_strength; // used by storm objects
double diameter; // used by thermal and storm objects
double height_msl; // used by thermal and storm objects
double eda; // used by ballistic objects
double life; // life span in seconds
double buoyancy; // acceleration in ft per sec2
double wind_from_east; // in feet per second
double wind_from_north; // in feet per second
double cd; // coefficient of drag
bool wind; // if true, model reacts to parent wind
double mass; // in slugs
bool aero_stabilised; // if true, ballistic object aligns with trajectory
list<string> solid_objects; // List of solid object names
list<string> wire_objects; // List of wire object names
list<string> catapult_objects; // List of catapult object names
Mathias Fröhlich: I have introduced the posibility to start directly on the carrier. With that patch you will have a --carrrier=id argument where id can either be the pennant number configured in the nimitz scenario or the carriers name also configured in the carriers scenario. Additionaly you can use --parkpos=id to select different positions on the carrier. They are also configured in the scenario file. That includes the switch of the whole FGInterface class to make use of the groundcache. That means that an aircraft no longer uses the current elevation value from the scenery class. It rather has its own local cache of the aircrafts environment which is setup in the common_init method of FGInterface and updated either manually by calling FGInterface::get_groundlevel_m(lat, lon, alt_m); or implicitly by calling the above method in the FGInterface::_updateGeo*Position(lat, lon, alt); methods. A call get_groundlevel_m rebuilds the groundcache if the request is outside the range of the cache. Note that for the real usage of the groundcache including the correct information about the movement of objects and the velocity information, you still need to set up the groundcache in the usual way like YASim and JSBSim currently does. If you use the native interface, you will get only static objects correctly. But for FDM's only using one single ground level for a whole step this is IMO sufficient. The AIManager gets a way to return the location of a object which is placed wrt an AI Object. At the moment it only honours AICarriers for that. That method is a static one, which loads the scenario file for that reason and throws it away afterwards. This looked like the aprioriate way, because the AIManager is initialized much later in flightgears bootstrap, and I did not find an easy way to reorder that for my needs. Since this additional load is very small and does only happen if such a relative location is required, I think that this is ok. Note that moving on the carrier will only work correctly for JSBSim and YASim, but you should now be able to start and move on every not itself moving object with any FDM.
2005-07-03 09:39:14 +00:00
list<ParkPosition> ppositions; // List of positions on a carrier where an aircraft can start.
Point3D flols_offset; // used by carrier objects, in meters
double radius; // used by ship objects, in feet
string name; // used by carrier objects
string pennant_number; // used by carrier objects
string acType; // used by aircraft objects
string company; // used by aircraft objects
string TACAN_channel_ID; // used by carrier objects
double max_lat; // used by carrier objects
double min_lat; // used by carrier objects
double max_long; // used by carrier objects
double min_long; // used by carrier objects
} FGAIModelEntity;
David Culp: Here's a new batch of AI code which includes a working radar instrument. I put the radar calculations into the existing AIAircraft class. It was easier that way, and it can always be migrated out later if we have to. Every tenth sim cycle the AIManager makes a copy of the current user state information. When the AIAircraft updates it uses this information to calculate the radar numbers. It calculates: 1) bearing from user to target 2) range to target in nautical miles 3) "horizontal offset" to target. This is the angle from the nose to the target, in degrees, from -180 to 180. This will be useful later for a HUD. 4) elevation, in degrees (vertical angle from user's position to target position) 5) vertical offset, in degrees (this is elevation corrected for user's pitch) 6) rdot (range rate in knots, note: not working yet, so I commented it out) and three items used by the radar instrument to place the "blip" 7) y_shift, in nautical miles 8) x_shift, in nautical miles 9) rotation, in degrees The radar instrument uses the above three items, and applies a scale factor to the x-shift and y-shift in order to match the instrument's scale. Changing the display scale can be done entirely in the XML code for the instrument. Right now it's set up only to display a 40 mile scale. The radar is an AWACS view, which is not very realistic, but it is useful and demonstrates the technology. With just a little more work I can get a HUD marker. All I need to do there is make a bank angle adjustment to the current values.
2004-02-27 10:20:17 +00:00
class FGAIBase {
public:
FGAIBase();
virtual ~FGAIBase();
virtual void update(double dt);
inline const Point3D& GetPos() const { return(pos); }
enum object_type { otNull = 0, otAircraft, otShip, otCarrier, otBallistic,
otRocket, otStorm, otThermal, otStatic, otMultiplayer,
MAX_OBJECTS }; // Needs to be last!!!
virtual bool init();
virtual void bind();
virtual void unbind();
void setPath( const char* model );
void setSpeed( double speed_KTAS );
void setAltitude( double altitude_ft );
void setHeading( double heading );
void setLatitude( double latitude );
void setLongitude( double longitude );
void setBank( double bank );
void setPitch( double newpitch );
void setRadius ( double radius );
void setXoffset( double x_offset );
void setYoffset( double y_offset );
void setZoffset( double z_offset );
int getID() const;
void setDie( bool die );
bool getDie();
Mathias Fröhlich: I have introduced the posibility to start directly on the carrier. With that patch you will have a --carrrier=id argument where id can either be the pennant number configured in the nimitz scenario or the carriers name also configured in the carriers scenario. Additionaly you can use --parkpos=id to select different positions on the carrier. They are also configured in the scenario file. That includes the switch of the whole FGInterface class to make use of the groundcache. That means that an aircraft no longer uses the current elevation value from the scenery class. It rather has its own local cache of the aircrafts environment which is setup in the common_init method of FGInterface and updated either manually by calling FGInterface::get_groundlevel_m(lat, lon, alt_m); or implicitly by calling the above method in the FGInterface::_updateGeo*Position(lat, lon, alt); methods. A call get_groundlevel_m rebuilds the groundcache if the request is outside the range of the cache. Note that for the real usage of the groundcache including the correct information about the movement of objects and the velocity information, you still need to set up the groundcache in the usual way like YASim and JSBSim currently does. If you use the native interface, you will get only static objects correctly. But for FDM's only using one single ground level for a whole step this is IMO sufficient. The AIManager gets a way to return the location of a object which is placed wrt an AI Object. At the moment it only honours AICarriers for that. That method is a static one, which loads the scenario file for that reason and throws it away afterwards. This looked like the aprioriate way, because the AIManager is initialized much later in flightgears bootstrap, and I did not find an easy way to reorder that for my needs. Since this additional load is very small and does only happen if such a relative location is required, I think that this is ok. Note that moving on the carrier will only work correctly for JSBSim and YASim, but you should now be able to start and move on every not itself moving object with any FDM.
2005-07-03 09:39:14 +00:00
Point3D getCartPosAt(const Point3D& off) const;
Point3D getGeocPosAt(const Point3D& off) const;
protected:
SGPropertyNode_ptr props;
David Culp: Here's a new batch of AI code which includes a working radar instrument. I put the radar calculations into the existing AIAircraft class. It was easier that way, and it can always be migrated out later if we have to. Every tenth sim cycle the AIManager makes a copy of the current user state information. When the AIAircraft updates it uses this information to calculate the radar numbers. It calculates: 1) bearing from user to target 2) range to target in nautical miles 3) "horizontal offset" to target. This is the angle from the nose to the target, in degrees, from -180 to 180. This will be useful later for a HUD. 4) elevation, in degrees (vertical angle from user's position to target position) 5) vertical offset, in degrees (this is elevation corrected for user's pitch) 6) rdot (range rate in knots, note: not working yet, so I commented it out) and three items used by the radar instrument to place the "blip" 7) y_shift, in nautical miles 8) x_shift, in nautical miles 9) rotation, in degrees The radar instrument uses the above three items, and applies a scale factor to the x-shift and y-shift in order to match the instrument's scale. Changing the display scale can be done entirely in the XML code for the instrument. Right now it's set up only to display a 40 mile scale. The radar is an AWACS view, which is not very realistic, but it is useful and demonstrates the technology. With just a little more work I can get a HUD marker. All I need to do there is make a bank angle adjustment to the current values.
2004-02-27 10:20:17 +00:00
FGAIManager* manager;
David Culp: Here's a new batch of AI code which includes a working radar instrument. I put the radar calculations into the existing AIAircraft class. It was easier that way, and it can always be migrated out later if we have to. Every tenth sim cycle the AIManager makes a copy of the current user state information. When the AIAircraft updates it uses this information to calculate the radar numbers. It calculates: 1) bearing from user to target 2) range to target in nautical miles 3) "horizontal offset" to target. This is the angle from the nose to the target, in degrees, from -180 to 180. This will be useful later for a HUD. 4) elevation, in degrees (vertical angle from user's position to target position) 5) vertical offset, in degrees (this is elevation corrected for user's pitch) 6) rdot (range rate in knots, note: not working yet, so I commented it out) and three items used by the radar instrument to place the "blip" 7) y_shift, in nautical miles 8) x_shift, in nautical miles 9) rotation, in degrees The radar instrument uses the above three items, and applies a scale factor to the x-shift and y-shift in order to match the instrument's scale. Changing the display scale can be done entirely in the XML code for the instrument. Right now it's set up only to display a 40 mile scale. The radar is an AWACS view, which is not very realistic, but it is useful and demonstrates the technology. With just a little more work I can get a HUD marker. All I need to do there is make a bank angle adjustment to the current values.
2004-02-27 10:20:17 +00:00
// these describe the model's actual state
Point3D pos; // WGS84 lat & lon in degrees, elev above sea-level in meters
double hdg; // True heading in degrees
double roll; // degrees, left is negative
double pitch; // degrees, nose-down is negative
double speed; // knots true airspeed
double altitude; // meters above sea level
double vs; // vertical speed, feet per minute
double turn_radius_ft; // turn radius ft at 15 kts rudder angle 15 degrees
double ft_per_deg_lon;
double ft_per_deg_lat;
David Culp: Here's a new batch of AI code which includes a working radar instrument. I put the radar calculations into the existing AIAircraft class. It was easier that way, and it can always be migrated out later if we have to. Every tenth sim cycle the AIManager makes a copy of the current user state information. When the AIAircraft updates it uses this information to calculate the radar numbers. It calculates: 1) bearing from user to target 2) range to target in nautical miles 3) "horizontal offset" to target. This is the angle from the nose to the target, in degrees, from -180 to 180. This will be useful later for a HUD. 4) elevation, in degrees (vertical angle from user's position to target position) 5) vertical offset, in degrees (this is elevation corrected for user's pitch) 6) rdot (range rate in knots, note: not working yet, so I commented it out) and three items used by the radar instrument to place the "blip" 7) y_shift, in nautical miles 8) x_shift, in nautical miles 9) rotation, in degrees The radar instrument uses the above three items, and applies a scale factor to the x-shift and y-shift in order to match the instrument's scale. Changing the display scale can be done entirely in the XML code for the instrument. Right now it's set up only to display a 40 mile scale. The radar is an AWACS view, which is not very realistic, but it is useful and demonstrates the technology. With just a little more work I can get a HUD marker. All I need to do there is make a bank angle adjustment to the current values.
2004-02-27 10:20:17 +00:00
// these describe the model's desired state
double tgt_heading; // target heading, degrees true
double tgt_altitude; // target altitude, *feet* above sea level
double tgt_speed; // target speed, KTAS
double tgt_roll;
double tgt_pitch;
double tgt_yaw;
double tgt_vs;
David Culp: Here's a new batch of AI code which includes a working radar instrument. I put the radar calculations into the existing AIAircraft class. It was easier that way, and it can always be migrated out later if we have to. Every tenth sim cycle the AIManager makes a copy of the current user state information. When the AIAircraft updates it uses this information to calculate the radar numbers. It calculates: 1) bearing from user to target 2) range to target in nautical miles 3) "horizontal offset" to target. This is the angle from the nose to the target, in degrees, from -180 to 180. This will be useful later for a HUD. 4) elevation, in degrees (vertical angle from user's position to target position) 5) vertical offset, in degrees (this is elevation corrected for user's pitch) 6) rdot (range rate in knots, note: not working yet, so I commented it out) and three items used by the radar instrument to place the "blip" 7) y_shift, in nautical miles 8) x_shift, in nautical miles 9) rotation, in degrees The radar instrument uses the above three items, and applies a scale factor to the x-shift and y-shift in order to match the instrument's scale. Changing the display scale can be done entirely in the XML code for the instrument. Right now it's set up only to display a 40 mile scale. The radar is an AWACS view, which is not very realistic, but it is useful and demonstrates the technology. With just a little more work I can get a HUD marker. All I need to do there is make a bank angle adjustment to the current values.
2004-02-27 10:20:17 +00:00
// these describe radar information for the user
bool in_range; // true if in range of the radar, otherwise false
David Culp: Here's a new batch of AI code which includes a working radar instrument. I put the radar calculations into the existing AIAircraft class. It was easier that way, and it can always be migrated out later if we have to. Every tenth sim cycle the AIManager makes a copy of the current user state information. When the AIAircraft updates it uses this information to calculate the radar numbers. It calculates: 1) bearing from user to target 2) range to target in nautical miles 3) "horizontal offset" to target. This is the angle from the nose to the target, in degrees, from -180 to 180. This will be useful later for a HUD. 4) elevation, in degrees (vertical angle from user's position to target position) 5) vertical offset, in degrees (this is elevation corrected for user's pitch) 6) rdot (range rate in knots, note: not working yet, so I commented it out) and three items used by the radar instrument to place the "blip" 7) y_shift, in nautical miles 8) x_shift, in nautical miles 9) rotation, in degrees The radar instrument uses the above three items, and applies a scale factor to the x-shift and y-shift in order to match the instrument's scale. Changing the display scale can be done entirely in the XML code for the instrument. Right now it's set up only to display a 40 mile scale. The radar is an AWACS view, which is not very realistic, but it is useful and demonstrates the technology. With just a little more work I can get a HUD marker. All I need to do there is make a bank angle adjustment to the current values.
2004-02-27 10:20:17 +00:00
double bearing; // true bearing from user to this model
double elevation; // elevation in degrees from user to this model
double range; // range from user to this model, nm
double rdot; // range rate, in knots
double horiz_offset; // look left/right from user to me, deg
double vert_offset; // look up/down from user to me, deg
double x_shift; // value used by radar display instrument
double y_shift; // value used by radar display instrument
double rotation; // value used by radar display instrument
string model_path; //Path to the 3D model
ssgSharedPtr<ssgBranch> model; //The 3D model object
SGModelPlacement aip;
bool delete_me;
bool invisible;
bool no_roll;
double life;
FGAIFlightPlan *fp;
void Transform();
void CalculateMach();
double UpdateRadar(FGAIManager* manager);
string _type_str;
object_type _otype;
int index;
static int _newAIModelID();
private:
const int _refID;
public:
object_type getType();
bool isa( object_type otype );
double _getVS_fps() const;
void _setVS_fps( double _vs );
double _getAltitude() const;
void _setAltitude( double _alt );
void _setLongitude( double longitude );
void _setLatitude ( double latitude );
double _getLongitude() const;
double _getLatitude () const;
double _getBearing() const;
double _getElevation() const;
double _getRdot() const;
double _getH_offset() const;
double _getV_offset() const;
double _getX_shift() const;
double _getY_shift() const;
double _getRotation() const;
David Culp: Here's a new batch of AI code which includes a working radar instrument. I put the radar calculations into the existing AIAircraft class. It was easier that way, and it can always be migrated out later if we have to. Every tenth sim cycle the AIManager makes a copy of the current user state information. When the AIAircraft updates it uses this information to calculate the radar numbers. It calculates: 1) bearing from user to target 2) range to target in nautical miles 3) "horizontal offset" to target. This is the angle from the nose to the target, in degrees, from -180 to 180. This will be useful later for a HUD. 4) elevation, in degrees (vertical angle from user's position to target position) 5) vertical offset, in degrees (this is elevation corrected for user's pitch) 6) rdot (range rate in knots, note: not working yet, so I commented it out) and three items used by the radar instrument to place the "blip" 7) y_shift, in nautical miles 8) x_shift, in nautical miles 9) rotation, in degrees The radar instrument uses the above three items, and applies a scale factor to the x-shift and y-shift in order to match the instrument's scale. Changing the display scale can be done entirely in the XML code for the instrument. Right now it's set up only to display a 40 mile scale. The radar is an AWACS view, which is not very realistic, but it is useful and demonstrates the technology. With just a little more work I can get a HUD marker. All I need to do there is make a bank angle adjustment to the current values.
2004-02-27 10:20:17 +00:00
double rho;
double T; // temperature, degs farenheit
double p; // pressure lbs/sq ft
double a; // speed of sound at altitude (ft/s)
double Mach; // Mach number
static const double e;
static const double lbs_to_slugs;
inline double _getRange() { return range; };
ssgBranch * load3DModel(const string& fg_root,
const string &path,
SGPropertyNode *prop_root,
double sim_time_sec);
2004-05-28 19:03:55 +00:00
static bool _isNight();
};
inline void FGAIBase::setPath( const char* model ) {
model_path.append(model);
}
inline void FGAIBase::setSpeed( double speed_KTAS ) {
speed = tgt_speed = speed_KTAS;
}
inline void FGAIBase::setRadius( double radius ) {
turn_radius_ft = radius;
}
inline void FGAIBase::setHeading( double heading ) {
hdg = tgt_heading = heading;
}
inline void FGAIBase::setAltitude( double altitude_ft ) {
altitude = tgt_altitude = altitude_ft;
pos.setelev(altitude * SG_FEET_TO_METER);
}
inline void FGAIBase::setBank( double bank ) {
roll = tgt_roll = bank;
no_roll = false;
}
inline void FGAIBase::setPitch( double newpitch ) {
pitch = tgt_pitch = newpitch;
}
inline void FGAIBase::setLongitude( double longitude ) {
pos.setlon( longitude );
}
inline void FGAIBase::setLatitude ( double latitude ) {
pos.setlat( latitude );
}
inline void FGAIBase::setDie( bool die ) { delete_me = die; }
inline bool FGAIBase::getDie() { return delete_me; }
inline FGAIBase::object_type FGAIBase::getType() { return _otype; }
#endif // _FG_AIBASE_HXX