Merge branch 'next' of D:\Git_New\flightgear into next
This commit is contained in:
commit
02fb83c774
143 changed files with 11811 additions and 6824 deletions
|
@ -192,6 +192,15 @@ texture-unit - has several child properties:
|
|||
wrap-s
|
||||
wrap-t
|
||||
wrap-r
|
||||
mipmap-control - controls how the mipmap levels are computed.
|
||||
Each color channel can be computed with different functions
|
||||
among average, sum, product, min and max. For example :
|
||||
<function-r>average</function-r>
|
||||
<function-a>min</function-a>
|
||||
function-r - function for red
|
||||
function-g - function for green
|
||||
function-b - function for blue
|
||||
function-a - function for alpha
|
||||
The following built-in types are supported:
|
||||
white - 1 pixel white texture
|
||||
noise - a 3d noise texture
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -2055,14 +2055,6 @@
|
|||
RelativePath="..\..\..\src\FDM\JSBSim\FGJSBBase.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\FDM\JSBSim\FGState.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\FDM\JSBSim\FGState.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\FDM\JSBSim\JSBSim.cxx"
|
||||
>
|
||||
|
@ -4203,6 +4195,46 @@
|
|||
RelativePath="..\..\..\src\Navaids\positioned.hxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\Navaids\airways.hxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\Navaids\airways.cxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\Navaids\procedure.hxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\Navaids\procedure.cxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\Navaids\route.cxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\Navaids\route.hxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\Navaids\routePath.hxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\Navaids\routePath.cxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\Navaids\waypoint.cxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\Navaids\waypoint.hxx"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Lib_Network"
|
||||
|
@ -4855,6 +4887,14 @@
|
|||
RelativePath="..\..\..\src\Instrumentation\gps.hxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\Instrumentation\rnav_waypt_controller.cxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\Instrumentation\rnav_waypt_controller.hxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\Instrumentation\groundradar.cxx"
|
||||
>
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include <Scenery/scenery.hxx>
|
||||
#include <Scenery/tilemgr.hxx>
|
||||
#include <Airports/dynamics.hxx>
|
||||
#include <Airports/simple.hxx>
|
||||
|
||||
#include <string>
|
||||
#include <math.h>
|
||||
|
@ -421,7 +422,7 @@ void FGAIAircraft::getGroundElev(double dt) {
|
|||
double range = 500.0;
|
||||
if (!globals->get_tile_mgr()->scenery_available(pos, range)) {
|
||||
// Try to shedule tiles for that position.
|
||||
globals->get_tile_mgr()->update( pos, range );
|
||||
globals->get_tile_mgr()->schedule_tiles_at( pos, range );
|
||||
}
|
||||
|
||||
double alt;
|
||||
|
|
|
@ -24,26 +24,18 @@
|
|||
#include <string>
|
||||
|
||||
|
||||
#include <Airports/simple.hxx>
|
||||
#include <Navaids/awynet.hxx>
|
||||
|
||||
#include "AIBase.hxx"
|
||||
|
||||
|
||||
|
||||
using std::vector;
|
||||
using std::string;
|
||||
|
||||
class FGTaxiRoute;
|
||||
class FGRunway;
|
||||
class FGAIAircraft;
|
||||
class FGAirport;
|
||||
class SGGeod;
|
||||
|
||||
class FGAIFlightPlan {
|
||||
|
||||
public:
|
||||
|
||||
typedef struct {
|
||||
string name;
|
||||
std::string name;
|
||||
double latitude;
|
||||
double longitude;
|
||||
double altitude;
|
||||
|
@ -56,11 +48,11 @@ public:
|
|||
int routeIndex; // For AI/ATC purposes;
|
||||
double time_sec;
|
||||
double trackLength; // distance from previous waypoint (for AI purposes);
|
||||
string time;
|
||||
std::string time;
|
||||
|
||||
} waypoint;
|
||||
FGAIFlightPlan();
|
||||
FGAIFlightPlan(const string& filename);
|
||||
FGAIFlightPlan(const std::string& filename);
|
||||
FGAIFlightPlan(FGAIAircraft *,
|
||||
const std::string& p,
|
||||
double course,
|
||||
|
@ -73,9 +65,9 @@ public:
|
|||
double lat,
|
||||
double lon,
|
||||
double speed,
|
||||
const string& fltType,
|
||||
const string& acType,
|
||||
const string& airline);
|
||||
const std::string& fltType,
|
||||
const std::string& acType,
|
||||
const std::string& airline);
|
||||
~FGAIFlightPlan();
|
||||
|
||||
waypoint* const getPreviousWaypoint( void ) const;
|
||||
|
@ -91,18 +83,18 @@ public:
|
|||
double getLeadDistance( void ) const {return lead_distance;}
|
||||
double getBearing(waypoint* previous, waypoint* next) const;
|
||||
double getBearing(double lat, double lon, waypoint* next) const;
|
||||
double checkTrackLength(string wptName);
|
||||
double checkTrackLength(std::string wptName);
|
||||
time_t getStartTime() const { return start_time; }
|
||||
time_t getArrivalTime() const { return arrivalTime; }
|
||||
|
||||
void create(FGAIAircraft *, FGAirport *dep, FGAirport *arr, int leg, double alt, double speed, double lat, double lon,
|
||||
bool firstLeg, double radius, const string& fltType, const string& aircraftType, const string& airline, double distance);
|
||||
bool firstLeg, double radius, const std::string& fltType, const std::string& aircraftType, const std::string& airline, double distance);
|
||||
|
||||
void setLeg(int val) { leg = val;}
|
||||
void setTime(time_t st) { start_time = st; }
|
||||
int getGate() const { return gateId; }
|
||||
double getLeadInAngle() const { return leadInAngle; }
|
||||
const string& getRunway() const;
|
||||
const std::string& getRunway() const;
|
||||
|
||||
void setRepeat(bool r) { repeat = r; }
|
||||
bool getRepeat(void) const { return repeat; }
|
||||
|
@ -111,16 +103,16 @@ public:
|
|||
int getRouteIndex(int i); // returns the AI related index of this current routes.
|
||||
FGTaxiRoute *getTaxiRoute() { return taxiRoute; }
|
||||
void deleteTaxiRoute();
|
||||
string getRunway() { return activeRunway; }
|
||||
std::string getRunway() { return activeRunway; }
|
||||
bool isActive(time_t time) {return time >= this->getStartTime();}
|
||||
|
||||
void setRunway(string rwy) { activeRunway = rwy; };
|
||||
string getRunwayClassFromTrafficType(string fltType);
|
||||
void setRunway(std::string rwy) { activeRunway = rwy; };
|
||||
std::string getRunwayClassFromTrafficType(std::string fltType);
|
||||
|
||||
void addWaypoint(waypoint* wpt) { waypoints.push_back(wpt); };
|
||||
|
||||
void setName(string n) { name = n; };
|
||||
string getName() { return name; };
|
||||
void setName(std::string n) { name = n; };
|
||||
std::string getName() { return name; };
|
||||
|
||||
void setSID(FGAIFlightPlan* fp) { sid = fp;};
|
||||
FGAIFlightPlan* getSID() { return sid; };
|
||||
|
@ -128,7 +120,7 @@ public:
|
|||
private:
|
||||
FGRunway* rwy;
|
||||
FGAIFlightPlan *sid;
|
||||
typedef vector <waypoint*> wpt_vector_type;
|
||||
typedef std::vector <waypoint*> wpt_vector_type;
|
||||
typedef wpt_vector_type::const_iterator wpt_vector_iterator;
|
||||
|
||||
|
||||
|
@ -143,26 +135,25 @@ private:
|
|||
time_t arrivalTime; // For AI/ATC purposes.
|
||||
int leg;
|
||||
int gateId, lastNodeVisited;
|
||||
string activeRunway;
|
||||
FGAirRoute airRoute;
|
||||
std::string activeRunway;
|
||||
FGTaxiRoute *taxiRoute;
|
||||
string name;
|
||||
std::string name;
|
||||
|
||||
void createPushBack(FGAIAircraft *, bool, FGAirport*, double, double, double, const string&, const string&, const string&);
|
||||
void createPushBackFallBack(FGAIAircraft *, bool, FGAirport*, double, double, double, const string&, const string&, const string&);
|
||||
void createTakeOff(FGAIAircraft *, bool, FGAirport *, double, const string&);
|
||||
void createClimb(FGAIAircraft *, bool, FGAirport *, double, double, const string&);
|
||||
void createCruise(FGAIAircraft *, bool, FGAirport*, FGAirport*, double, double, double, double, const string&);
|
||||
void createDescent(FGAIAircraft *, FGAirport *, double latitude, double longitude, double speed, double alt,const string&, double distance);
|
||||
void createLanding(FGAIAircraft *, FGAirport *, const string&);
|
||||
void createPushBack(FGAIAircraft *, bool, FGAirport*, double, double, double, const std::string&, const std::string&, const std::string&);
|
||||
void createPushBackFallBack(FGAIAircraft *, bool, FGAirport*, double, double, double, const std::string&, const std::string&, const std::string&);
|
||||
void createTakeOff(FGAIAircraft *, bool, FGAirport *, double, const std::string&);
|
||||
void createClimb(FGAIAircraft *, bool, FGAirport *, double, double, const std::string&);
|
||||
void createCruise(FGAIAircraft *, bool, FGAirport*, FGAirport*, double, double, double, double, const std::string&);
|
||||
void createDescent(FGAIAircraft *, FGAirport *, double latitude, double longitude, double speed, double alt,const std::string&, double distance);
|
||||
void createLanding(FGAIAircraft *, FGAirport *, const std::string&);
|
||||
void createParking(FGAIAircraft *, FGAirport *, double radius);
|
||||
void deleteWaypoints();
|
||||
void resetWaypoints();
|
||||
|
||||
void createLandingTaxi(FGAIAircraft *, FGAirport *apt, double radius, const string& fltType, const string& acType, const string& airline);
|
||||
void createLandingTaxi(FGAIAircraft *, FGAirport *apt, double radius, const std::string& fltType, const std::string& acType, const std::string& airline);
|
||||
void createDefaultLandingTaxi(FGAIAircraft *, FGAirport* aAirport);
|
||||
void createDefaultTakeoffTaxi(FGAIAircraft *, FGAirport* aAirport, FGRunway* aRunway);
|
||||
void createTakeoffTaxi(FGAIAircraft *, bool firstFlight, FGAirport *apt, double radius, const string& fltType, const string& acType, const string& airline);
|
||||
void createTakeoffTaxi(FGAIAircraft *, bool firstFlight, FGAirport *apt, double radius, const std::string& fltType, const std::string& acType, const std::string& airline);
|
||||
|
||||
double getTurnRadius(double, bool);
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include <simgear/props/props.hxx>
|
||||
#include <simgear/props/props_io.hxx>
|
||||
|
||||
#include <Airports/simple.hxx>
|
||||
#include <Airports/runways.hxx>
|
||||
#include <Airports/dynamics.hxx>
|
||||
#include "AIAircraft.hxx"
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
#include <iostream>
|
||||
#include <simgear/route/waypoint.hxx>
|
||||
|
||||
#include <Navaids/awynet.hxx>
|
||||
#include <Airports/simple.hxx>
|
||||
#include <Airports/runways.hxx>
|
||||
#include <Airports/dynamics.hxx>
|
||||
|
||||
|
@ -40,6 +40,7 @@
|
|||
|
||||
using std::iostream;
|
||||
|
||||
/*
|
||||
void FGAIFlightPlan::evaluateRoutePart(double deplat,
|
||||
double deplon,
|
||||
double arrlat,
|
||||
|
@ -97,7 +98,7 @@ void FGAIFlightPlan::evaluateRoutePart(double deplat,
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
*/
|
||||
/*
|
||||
void FGAIFlightPlan::createCruise(bool firstFlight, FGAirport *dep,
|
||||
FGAirport *arr, double latitude,
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
#endif
|
||||
|
||||
#include <simgear/math/sg_geodesy.hxx>
|
||||
|
||||
#include <Airports/simple.hxx>
|
||||
#include <Airports/runways.hxx>
|
||||
#include <Airports/dynamics.hxx>
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
#include <Traffic/TrafficMgr.hxx>
|
||||
#include <Airports/groundnetwork.hxx>
|
||||
#include <Airports/dynamics.hxx>
|
||||
|
||||
#include <Airports/simple.hxx>
|
||||
|
||||
using std::sort;
|
||||
|
||||
|
|
|
@ -26,8 +26,6 @@
|
|||
|
||||
#include <simgear/compiler.h>
|
||||
|
||||
#include <plib/ul.h>
|
||||
|
||||
#include <Environment/environment_mgr.hxx>
|
||||
#include <Environment/environment.hxx>
|
||||
#include <simgear/misc/sg_path.hxx>
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include <simgear/debug/logstream.hxx>
|
||||
#include <simgear/route/waypoint.hxx>
|
||||
|
||||
#include <Airports/simple.hxx>
|
||||
#include <Airports/dynamics.hxx>
|
||||
|
||||
#include <AIModel/AIAircraft.hxx>
|
||||
|
|
|
@ -37,6 +37,9 @@
|
|||
|
||||
#include "runways.hxx"
|
||||
|
||||
#include <Airports/simple.hxx>
|
||||
#include <Navaids/procedure.hxx>
|
||||
|
||||
using std::string;
|
||||
|
||||
static std::string cleanRunwayNo(const std::string& aRwyNo)
|
||||
|
@ -168,3 +171,30 @@ void FGRunway::setReciprocalRunway(FGRunway* other)
|
|||
_reciprocal = other;
|
||||
}
|
||||
|
||||
std::vector<flightgear::SID*> FGRunway::getSIDs()
|
||||
{
|
||||
std::vector<flightgear::SID*> result;
|
||||
for (unsigned int i=0; i<_airport->numSIDs(); ++i) {
|
||||
flightgear::SID* s = _airport->getSIDByIndex(i);
|
||||
if (s->isForRunway(this)) {
|
||||
result.push_back(s);
|
||||
}
|
||||
} // of SIDs at the airport iteration
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<flightgear::STAR*> FGRunway::getSTARs()
|
||||
{
|
||||
std::vector<flightgear::STAR*> result;
|
||||
for (unsigned int i=0; i<_airport->numSTARs(); ++i) {
|
||||
flightgear::STAR* s = _airport->getSTARByIndex(i);
|
||||
if (s->isForRunway(this)) {
|
||||
result.push_back(s);
|
||||
}
|
||||
} // of STARs at the airport iteration
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -33,6 +33,11 @@ class FGAirport;
|
|||
class FGNavRecord;
|
||||
class SGPropertyNode;
|
||||
|
||||
namespace flightgear {
|
||||
class SID;
|
||||
class STAR;
|
||||
}
|
||||
|
||||
class FGRunway : public FGRunwayBase
|
||||
{
|
||||
FGAirport* _airport;
|
||||
|
@ -115,6 +120,16 @@ public:
|
|||
* Helper to process property data loaded from an ICAO.threshold.xml file
|
||||
*/
|
||||
void processThreshold(SGPropertyNode* aThreshold);
|
||||
|
||||
/**
|
||||
* Get SIDs (DPs) associated with this runway
|
||||
*/
|
||||
std::vector<flightgear::SID*> getSIDs();
|
||||
|
||||
/**
|
||||
* Get STARs associared with this runway
|
||||
*/
|
||||
std::vector<flightgear::STAR*> getSTARs();
|
||||
};
|
||||
|
||||
#endif // _FG_RUNWAYS_HXX
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#define _SIDSTAR_HXX_
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
#include <simgear/misc/sg_path.hxx>
|
||||
|
||||
|
@ -36,12 +37,10 @@
|
|||
#include "runwayprefs.hxx"
|
||||
|
||||
|
||||
using std::string;
|
||||
|
||||
class FGAirport;
|
||||
|
||||
typedef vector<FGAIFlightPlan*> FlightPlanVec;
|
||||
typedef vector<FGAIFlightPlan*>::iterator FlightPlanVecIterator;
|
||||
typedef std::vector<FGAIFlightPlan*> FlightPlanVec;
|
||||
typedef std::vector<FGAIFlightPlan*>::iterator FlightPlanVecIterator;
|
||||
|
||||
typedef std::map < std::string, FlightPlanVec > FlightPlanVecMap;
|
||||
|
||||
|
@ -49,7 +48,7 @@ typedef std::map < std::string, FlightPlanVec > FlightPlanVecMap;
|
|||
class FGSidStar
|
||||
{
|
||||
private:
|
||||
string id;
|
||||
std::string id;
|
||||
bool initialized;
|
||||
FlightPlanVecMap data;
|
||||
|
||||
|
@ -57,9 +56,9 @@ class FGSidStar
|
|||
FGSidStar(FGAirport *ap);
|
||||
FGSidStar(const FGSidStar &other);
|
||||
|
||||
string getId() { return id; };
|
||||
std::string getId() { return id; };
|
||||
void load(SGPath path);
|
||||
FGAIFlightPlan *getBest(string activeRunway, double heading);
|
||||
FGAIFlightPlan *getBest(std::string activeRunway, double heading);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -45,6 +45,11 @@
|
|||
#include <Airports/pavement.hxx>
|
||||
#include <Airports/dynamics.hxx>
|
||||
#include <Airports/xmlloader.hxx>
|
||||
#include <Navaids/procedure.hxx>
|
||||
#include <Navaids/waypoint.hxx>
|
||||
|
||||
using std::vector;
|
||||
using namespace flightgear;
|
||||
|
||||
// magic import of a helper which uses FGPositioned internals
|
||||
extern char** searchAirportNamesAndIdents(const std::string& aFilter);
|
||||
|
@ -187,6 +192,30 @@ FGRunway* FGAirport::findBestRunwayForHeading(double aHeading) const
|
|||
return result;
|
||||
}
|
||||
|
||||
FGRunway* FGAirport::findBestRunwayForPos(const SGGeod& aPos) const
|
||||
{
|
||||
loadRunways();
|
||||
|
||||
Runway_iterator it = mRunways.begin();
|
||||
FGRunway* result = NULL;
|
||||
double currentLowestDev = 180.0;
|
||||
|
||||
for (; it != mRunways.end(); ++it) {
|
||||
double inboundCourse = SGGeodesy::courseDeg(aPos, (*it)->end());
|
||||
double dev = inboundCourse - (*it)->headingDeg();
|
||||
SG_NORMALIZE_RANGE(dev, -180.0, 180.0);
|
||||
|
||||
dev = fabs(dev);
|
||||
if (dev < currentLowestDev) { // new best match
|
||||
currentLowestDev = dev;
|
||||
result = *it;
|
||||
}
|
||||
} // of runway iteration
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
bool FGAirport::hasHardRunwayOfLengthFt(double aLengthFt) const
|
||||
{
|
||||
loadRunways();
|
||||
|
@ -350,6 +379,23 @@ void FGAirport::loadTaxiways() const
|
|||
}
|
||||
}
|
||||
|
||||
void FGAirport::loadProcedures() const
|
||||
{
|
||||
if (mProceduresLoaded) {
|
||||
return;
|
||||
}
|
||||
|
||||
mProceduresLoaded = true;
|
||||
SGPath path;
|
||||
if (!XMLLoader::findAirportData(ident(), "procedures", path)) {
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "no procedures data available for " << ident());
|
||||
return;
|
||||
}
|
||||
|
||||
SG_LOG(SG_GENERAL, SG_INFO, ident() << ": loading procedures from " << path.str());
|
||||
Route::loadAirportProcedures(path, const_cast<FGAirport*>(this));
|
||||
}
|
||||
|
||||
void FGAirport::loadSceneryDefintions() const
|
||||
{
|
||||
// allow users to disable the scenery data in the short-term
|
||||
|
@ -412,6 +458,203 @@ void FGAirport::readTowerData(SGPropertyNode* aRoot)
|
|||
_tower_location = SGGeod::fromDegM(lon, lat, elevM);
|
||||
}
|
||||
|
||||
bool FGAirport::buildApproach(Waypt* aEnroute, STAR* aSTAR, FGRunway* aRwy, WayptVec& aRoute)
|
||||
{
|
||||
loadProcedures();
|
||||
|
||||
if ((aRwy && (aRwy->airport() != this))) {
|
||||
throw sg_exception("invalid parameters", "FGAirport::buildApproach");
|
||||
}
|
||||
|
||||
if (aSTAR) {
|
||||
bool ok = aSTAR->route(aRwy, aEnroute, aRoute);
|
||||
if (!ok) {
|
||||
SG_LOG(SG_GENERAL, SG_WARN, ident() << ": build approach, STAR " << aSTAR->ident()
|
||||
<< " failed to route from transition " << aEnroute->ident());
|
||||
return false;
|
||||
}
|
||||
} else if (aEnroute) {
|
||||
// no a STAR specified, just use enroute point directly
|
||||
aRoute.push_back(aEnroute);
|
||||
}
|
||||
|
||||
if (!aRwy) {
|
||||
// no runway selected yet, but we loaded the STAR, so that's fine, we're done
|
||||
return true;
|
||||
}
|
||||
|
||||
// build the approach (possibly including transition), and including the missed segment
|
||||
vector<Approach*> aps;
|
||||
for (unsigned int j=0; j<mApproaches.size();++j) {
|
||||
if (mApproaches[j]->runway() == aRwy) {
|
||||
aps.push_back(mApproaches[j]);
|
||||
}
|
||||
} // of approach filter by runway
|
||||
|
||||
if (aps.empty()) {
|
||||
SG_LOG(SG_GENERAL, SG_INFO, ident() << "; no approaches defined for runway " << aRwy->ident());
|
||||
// could build a fallback approach here
|
||||
return false;
|
||||
}
|
||||
|
||||
for (unsigned int k=0; k<aps.size(); ++k) {
|
||||
if (aps[k]->route(aRoute.back(), aRoute)) {
|
||||
return true;
|
||||
}
|
||||
} // of initial approach iteration
|
||||
|
||||
SG_LOG(SG_GENERAL, SG_INFO, ident() << ": unable to find transition to runway "
|
||||
<< aRwy->ident() << ", assume vectors");
|
||||
|
||||
WayptRef v(new ATCVectors(NULL, this));
|
||||
aRoute.push_back(v);
|
||||
return aps.front()->routeFromVectors(aRoute);
|
||||
}
|
||||
|
||||
pair<flightgear::SID*, WayptRef>
|
||||
FGAirport::selectSID(const SGGeod& aDest, FGRunway* aRwy)
|
||||
{
|
||||
loadProcedures();
|
||||
|
||||
WayptRef enroute;
|
||||
flightgear::SID* sid = NULL;
|
||||
double d = 1e9;
|
||||
|
||||
for (unsigned int i=0; i<mSIDs.size(); ++i) {
|
||||
if (aRwy && !mSIDs[i]->isForRunway(aRwy)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
WayptRef e = mSIDs[i]->findBestTransition(aDest);
|
||||
if (!e) {
|
||||
continue; // strange, but let's not worry about it
|
||||
}
|
||||
|
||||
// assert(e->isFixedPosition());
|
||||
double ed = SGGeodesy::distanceM(aDest, e->position());
|
||||
if (ed < d) { // new best match
|
||||
enroute = e;
|
||||
d = ed;
|
||||
sid = mSIDs[i];
|
||||
}
|
||||
} // of SID iteration
|
||||
|
||||
if (!mSIDs.empty() && !sid) {
|
||||
SG_LOG(SG_GENERAL, SG_INFO, ident() << "selectSID, no SID found (runway="
|
||||
<< (aRwy ? aRwy->ident() : "no runway preference"));
|
||||
}
|
||||
|
||||
return make_pair(sid, enroute);
|
||||
}
|
||||
|
||||
pair<STAR*, WayptRef>
|
||||
FGAirport::selectSTAR(const SGGeod& aOrigin, FGRunway* aRwy)
|
||||
{
|
||||
loadProcedures();
|
||||
|
||||
WayptRef enroute;
|
||||
STAR* star = NULL;
|
||||
double d = 1e9;
|
||||
|
||||
for (unsigned int i=0; i<mSTARs.size(); ++i) {
|
||||
if (!mSTARs[i]->isForRunway(aRwy)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "STAR " << mSTARs[i]->ident() << " is valid for runway");
|
||||
WayptRef e = mSTARs[i]->findBestTransition(aOrigin);
|
||||
if (!e) {
|
||||
continue; // strange, but let's not worry about it
|
||||
}
|
||||
|
||||
// assert(e->isFixedPosition());
|
||||
double ed = SGGeodesy::distanceM(aOrigin, e->position());
|
||||
if (ed < d) { // new best match
|
||||
enroute = e;
|
||||
d = ed;
|
||||
star = mSTARs[i];
|
||||
}
|
||||
} // of STAR iteration
|
||||
|
||||
return make_pair(star, enroute);
|
||||
}
|
||||
|
||||
|
||||
void FGAirport::addSID(flightgear::SID* aSid)
|
||||
{
|
||||
mSIDs.push_back(aSid);
|
||||
}
|
||||
|
||||
void FGAirport::addSTAR(STAR* aStar)
|
||||
{
|
||||
mSTARs.push_back(aStar);
|
||||
}
|
||||
|
||||
void FGAirport::addApproach(Approach* aApp)
|
||||
{
|
||||
mApproaches.push_back(aApp);
|
||||
}
|
||||
|
||||
unsigned int FGAirport::numSIDs() const
|
||||
{
|
||||
loadProcedures();
|
||||
return mSIDs.size();
|
||||
}
|
||||
|
||||
flightgear::SID* FGAirport::getSIDByIndex(unsigned int aIndex) const
|
||||
{
|
||||
loadProcedures();
|
||||
return mSIDs[aIndex];
|
||||
}
|
||||
|
||||
flightgear::SID* FGAirport::findSIDWithIdent(const std::string& aIdent) const
|
||||
{
|
||||
loadProcedures();
|
||||
for (unsigned int i=0; i<mSIDs.size(); ++i) {
|
||||
if (mSIDs[i]->ident() == aIdent) {
|
||||
return mSIDs[i];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
unsigned int FGAirport::numSTARs() const
|
||||
{
|
||||
loadProcedures();
|
||||
return mSTARs.size();
|
||||
}
|
||||
|
||||
STAR* FGAirport::getSTARByIndex(unsigned int aIndex) const
|
||||
{
|
||||
loadProcedures();
|
||||
return mSTARs[aIndex];
|
||||
}
|
||||
|
||||
STAR* FGAirport::findSTARWithIdent(const std::string& aIdent) const
|
||||
{
|
||||
loadProcedures();
|
||||
for (unsigned int i=0; i<mSTARs.size(); ++i) {
|
||||
if (mSTARs[i]->ident() == aIdent) {
|
||||
return mSTARs[i];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
unsigned int FGAirport::numApproaches() const
|
||||
{
|
||||
loadProcedures();
|
||||
return mApproaches.size();
|
||||
}
|
||||
|
||||
Approach* FGAirport::getApproachByIndex(unsigned int aIndex) const
|
||||
{
|
||||
loadProcedures();
|
||||
return mApproaches[aIndex];
|
||||
}
|
||||
|
||||
// get airport elevation
|
||||
double fgGetAirportElev( const string& id )
|
||||
{
|
||||
|
|
|
@ -45,6 +45,19 @@ typedef SGSharedPtr<FGRunway> FGRunwayPtr;
|
|||
typedef SGSharedPtr<FGTaxiway> FGTaxiwayPtr;
|
||||
typedef SGSharedPtr<FGPavement> FGPavementPtr;
|
||||
|
||||
namespace flightgear {
|
||||
class SID;
|
||||
class STAR;
|
||||
class Approach;
|
||||
class Waypt;
|
||||
|
||||
|
||||
typedef SGSharedPtr<Waypt> WayptRef;
|
||||
typedef std::vector<WayptRef> WayptVec;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************************************************************************
|
||||
*
|
||||
**************************************************************************************/
|
||||
|
@ -85,6 +98,15 @@ public:
|
|||
FGRunway* getRunwayByIdent(const std::string& aIdent) const;
|
||||
FGRunway* findBestRunwayForHeading(double aHeading) const;
|
||||
|
||||
/**
|
||||
* return the most likely target runway based on a position.
|
||||
* Specifically, return the runway for which the course from aPos
|
||||
* to the runway end, mostly closely matches the runway heading.
|
||||
* This is a good approximation of which runway the position is on or
|
||||
* aiming towards.
|
||||
*/
|
||||
FGRunway* findBestRunwayForPos(const SGGeod& aPos) const;
|
||||
|
||||
/**
|
||||
* Useful predicate for FMS/GPS/NAV displays and similar - check if this
|
||||
* aiport has a hard-surfaced runway of at least the specified length.
|
||||
|
@ -143,6 +165,26 @@ public:
|
|||
double mMinLengthFt;
|
||||
};
|
||||
|
||||
|
||||
void setProcedures(const std::vector<flightgear::SID*>& aSids,
|
||||
const std::vector<flightgear::STAR*>& aStars,
|
||||
const std::vector<flightgear::Approach*>& aApproaches);
|
||||
|
||||
void addSID(flightgear::SID* aSid);
|
||||
void addSTAR(flightgear::STAR* aStar);
|
||||
void addApproach(flightgear::Approach* aApp);
|
||||
|
||||
unsigned int numSIDs() const;
|
||||
flightgear::SID* getSIDByIndex(unsigned int aIndex) const;
|
||||
flightgear::SID* findSIDWithIdent(const std::string& aIdent) const;
|
||||
|
||||
unsigned int numSTARs() const;
|
||||
flightgear::STAR* getSTARByIndex(unsigned int aIndex) const;
|
||||
flightgear::STAR* findSTARWithIdent(const std::string& aIdent) const;
|
||||
|
||||
unsigned int numApproaches() const;
|
||||
flightgear::Approach* getApproachByIndex(unsigned int aIndex) const;
|
||||
|
||||
/**
|
||||
* Syntactic wrapper around FGPositioned::findClosest - find the closest
|
||||
* match for filter, and return it cast to FGAirport. The default filter
|
||||
|
@ -169,6 +211,23 @@ public:
|
|||
* matches in a format suitable for use by a puaList.
|
||||
*/
|
||||
static char** searchNamesAndIdents(const std::string& aFilter);
|
||||
|
||||
bool buildApproach(flightgear::Waypt* aEnroute, flightgear::STAR* aSTAR,
|
||||
FGRunway* aRwy, flightgear::WayptVec& aRoute);
|
||||
|
||||
/**
|
||||
* Given a destiation point, select the best SID and transition waypt from
|
||||
* this airport. Returns (NULL,NULL) is no SIDs are defined, otherwise the
|
||||
* best SID/transition is that which is closest to the destination point.
|
||||
*/
|
||||
std::pair<flightgear::SID*, flightgear::WayptRef> selectSID(const SGGeod& aDest, FGRunway* aRwy);
|
||||
|
||||
/**
|
||||
* Select a STAR and enroute transition waypt, given an origin (departure) position.
|
||||
* returns (NULL, NULL) is no suitable STAR is exists
|
||||
*/
|
||||
std::pair<flightgear::STAR*, flightgear::WayptRef> selectSTAR(const SGGeod& aOrigin, FGRunway* aRwy);
|
||||
|
||||
private:
|
||||
typedef std::vector<FGRunwayPtr>::const_iterator Runway_iterator;
|
||||
/**
|
||||
|
@ -203,13 +262,19 @@ private:
|
|||
|
||||
void loadRunways() const;
|
||||
void loadTaxiways() const;
|
||||
void loadProcedures() const;
|
||||
|
||||
mutable bool mRunwaysLoaded;
|
||||
mutable bool mTaxiwaysLoaded;
|
||||
mutable bool mProceduresLoaded;
|
||||
|
||||
std::vector<FGRunwayPtr> mRunways;
|
||||
std::vector<FGTaxiwayPtr> mTaxiways;
|
||||
std::vector<FGPavementPtr> mPavements;
|
||||
|
||||
std::vector<flightgear::SID*> mSIDs;
|
||||
std::vector<flightgear::STAR*> mSTARs;
|
||||
std::vector<flightgear::Approach*> mApproaches;
|
||||
};
|
||||
|
||||
// find basic airport location info from airport database
|
||||
|
|
|
@ -343,8 +343,10 @@ void DigitalFilter::update( bool firstTime, double dt)
|
|||
{
|
||||
if( _implementation == NULL ) return;
|
||||
|
||||
if( firstTime )
|
||||
_implementation->initialize( get_output_value() );
|
||||
if( firstTime ) {
|
||||
SG_LOG(SG_AUTOPILOT,SG_DEBUG, "First time initialization of " << get_name() << " to " << _valueInput.get_value() );
|
||||
_implementation->initialize( _valueInput.get_value() );
|
||||
}
|
||||
|
||||
double input = _valueInput.get_value() - _referenceInput.get_value();
|
||||
double output = _implementation->compute( dt, input );
|
||||
|
|
|
@ -23,15 +23,6 @@
|
|||
|
||||
#include "predictor.hxx"
|
||||
|
||||
#ifdef SG_BULK
|
||||
#undef SG_BULK
|
||||
#endif
|
||||
#define SG_BULK SG_ALERT
|
||||
#ifdef SG_INFO
|
||||
#undef SG_INFO
|
||||
#endif
|
||||
#define SG_INFO SG_ALERT
|
||||
|
||||
using namespace FGXMLAutopilot;
|
||||
|
||||
Predictor::Predictor () :
|
||||
|
@ -40,9 +31,18 @@ Predictor::Predictor () :
|
|||
{
|
||||
}
|
||||
|
||||
bool Predictor::configure(const string& nodeName, SGPropertyNode* configNode)
|
||||
bool Predictor::configure(const string& nodeName, SGPropertyNode_ptr configNode)
|
||||
{
|
||||
SG_LOG( SG_AUTOPILOT, SG_BULK, "Predictor::configure(" << nodeName << ")" << endl );
|
||||
|
||||
if( AnalogComponent::configure( nodeName, configNode ) )
|
||||
return true;
|
||||
|
||||
if( nodeName == "config" ) {
|
||||
Component::configure( configNode );
|
||||
return true;
|
||||
}
|
||||
|
||||
if (nodeName == "seconds") {
|
||||
_seconds.push_back( new InputValue( configNode, 0 ) );
|
||||
return true;
|
||||
|
|
|
@ -53,7 +53,7 @@ private:
|
|||
InputValueList _filter_gain;
|
||||
|
||||
protected:
|
||||
bool configure(const std::string& nodeName, SGPropertyNode* configNode );
|
||||
bool configure(const std::string& nodeName, SGPropertyNode_ptr configNode );
|
||||
|
||||
public:
|
||||
Predictor();
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -28,9 +28,11 @@
|
|||
#include <simgear/route/waypoint.hxx>
|
||||
#include <simgear/structure/subsystem_mgr.hxx>
|
||||
|
||||
#include <Navaids/route.hxx>
|
||||
|
||||
// forward decls
|
||||
class SGRoute;
|
||||
class SGPath;
|
||||
class PropertyWatcher;
|
||||
|
||||
class FGAirport;
|
||||
typedef SGSharedPtr<FGAirport> FGAirportRef;
|
||||
|
@ -42,9 +44,91 @@ typedef SGSharedPtr<FGAirport> FGAirportRef;
|
|||
|
||||
class FGRouteMgr : public SGSubsystem
|
||||
{
|
||||
public:
|
||||
FGRouteMgr();
|
||||
~FGRouteMgr();
|
||||
|
||||
void init ();
|
||||
void postinit ();
|
||||
void bind ();
|
||||
void unbind ();
|
||||
void update (double dt);
|
||||
|
||||
void insertWayptAtIndex(flightgear::Waypt* aWpt, int aIndex);
|
||||
flightgear::WayptRef removeWayptAtIndex(int index);
|
||||
|
||||
void clearRoute();
|
||||
|
||||
typedef enum {
|
||||
ROUTE_HIGH_AIRWAYS, ///< high-level airways routing
|
||||
ROUTE_LOW_AIRWAYS, ///< low-level airways routing
|
||||
ROUTE_VOR ///< VOR-VOR routing
|
||||
} RouteType;
|
||||
|
||||
/**
|
||||
* Insert waypoints from index-1 to index. In practice this means you can
|
||||
* 'fill in the gaps' between defined waypoints. If index=0, the departure
|
||||
* airport is used as index-1; if index is -1, the destination airport is
|
||||
* used as the final waypoint.
|
||||
*/
|
||||
bool routeToIndex(int index, RouteType aRouteType);
|
||||
|
||||
void autoRoute();
|
||||
|
||||
bool isRouteActive() const;
|
||||
|
||||
int currentIndex() const
|
||||
{ return _currentIndex; }
|
||||
|
||||
flightgear::Waypt* currentWaypt() const;
|
||||
flightgear::Waypt* nextWaypt() const;
|
||||
flightgear::Waypt* previousWaypt() const;
|
||||
|
||||
const flightgear::WayptVec& waypts() const
|
||||
{ return _route; }
|
||||
|
||||
int numWaypts() const
|
||||
{ return _route.size(); }
|
||||
|
||||
flightgear::Waypt* wayptAtIndex(int index) const;
|
||||
|
||||
/**
|
||||
* Find a waypoint in the route, by position, and return its index, or
|
||||
* -1 if no matching waypoint was found in the route.
|
||||
*/
|
||||
int findWayptIndex(const SGGeod& aPos) const;
|
||||
|
||||
/**
|
||||
* Activate a built route. This checks for various mandatory pieces of
|
||||
* data, such as departure and destination airports, and creates waypoints
|
||||
* for them on the route structure.
|
||||
*
|
||||
* returns true if the route was activated successfully, or false if the
|
||||
* route could not be activated for some reason
|
||||
*/
|
||||
bool activate();
|
||||
|
||||
/**
|
||||
* Step to the next waypoint on the active route
|
||||
*/
|
||||
void sequence();
|
||||
|
||||
/**
|
||||
* Set the current waypoint to the specified index.
|
||||
*/
|
||||
void jumpToIndex(int index);
|
||||
|
||||
void saveRoute();
|
||||
void loadRoute();
|
||||
|
||||
/**
|
||||
* Helper command to setup current airport/runway if necessary
|
||||
*/
|
||||
void initAtPosition();
|
||||
private:
|
||||
SGRoute* _route;
|
||||
flightgear::WayptVec _route;
|
||||
int _currentIndex;
|
||||
|
||||
time_t _takeoffTime;
|
||||
time_t _touchdownTime;
|
||||
FGAirportRef _departure;
|
||||
|
@ -77,6 +161,8 @@ private:
|
|||
SGPropertyNode_ptr _pathNode;
|
||||
SGPropertyNode_ptr _currentWpt;
|
||||
|
||||
/// integer property corresponding to the RouteType enum
|
||||
SGPropertyNode_ptr _routingType;
|
||||
|
||||
/**
|
||||
* Signal property to notify people that the route was edited
|
||||
|
@ -111,10 +197,17 @@ private:
|
|||
* - airport-id/runway-id
|
||||
* - navaid/radial-deg/offset-nm
|
||||
*/
|
||||
SGWayPoint* make_waypoint(const string& target);
|
||||
flightgear::WayptRef waypointFromString(const std::string& target);
|
||||
|
||||
|
||||
void departureChanged();
|
||||
void buildDeparture(flightgear::WayptRef enroute, flightgear::WayptVec& wps);
|
||||
|
||||
void arrivalChanged();
|
||||
void buildArrival(flightgear::WayptRef enroute, flightgear::WayptVec& wps);
|
||||
|
||||
/**
|
||||
* Helper to keep various pieces of state in sync when the SGRoute is
|
||||
* Helper to keep various pieces of state in sync when the route is
|
||||
* modified (waypoints added, inserted, removed). Notably, this fires the
|
||||
* 'edited' signal.
|
||||
*/
|
||||
|
@ -138,6 +231,17 @@ private:
|
|||
|
||||
void loadPlainTextRoute(const SGPath& path);
|
||||
|
||||
void loadVersion1XMLRoute(SGPropertyNode_ptr routeData);
|
||||
void loadVersion2XMLRoute(SGPropertyNode_ptr routeData);
|
||||
void loadXMLRouteHeader(SGPropertyNode_ptr routeData);
|
||||
flightgear::WayptRef parseVersion1XMLWaypt(SGPropertyNode* aWP);
|
||||
|
||||
/**
|
||||
* Predicate for helping the UI - test if at least one waypoint was
|
||||
* entered by the user (as opposed to being generated by the route-manager)
|
||||
*/
|
||||
bool haveUserWaypoints() const;
|
||||
|
||||
// tied getters and setters
|
||||
const char* getDepartureICAO() const;
|
||||
const char* getDepartureName() const;
|
||||
|
@ -146,64 +250,9 @@ private:
|
|||
const char* getDestinationICAO() const;
|
||||
const char* getDestinationName() const;
|
||||
void setDestinationICAO(const char* aIdent);
|
||||
|
||||
public:
|
||||
|
||||
FGRouteMgr();
|
||||
~FGRouteMgr();
|
||||
|
||||
void init ();
|
||||
void postinit ();
|
||||
void bind ();
|
||||
void unbind ();
|
||||
void update (double dt);
|
||||
|
||||
bool build ();
|
||||
|
||||
void new_waypoint( const string& tgt_alt, int n = -1 );
|
||||
void add_waypoint( const SGWayPoint& wp, int n = -1 );
|
||||
SGWayPoint pop_waypoint( int i = 0 );
|
||||
|
||||
SGWayPoint get_waypoint( int i ) const;
|
||||
int size() const;
|
||||
|
||||
bool isRouteActive() const;
|
||||
|
||||
int currentWaypoint() const;
|
||||
|
||||
/**
|
||||
* Find a waypoint in the route, by position, and return its index, or
|
||||
* -1 if no matching waypoint was found in the route.
|
||||
*/
|
||||
int findWaypoint(const SGGeod& aPos) const;
|
||||
|
||||
/**
|
||||
* Activate a built route. This checks for various mandatory pieces of
|
||||
* data, such as departure and destination airports, and creates waypoints
|
||||
* for them on the route structure.
|
||||
*
|
||||
* returns true if the route was activated successfully, or false if the
|
||||
* route could not be activated for some reason
|
||||
*/
|
||||
bool activate();
|
||||
|
||||
/**
|
||||
* Step to the next waypoint on the active route
|
||||
*/
|
||||
void sequence();
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
void jumpToIndex(int index);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
void setWaypointTargetAltitudeFt(unsigned int index, int altFt);
|
||||
|
||||
void saveRoute();
|
||||
void loadRoute();
|
||||
PropertyWatcher* _departureWatcher;
|
||||
PropertyWatcher* _arrivalWatcher;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -37,8 +37,6 @@
|
|||
#include <simgear/props/props.hxx>
|
||||
#include <simgear/timing/sg_time.hxx>
|
||||
|
||||
#include <Include/general.hxx>
|
||||
|
||||
#include <Main/globals.hxx>
|
||||
#include <Main/fg_props.hxx>
|
||||
#include <Main/viewmgr.hxx>
|
||||
|
@ -198,7 +196,7 @@ float get_sideslip( void )
|
|||
|
||||
float get_frame_rate( void )
|
||||
{
|
||||
return general.get_frame_rate();
|
||||
return fgGetInt("/sim/frame-rate");
|
||||
}
|
||||
|
||||
float get_fov( void )
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
#include <simgear/misc/sg_path.hxx>
|
||||
#include <simgear/props/props_io.hxx>
|
||||
|
||||
#include <osg/GLU>
|
||||
#include <osg/Matrixf>
|
||||
|
||||
#include <GUI/new_gui.hxx> // FGFontCache
|
||||
#include <Main/globals.hxx>
|
||||
|
@ -338,27 +338,31 @@ void fgUpdateHUD( osg::State* state ) {
|
|||
|
||||
void fgUpdateHUDVirtual(osg::State* state)
|
||||
{
|
||||
using namespace osg;
|
||||
FGViewer* view = globals->get_current_view();
|
||||
|
||||
// Standard fgfs projection, with essentially meaningless clip
|
||||
// planes (we'll map the whole HUD plane to z=-1)
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
gluPerspective(view->get_v_fov(), 1/view->get_aspect_ratio(), 0.1, 10);
|
||||
Matrixf proj
|
||||
= Matrixf::perspective(view->get_v_fov(), 1/view->get_aspect_ratio(),
|
||||
0.1, 10);
|
||||
glLoadMatrix(proj.ptr());
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
|
||||
// Standard fgfs view direction computation
|
||||
float lookat[3];
|
||||
Vec3f lookat;
|
||||
lookat[0] = -sin(SG_DEGREES_TO_RADIANS * view->getHeadingOffset_deg());
|
||||
lookat[1] = tan(SG_DEGREES_TO_RADIANS * view->getPitchOffset_deg());
|
||||
lookat[2] = -cos(SG_DEGREES_TO_RADIANS * view->getHeadingOffset_deg());
|
||||
if (fabs(lookat[1]) > 9999)
|
||||
lookat[1] = 9999; // FPU sanity
|
||||
gluLookAt(0, 0, 0, lookat[0], lookat[1], lookat[2], 0, 1, 0);
|
||||
Matrixf mv = Matrixf::lookAt(Vec3f(0.0, 0.0, 0.0), lookat,
|
||||
Vec3f(0.0, 1.0, 0.0));
|
||||
glLoadMatrix(mv.ptr());
|
||||
|
||||
// Map the -1:1 square to a 55.0x41.25 degree wide patch at z=1.
|
||||
// This is the default fgfs field of view, which the HUD files are
|
||||
|
@ -391,10 +395,11 @@ void fgUpdateHUDVirtual(osg::State* state)
|
|||
void fgUpdateHUD( osg::State* state, GLfloat x_start, GLfloat y_start,
|
||||
GLfloat x_end, GLfloat y_end )
|
||||
{
|
||||
using namespace osg;
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
gluOrtho2D(x_start, x_end, y_start, y_end);
|
||||
Matrixf proj = Matrixf::ortho2D(x_start, x_end, y_start, y_end);
|
||||
glLoadMatrix(proj.ptr());
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
|
|
|
@ -32,8 +32,7 @@
|
|||
#include <ATCDCL/ATCutils.hxx>
|
||||
#include <Main/viewer.hxx>
|
||||
|
||||
#include <osg/GLU>
|
||||
|
||||
#include <simgear/math/project.hxx>
|
||||
|
||||
// int x, int y, int width, int height, float scale_data, bool working)
|
||||
|
||||
|
@ -98,11 +97,6 @@ void runway_instr::draw()
|
|||
double sPitch = sin(pitch), cPitch = cos(pitch),
|
||||
sYaw = sin(yaw), cYaw = cos(yaw);
|
||||
|
||||
//Assuming that the "Cockpit View" is always at position zero!!!
|
||||
if (curr_view_id != 0) {
|
||||
globals->get_viewmgr()->set_view(0);
|
||||
globals->get_viewmgr()->copyToCurrent();
|
||||
}
|
||||
//Set the camera to the cockpit view to get the view of the runway from the cockpit
|
||||
// OSGFIXME
|
||||
// ssgSetCamera((sgVec4 *)cockpit_view->get_VIEW());
|
||||
|
@ -134,8 +128,9 @@ void runway_instr::draw()
|
|||
//Calculate the 2D points via gluProject
|
||||
int result = GL_TRUE;
|
||||
for (int i = 0; i < 6; i++) {
|
||||
result = gluProject(points3d[i][0], points3d[i][1], points3d[i][2], mm,
|
||||
pm, view, &points2d[i][0], &points2d[i][1], &points2d[i][2]);
|
||||
result = simgear::project(points3d[i][0], points3d[i][1], points3d[i][2],
|
||||
mm, pm, view,
|
||||
&points2d[i][0], &points2d[i][1], &points2d[i][2]);
|
||||
}
|
||||
//set the line width based on our distance from the runway
|
||||
setLineWidth();
|
||||
|
@ -156,15 +151,6 @@ void runway_instr::draw()
|
|||
drawArrow(); //draw indication arrow
|
||||
}
|
||||
|
||||
//Restore the current view and any offsets
|
||||
if (curr_view_id != 0) {
|
||||
globals->get_viewmgr()->set_view(curr_view_id);
|
||||
globals->get_viewmgr()->copyToCurrent();
|
||||
curr_view->setHeadingOffset_deg(ho);
|
||||
curr_view->setPitchOffset_deg(po);
|
||||
curr_view->setGoalHeadingOffset_deg(gho);
|
||||
curr_view->setGoalPitchOffset_deg(gpo);
|
||||
}
|
||||
//Set the camera back to the current view
|
||||
// OSGFIXME
|
||||
// ssgSetCamera((sgVec4 *)curr_view);
|
||||
|
@ -239,7 +225,8 @@ bool runway_instr::drawLine(const sgdVec3& a1, const sgdVec3& a2, const sgdVec3&
|
|||
sgdVec3 newPt;
|
||||
sgdCopyVec3(newPt, a1);
|
||||
sgdAddVec3(newPt, vec);
|
||||
if (gluProject(newPt[0], newPt[1], newPt[2], mm, pm, view, &p2[0], &p2[1], &p2[2])
|
||||
if (simgear::project(newPt[0], newPt[1], newPt[2], mm, pm, view,
|
||||
&p2[0], &p2[1], &p2[2])
|
||||
&& (p2[2] > 0 && p2[2] < 1.0)) {
|
||||
boundPoint(p1, p2);
|
||||
glBegin(GL_LINES);
|
||||
|
@ -255,7 +242,8 @@ bool runway_instr::drawLine(const sgdVec3& a1, const sgdVec3& a2, const sgdVec3&
|
|||
sgdVec3 newPt;
|
||||
sgdCopyVec3(newPt, a2);
|
||||
sgdAddVec3(newPt, vec);
|
||||
if (gluProject(newPt[0], newPt[1], newPt[2], mm, pm, view, &p1[0], &p1[1], &p1[2])
|
||||
if (simgear::project(newPt[0], newPt[1], newPt[2], mm, pm, view,
|
||||
&p1[0], &p1[1], &p1[2])
|
||||
&& (p1[2] > 0 && p1[2] < 1.0)) {
|
||||
boundPoint(p2, p1);
|
||||
glBegin(GL_LINES);
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
#include <osg/CullFace>
|
||||
#include <osg/Depth>
|
||||
#include <osg/Material>
|
||||
#include <osg/Matrixf>
|
||||
#include <osg/TexEnv>
|
||||
#include <osg/PolygonOffset>
|
||||
|
||||
|
@ -273,6 +274,7 @@ FGPanel::update (double dt)
|
|||
void
|
||||
FGPanel::update (osg::State& state, GLfloat winx, GLfloat winw, GLfloat winy, GLfloat winh)
|
||||
{
|
||||
using namespace osg;
|
||||
// Calculate accelerations
|
||||
// and jiggle the panel accordingly
|
||||
// The factors and bounds are just
|
||||
|
@ -284,12 +286,13 @@ FGPanel::update (osg::State& state, GLfloat winx, GLfloat winw, GLfloat winy, GL
|
|||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
Matrixf proj;
|
||||
if ( _flipx->getBoolValue() ) {
|
||||
gluOrtho2D(winx + winw, winx, winy + winh, winy); /* up side down */
|
||||
proj = Matrixf::ortho2D(winx + winw, winx, winy + winh, winy); /* up side down */
|
||||
} else {
|
||||
gluOrtho2D(winx, winx + winw, winy, winy + winh); /* right side up */
|
||||
proj = Matrixf::ortho2D(winx, winx + winw, winy, winy + winh); /* right side up */
|
||||
}
|
||||
glLoadMatrix(proj.ptr());
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
|
|
|
@ -55,6 +55,9 @@ public:
|
|||
protected:
|
||||
void bind();
|
||||
void unbind();
|
||||
void update( double dt );
|
||||
|
||||
virtual void update( bool first, double dt ) = 0;
|
||||
|
||||
long getMetarMaxAgeMin() const { return _max_age_n == NULL ? 0 : _max_age_n->getLongValue(); }
|
||||
|
||||
|
@ -65,6 +68,7 @@ protected:
|
|||
SGPropertyNode_ptr _max_age_n;
|
||||
|
||||
bool _enabled;
|
||||
bool __enabled;
|
||||
TiedPropertyList _tiedProperties;
|
||||
MetarProperties _metarProperties;
|
||||
};
|
||||
|
@ -83,6 +87,7 @@ BasicRealWxController::BasicRealWxController( SGPropertyNode_ptr rootNode ) :
|
|||
_ground_elevation_n( fgGetNode( "/position/ground-elev-m", true )),
|
||||
_max_age_n( fgGetNode( "/environment/params/metar-max-age-min", false ) ),
|
||||
_enabled(true),
|
||||
__enabled(false),
|
||||
_metarProperties( fgGetNode( rootNode->getStringValue("metar", "/environment/metar"), true ) )
|
||||
{
|
||||
}
|
||||
|
@ -93,11 +98,13 @@ BasicRealWxController::~BasicRealWxController()
|
|||
|
||||
void BasicRealWxController::init()
|
||||
{
|
||||
__enabled = false;
|
||||
update(0); // fetch data ASAP
|
||||
}
|
||||
|
||||
void BasicRealWxController::reinit()
|
||||
{
|
||||
__enabled = false;
|
||||
}
|
||||
|
||||
void BasicRealWxController::bind()
|
||||
|
@ -111,13 +118,23 @@ void BasicRealWxController::unbind()
|
|||
_tiedProperties.Untie();
|
||||
}
|
||||
|
||||
void BasicRealWxController::update( double dt )
|
||||
{
|
||||
if( _enabled ) {
|
||||
update( !__enabled, dt );
|
||||
__enabled = true;
|
||||
} else {
|
||||
__enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------------- */
|
||||
|
||||
class NoaaMetarRealWxController : public BasicRealWxController {
|
||||
public:
|
||||
NoaaMetarRealWxController( SGPropertyNode_ptr rootNode );
|
||||
virtual ~NoaaMetarRealWxController();
|
||||
virtual void update (double delta_time_sec);
|
||||
virtual void update (bool first, double delta_time_sec);
|
||||
|
||||
class MetarLoadRequest {
|
||||
public:
|
||||
|
@ -146,12 +163,13 @@ private:
|
|||
#if defined(ENABLE_THREADS)
|
||||
class MetarLoadThread : public OpenThreads::Thread {
|
||||
public:
|
||||
MetarLoadThread( long maxAge );
|
||||
void requestMetar( const MetarLoadRequest & metarRequest );
|
||||
bool hasMetar() { return _responseQueue.size() > 0; }
|
||||
string getMetar() { return _responseQueue.pop(); }
|
||||
virtual void run();
|
||||
MetarLoadThread( long maxAge );
|
||||
void requestMetar( const MetarLoadRequest & metarRequest, bool background = true );
|
||||
bool hasMetar() { return _responseQueue.size() > 0; }
|
||||
string getMetar() { return _responseQueue.pop(); }
|
||||
virtual void run();
|
||||
private:
|
||||
void fetch( const MetarLoadRequest & );
|
||||
long _maxAge;
|
||||
SGBlockingQueue <MetarLoadRequest> _requestQueue;
|
||||
SGBlockingQueue <string> _responseQueue;
|
||||
|
@ -188,17 +206,8 @@ NoaaMetarRealWxController::~NoaaMetarRealWxController()
|
|||
#endif // ENABLE_THREADS
|
||||
}
|
||||
|
||||
void NoaaMetarRealWxController::update( double dt )
|
||||
void NoaaMetarRealWxController::update( bool first, double dt )
|
||||
{
|
||||
if( !_enabled )
|
||||
return;
|
||||
|
||||
if( _metarLoadThread->hasMetar() ) {
|
||||
string metar = _metarLoadThread->getMetar();
|
||||
SG_LOG( SG_ALL, SG_ALERT, "NoaaMetarRwalWxController::update() received METAR " << metar );
|
||||
_metarDataNode->setStringValue( metar );
|
||||
}
|
||||
|
||||
_metarTimeToLive -= dt;
|
||||
_positionTimeToLive -= dt;
|
||||
_minimumRequestInterval -= dt;
|
||||
|
@ -234,11 +243,21 @@ void NoaaMetarRealWxController::update( double dt )
|
|||
if( !valid ) {
|
||||
if( _minimumRequestInterval <= 0 && stationId.length() > 0 ) {
|
||||
MetarLoadRequest request( stationId );
|
||||
_metarLoadThread->requestMetar( request );
|
||||
// load the first metar in the foreground to make sure a metar is received
|
||||
// before the automatic runway selection code runs. All subsequent calls
|
||||
// run in the background
|
||||
_metarLoadThread->requestMetar( request, !first );
|
||||
_minimumRequestInterval = 10;
|
||||
}
|
||||
}
|
||||
|
||||
if( _metarLoadThread->hasMetar() ) {
|
||||
string metar = _metarLoadThread->getMetar();
|
||||
SG_LOG( SG_ALL, SG_ALERT, "NoaaMetarRwalWxController::update() received METAR " << metar );
|
||||
_metarDataNode->setStringValue( metar );
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------------- */
|
||||
|
@ -249,16 +268,20 @@ NoaaMetarRealWxController::MetarLoadThread::MetarLoadThread( long maxAge ) :
|
|||
{
|
||||
}
|
||||
|
||||
void NoaaMetarRealWxController::MetarLoadThread::requestMetar( const MetarLoadRequest & metarRequest )
|
||||
void NoaaMetarRealWxController::MetarLoadThread::requestMetar( const MetarLoadRequest & metarRequest, bool background )
|
||||
{
|
||||
if( _requestQueue.size() > 10 ) {
|
||||
SG_LOG(SG_ALL,SG_ALERT,
|
||||
"NoaaMetarRealWxController::MetarLoadThread::requestMetar() more than 10 outstanding METAR requests, dropping "
|
||||
<< metarRequest._stationId );
|
||||
return;
|
||||
}
|
||||
if( background ) {
|
||||
if( _requestQueue.size() > 10 ) {
|
||||
SG_LOG(SG_ALL,SG_ALERT,
|
||||
"NoaaMetarRealWxController::MetarLoadThread::requestMetar() more than 10 outstanding METAR requests, dropping "
|
||||
<< metarRequest._stationId );
|
||||
return;
|
||||
}
|
||||
|
||||
_requestQueue.push( metarRequest );
|
||||
_requestQueue.push( metarRequest );
|
||||
} else {
|
||||
fetch( metarRequest );
|
||||
}
|
||||
}
|
||||
|
||||
void NoaaMetarRealWxController::MetarLoadThread::run()
|
||||
|
@ -269,34 +292,40 @@ void NoaaMetarRealWxController::MetarLoadThread::run()
|
|||
if( request._stationId.size() == 0 )
|
||||
break;
|
||||
|
||||
SGSharedPtr<FGMetar> result = NULL;
|
||||
|
||||
try {
|
||||
result = new FGMetar( request._stationId, request._proxyHost, request._proxyPort, request._proxyAuth );
|
||||
} catch (const sg_io_exception& e) {
|
||||
SG_LOG( SG_GENERAL, SG_WARN, "NoaaMetarRealWxController::fetchMetar(): can't get METAR for "
|
||||
<< request._stationId << ":" << e.getFormattedMessage().c_str() );
|
||||
continue;
|
||||
}
|
||||
|
||||
string reply = result->getData();
|
||||
std::replace(reply.begin(), reply.end(), '\n', ' ');
|
||||
string metar = simgear::strutils::strip( reply );
|
||||
|
||||
if( metar.empty() ) {
|
||||
SG_LOG( SG_GENERAL, SG_WARN, "NoaaMetarRealWxController::fetchMetar(): dropping empty METAR for "
|
||||
<< request._stationId );
|
||||
}
|
||||
|
||||
if( _maxAge && result->getAge_min() > _maxAge ) {
|
||||
SG_LOG( SG_GENERAL, SG_ALERT, "NoaaMetarRealWxController::fetchMetar(): dropping outdated METAR "
|
||||
<< metar );
|
||||
return;
|
||||
}
|
||||
|
||||
_responseQueue.push( metar );
|
||||
fetch( request );
|
||||
}
|
||||
}
|
||||
|
||||
void NoaaMetarRealWxController::MetarLoadThread::fetch( const MetarLoadRequest & request )
|
||||
{
|
||||
SGSharedPtr<FGMetar> result = NULL;
|
||||
|
||||
try {
|
||||
result = new FGMetar( request._stationId, request._proxyHost, request._proxyPort, request._proxyAuth );
|
||||
} catch (const sg_io_exception& e) {
|
||||
SG_LOG( SG_GENERAL, SG_WARN, "NoaaMetarRealWxController::fetchMetar(): can't get METAR for "
|
||||
<< request._stationId << ":" << e.getFormattedMessage().c_str() );
|
||||
return;
|
||||
}
|
||||
|
||||
string reply = result->getData();
|
||||
std::replace(reply.begin(), reply.end(), '\n', ' ');
|
||||
string metar = simgear::strutils::strip( reply );
|
||||
|
||||
if( metar.empty() ) {
|
||||
SG_LOG( SG_GENERAL, SG_WARN, "NoaaMetarRealWxController::fetchMetar(): dropping empty METAR for "
|
||||
<< request._stationId );
|
||||
return;
|
||||
}
|
||||
|
||||
if( _maxAge && result->getAge_min() > _maxAge ) {
|
||||
SG_LOG( SG_GENERAL, SG_ALERT, "NoaaMetarRealWxController::fetchMetar(): dropping outdated METAR "
|
||||
<< metar );
|
||||
return;
|
||||
}
|
||||
|
||||
_responseQueue.push( metar );
|
||||
}
|
||||
#endif
|
||||
|
||||
/* -------------------------------------------------------------------------------- */
|
||||
|
|
|
@ -24,8 +24,11 @@
|
|||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include <simgear/debug/logstream.hxx>
|
||||
#include <simgear/io/lowlevel.hxx> // endian tests
|
||||
#include <simgear/io/sg_netBuffer.hxx>
|
||||
|
||||
#include <Main/fg_props.hxx>
|
||||
#include <Network/native_ctrls.hxx>
|
||||
|
@ -34,6 +37,49 @@
|
|||
#include "ExternalNet.hxx"
|
||||
|
||||
|
||||
class HTTPClient : public simgear::NetBufferChannel
|
||||
{
|
||||
|
||||
bool done;
|
||||
SGTimeStamp start;
|
||||
|
||||
public:
|
||||
|
||||
HTTPClient ( const char* host, int port, const char* path ) :
|
||||
done( false )
|
||||
{
|
||||
open ();
|
||||
connect (host, port);
|
||||
|
||||
char buffer[256];
|
||||
::snprintf (buffer, 256, "GET %s HTTP/1.0\r\n\r\n", path );
|
||||
bufferSend(buffer, strlen(buffer) ) ;
|
||||
|
||||
start.stamp();
|
||||
}
|
||||
|
||||
virtual void handleBufferRead (simgear::NetBuffer& buffer)
|
||||
{
|
||||
const char* s = buffer.getData();
|
||||
while (*s)
|
||||
fputc(*s++,stdout);
|
||||
|
||||
printf("done\n");
|
||||
buffer.remove();
|
||||
printf("after buffer.remove()\n");
|
||||
done = true;
|
||||
}
|
||||
|
||||
bool isDone() const { return done; }
|
||||
bool isDone( long usec ) const {
|
||||
if ( start + SGTimeStamp::fromUSec(usec) < SGTimeStamp::now() ) {
|
||||
return true;
|
||||
} else {
|
||||
return done;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
FGExternalNet::FGExternalNet( double dt, string host, int dop, int dip, int cp )
|
||||
{
|
||||
// set_delta_t( dt );
|
||||
|
|
|
@ -23,59 +23,14 @@
|
|||
#ifndef _EXTERNAL_NET_HXX
|
||||
#define _EXTERNAL_NET_HXX
|
||||
|
||||
#include <plib/netBuffer.h>
|
||||
#include <plib/netSocket.h>
|
||||
|
||||
#include <simgear/timing/timestamp.hxx> // fine grained timing measurements
|
||||
#include <simgear/io/raw_socket.hxx>
|
||||
|
||||
#include <Network/net_ctrls.hxx>
|
||||
#include <Network/net_fdm.hxx>
|
||||
#include <FDM/flight.hxx>
|
||||
|
||||
|
||||
class HTTPClient : public netBufferChannel
|
||||
{
|
||||
|
||||
bool done;
|
||||
SGTimeStamp start;
|
||||
|
||||
public:
|
||||
|
||||
HTTPClient ( const char* host, int port, const char* path ) :
|
||||
done( false )
|
||||
{
|
||||
open ();
|
||||
connect (host, port);
|
||||
|
||||
const char* s = netFormat ( "GET %s HTTP/1.0\r\n\r\n", path );
|
||||
bufferSend( s, strlen(s) ) ;
|
||||
|
||||
start.stamp();
|
||||
}
|
||||
|
||||
virtual void handleBufferRead (netBuffer& buffer)
|
||||
{
|
||||
const char* s = buffer.getData();
|
||||
while (*s)
|
||||
fputc(*s++,stdout);
|
||||
|
||||
printf("done\n");
|
||||
buffer.remove();
|
||||
printf("after buffer.remove()\n");
|
||||
done = true;
|
||||
}
|
||||
|
||||
bool isDone() const { return done; }
|
||||
bool isDone( long usec ) const {
|
||||
if ( start + SGTimeStamp::fromUSec(usec) < SGTimeStamp::now() ) {
|
||||
return true;
|
||||
} else {
|
||||
return done;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class FGExternalNet: public FGInterface {
|
||||
|
||||
private:
|
||||
|
@ -85,8 +40,8 @@ private:
|
|||
int cmd_port;
|
||||
string fdm_host;
|
||||
|
||||
netSocket data_client;
|
||||
netSocket data_server;
|
||||
simgear::Socket data_client;
|
||||
simgear::Socket data_server;
|
||||
|
||||
bool valid;
|
||||
|
||||
|
|
|
@ -71,16 +71,9 @@ using namespace std;
|
|||
|
||||
namespace JSBSim {
|
||||
|
||||
static const char *IdSrc = "$Id: FGFDMExec.cpp,v 1.80 2010/08/21 22:56:10 jberndt Exp $";
|
||||
static const char *IdSrc = "$Id: FGFDMExec.cpp,v 1.82 2010/10/07 03:17:29 jberndt Exp $";
|
||||
static const char *IdHdr = ID_FDMEXEC;
|
||||
|
||||
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
GLOBAL DECLARATIONS
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
|
||||
|
||||
unsigned int FGFDMExec::FDMctr = 0;
|
||||
FGPropertyManager* FGFDMExec::master=0;
|
||||
|
||||
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
CLASS IMPLEMENTATION
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
|
||||
|
@ -102,11 +95,21 @@ void checkTied ( FGPropertyManager *node )
|
|||
}
|
||||
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
// Constructor
|
||||
|
||||
// Constructors
|
||||
FGFDMExec::FGFDMExec(FGPropertyManager* root) : Root(root)
|
||||
{
|
||||
FDMctr = new unsigned int;
|
||||
*FDMctr = 0;
|
||||
Initialize();
|
||||
}
|
||||
|
||||
FGFDMExec::FGFDMExec(FGPropertyManager* root, unsigned int* fdmctr) : Root(root), FDMctr(fdmctr)
|
||||
{
|
||||
Initialize();
|
||||
}
|
||||
|
||||
void FGFDMExec::Initialize()
|
||||
{
|
||||
Frame = 0;
|
||||
Error = 0;
|
||||
GroundCallback = 0;
|
||||
|
@ -138,22 +141,26 @@ FGFDMExec::FGFDMExec(FGPropertyManager* root) : Root(root)
|
|||
dT = 1.0/120.0; // a default timestep size. This is needed for when JSBSim is
|
||||
// run in standalone mode with no initialization file.
|
||||
|
||||
IdFDM = FDMctr; // The main (parent) JSBSim instance is always the "zeroth"
|
||||
FDMctr++; // instance. "child" instances are loaded last.
|
||||
|
||||
try {
|
||||
char* num = getenv("JSBSIM_DEBUG");
|
||||
if (num) debug_lvl = atoi(num); // set debug level
|
||||
} catch (...) { // if error set to 1
|
||||
} catch (...) { // if error set to 1
|
||||
debug_lvl = 1;
|
||||
}
|
||||
|
||||
if (Root == 0) {
|
||||
if (master == 0)
|
||||
master = new FGPropertyManager;
|
||||
Root = master;
|
||||
if (Root == 0) { // Then this is the root FDM
|
||||
Root = new FGPropertyManager; // Create the property manager
|
||||
|
||||
FDMctr = new unsigned int; // Create and initialize the child FDM counter
|
||||
(*FDMctr) = 0;
|
||||
}
|
||||
|
||||
// Store this FDM's ID
|
||||
IdFDM = (*FDMctr); // The main (parent) JSBSim instance is always the "zeroth"
|
||||
|
||||
// Prepare FDMctr for the next child FDM id
|
||||
(*FDMctr)++; // instance. "child" instances are loaded last.
|
||||
|
||||
instance = Root->GetNode("/fdm/jsbsim",IdFDM,true);
|
||||
Debug(0);
|
||||
// this is to catch errors in binding member functions to the property tree.
|
||||
|
@ -186,7 +193,17 @@ FGFDMExec::~FGFDMExec()
|
|||
try {
|
||||
checkTied( instance );
|
||||
DeAllocate();
|
||||
if (Root == 0) delete master;
|
||||
|
||||
if (IdFDM == 0) { // Meaning this is no child FDM
|
||||
if(Root != 0) {
|
||||
delete Root;
|
||||
Root = 0;
|
||||
}
|
||||
if(FDMctr != 0) {
|
||||
delete FDMctr;
|
||||
FDMctr = 0;
|
||||
}
|
||||
}
|
||||
} catch ( string msg ) {
|
||||
cout << "Caught error: " << msg << endl;
|
||||
}
|
||||
|
@ -439,7 +456,7 @@ vector <string> FGFDMExec::EnumerateFDMs(void)
|
|||
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
bool FGFDMExec::LoadScript(string script, double deltaT)
|
||||
bool FGFDMExec::LoadScript(const string& script, double deltaT)
|
||||
{
|
||||
bool result;
|
||||
|
||||
|
@ -451,8 +468,8 @@ bool FGFDMExec::LoadScript(string script, double deltaT)
|
|||
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
bool FGFDMExec::LoadModel(string AircraftPath, string EnginePath, string SystemsPath,
|
||||
string model, bool addModelToPath)
|
||||
bool FGFDMExec::LoadModel(const string& AircraftPath, const string& EnginePath, const string& SystemsPath,
|
||||
const string& model, bool addModelToPath)
|
||||
{
|
||||
FGFDMExec::AircraftPath = RootDir + AircraftPath;
|
||||
FGFDMExec::EnginePath = RootDir + EnginePath;
|
||||
|
@ -463,7 +480,7 @@ bool FGFDMExec::LoadModel(string AircraftPath, string EnginePath, string Systems
|
|||
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
bool FGFDMExec::LoadModel(string model, bool addModelToPath)
|
||||
bool FGFDMExec::LoadModel(const string& model, bool addModelToPath)
|
||||
{
|
||||
string token;
|
||||
string aircraftCfgFileName;
|
||||
|
@ -730,7 +747,7 @@ void FGFDMExec::BuildPropertyCatalog(struct PropertyCatalogStructure* pcs)
|
|||
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
string FGFDMExec::QueryPropertyCatalog(string in)
|
||||
string FGFDMExec::QueryPropertyCatalog(const string& in)
|
||||
{
|
||||
string results="";
|
||||
for (unsigned i=0; i<PropertyCatalog.size(); i++) {
|
||||
|
@ -852,7 +869,7 @@ bool FGFDMExec::ReadChild(Element* el)
|
|||
|
||||
struct childData* child = new childData;
|
||||
|
||||
child->exec = new FGFDMExec();
|
||||
child->exec = new FGFDMExec(Root, FDMctr);
|
||||
child->exec->SetChild(true);
|
||||
|
||||
string childAircraft = el->GetAttributeValue("name");
|
||||
|
@ -922,7 +939,7 @@ void FGFDMExec::EnableOutput(void)
|
|||
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
bool FGFDMExec::SetOutputDirectives(string fname)
|
||||
bool FGFDMExec::SetOutputDirectives(const string& fname)
|
||||
{
|
||||
bool result;
|
||||
|
||||
|
|
|
@ -60,7 +60,7 @@ INCLUDES
|
|||
DEFINITIONS
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
|
||||
|
||||
#define ID_FDMEXEC "$Id: FGFDMExec.h,v 1.52 2010/07/04 13:50:21 jberndt Exp $"
|
||||
#define ID_FDMEXEC "$Id: FGFDMExec.h,v 1.54 2010/10/07 03:17:29 jberndt Exp $"
|
||||
|
||||
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
FORWARD DECLARATIONS
|
||||
|
@ -169,7 +169,7 @@ CLASS DOCUMENTATION
|
|||
property actually maps toa function call of DoTrim().
|
||||
|
||||
@author Jon S. Berndt
|
||||
@version $Revision: 1.52 $
|
||||
@version $Revision: 1.54 $
|
||||
*/
|
||||
|
||||
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
@ -206,8 +206,9 @@ class FGFDMExec : public FGJSBBase, public FGXMLFileRead
|
|||
|
||||
public:
|
||||
|
||||
/// Default constructor
|
||||
/// Default constructors
|
||||
FGFDMExec(FGPropertyManager* root = 0);
|
||||
FGFDMExec(FGPropertyManager* root, unsigned int* fdmctr);
|
||||
|
||||
/// Default destructor
|
||||
~FGFDMExec();
|
||||
|
@ -252,8 +253,8 @@ public:
|
|||
@param addModelToPath set to true to add the model name to the
|
||||
AircraftPath, defaults to true
|
||||
@return true if successful */
|
||||
bool LoadModel(string AircraftPath, string EnginePath, string SystemsPath,
|
||||
string model, bool addModelToPath = true);
|
||||
bool LoadModel(const string& AircraftPath, const string& EnginePath, const string& SystemsPath,
|
||||
const string& model, bool addModelToPath = true);
|
||||
|
||||
/** Loads an aircraft model. The paths to the aircraft and engine
|
||||
config file directories must be set prior to calling this. See
|
||||
|
@ -265,28 +266,28 @@ public:
|
|||
@param addModelToPath set to true to add the model name to the
|
||||
AircraftPath, defaults to true
|
||||
@return true if successful*/
|
||||
bool LoadModel(string model, bool addModelToPath = true);
|
||||
bool LoadModel(const string& model, bool addModelToPath = true);
|
||||
|
||||
/** Loads a script
|
||||
@param Script the full path name and file name for the script to be loaded.
|
||||
@return true if successfully loadsd; false otherwise. */
|
||||
bool LoadScript(string Script, double deltaT);
|
||||
bool LoadScript(const string& Script, double deltaT);
|
||||
|
||||
/** Sets the path to the engine config file directories.
|
||||
@param path path to the directory under which engine config
|
||||
files are kept, for instance "engine" */
|
||||
bool SetEnginePath(string path) { EnginePath = RootDir + path; return true; }
|
||||
bool SetEnginePath(const string& path) { EnginePath = RootDir + path; return true; }
|
||||
|
||||
/** Sets the path to the aircraft config file directories.
|
||||
@param path path to the aircraft directory. For instance:
|
||||
"aircraft". Under aircraft, then, would be directories for various
|
||||
modeled aircraft such as C172/, x15/, etc. */
|
||||
bool SetAircraftPath(string path) { AircraftPath = RootDir + path; return true; }
|
||||
bool SetAircraftPath(const string& path) { AircraftPath = RootDir + path; return true; }
|
||||
|
||||
/** Sets the path to the systems config file directories.
|
||||
@param path path to the directory under which systems config
|
||||
files are kept, for instance "systems" */
|
||||
bool SetSystemsPath(string path) { SystemsPath = RootDir + path; return true; }
|
||||
bool SetSystemsPath(const string& path) { SystemsPath = RootDir + path; return true; }
|
||||
|
||||
/// @name Top-level executive State and Model retrieval mechanism
|
||||
//@{
|
||||
|
@ -327,28 +328,28 @@ public:
|
|||
//@}
|
||||
|
||||
/// Retrieves the engine path.
|
||||
inline string GetEnginePath(void) {return EnginePath;}
|
||||
inline const string& GetEnginePath(void) {return EnginePath;}
|
||||
/// Retrieves the aircraft path.
|
||||
inline string GetAircraftPath(void) {return AircraftPath;}
|
||||
inline const string& GetAircraftPath(void) {return AircraftPath;}
|
||||
/// Retrieves the systems path.
|
||||
inline string GetSystemsPath(void) {return SystemsPath;}
|
||||
inline const string& GetSystemsPath(void) {return SystemsPath;}
|
||||
/// Retrieves the full aircraft path name.
|
||||
inline string GetFullAircraftPath(void) {return FullAircraftPath;}
|
||||
inline const string& GetFullAircraftPath(void) {return FullAircraftPath;}
|
||||
|
||||
/** Retrieves the value of a property.
|
||||
@param property the name of the property
|
||||
@result the value of the specified property */
|
||||
inline double GetPropertyValue(string property) {return instance->GetDouble(property);}
|
||||
inline double GetPropertyValue(const string& property) {return instance->GetDouble(property);}
|
||||
|
||||
/** Sets a property value.
|
||||
@param property the property to be set
|
||||
@param value the value to set the property to */
|
||||
inline void SetPropertyValue(string property, double value) {
|
||||
inline void SetPropertyValue(const string& property, double value) {
|
||||
instance->SetDouble(property, value);
|
||||
}
|
||||
|
||||
/// Returns the model name.
|
||||
string GetModelName(void) { return modelName; }
|
||||
const string& GetModelName(void) { return modelName; }
|
||||
/*
|
||||
/// Returns the current time.
|
||||
double GetSimTime(void);
|
||||
|
@ -382,12 +383,12 @@ public:
|
|||
be logged.
|
||||
@param fname the filename of an output directives file.
|
||||
*/
|
||||
bool SetOutputDirectives(string fname);
|
||||
bool SetOutputDirectives(const string& fname);
|
||||
|
||||
/** Sets (or overrides) the output filename
|
||||
@param fname the name of the file to output data to
|
||||
@return true if successful, false if there is no output specified for the flight model */
|
||||
bool SetOutputFileName(string fname) {
|
||||
bool SetOutputFileName(const string& fname) {
|
||||
if (Outputs.size() > 0) Outputs[0]->SetOutputFileName(fname);
|
||||
else return false;
|
||||
return true;
|
||||
|
@ -447,7 +448,7 @@ public:
|
|||
* @param check The string to search for in the property catalog.
|
||||
* @return the carriage-return-delimited string containing all matching strings
|
||||
* in the catalog. */
|
||||
string QueryPropertyCatalog(string check);
|
||||
string QueryPropertyCatalog(const string& check);
|
||||
|
||||
// Print the contents of the property catalog for the loaded aircraft.
|
||||
void PrintPropertyCatalog(void);
|
||||
|
@ -495,11 +496,11 @@ public:
|
|||
|
||||
/** Sets the root directory where JSBSim starts looking for its system directories.
|
||||
@param rootDir the string containing the root directory. */
|
||||
void SetRootDir(string rootDir) {RootDir = rootDir;}
|
||||
void SetRootDir(const string& rootDir) {RootDir = rootDir;}
|
||||
|
||||
/** Retrieves teh Root Directory.
|
||||
@return the string representing the root (base) JSBSim directory. */
|
||||
string GetRootDir(void) const {return RootDir;}
|
||||
const string& GetRootDir(void) const {return RootDir;}
|
||||
|
||||
/** Increments the simulation time.
|
||||
@return the new simulation time. */
|
||||
|
@ -512,7 +513,6 @@ public:
|
|||
int GetDebugLevel(void) const {return debug_lvl;};
|
||||
|
||||
private:
|
||||
static unsigned int FDMctr;
|
||||
int Error;
|
||||
unsigned int Frame;
|
||||
unsigned int IdFDM;
|
||||
|
@ -536,8 +536,6 @@ private:
|
|||
bool trim_status;
|
||||
int ta_mode;
|
||||
|
||||
static FGPropertyManager *master;
|
||||
|
||||
FGGroundCallback* GroundCallback;
|
||||
FGAtmosphere* Atmosphere;
|
||||
FGFCS* FCS;
|
||||
|
@ -558,12 +556,16 @@ private:
|
|||
|
||||
FGPropertyManager* Root;
|
||||
FGPropertyManager* instance;
|
||||
|
||||
// The FDM counter is used to give each child FDM an unique ID. The root FDM has the ID 0
|
||||
unsigned int* FDMctr;
|
||||
|
||||
vector <string> PropertyCatalog;
|
||||
vector <FGOutput*> Outputs;
|
||||
vector <childData*> ChildFDMList;
|
||||
vector <FGModel*> Models;
|
||||
|
||||
void Initialize();
|
||||
bool ReadFileHeader(Element*);
|
||||
bool ReadChild(Element*);
|
||||
bool ReadPrologue(Element*);
|
||||
|
|
|
@ -1,178 +0,0 @@
|
|||
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
Module: FGState.cpp
|
||||
Author: Jon Berndt
|
||||
Date started: 11/17/98
|
||||
Called by: FGFDMExec and accessed by all models.
|
||||
|
||||
------------- Copyright (C) 1999 Jon S. Berndt (jon@jsbsim.org) -------------
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser 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 Lesser General Public License for more
|
||||
details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
||||
Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
Further information about the GNU Lesser General Public License can also be found on
|
||||
the world wide web at http://www.gnu.org.
|
||||
|
||||
FUNCTIONAL DESCRIPTION
|
||||
--------------------------------------------------------------------------------
|
||||
See header file.
|
||||
|
||||
HISTORY
|
||||
--------------------------------------------------------------------------------
|
||||
11/17/98 JSB Created
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
INCLUDES
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
|
||||
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
|
||||
#include "FGState.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace JSBSim {
|
||||
|
||||
static const char *IdSrc = "$Id: FGState.cpp,v 1.15 2009/10/24 22:59:30 jberndt Exp $";
|
||||
static const char *IdHdr = ID_STATE;
|
||||
|
||||
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
MACROS
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
|
||||
|
||||
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
CLASS IMPLEMENTATION
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
|
||||
|
||||
FGState::FGState(FGFDMExec* fdex)
|
||||
{
|
||||
FDMExec = fdex;
|
||||
|
||||
sim_time = 0.0;
|
||||
dt = 1.0/120.0; // a default timestep size. This is needed for when JSBSim is
|
||||
// run in standalone mode with no initialization file.
|
||||
|
||||
Aircraft = FDMExec->GetAircraft();
|
||||
Propagate = FDMExec->GetPropagate();
|
||||
Auxiliary = FDMExec->GetAuxiliary();
|
||||
FCS = FDMExec->GetFCS();
|
||||
Atmosphere = FDMExec->GetAtmosphere();
|
||||
Aerodynamics = FDMExec->GetAerodynamics();
|
||||
GroundReactions = FDMExec->GetGroundReactions();
|
||||
Propulsion = FDMExec->GetPropulsion();
|
||||
PropertyManager = FDMExec->GetPropertyManager();
|
||||
|
||||
bind();
|
||||
|
||||
Debug(0);
|
||||
}
|
||||
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
FGState::~FGState()
|
||||
{
|
||||
Debug(1);
|
||||
}
|
||||
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
void FGState::Initialize(FGInitialCondition *FGIC)
|
||||
{
|
||||
sim_time = 0.0;
|
||||
|
||||
Propagate->SetInitialState( FGIC );
|
||||
|
||||
Atmosphere->Run();
|
||||
Atmosphere->SetWindNED( FGIC->GetWindNFpsIC(),
|
||||
FGIC->GetWindEFpsIC(),
|
||||
FGIC->GetWindDFpsIC() );
|
||||
|
||||
FGColumnVector3 vAeroUVW;
|
||||
vAeroUVW = Propagate->GetUVW() + Propagate->GetTl2b()*Atmosphere->GetTotalWindNED();
|
||||
|
||||
double alpha, beta;
|
||||
if (vAeroUVW(eW) != 0.0)
|
||||
alpha = vAeroUVW(eU)*vAeroUVW(eU) > 0.0 ? atan2(vAeroUVW(eW), vAeroUVW(eU)) : 0.0;
|
||||
else
|
||||
alpha = 0.0;
|
||||
if (vAeroUVW(eV) != 0.0)
|
||||
beta = vAeroUVW(eU)*vAeroUVW(eU)+vAeroUVW(eW)*vAeroUVW(eW) > 0.0 ? atan2(vAeroUVW(eV), (fabs(vAeroUVW(eU))/vAeroUVW(eU))*sqrt(vAeroUVW(eU)*vAeroUVW(eU) + vAeroUVW(eW)*vAeroUVW(eW))) : 0.0;
|
||||
else
|
||||
beta = 0.0;
|
||||
|
||||
Auxiliary->SetAB(alpha, beta);
|
||||
|
||||
double Vt = vAeroUVW.Magnitude();
|
||||
Auxiliary->SetVt(Vt);
|
||||
|
||||
Auxiliary->SetMach(Vt/Atmosphere->GetSoundSpeed());
|
||||
|
||||
double qbar = 0.5*Vt*Vt*Atmosphere->GetDensity();
|
||||
Auxiliary->Setqbar(qbar);
|
||||
}
|
||||
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
void FGState::bind(void)
|
||||
{
|
||||
PropertyManager->Tie("sim-time-sec", this, &FGState::Getsim_time);
|
||||
}
|
||||
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
// The bitmasked value choices are as follows:
|
||||
// unset: In this case (the default) JSBSim would only print
|
||||
// out the normally expected messages, essentially echoing
|
||||
// the config files as they are read. If the environment
|
||||
// variable is not set, debug_lvl is set to 1 internally
|
||||
// 0: This requests JSBSim not to output any messages
|
||||
// whatsoever.
|
||||
// 1: This value explicity requests the normal JSBSim
|
||||
// startup messages
|
||||
// 2: This value asks for a message to be printed out when
|
||||
// a class is instantiated
|
||||
// 4: When this value is set, a message is displayed when a
|
||||
// FGModel object executes its Run() method
|
||||
// 8: When this value is set, various runtime state variables
|
||||
// are printed out periodically
|
||||
// 16: When set various parameters are sanity checked and
|
||||
// a message is printed out when they go out of bounds
|
||||
|
||||
void FGState::Debug(int from)
|
||||
{
|
||||
if (debug_lvl <= 0) return;
|
||||
|
||||
if (debug_lvl & 1) { // Standard console startup message output
|
||||
if (from == 0) { // Constructor
|
||||
|
||||
}
|
||||
}
|
||||
if (debug_lvl & 2 ) { // Instantiation/Destruction notification
|
||||
if (from == 0) cout << "Instantiated: FGState" << endl;
|
||||
if (from == 1) cout << "Destroyed: FGState" << endl;
|
||||
}
|
||||
if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
|
||||
}
|
||||
if (debug_lvl & 8 ) { // Runtime state variables
|
||||
}
|
||||
if (debug_lvl & 16) { // Sanity checking
|
||||
}
|
||||
if (debug_lvl & 64) {
|
||||
if (from == 0) { // Constructor
|
||||
cout << IdSrc << endl;
|
||||
cout << IdHdr << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,166 +0,0 @@
|
|||
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
Header: FGState.h
|
||||
Author: Jon S. Berndt
|
||||
Date started: 11/17/98
|
||||
|
||||
------------- Copyright (C) 1999 Jon S. Berndt (jon@jsbsim.org) -------------
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser 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 Lesser General Public License for more
|
||||
details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
||||
Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
Further information about the GNU Lesser General Public License can also be found on
|
||||
the world wide web at http://www.gnu.org.
|
||||
|
||||
FUNCTIONAL DESCRIPTION
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
HISTORY
|
||||
--------------------------------------------------------------------------------
|
||||
11/17/98 JSB Created
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
SENTRY
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
|
||||
|
||||
#ifndef FGSTATE_H
|
||||
#define FGSTATE_H
|
||||
|
||||
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
INCLUDES
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
|
||||
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include "FGJSBBase.h"
|
||||
#include "initialization/FGInitialCondition.h"
|
||||
#include "math/FGColumnVector3.h"
|
||||
#include "math/FGQuaternion.h"
|
||||
#include "FGFDMExec.h"
|
||||
#include "models/FGAtmosphere.h"
|
||||
#include "models/FGFCS.h"
|
||||
#include "models/FGPropagate.h"
|
||||
#include "models/FGAuxiliary.h"
|
||||
#include "models/FGAerodynamics.h"
|
||||
#include "models/FGAircraft.h"
|
||||
#include "models/FGGroundReactions.h"
|
||||
#include "models/FGPropulsion.h"
|
||||
|
||||
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
DEFINITIONS
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
|
||||
|
||||
#define ID_STATE "$Id: FGState.h,v 1.15 2009/10/02 10:30:07 jberndt Exp $"
|
||||
|
||||
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
FORWARD DECLARATIONS
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
|
||||
|
||||
namespace JSBSim {
|
||||
|
||||
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
CLASS DOCUMENTATION
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
|
||||
|
||||
/** Encapsulates the calculation of aircraft state.
|
||||
<h3>Properties</h3>
|
||||
@property sim-time-sec (read only) cumulative simulation in seconds.
|
||||
@author Jon S. Berndt
|
||||
@version $Revision: 1.15 $
|
||||
*/
|
||||
|
||||
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
CLASS DECLARATION
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
|
||||
|
||||
class FGState : public FGJSBBase
|
||||
{
|
||||
public:
|
||||
/** Constructor
|
||||
@param Executive a pointer to the parent executive object */
|
||||
FGState(FGFDMExec*);
|
||||
/// Destructor
|
||||
~FGState();
|
||||
|
||||
/** Initializes the simulation state based on parameters from an Initial Conditions object.
|
||||
@param FGIC pointer to an initial conditions object.
|
||||
@see FGInitialConditions. */
|
||||
void Initialize(FGInitialCondition *FGIC);
|
||||
|
||||
/// Returns the cumulative simulation time in seconds.
|
||||
inline double Getsim_time(void) const { return sim_time; }
|
||||
|
||||
/// Returns the simulation delta T.
|
||||
inline double Getdt(void) {return dt;}
|
||||
|
||||
/// Suspends the simulation and sets the delta T to zero.
|
||||
inline void SuspendIntegration(void) {saved_dt = dt; dt = 0.0;}
|
||||
|
||||
/// Resumes the simulation by resetting delta T to the correct value.
|
||||
inline void ResumeIntegration(void) {dt = saved_dt;}
|
||||
|
||||
/** Returns the simulation suspension state.
|
||||
@return true if suspended, false if executing */
|
||||
bool IntegrationSuspended(void) {return dt == 0.0;}
|
||||
|
||||
/** Sets the current sim time.
|
||||
@param cur_time the current time
|
||||
@return the current simulation time. */
|
||||
inline double Setsim_time(double cur_time) {
|
||||
sim_time = cur_time;
|
||||
return sim_time;
|
||||
}
|
||||
|
||||
/** Sets the integration time step for the simulation executive.
|
||||
@param delta_t the time step in seconds. */
|
||||
inline void Setdt(double delta_t) { dt = delta_t; }
|
||||
|
||||
/** Increments the simulation time.
|
||||
@return the new simulation time. */
|
||||
inline double IncrTime(void) {
|
||||
sim_time+=dt;
|
||||
return sim_time;
|
||||
}
|
||||
|
||||
/** Prints a summary of simulator state (speed, altitude,
|
||||
configuration, etc.) */
|
||||
// void ReportState(void);
|
||||
|
||||
private:
|
||||
double sim_time, dt;
|
||||
double saved_dt;
|
||||
|
||||
FGFDMExec* FDMExec;
|
||||
|
||||
FGAircraft* Aircraft;
|
||||
FGPropagate* Propagate;
|
||||
FGAtmosphere* Atmosphere;
|
||||
FGFCS* FCS;
|
||||
FGAerodynamics* Aerodynamics;
|
||||
FGGroundReactions* GroundReactions;
|
||||
FGPropulsion* Propulsion;
|
||||
FGAuxiliary* Auxiliary;
|
||||
FGPropertyManager* PropertyManager;
|
||||
|
||||
void bind();
|
||||
|
||||
void Debug(int from);
|
||||
};
|
||||
}
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -18,7 +18,7 @@
|
|||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
// $Id: JSBSim.cxx,v 1.62 2010/07/14 05:50:40 ehofman Exp $
|
||||
// $Id: JSBSim.cxx,v 1.63 2010/10/07 03:45:40 jberndt Exp $
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
|
@ -97,14 +97,15 @@ public:
|
|||
|
||||
/** Compute the altitude above ground. */
|
||||
virtual double GetAGLevel(double t, const FGLocation& l,
|
||||
FGLocation& cont,
|
||||
FGColumnVector3& n, FGColumnVector3& v) const {
|
||||
FGLocation& cont, FGColumnVector3& n,
|
||||
FGColumnVector3& v, FGColumnVector3& w) const {
|
||||
double loc_cart[3] = { l(eX), l(eY), l(eZ) };
|
||||
double contact[3], normal[3], vel[3], agl = 0;
|
||||
double contact[3], normal[3], vel[3], angularVel[3], agl = 0;
|
||||
mInterface->get_agl_ft(t, loc_cart, SG_METER_TO_FEET*2, contact, normal,
|
||||
vel, &agl);
|
||||
vel, angularVel, &agl);
|
||||
n = FGColumnVector3( normal[0], normal[1], normal[2] );
|
||||
v = FGColumnVector3( vel[0], vel[1], vel[2] );
|
||||
w = FGColumnVector3( angularVel[0], angularVel[1], angularVel[2] );
|
||||
cont = FGColumnVector3( contact[0], contact[1], contact[2] );
|
||||
return agl;
|
||||
}
|
||||
|
@ -489,7 +490,7 @@ void FGJSBsim::update( double dt )
|
|||
if ( startup_trim->getBoolValue() ) {
|
||||
double contact[3], d[3], agl;
|
||||
get_agl_ft(fdmex->GetSimTime(), cart_pos, SG_METER_TO_FEET*2, contact,
|
||||
d, d, &agl);
|
||||
d, d, d, &agl);
|
||||
double terrain_alt = sqrt(contact[0]*contact[0] + contact[1]*contact[1]
|
||||
+ contact[2]*contact[2]) - fgic->GetSeaLevelRadiusFtIC();
|
||||
|
||||
|
@ -743,7 +744,7 @@ bool FGJSBsim::copy_from_JSBsim()
|
|||
double loc_cart[3] = { l(FGJSBBase::eX), l(FGJSBBase::eY), l(FGJSBBase::eZ) };
|
||||
double contact[3], d[3], sd, t;
|
||||
is_valid_m(&t, d, &sd);
|
||||
get_agl_ft(t, loc_cart, SG_METER_TO_FEET*2, contact, d, d, &sd);
|
||||
get_agl_ft(t, loc_cart, SG_METER_TO_FEET*2, contact, d, d, d, &sd);
|
||||
double rwrad
|
||||
= FGColumnVector3( contact[0], contact[1], contact[2] ).Magnitude();
|
||||
_set_Runway_altitude( rwrad - get_Sea_level_radius() );
|
||||
|
@ -1204,9 +1205,8 @@ void FGJSBsim::update_ic(void)
|
|||
bool
|
||||
FGJSBsim::get_agl_ft(double t, const double pt[3], double alt_off,
|
||||
double contact[3], double normal[3], double vel[3],
|
||||
double *agl)
|
||||
double angularVel[3], double *agl)
|
||||
{
|
||||
double angularVel[3];
|
||||
const SGMaterial* material;
|
||||
simgear::BVHNode::Id id;
|
||||
if (!FGInterface::get_agl_ft(t, pt, alt_off, contact, normal, vel,
|
||||
|
@ -1289,10 +1289,12 @@ void FGJSBsim::update_external_forces(double t_off)
|
|||
double contact[3];
|
||||
double ground_normal[3];
|
||||
double ground_vel[3];
|
||||
double ground_angular_vel[3];
|
||||
double root_agl_ft;
|
||||
|
||||
if (!got_wire) {
|
||||
bool got = get_agl_ft(t_off, hook_area[1], 0, contact, ground_normal, ground_vel, &root_agl_ft);
|
||||
bool got = get_agl_ft(t_off, hook_area[1], 0, contact, ground_normal,
|
||||
ground_vel, ground_angular_vel, &root_agl_ft);
|
||||
if (got && root_agl_ft > 0 && root_agl_ft < hook_length) {
|
||||
FGColumnVector3 ground_normal_body = Tl2b * (Tec2l * FGColumnVector3(ground_normal[0], ground_normal[1], ground_normal[2]));
|
||||
FGColumnVector3 contact_body = Tl2b * Location.LocationToLocal(FGColumnVector3(contact[0], contact[1], contact[2]));
|
||||
|
|
|
@ -58,7 +58,6 @@ FORWARD DECLARATIONS
|
|||
#include <FDM/JSBSim/FGFDMExec.h>
|
||||
|
||||
namespace JSBSim {
|
||||
class FGState;
|
||||
class FGAtmosphere;
|
||||
class FGFCS;
|
||||
class FGPropulsion;
|
||||
|
@ -86,7 +85,7 @@ CLASS DOCUMENTATION
|
|||
documentation for main for direction on running JSBSim apart from FlightGear.
|
||||
@author Curtis L. Olson (original)
|
||||
@author Tony Peden (Maintained and refined)
|
||||
@version $Id: JSBSim.hxx,v 1.13 2010/07/07 20:46:36 andgi Exp $
|
||||
@version $Id: JSBSim.hxx,v 1.15 2010/10/07 03:45:40 jberndt Exp $
|
||||
@see main in file JSBSim.cpp (use main() wrapper for standalone usage)
|
||||
*/
|
||||
|
||||
|
@ -208,13 +207,12 @@ public:
|
|||
|
||||
bool get_agl_ft(double t, const double pt[3], double alt_off,
|
||||
double contact[3], double normal[3], double vel[3],
|
||||
double *agl);
|
||||
double angularVel[3], double *agl);
|
||||
private:
|
||||
JSBSim::FGFDMExec *fdmex;
|
||||
JSBSim::FGInitialCondition *fgic;
|
||||
bool needTrim;
|
||||
|
||||
JSBSim::FGState* State;
|
||||
JSBSim::FGAtmosphere* Atmosphere;
|
||||
JSBSim::FGFCS* FCS;
|
||||
JSBSim::FGPropulsion* Propulsion;
|
||||
|
|
|
@ -2,8 +2,8 @@ SUBDIRS = initialization models input_output math
|
|||
|
||||
noinst_LIBRARIES = libJSBSim.a
|
||||
|
||||
libJSBSim_a_SOURCES = FGFDMExec.cpp FGJSBBase.cpp FGState.cpp JSBSim.cxx
|
||||
libJSBSim_a_SOURCES = FGFDMExec.cpp FGJSBBase.cpp JSBSim.cxx
|
||||
|
||||
noinst_HEADERS = FGFDMExec.h FGJSBBase.h FGState.h JSBSim.hxx
|
||||
noinst_HEADERS = FGFDMExec.h FGJSBBase.h JSBSim.hxx
|
||||
|
||||
INCLUDES = -I$(top_srcdir)/src -I$(top_srcdir)/src/FDM/JSBSim
|
||||
|
|
|
@ -62,7 +62,7 @@ using namespace std;
|
|||
|
||||
namespace JSBSim {
|
||||
|
||||
static const char *IdSrc = "$Id: FGInitialCondition.cpp,v 1.44 2010/09/18 22:48:12 jberndt Exp $";
|
||||
static const char *IdSrc = "$Id: FGInitialCondition.cpp,v 1.46 2010/09/29 02:19:05 jberndt Exp $";
|
||||
static const char *IdHdr = ID_INITIALCONDITION;
|
||||
|
||||
//******************************************************************************
|
||||
|
@ -120,7 +120,7 @@ void FGInitialCondition::ResetIC(double u0, double v0, double w0,
|
|||
FGQuaternion Quat( phi, theta, psi );
|
||||
Quat.Normalize();
|
||||
|
||||
const FGMatrix33& _Tl2b = Quat.GetT(); // local to body frame
|
||||
// const FGMatrix33& _Tl2b = Quat.GetT(); // local to body frame
|
||||
const FGMatrix33& _Tb2l = Quat.GetTInv(); // body to local
|
||||
|
||||
FGColumnVector3 _vUVW_BODY(u,v,w);
|
||||
|
@ -863,17 +863,22 @@ bool FGInitialCondition::Load(string rstfile, bool useStoredPath)
|
|||
}
|
||||
|
||||
double version = document->GetAttributeValueAsNumber("version");
|
||||
bool result = false;
|
||||
|
||||
if (version == HUGE_VAL) {
|
||||
return Load_v1(); // Default to the old version
|
||||
result = Load_v1(); // Default to the old version
|
||||
} else if (version >= 3.0) {
|
||||
cerr << "Only initialization file formats 1 and 2 are currently supported" << endl;
|
||||
exit (-1);
|
||||
} else if (version >= 2.0) {
|
||||
return Load_v2();
|
||||
result = Load_v2();
|
||||
} else if (version >= 1.0) {
|
||||
return Load_v1();
|
||||
result = Load_v1();
|
||||
}
|
||||
|
||||
fdmex->GetPropagate()->DumpState();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
|
@ -962,6 +967,7 @@ bool FGInitialCondition::Load_v1(void)
|
|||
bool FGInitialCondition::Load_v2(void)
|
||||
{
|
||||
int n;
|
||||
double epa = 0.0;
|
||||
FGColumnVector3 vLoc, vOrient;
|
||||
bool result = true;
|
||||
FGInertial* Inertial = fdmex->GetInertial();
|
||||
|
@ -969,10 +975,10 @@ bool FGInitialCondition::Load_v2(void)
|
|||
FGColumnVector3 vOmegaEarth = FGColumnVector3(0.0, 0.0, Inertial->omega());
|
||||
|
||||
if (document->FindElement("earth_position_angle")) {
|
||||
double epa = document->FindElementValueAsNumberConvertTo("earth_position_angle", "RAD");
|
||||
epa = document->FindElementValueAsNumberConvertTo("earth_position_angle", "RAD");
|
||||
}
|
||||
Inertial->SetEarthPositionAngle(epa);
|
||||
Propagate->GetVState()->vLocation.SetEarthPositionAngle(epa);
|
||||
}
|
||||
|
||||
Propagate->SetSeaLevelRadius(GetSeaLevelRadiusFtIC());
|
||||
|
||||
|
@ -989,15 +995,15 @@ bool FGInitialCondition::Load_v2(void)
|
|||
|
||||
Element* position = document->FindElement("position");
|
||||
if (position) {
|
||||
vLoc = position->FindElementTripletConvertTo("FT");
|
||||
string frame = position->GetAttributeValue("frame");
|
||||
frame = to_lower(frame);
|
||||
if (frame == "eci") { // Need to transform vLoc to ECEF for storage and use in FGLocation.
|
||||
vLoc = position->FindElementTripletConvertTo("FT");
|
||||
vLoc = Propagate->GetTi2ec()*vLoc;
|
||||
Propagate->SetLocation(vLoc);
|
||||
} else if (frame == "ecef") {
|
||||
double AltitudeASL = 0.0;
|
||||
if (vLoc.Magnitude() == 0.0) {
|
||||
if (!position->FindElement("x") && !position->FindElement("y") && !position->FindElement("z")) {
|
||||
if (position->FindElement("radius")) {
|
||||
AltitudeASL = position->FindElementValueAsNumberConvertTo("radius", "FT") - sea_level_radius;
|
||||
} else if (position->FindElement("altitudeAGL")) {
|
||||
|
@ -1008,11 +1014,15 @@ bool FGInitialCondition::Load_v2(void)
|
|||
cerr << endl << " No altitude or radius initial condition is given." << endl;
|
||||
result = false;
|
||||
}
|
||||
Propagate->SetPosition(
|
||||
position->FindElementValueAsNumberConvertTo("longitude", "RAD"),
|
||||
position->FindElementValueAsNumberConvertTo("latitude", "RAD"),
|
||||
AltitudeASL + GetSeaLevelRadiusFtIC());
|
||||
double lat_rad=0.0;
|
||||
double long_rad = 0.0;
|
||||
if (position->FindElement("longitude"))
|
||||
long_rad = position->FindElementValueAsNumberConvertTo("longitude", "RAD");
|
||||
if (position->FindElement("latitude"))
|
||||
lat_rad = position->FindElementValueAsNumberConvertTo("latitude", "RAD");
|
||||
Propagate->SetPosition(long_rad, lat_rad, AltitudeASL + GetSeaLevelRadiusFtIC());
|
||||
} else {
|
||||
vLoc = position->FindElementTripletConvertTo("FT");
|
||||
Propagate->SetLocation(vLoc);
|
||||
}
|
||||
} else {
|
||||
|
@ -1072,7 +1082,9 @@ bool FGInitialCondition::Load_v2(void)
|
|||
// Q_b/i = Q_e/i * Q_b/e
|
||||
|
||||
FGQuaternion QuatEC2Body(vOrient); // Store relationship of Body frame wrt ECEF frame, Q_b/e
|
||||
QuatEC2Body.Normalize();
|
||||
FGQuaternion QuatI2EC = Propagate->GetTi2ec(); // Get Q_e/i from matrix
|
||||
QuatI2EC.Normalize();
|
||||
QuatI2Body = QuatI2EC * QuatEC2Body; // Q_b/i = Q_e/i * Q_b/e
|
||||
|
||||
} else if (frame == "local") {
|
||||
|
@ -1089,8 +1101,11 @@ bool FGInitialCondition::Load_v2(void)
|
|||
// Q_b/i = Q_e/i * Q_n/e * Q_b/n
|
||||
|
||||
FGQuaternion QuatLocal2Body = FGQuaternion(vOrient); // Store relationship of Body frame wrt local (NED) frame, Q_b/n
|
||||
QuatLocal2Body.Normalize();
|
||||
FGQuaternion QuatEC2Local = Propagate->GetTec2l(); // Get Q_n/e from matrix
|
||||
QuatEC2Local.Normalize();
|
||||
FGQuaternion QuatI2EC = Propagate->GetTi2ec(); // Get Q_e/i from matrix
|
||||
QuatI2EC.Normalize();
|
||||
QuatI2Body = QuatI2EC * QuatEC2Local * QuatLocal2Body; // Q_b/i = Q_e/i * Q_n/e * Q_b/n
|
||||
|
||||
} else {
|
||||
|
@ -1102,6 +1117,7 @@ bool FGInitialCondition::Load_v2(void)
|
|||
}
|
||||
}
|
||||
|
||||
QuatI2Body.Normalize();
|
||||
Propagate->SetInertialOrientation(QuatI2Body);
|
||||
|
||||
// Initialize vehicle velocity
|
||||
|
@ -1201,7 +1217,9 @@ bool FGInitialCondition::Load_v2(void)
|
|||
running_elements = document->FindNextElement("running");
|
||||
}
|
||||
|
||||
// fdmex->RunIC();
|
||||
fdmex->SuspendIntegration(); // saves the integration rate, dt, then sets it to 0.0.
|
||||
fdmex->Run();
|
||||
fdmex->ResumeIntegration(); // Restores the integration rate to what it was.
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -68,9 +68,10 @@ double FGGroundCallback::GetAltitude(const FGLocation& loc) const
|
|||
|
||||
double FGGroundCallback::GetAGLevel(double t, const FGLocation& loc,
|
||||
FGLocation& contact, FGColumnVector3& normal,
|
||||
FGColumnVector3& vel) const
|
||||
FGColumnVector3& vel, FGColumnVector3& angularVel) const
|
||||
{
|
||||
vel = FGColumnVector3(0.0, 0.0, 0.0);
|
||||
angularVel = FGColumnVector3(0.0, 0.0, 0.0);
|
||||
normal = FGColumnVector3(loc).Normalize();
|
||||
double loc_radius = loc.GetRadius(); // Get the radius of the given location
|
||||
// (e.g. the CG)
|
||||
|
|
|
@ -45,7 +45,7 @@ INCLUDES
|
|||
DEFINITIONS
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
|
||||
|
||||
#define ID_GROUNDCALLBACK "$Id: FGGroundCallback.h,v 1.8 2009/10/02 10:30:09 jberndt Exp $"
|
||||
#define ID_GROUNDCALLBACK "$Id: FGGroundCallback.h,v 1.9 2010/10/07 03:45:40 jberndt Exp $"
|
||||
|
||||
namespace JSBSim {
|
||||
|
||||
|
@ -59,7 +59,7 @@ CLASS DOCUMENTATION
|
|||
ball formed earth.
|
||||
|
||||
@author Mathias Froehlich
|
||||
@version $Id: FGGroundCallback.h,v 1.8 2009/10/02 10:30:09 jberndt Exp $
|
||||
@version $Id: FGGroundCallback.h,v 1.9 2010/10/07 03:45:40 jberndt Exp $
|
||||
*/
|
||||
|
||||
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
@ -85,7 +85,8 @@ public:
|
|||
virtual double GetAltitude(const FGLocation& l) const;
|
||||
/** Compute the altitude above ground. Defaults to sealevel altitude. */
|
||||
virtual double GetAGLevel(double t, const FGLocation& l, FGLocation& cont,
|
||||
FGColumnVector3& n, FGColumnVector3& v) const;
|
||||
FGColumnVector3& n, FGColumnVector3& v,
|
||||
FGColumnVector3& w) const;
|
||||
virtual void SetTerrainGeoCentRadius(double radius) {mReferenceRadius = radius;}
|
||||
virtual double GetTerrainGeoCentRadius(void) const {return mReferenceRadius;}
|
||||
private:
|
||||
|
|
|
@ -42,7 +42,7 @@ FORWARD DECLARATIONS
|
|||
|
||||
namespace JSBSim {
|
||||
|
||||
static const char *IdSrc = "$Id: FGXMLElement.cpp,v 1.30 2010/09/04 14:15:15 jberndt Exp $";
|
||||
static const char *IdSrc = "$Id: FGXMLElement.cpp,v 1.31 2010/09/29 02:22:03 jberndt Exp $";
|
||||
static const char *IdHdr = ID_XMLELEMENT;
|
||||
|
||||
bool Element::converterIsInitialized = false;
|
||||
|
@ -93,10 +93,10 @@ Element::Element(const string& nm)
|
|||
convert["SLUG*FT2"]["KG*M2"] = 1.35594;
|
||||
convert["KG*M2"]["SLUG*FT2"] = 1.0/convert["SLUG*FT2"]["KG*M2"];
|
||||
// Angles
|
||||
convert["RAD"]["DEG"] = 360.0/(2.0*3.1415926);
|
||||
convert["RAD"]["DEG"] = 180.0/M_PI;
|
||||
convert["DEG"]["RAD"] = 1.0/convert["RAD"]["DEG"];
|
||||
// Angular rates
|
||||
convert["RAD/SEC"]["DEG/SEC"] = 360.0/(2.0*3.1415926);
|
||||
convert["RAD/SEC"]["DEG/SEC"] = convert["RAD"]["DEG"];
|
||||
convert["DEG/SEC"]["RAD/SEC"] = 1.0/convert["RAD/SEC"]["DEG/SEC"];
|
||||
// Spring force
|
||||
convert["LBS/FT"]["N/M"] = 14.5939;
|
||||
|
@ -478,7 +478,6 @@ FGColumnVector3 Element::FindElementTripletConvertTo( const string& target_units
|
|||
if (!supplied_units.empty()) value *= convert[supplied_units][target_units];
|
||||
} else {
|
||||
value = 0.0;
|
||||
cerr << "Could not find an X triplet item for this column vector." << endl;
|
||||
}
|
||||
triplet(1) = value;
|
||||
|
||||
|
@ -489,7 +488,6 @@ FGColumnVector3 Element::FindElementTripletConvertTo( const string& target_units
|
|||
if (!supplied_units.empty()) value *= convert[supplied_units][target_units];
|
||||
} else {
|
||||
value = 0.0;
|
||||
cerr << "Could not find a Y triplet item for this column vector." << endl;
|
||||
}
|
||||
triplet(2) = value;
|
||||
|
||||
|
@ -500,7 +498,6 @@ FGColumnVector3 Element::FindElementTripletConvertTo( const string& target_units
|
|||
if (!supplied_units.empty()) value *= convert[supplied_units][target_units];
|
||||
} else {
|
||||
value = 0.0;
|
||||
cerr << "Could not find a Z triplet item for this column vector." << endl;
|
||||
}
|
||||
triplet(3) = value;
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ using namespace std;
|
|||
|
||||
namespace JSBSim {
|
||||
|
||||
static const char *IdSrc = "$Id: FGXMLParse.cpp,v 1.10 2009/10/24 22:59:30 jberndt Exp $";
|
||||
static const char *IdSrc = "$Id: FGXMLParse.cpp,v 1.11 2010/09/28 02:54:03 jberndt Exp $";
|
||||
static const char *IdHdr = ID_XMLPARSE;
|
||||
|
||||
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
@ -122,7 +122,7 @@ void FGXMLParse::endElement (const char * name)
|
|||
{
|
||||
if (!working_string.empty()) {
|
||||
vector <string> work_strings = split(working_string, '\n');
|
||||
for (int i=0; i<work_strings.size(); i++) current_element->AddData(work_strings[i]);
|
||||
for (unsigned int i=0; i<work_strings.size(); i++) current_element->AddData(work_strings[i]);
|
||||
}
|
||||
|
||||
current_element = current_element->GetParent();
|
||||
|
|
|
@ -65,7 +65,7 @@ INCLUDES
|
|||
DEFINITIONS
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
|
||||
|
||||
#define ID_FDMSOCKET "$Id: FGfdmSocket.h,v 1.19 2010/05/13 03:07:59 jberndt Exp $"
|
||||
#define ID_FDMSOCKET "$Id: FGfdmSocket.h,v 1.20 2010/10/15 11:30:28 jberndt Exp $"
|
||||
|
||||
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
FORWARD DECLARATIONS
|
||||
|
@ -107,7 +107,7 @@ public:
|
|||
void Close(void);
|
||||
bool GetConnectStatus(void) {return connected;}
|
||||
|
||||
enum {ptUDP, ptTCP};
|
||||
enum ProtocolType {ptUDP, ptTCP} ;
|
||||
|
||||
private:
|
||||
int sckt;
|
||||
|
|
|
@ -45,7 +45,7 @@ INCLUDES
|
|||
|
||||
namespace JSBSim {
|
||||
|
||||
static const char *IdSrc = "$Id: FGLocation.cpp,v 1.22 2010/09/18 22:47:17 jberndt Exp $";
|
||||
static const char *IdSrc = "$Id: FGLocation.cpp,v 1.23 2010/09/22 11:34:09 jberndt Exp $";
|
||||
static const char *IdHdr = ID_LOCATION;
|
||||
using std::cerr;
|
||||
using std::endl;
|
||||
|
@ -319,7 +319,7 @@ void FGLocation::ComputeDerivedUnconditional(void) const
|
|||
|
||||
if (a != 0.0 && b != 0.0) {
|
||||
double c, p, q, s, t, u, v, w, z, p2, u2, r0;
|
||||
double Ne, P, Q0, Q, signz0, sqrt_q;
|
||||
double Ne, P, Q0, Q, signz0, sqrt_q, z_term;
|
||||
p = fabs(mECLoc(eZ))/eps2;
|
||||
s = r02/(e2*eps2);
|
||||
p2 = p*p;
|
||||
|
@ -328,8 +328,7 @@ void FGLocation::ComputeDerivedUnconditional(void) const
|
|||
if (q>0)
|
||||
{
|
||||
u = p/sqrt_q;
|
||||
// u2 = p2/q;
|
||||
u2 = u*u;
|
||||
u2 = p2/q;
|
||||
v = b2*u2/q;
|
||||
P = 27.0*v*s/q;
|
||||
Q0 = sqrt(P+1) + sqrt(P);
|
||||
|
@ -338,10 +337,11 @@ void FGLocation::ComputeDerivedUnconditional(void) const
|
|||
c = sqrt(u2 - 1 + 2.0*t);
|
||||
w = (c - u)/2.0;
|
||||
signz0 = mECLoc(eZ)>=0?1.0:-1.0;
|
||||
if ((sqrt(t*t+v)-u*w-0.5*t-0.25) < 0.0) {
|
||||
z_term = sqrt(t*t+v)-u*w-0.5*t-0.25;
|
||||
if (z_term < 0.0) {
|
||||
z = 0.0;
|
||||
} else {
|
||||
z = signz0*sqrt_q*(w+sqrt(sqrt(t*t+v)-u*w-0.5*t-0.25));
|
||||
z = signz0*sqrt_q*(w+sqrt(z_term));
|
||||
}
|
||||
Ne = a*sqrt(1+eps2*z*z/b2);
|
||||
mGeodLat = asin((eps2+1.0)*(z/Ne));
|
||||
|
|
|
@ -47,7 +47,7 @@ SENTRY
|
|||
DEFINITIONS
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
|
||||
|
||||
#define ID_QUATERNION "$Id: FGQuaternion.h,v 1.17 2010/06/30 03:13:40 jberndt Exp $"
|
||||
#define ID_QUATERNION "$Id: FGQuaternion.h,v 1.18 2010/09/29 02:19:05 jberndt Exp $"
|
||||
|
||||
namespace JSBSim {
|
||||
|
||||
|
@ -177,7 +177,7 @@ public:
|
|||
const FGMatrix33& GetTInv(void) const { ComputeDerived(); return mTInv; }
|
||||
|
||||
/** Retrieves the Euler angles.
|
||||
@return a reference to the triad of euler angles corresponding
|
||||
@return a reference to the triad of Euler angles corresponding
|
||||
to this quaternion rotation.
|
||||
units radians */
|
||||
const FGColumnVector3& GetEuler(void) const {
|
||||
|
@ -186,7 +186,7 @@ public:
|
|||
}
|
||||
|
||||
/** Retrieves the Euler angles.
|
||||
@param i the euler angle index.
|
||||
@param i the Euler angle index.
|
||||
units radians.
|
||||
@return a reference to the i-th euler angles corresponding
|
||||
to this quaternion rotation.
|
||||
|
@ -197,7 +197,7 @@ public:
|
|||
}
|
||||
|
||||
/** Retrieves the Euler angles.
|
||||
@param i the euler angle index.
|
||||
@param i the Euler angle index.
|
||||
@return a reference to the i-th euler angles corresponding
|
||||
to this quaternion rotation.
|
||||
units degrees */
|
||||
|
@ -206,6 +206,15 @@ public:
|
|||
return radtodeg*mEulerAngles(i);
|
||||
}
|
||||
|
||||
/** Retrieves the Euler angle vector.
|
||||
@return an Euler angle column vector corresponding
|
||||
to this quaternion rotation.
|
||||
units degrees */
|
||||
FGColumnVector3 const GetEulerDeg(void) const {
|
||||
ComputeDerived();
|
||||
return radtodeg*mEulerAngles;
|
||||
}
|
||||
|
||||
/** Retrieves sine of the given euler angle.
|
||||
@return the sine of the Euler angle theta (pitch attitude) corresponding
|
||||
to this quaternion rotation. */
|
||||
|
|
|
@ -47,7 +47,7 @@ using namespace std;
|
|||
|
||||
namespace JSBSim {
|
||||
|
||||
static const char *IdSrc = "$Id: FGTable.cpp,v 1.23 2010/09/16 11:01:24 jberndt Exp $";
|
||||
static const char *IdSrc = "$Id: FGTable.cpp,v 1.27 2010/10/21 11:09:56 jberndt Exp $";
|
||||
static const char *IdHdr = ID_TABLE;
|
||||
|
||||
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
@ -143,13 +143,12 @@ FGTable::FGTable(FGPropertyManager* propMan, Element* el) : PropertyManager(prop
|
|||
internal = true;
|
||||
} else {
|
||||
// internal table is a child element of a restricted type
|
||||
cerr << endl << fgred << " An internal table cannot be nested within another type," << endl;
|
||||
cerr << " such as a function. The 'internal' keyword is ignored." << fgdef << endl << endl;
|
||||
throw(" An internal table cannot be nested within another type,"
|
||||
" such as a function. The 'internal' keyword is ignored.");
|
||||
}
|
||||
} else if (!call_type.empty()) {
|
||||
cerr << endl << fgred << " An unknown table type attribute is listed: " << call_type
|
||||
<< ". Execution cannot continue." << fgdef << endl << endl;
|
||||
abort();
|
||||
throw(" An unknown table type attribute is listed: "
|
||||
". Execution cannot continue.");
|
||||
}
|
||||
|
||||
// Determine and store the lookup properties for this table unless this table
|
||||
|
@ -218,8 +217,7 @@ FGTable::FGTable(FGPropertyManager* propMan, Element* el) : PropertyManager(prop
|
|||
brkpt_string = el->GetAttributeValue("breakPoint");
|
||||
if (brkpt_string.empty()) {
|
||||
// no independentVars found, and table is not marked as internal, nor is it a 3D table
|
||||
cerr << endl << fgred << "No independent variable found for table." << fgdef << endl << endl;
|
||||
abort();
|
||||
throw("No independent variable found for table.");
|
||||
}
|
||||
}
|
||||
// end lookup property code
|
||||
|
@ -249,10 +247,11 @@ FGTable::FGTable(FGPropertyManager* propMan, Element* el) : PropertyManager(prop
|
|||
case 2:
|
||||
nRows = tableData->GetNumDataLines()-1;
|
||||
|
||||
if (nRows >= 2) nCols = FindNumColumns(tableData->GetDataLine(0));
|
||||
else {
|
||||
cerr << endl << fgred << "Not enough rows in this table." << fgdef << endl;
|
||||
abort();
|
||||
if (nRows >= 2) {
|
||||
nCols = FindNumColumns(tableData->GetDataLine(0));
|
||||
if (nCols < 2) throw(string("Not enough columns in table data."));
|
||||
} else {
|
||||
throw(string("Not enough rows in the table data."));
|
||||
}
|
||||
|
||||
Type = tt2D;
|
||||
|
@ -290,6 +289,63 @@ FGTable::FGTable(FGPropertyManager* propMan, Element* el) : PropertyManager(prop
|
|||
break;
|
||||
}
|
||||
|
||||
// Sanity checks: lookup indices must be increasing monotonically
|
||||
unsigned int r,c,b;
|
||||
|
||||
// find next xml element containing a name attribute
|
||||
// to indicate where the error occured
|
||||
Element* nameel = el;
|
||||
while (nameel != 0 && nameel->GetAttributeValue("name") == "")
|
||||
nameel=nameel->GetParent();
|
||||
|
||||
// check breakpoints, if applicable
|
||||
if (dimension > 2) {
|
||||
for (b=2; b<=nTables; ++b) {
|
||||
if (Data[b][1] <= Data[b-1][1]) {
|
||||
stringstream errormsg;
|
||||
errormsg << fgred << highint << endl
|
||||
<< " FGTable: breakpoint lookup is not monotonically increasing" << endl
|
||||
<< " in breakpoint " << b;
|
||||
if (nameel != 0) errormsg << " of table in " << nameel->GetAttributeValue("name");
|
||||
errormsg << ":" << reset << endl
|
||||
<< " " << Data[b][1] << "<=" << Data[b-1][1] << endl;
|
||||
throw(errormsg.str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check columns, if applicable
|
||||
if (dimension > 1) {
|
||||
for (c=2; c<=nCols; ++c) {
|
||||
if (Data[0][c] <= Data[0][c-1]) {
|
||||
stringstream errormsg;
|
||||
errormsg << fgred << highint << endl
|
||||
<< " FGTable: column lookup is not monotonically increasing" << endl
|
||||
<< " in column " << c;
|
||||
if (nameel != 0) errormsg << " of table in " << nameel->GetAttributeValue("name");
|
||||
errormsg << ":" << reset << endl
|
||||
<< " " << Data[0][c] << "<=" << Data[0][c-1] << endl;
|
||||
throw(errormsg.str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check rows
|
||||
if (dimension < 3) { // in 3D tables, check only rows of subtables
|
||||
for (r=2; r<=nRows; ++r) {
|
||||
if (Data[r][0]<=Data[r-1][0]) {
|
||||
stringstream errormsg;
|
||||
errormsg << fgred << highint << endl
|
||||
<< " FGTable: row lookup is not monotonically increasing" << endl
|
||||
<< " in row " << r;
|
||||
if (nameel != 0) errormsg << " of table in " << nameel->GetAttributeValue("name");
|
||||
errormsg << ":" << reset << endl
|
||||
<< " " << Data[r][0] << "<=" << Data[r-1][0] << endl;
|
||||
throw(errormsg.str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bind();
|
||||
|
||||
if (debug_lvl & 1) Print();
|
||||
|
|
|
@ -52,7 +52,7 @@ using namespace std;
|
|||
|
||||
namespace JSBSim {
|
||||
|
||||
static const char *IdSrc = "$Id: FGAerodynamics.cpp,v 1.32 2010/09/07 00:40:03 jberndt Exp $";
|
||||
static const char *IdSrc = "$Id: FGAerodynamics.cpp,v 1.34 2010/10/15 11:32:41 jberndt Exp $";
|
||||
static const char *IdHdr = ID_AERODYNAMICS;
|
||||
|
||||
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
@ -349,7 +349,14 @@ bool FGAerodynamics::Load(Element *element)
|
|||
axis = axis_element->GetAttributeValue("name");
|
||||
function_element = axis_element->FindElement("function");
|
||||
while (function_element) {
|
||||
ca.push_back( new FGFunction(PropertyManager, function_element) );
|
||||
string current_func_name = function_element->GetAttributeValue("name");
|
||||
try {
|
||||
ca.push_back( new FGFunction(PropertyManager, function_element) );
|
||||
} catch (string const str) {
|
||||
cerr << endl << fgred << "Error loading aerodynamic function in "
|
||||
<< current_func_name << ":" << str << " Aborting." << reset << endl;
|
||||
return false;
|
||||
}
|
||||
function_element = axis_element->FindNextElement("function");
|
||||
}
|
||||
Coeff[AxisIdx[axis]] = ca;
|
||||
|
|
|
@ -59,7 +59,7 @@ using namespace std;
|
|||
|
||||
namespace JSBSim {
|
||||
|
||||
static const char *IdSrc = "$Id: FGAuxiliary.cpp,v 1.42 2010/07/27 23:18:19 jberndt Exp $";
|
||||
static const char *IdSrc = "$Id: FGAuxiliary.cpp,v 1.44 2010/10/10 15:10:15 jberndt Exp $";
|
||||
static const char *IdHdr = ID_AUXILIARY;
|
||||
|
||||
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
@ -173,7 +173,7 @@ bool FGAuxiliary::Run()
|
|||
vAeroUVW = vUVW - wind;
|
||||
|
||||
Vt = vAeroUVW.Magnitude();
|
||||
if ( Vt > 0.05) {
|
||||
if ( Vt > 1.0 ) {
|
||||
if (vAeroUVW(eW) != 0.0)
|
||||
alpha = vAeroUVW(eU)*vAeroUVW(eU) > 0.0 ? atan2(vAeroUVW(eW), vAeroUVW(eU)) : 0.0;
|
||||
if (vAeroUVW(eV) != 0.0)
|
||||
|
@ -182,10 +182,9 @@ bool FGAuxiliary::Run()
|
|||
|
||||
double mUW = (vAeroUVW(eU)*vAeroUVW(eU) + vAeroUVW(eW)*vAeroUVW(eW));
|
||||
double signU=1;
|
||||
if (vAeroUVW(eU) != 0.0)
|
||||
signU = vAeroUVW(eU)/fabs(vAeroUVW(eU));
|
||||
if (vAeroUVW(eU) < 0.0) signU=-1;
|
||||
|
||||
if ( (mUW == 0.0) || (Vt == 0.0) ) {
|
||||
if ( mUW < 1.0 ) {
|
||||
adot = 0.0;
|
||||
bdot = 0.0;
|
||||
} else {
|
||||
|
|
|
@ -63,7 +63,7 @@ using namespace std;
|
|||
|
||||
namespace JSBSim {
|
||||
|
||||
static const char *IdSrc = "$Id: FGFCS.cpp,v 1.70 2010/08/21 22:56:11 jberndt Exp $";
|
||||
static const char *IdSrc = "$Id: FGFCS.cpp,v 1.71 2010/09/28 02:54:03 jberndt Exp $";
|
||||
static const char *IdHdr = ID_FCS;
|
||||
|
||||
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
@ -187,7 +187,7 @@ bool FGFCS::InitModel(void)
|
|||
|
||||
void FGFCS::LateBind(void)
|
||||
{
|
||||
int i;
|
||||
unsigned int i;
|
||||
|
||||
for (i=0; i<Systems.size(); i++) Systems[i]->LateBind();
|
||||
for (i=0; i<APComponents.size(); i++) APComponents[i]->LateBind();
|
||||
|
|
|
@ -51,7 +51,7 @@ INCLUDES
|
|||
DEFINITIONS
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
|
||||
|
||||
#define ID_FCS "$Id: FGFCS.h,v 1.30 2010/09/05 17:31:40 jberndt Exp $"
|
||||
#define ID_FCS "$Id: FGFCS.h,v 1.31 2010/09/22 11:33:40 jberndt Exp $"
|
||||
|
||||
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
FORWARD DECLARATIONS
|
||||
|
@ -168,7 +168,7 @@ CLASS DOCUMENTATION
|
|||
@property gear/tailhook-pos-norm
|
||||
|
||||
@author Jon S. Berndt
|
||||
@version $Revision: 1.30 $
|
||||
@version $Revision: 1.31 $
|
||||
@see FGActuator
|
||||
@see FGDeadBand
|
||||
@see FGFCSFunction
|
||||
|
@ -345,11 +345,6 @@ public:
|
|||
bool GetPropFeather(int engine) const { return PropFeather[engine]; }
|
||||
//@}
|
||||
|
||||
/** Retrieves the State object pointer.
|
||||
This is used by the FGFCS-owned components.
|
||||
@return pointer to the State object */
|
||||
FGState* GetState(void) { return State; }
|
||||
|
||||
/** Retrieves all component names for inclusion in output stream
|
||||
@param delimiter either a tab or comma string depending on output type
|
||||
@return a string containing the descriptive names for all components */
|
||||
|
|
|
@ -45,7 +45,7 @@ using namespace std;
|
|||
|
||||
namespace JSBSim {
|
||||
|
||||
static const char *IdSrc = "$Id: FGInertial.cpp,v 1.18 2010/03/28 05:57:00 jberndt Exp $";
|
||||
static const char *IdSrc = "$Id: FGInertial.cpp,v 1.19 2010/10/10 15:06:38 jberndt Exp $";
|
||||
static const char *IdHdr = ID_INERTIAL;
|
||||
|
||||
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
@ -148,7 +148,8 @@ FGColumnVector3 FGInertial::GetGravityJ2(FGColumnVector3 position) const
|
|||
double lat = Propagate->GetLatitude();
|
||||
double sinLat = sin(lat);
|
||||
|
||||
double preCommon = 1.5*J2*(a/r)*(a/r);
|
||||
double adivr = a/r;
|
||||
double preCommon = 1.5*J2*adivr*adivr;
|
||||
double xy = 1.0 - 5.0*(sinLat*sinLat);
|
||||
double z = 3.0 - 5.0*(sinLat*sinLat);
|
||||
double GMOverr2 = GM/(r*r);
|
||||
|
|
|
@ -48,6 +48,7 @@ INCLUDES
|
|||
#include "FGMassBalance.h"
|
||||
#include "math/FGTable.h"
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
@ -61,7 +62,7 @@ DEFINITIONS
|
|||
GLOBAL DATA
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
|
||||
|
||||
static const char *IdSrc = "$Id: FGLGear.cpp,v 1.76 2010/07/30 11:50:01 jberndt Exp $";
|
||||
static const char *IdSrc = "$Id: FGLGear.cpp,v 1.78 2010/10/07 03:45:40 jberndt Exp $";
|
||||
static const char *IdHdr = ID_LGEAR;
|
||||
|
||||
// Body To Structural (body frame is rotated 180 deg about Y and lengths are given in
|
||||
|
@ -76,7 +77,8 @@ FGLGear::FGLGear(Element* el, FGFDMExec* fdmex, int number) :
|
|||
FGForce(fdmex),
|
||||
GearNumber(number),
|
||||
SteerAngle(0.0),
|
||||
Castered(false)
|
||||
Castered(false),
|
||||
StaticFriction(false)
|
||||
{
|
||||
Element *force_table=0;
|
||||
Element *dampCoeff=0;
|
||||
|
@ -254,9 +256,7 @@ FGLGear::FGLGear(Element* el, FGFDMExec* fdmex, int number) :
|
|||
Curvature = 1.03;
|
||||
|
||||
// Initialize Lagrange multipliers
|
||||
LMultiplier[ftRoll].value = 0.;
|
||||
LMultiplier[ftSide].value = 0.;
|
||||
LMultiplier[ftRoll].value = 0.;
|
||||
memset(LMultiplier, 0, sizeof(LMultiplier));
|
||||
|
||||
Debug(0);
|
||||
}
|
||||
|
@ -281,13 +281,15 @@ FGColumnVector3& FGLGear::GetBodyForces(void)
|
|||
if (isRetractable) ComputeRetractionState();
|
||||
|
||||
if (GearDown) {
|
||||
FGColumnVector3 angularVel;
|
||||
|
||||
vWhlBodyVec = MassBalance->StructuralToBody(vXYZn); // Get wheel in body frame
|
||||
vLocalGear = Propagate->GetTb2l() * vWhlBodyVec; // Get local frame wheel location
|
||||
|
||||
gearLoc = Propagate->GetLocation().LocalToLocation(vLocalGear);
|
||||
// Compute the height of the theoretical location of the wheel (if strut is
|
||||
// not compressed) with respect to the ground level
|
||||
double height = fdmex->GetGroundCallback()->GetAGLevel(t, gearLoc, contact, normal, cvel);
|
||||
double height = fdmex->GetGroundCallback()->GetAGLevel(t, gearLoc, contact, normal, cvel, angularVel);
|
||||
vGroundNormal = Propagate->GetTec2b() * normal;
|
||||
|
||||
// The height returned above is the AGL and is expressed in the Z direction
|
||||
|
|
|
@ -47,7 +47,7 @@ INCLUDES
|
|||
DEFINITIONS
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
|
||||
|
||||
#define ID_LGEAR "$Id: FGLGear.h,v 1.40 2010/07/30 11:50:01 jberndt Exp $"
|
||||
#define ID_LGEAR "$Id: FGLGear.h,v 1.41 2010/09/22 11:33:40 jberndt Exp $"
|
||||
|
||||
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
FORWARD DECLARATIONS
|
||||
|
@ -58,7 +58,6 @@ namespace JSBSim {
|
|||
class FGAircraft;
|
||||
class FGPropagate;
|
||||
class FGFCS;
|
||||
class FGState;
|
||||
class FGMassBalance;
|
||||
class FGAuxiliary;
|
||||
class FGTable;
|
||||
|
@ -181,7 +180,7 @@ CLASS DOCUMENTATION
|
|||
</contact>
|
||||
@endcode
|
||||
@author Jon S. Berndt
|
||||
@version $Id: FGLGear.h,v 1.40 2010/07/30 11:50:01 jberndt Exp $
|
||||
@version $Id: FGLGear.h,v 1.41 2010/09/22 11:33:40 jberndt Exp $
|
||||
@see Richard E. McFarland, "A Standard Kinematic Model for Flight Simulation at
|
||||
NASA-Ames", NASA CR-2497, January 1975
|
||||
@see Barnes W. McCormick, "Aerodynamics, Aeronautics, and Flight Mechanics",
|
||||
|
|
|
@ -48,7 +48,7 @@ INCLUDES
|
|||
DEFINITIONS
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
|
||||
|
||||
#define ID_MODEL "$Id: FGModel.h,v 1.15 2010/09/07 00:19:46 jberndt Exp $"
|
||||
#define ID_MODEL "$Id: FGModel.h,v 1.16 2010/09/22 11:33:40 jberndt Exp $"
|
||||
|
||||
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
FORWARD DECLARATIONS
|
||||
|
@ -57,7 +57,6 @@ FORWARD DECLARATIONS
|
|||
namespace JSBSim {
|
||||
|
||||
class FGFDMExec;
|
||||
class FGState;
|
||||
class FGAtmosphere;
|
||||
class FGFCS;
|
||||
class FGPropulsion;
|
||||
|
@ -119,7 +118,6 @@ protected:
|
|||
virtual void Debug(int from);
|
||||
|
||||
FGFDMExec* FDMExec;
|
||||
FGState* State;
|
||||
FGAtmosphere* Atmosphere;
|
||||
FGFCS* FCS;
|
||||
FGPropulsion* Propulsion;
|
||||
|
|
|
@ -61,9 +61,6 @@ INCLUDES
|
|||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
|
||||
#include "input_output/net_fdm.hxx"
|
||||
#include "input_output/FGfdmSocket.h"
|
||||
|
||||
#if defined(WIN32) && !defined(__CYGWIN__)
|
||||
# include <windows.h>
|
||||
#else
|
||||
|
@ -77,7 +74,7 @@ using namespace std;
|
|||
|
||||
namespace JSBSim {
|
||||
|
||||
static const char *IdSrc = "$Id: FGOutput.cpp,v 1.48 2010/04/12 12:25:19 jberndt Exp $";
|
||||
static const char *IdSrc = "$Id: FGOutput.cpp,v 1.49 2010/10/15 11:30:29 jberndt Exp $";
|
||||
static const char *IdHdr = ID_OUTPUT;
|
||||
|
||||
// (stolen from FGFS native_fdm.cxx)
|
||||
|
@ -132,7 +129,6 @@ FGOutput::FGOutput(FGFDMExec* fdmex) : FGModel(fdmex)
|
|||
Name = "FGOutput";
|
||||
sFirstPass = dFirstPass = true;
|
||||
socket = 0;
|
||||
flightGearSocket = 0;
|
||||
runID_postfix = 0;
|
||||
Type = otNone;
|
||||
SubSystems = 0;
|
||||
|
@ -153,7 +149,6 @@ FGOutput::FGOutput(FGFDMExec* fdmex) : FGModel(fdmex)
|
|||
FGOutput::~FGOutput()
|
||||
{
|
||||
delete socket;
|
||||
delete flightGearSocket;
|
||||
OutputProperties.clear();
|
||||
Debug(1);
|
||||
}
|
||||
|
@ -231,6 +226,15 @@ void FGOutput::SetType(const string& type)
|
|||
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
void FGOutput::SetProtocol(const string& protocol)
|
||||
{
|
||||
if (protocol == "UDP") Protocol = FGfdmSocket::ptUDP;
|
||||
else if (protocol == "TCP") Protocol = FGfdmSocket::ptTCP;
|
||||
else Protocol = FGfdmSocket::ptTCP; // Default to TCP
|
||||
}
|
||||
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
void FGOutput::DelimitedOutput(const string& fname)
|
||||
{
|
||||
streambuf* buffer;
|
||||
|
@ -566,7 +570,6 @@ void FGOutput::SocketDataFill(FGNetFDM* net)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// Consumables
|
||||
net->num_tanks = Propulsion->GetNumTanks(); // Max number of fuel tanks
|
||||
|
||||
|
@ -574,7 +577,6 @@ void FGOutput::SocketDataFill(FGNetFDM* net)
|
|||
net->fuel_quantity[i] = (float)(((FGTank *)Propulsion->GetTank(i))->GetContents());
|
||||
}
|
||||
|
||||
|
||||
// Gear status
|
||||
net->num_wheels = GroundReactions->GetNumGearUnits();
|
||||
|
||||
|
@ -588,13 +590,11 @@ void FGOutput::SocketDataFill(FGNetFDM* net)
|
|||
net->gear_compression[i] = (float)(GroundReactions->GetGearUnit(i)->GetCompLen());
|
||||
}
|
||||
|
||||
|
||||
// Environment
|
||||
net->cur_time = (long int)1234567890; // Friday, Feb 13, 2009, 23:31:30 UTC (not processed by FGFS anyway)
|
||||
net->cur_time = (long int)1234567890; // Friday, Feb 13, 2009, 23:31:30 UTC (not processed by FGFS anyway)
|
||||
net->warp = 0; // offset in seconds to unix time
|
||||
net->visibility = 25000.0; // visibility in meters (for env. effects)
|
||||
|
||||
|
||||
// Control surface positions (normalized values)
|
||||
net->elevator = (float)(FCS->GetDePos(ofNorm)); // Norm Elevator Pos, --
|
||||
net->elevator_trim_tab = (float)(FCS->GetPitchTrimCmd()); // Norm Elev Trim Tab Pos, --
|
||||
|
@ -607,7 +607,6 @@ void FGOutput::SocketDataFill(FGNetFDM* net)
|
|||
net->speedbrake = (float)(FCS->GetDsbPos(ofNorm)); // Norm Speedbrake Pos, --
|
||||
net->spoilers = (float)(FCS->GetDspPos(ofNorm)); // Norm Spoiler Pos, --
|
||||
|
||||
|
||||
// Convert the net buffer to network format
|
||||
if ( isLittleEndian ) {
|
||||
net->version = htonl(net->version);
|
||||
|
@ -691,12 +690,11 @@ void FGOutput::FlightGearSocketOutput(void)
|
|||
{
|
||||
int length = sizeof(fgSockBuf);
|
||||
|
||||
|
||||
if (flightGearSocket == NULL) return;
|
||||
if (!flightGearSocket->GetConnectStatus()) return;
|
||||
if (socket == NULL) return;
|
||||
if (!socket->GetConnectStatus()) return;
|
||||
|
||||
SocketDataFill(&fgSockBuf);
|
||||
flightGearSocket->Send((char *)&fgSockBuf, length);
|
||||
socket->Send((char *)&fgSockBuf, length);
|
||||
}
|
||||
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
@ -944,11 +942,9 @@ void FGOutput::SocketStatusOutput(const string& out_str)
|
|||
|
||||
bool FGOutput::Load(Element* element)
|
||||
{
|
||||
string type="", parameter="";
|
||||
string parameter="";
|
||||
string name="";
|
||||
string protocol="tcp";
|
||||
int OutRate = 0;
|
||||
string property;
|
||||
unsigned int port;
|
||||
Element *property_element;
|
||||
|
||||
|
@ -967,19 +963,12 @@ bool FGOutput::Load(Element* element)
|
|||
if (!document) return false;
|
||||
|
||||
name = FDMExec->GetRootDir() + document->GetAttributeValue("name");
|
||||
type = document->GetAttributeValue("type");
|
||||
SetType(type);
|
||||
if (!document->GetAttributeValue("port").empty() && type == string("SOCKET")) {
|
||||
port = atoi(document->GetAttributeValue("port").c_str());
|
||||
socket = new FGfdmSocket(name, port);
|
||||
} else if (!document->GetAttributeValue("port").empty() && type == string("FLIGHTGEAR")) {
|
||||
port = atoi(document->GetAttributeValue("port").c_str());
|
||||
if (!document->GetAttributeValue("protocol").empty())
|
||||
protocol = document->GetAttributeValue("protocol");
|
||||
if (protocol == "udp")
|
||||
flightGearSocket = new FGfdmSocket(name, port, FGfdmSocket::ptUDP); // create udp socket
|
||||
else
|
||||
flightGearSocket = new FGfdmSocket(name, port, FGfdmSocket::ptTCP); // create tcp socket (default)
|
||||
SetType(document->GetAttributeValue("type"));
|
||||
Port = document->GetAttributeValue("port");
|
||||
if (!Port.empty() && (Type == otSocket || Type == otFlightGear)) {
|
||||
port = atoi(Port.c_str());
|
||||
SetProtocol(document->GetAttributeValue("protocol"));
|
||||
socket = new FGfdmSocket(name, port, Protocol);
|
||||
} else {
|
||||
BaseFilename = Filename = name;
|
||||
}
|
||||
|
|
|
@ -45,12 +45,13 @@ INCLUDES
|
|||
|
||||
#include "input_output/FGXMLFileRead.h"
|
||||
#include "input_output/net_fdm.hxx"
|
||||
#include "input_output/FGfdmSocket.h"
|
||||
|
||||
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
DEFINITIONS
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
|
||||
|
||||
#define ID_OUTPUT "$Id: FGOutput.h,v 1.17 2009/10/24 22:59:30 jberndt Exp $"
|
||||
#define ID_OUTPUT "$Id: FGOutput.h,v 1.18 2010/10/15 11:30:29 jberndt Exp $"
|
||||
|
||||
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
FORWARD DECLARATIONS
|
||||
|
@ -123,7 +124,7 @@ CLASS DOCUMENTATION
|
|||
propulsion ON|OFF
|
||||
</pre>
|
||||
NOTE that Time is always output with the data.
|
||||
@version $Id: FGOutput.h,v 1.17 2009/10/24 22:59:30 jberndt Exp $
|
||||
@version $Id: FGOutput.h,v 1.18 2010/10/15 11:30:29 jberndt Exp $
|
||||
*/
|
||||
|
||||
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
@ -145,17 +146,19 @@ public:
|
|||
void SocketStatusOutput(const std::string&);
|
||||
void SocketDataFill(FGNetFDM* net);
|
||||
|
||||
|
||||
void SetType(const std::string& type);
|
||||
void SetProtocol(const std::string& protocol);
|
||||
void SetPort(const std::string& port);
|
||||
void SetStartNewFile(bool tt) {StartNewFile = tt;}
|
||||
void SetSubsystems(int tt) {SubSystems = tt;}
|
||||
void Enable(void) { enabled = true; }
|
||||
void Disable(void) { enabled = false; }
|
||||
bool Toggle(void) {enabled = !enabled; return enabled;}
|
||||
bool Load(Element* el);
|
||||
void SetOutputFileName(const std::string& fname) {Filename = fname;}
|
||||
void SetDirectivesFile(const std::string& fname) {DirectivesFile = fname;}
|
||||
void SetRate(int rt);
|
||||
void Enable(void) { enabled = true; }
|
||||
void Disable(void) { enabled = false; }
|
||||
bool Toggle(void) {enabled = !enabled; return enabled;}
|
||||
|
||||
bool Load(Element* el);
|
||||
string GetOutputFileName(void) const {return Filename;}
|
||||
|
||||
/// Subsystem types for specifying which will be output in the FDM data logging
|
||||
|
@ -180,14 +183,15 @@ public:
|
|||
|
||||
private:
|
||||
enum {otNone, otCSV, otTab, otSocket, otTerminal, otFlightGear, otUnknown} Type;
|
||||
FGfdmSocket::ProtocolType Protocol;
|
||||
bool sFirstPass, dFirstPass, enabled;
|
||||
int SubSystems;
|
||||
int runID_postfix;
|
||||
bool StartNewFile;
|
||||
std::string output_file_name, delimeter, BaseFilename, Filename, DirectivesFile;
|
||||
std::string Port;
|
||||
std::ofstream datafile;
|
||||
FGfdmSocket* socket;
|
||||
FGfdmSocket* flightGearSocket;
|
||||
std::vector <FGPropertyManager*> OutputProperties;
|
||||
|
||||
void Debug(int from);
|
||||
|
|
|
@ -71,7 +71,7 @@ using namespace std;
|
|||
|
||||
namespace JSBSim {
|
||||
|
||||
static const char *IdSrc = "$Id: FGPropagate.cpp,v 1.65 2010/09/18 22:48:12 jberndt Exp $";
|
||||
static const char *IdSrc = "$Id: FGPropagate.cpp,v 1.71 2010/10/15 11:34:09 jberndt Exp $";
|
||||
static const char *IdHdr = ID_PROPAGATE;
|
||||
|
||||
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
@ -82,7 +82,7 @@ FGPropagate::FGPropagate(FGFDMExec* fdmex) : FGModel(fdmex)
|
|||
{
|
||||
Debug(0);
|
||||
Name = "FGPropagate";
|
||||
gravType = gtStandard;
|
||||
gravType = gtWGS84;
|
||||
|
||||
vPQRdot.InitMatrix();
|
||||
vQtrndot = FGQuaternion(0,0,0);
|
||||
|
@ -95,6 +95,7 @@ FGPropagate::FGPropagate(FGFDMExec* fdmex) : FGModel(fdmex)
|
|||
integrator_translational_position = eTrapezoidal;
|
||||
|
||||
VState.dqPQRdot.resize(4, FGColumnVector3(0.0,0.0,0.0));
|
||||
VState.dqPQRidot.resize(4, FGColumnVector3(0.0,0.0,0.0));
|
||||
VState.dqUVWidot.resize(4, FGColumnVector3(0.0,0.0,0.0));
|
||||
VState.dqInertialVelocity.resize(4, FGColumnVector3(0.0,0.0,0.0));
|
||||
VState.dqQtrndot.resize(4, FGQuaternion(0.0,0.0,0.0));
|
||||
|
@ -129,6 +130,7 @@ bool FGPropagate::InitModel(void)
|
|||
vInertialVelocity.InitMatrix();
|
||||
|
||||
VState.dqPQRdot.resize(4, FGColumnVector3(0.0,0.0,0.0));
|
||||
VState.dqPQRidot.resize(4, FGColumnVector3(0.0,0.0,0.0));
|
||||
VState.dqUVWidot.resize(4, FGColumnVector3(0.0,0.0,0.0));
|
||||
VState.dqInertialVelocity.resize(4, FGColumnVector3(0.0,0.0,0.0));
|
||||
VState.dqQtrndot.resize(4, FGColumnVector3(0.0,0.0,0.0));
|
||||
|
@ -204,6 +206,7 @@ void FGPropagate::SetInitialState(const FGInitialCondition *FGIC)
|
|||
FGIC->GetRRadpsIC() ) + Tl2b*vOmegaLocal;
|
||||
|
||||
VState.vPQRi = VState.vPQR + Ti2b * vOmegaEarth;
|
||||
VState.vPQRi_i = Tb2i * VState.vPQRi;
|
||||
|
||||
// Make an initial run and set past values
|
||||
InitializeDerivatives();
|
||||
|
@ -246,10 +249,11 @@ bool FGPropagate::Run(void)
|
|||
CalculateUVW(); // Translational position derivative (velocities are integrated in the inertial frame)
|
||||
|
||||
// Propagate rotational / translational velocity, angular /translational position, respectively.
|
||||
Integrate(VState.vPQRi, vPQRdot, VState.dqPQRdot, dt, integrator_rotational_rate);
|
||||
Integrate(VState.vInertialVelocity, vUVWidot, VState.dqUVWidot, dt, integrator_translational_rate);
|
||||
|
||||
Integrate(VState.vPQRi_i, vPQRidot, VState.dqPQRidot, dt, integrator_rotational_rate); // ECI integration
|
||||
Integrate(VState.qAttitudeECI, vQtrndot, VState.dqQtrndot, dt, integrator_rotational_position);
|
||||
Integrate(VState.vInertialPosition, VState.vInertialVelocity, VState.dqInertialVelocity, dt, integrator_translational_position);
|
||||
Integrate(VState.vInertialVelocity, vUVWidot, VState.dqUVWidot, dt, integrator_translational_rate);
|
||||
|
||||
// CAUTION : the order of the operations below is very important to get transformation
|
||||
// matrices that are consistent with the new state of the vehicle
|
||||
|
@ -280,6 +284,7 @@ bool FGPropagate::Run(void)
|
|||
|
||||
VehicleRadius = GetRadius(); // Calculate current aircraft radius from center of planet
|
||||
|
||||
VState.vPQRi = Ti2b * VState.vPQRi_i;
|
||||
VState.vPQR = VState.vPQRi - Ti2b * vOmegaEarth;
|
||||
|
||||
VState.qAttitudeLocal = Tl2b.GetQuaternion();
|
||||
|
@ -318,6 +323,7 @@ void FGPropagate::CalculatePQRdot(void)
|
|||
// frame.
|
||||
|
||||
vPQRdot = Jinv*(vMoments - VState.vPQRi*(J*VState.vPQRi));
|
||||
vPQRidot = Tb2i * vPQRdot;
|
||||
}
|
||||
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
@ -502,7 +508,7 @@ void FGPropagate::ResolveFrictionForces(double dt)
|
|||
// Instruct the algorithm to zero out the relative movement between the
|
||||
// aircraft and the ground.
|
||||
vdot += (VState.vUVW - Tec2b * LocalTerrainVelocity) / dt;
|
||||
wdot += VState.vPQR / dt;
|
||||
wdot += (VState.vPQR - Tec2b * LocalTerrainAngularVelocity) / dt;
|
||||
}
|
||||
|
||||
// Assemble the linear system of equations
|
||||
|
@ -557,6 +563,7 @@ void FGPropagate::ResolveFrictionForces(double dt)
|
|||
vUVWdot += invMass * Fc;
|
||||
vUVWidot += invMass * Tb2i * Fc;
|
||||
vPQRdot += Jinv * Mc;
|
||||
vPQRidot += Tb2i* Jinv * Mc;
|
||||
|
||||
// Save the value of the Lagrange multipliers to accelerate the convergence
|
||||
// of the Gauss-Seidel algorithm at next iteration.
|
||||
|
@ -609,7 +616,8 @@ void FGPropagate::SetInertialVelocity(FGColumnVector3 Vi) {
|
|||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
void FGPropagate::SetInertialRates(FGColumnVector3 vRates) {
|
||||
VState.vPQRi = Ti2b * vRates;
|
||||
VState.vPQRi_i = vRates;
|
||||
VState.vPQRi = Ti2b * VState.vPQRi_i;
|
||||
VState.vPQR = VState.vPQRi - Ti2b * vOmegaEarth;
|
||||
}
|
||||
|
||||
|
@ -626,11 +634,13 @@ void FGPropagate::InitializeDerivatives(void)
|
|||
|
||||
// Initialize past values deques
|
||||
VState.dqPQRdot.clear();
|
||||
VState.dqPQRidot.clear();
|
||||
VState.dqUVWidot.clear();
|
||||
VState.dqInertialVelocity.clear();
|
||||
VState.dqQtrndot.clear();
|
||||
for (int i=0; i<4; i++) {
|
||||
VState.dqPQRdot.push_front(vPQRdot);
|
||||
VState.dqPQRidot.push_front(vPQRidot);
|
||||
VState.dqUVWidot.push_front(vUVWdot);
|
||||
VState.dqInertialVelocity.push_front(VState.vInertialVelocity);
|
||||
VState.dqQtrndot.push_front(vQtrndot);
|
||||
|
@ -647,7 +657,7 @@ void FGPropagate::RecomputeLocalTerrainRadius(void)
|
|||
|
||||
// Get the LocalTerrain radius.
|
||||
FDMExec->GetGroundCallback()->GetAGLevel(t, VState.vLocation, contactloc, dv,
|
||||
LocalTerrainVelocity);
|
||||
LocalTerrainVelocity, LocalTerrainAngularVelocity);
|
||||
LocalTerrainRadius = contactloc.GetRadius();
|
||||
}
|
||||
|
||||
|
@ -712,6 +722,41 @@ void FGPropagate::SetDistanceAGL(double tt)
|
|||
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
void FGPropagate::DumpState(void)
|
||||
{
|
||||
cout << endl;
|
||||
cout << fgblue
|
||||
<< "------------------------------------------------------------------" << reset << endl;
|
||||
cout << highint
|
||||
<< "State Report at sim time: " << FDMExec->GetSimTime() << " seconds" << reset << endl;
|
||||
cout << " " << underon
|
||||
<< "Position" << underoff << endl;
|
||||
cout << " ECI: " << VState.vInertialPosition.Dump(", ") << " (x,y,z, in ft)" << endl;
|
||||
cout << " ECEF: " << VState.vLocation << " (x,y,z, in ft)" << endl;
|
||||
cout << " Local: " << VState.vLocation.GetLatitudeDeg()
|
||||
<< ", " << VState.vLocation.GetLongitudeDeg()
|
||||
<< ", " << GetAltitudeASL() << " (lat, lon, alt in deg and ft)" << endl;
|
||||
|
||||
cout << endl << " " << underon
|
||||
<< "Orientation" << underoff << endl;
|
||||
cout << " ECI: " << VState.qAttitudeECI.GetEulerDeg().Dump(", ") << " (phi, theta, psi in deg)" << endl;
|
||||
cout << " Local: " << VState.qAttitudeLocal.GetEulerDeg().Dump(", ") << " (phi, theta, psi in deg)" << endl;
|
||||
|
||||
cout << endl << " " << underon
|
||||
<< "Velocity" << underoff << endl;
|
||||
cout << " ECI: " << VState.vInertialVelocity.Dump(", ") << " (x,y,z in ft/s)" << endl;
|
||||
cout << " ECEF: " << (GetTb2ec() * VState.vUVW).Dump(", ") << " (x,y,z in ft/s)" << endl;
|
||||
cout << " Local: " << GetVel() << " (n,e,d in ft/sec)" << endl;
|
||||
cout << " Body: " << GetUVW() << " (u,v,w in ft/sec)" << endl;
|
||||
|
||||
cout << endl << " " << underon
|
||||
<< "Body Rates (relative to given frame, expressed in body frame)" << underoff << endl;
|
||||
cout << " ECI: " << (VState.vPQRi*radtodeg).Dump(", ") << " (p,q,r in deg/s)" << endl;
|
||||
cout << " ECEF: " << (VState.vPQR*radtodeg).Dump(", ") << " (p,q,r in deg/s)" << endl;
|
||||
}
|
||||
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
void FGPropagate::bind(void)
|
||||
{
|
||||
typedef double (FGPropagate::*PMF)(int) const;
|
||||
|
|
|
@ -49,7 +49,7 @@ INCLUDES
|
|||
DEFINITIONS
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
|
||||
|
||||
#define ID_PROPAGATE "$Id: FGPropagate.h,v 1.48 2010/09/18 22:48:12 jberndt Exp $"
|
||||
#define ID_PROPAGATE "$Id: FGPropagate.h,v 1.51 2010/10/07 03:45:40 jberndt Exp $"
|
||||
|
||||
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
FORWARD DECLARATIONS
|
||||
|
@ -102,7 +102,7 @@ CLASS DOCUMENTATION
|
|||
@endcode
|
||||
|
||||
@author Jon S. Berndt, Mathias Froehlich
|
||||
@version $Id: FGPropagate.h,v 1.48 2010/09/18 22:48:12 jberndt Exp $
|
||||
@version $Id: FGPropagate.h,v 1.51 2010/10/07 03:45:40 jberndt Exp $
|
||||
*/
|
||||
|
||||
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
@ -135,6 +135,11 @@ public:
|
|||
units rad/sec */
|
||||
FGColumnVector3 vPQRi;
|
||||
|
||||
/** The angular velocity vector for the vehicle body frame relative to the
|
||||
ECI frame, expressed in the ECI frame.
|
||||
units rad/sec */
|
||||
FGColumnVector3 vPQRi_i;
|
||||
|
||||
/** The current orientation of the vehicle, that is, the orientation of the
|
||||
body frame relative to the local, NED frame. */
|
||||
FGQuaternion qAttitudeLocal;
|
||||
|
@ -148,6 +153,7 @@ public:
|
|||
FGColumnVector3 vInertialPosition;
|
||||
|
||||
deque <FGColumnVector3> dqPQRdot;
|
||||
deque <FGColumnVector3> dqPQRidot;
|
||||
deque <FGColumnVector3> dqUVWidot;
|
||||
deque <FGColumnVector3> dqInertialVelocity;
|
||||
deque <FGQuaternion> dqQtrndot;
|
||||
|
@ -566,16 +572,6 @@ public:
|
|||
VState.vInertialPosition = GetTec2i() * VState.vLocation;
|
||||
UpdateLocationMatrices();
|
||||
}
|
||||
void SetLocation(const FGLocation& l) {
|
||||
VState.vLocation = l;
|
||||
VState.vInertialPosition = GetTec2i() * VState.vLocation;
|
||||
UpdateLocationMatrices();
|
||||
}
|
||||
void SetLocation(const FGColumnVector3& l) {
|
||||
VState.vLocation = l;
|
||||
VState.vInertialPosition = GetTec2i() * VState.vLocation;
|
||||
UpdateLocationMatrices();
|
||||
}
|
||||
void SetAltitudeASL(double altASL);
|
||||
void SetAltitudeASLmeters(double altASL) {SetAltitudeASL(altASL/fttom);}
|
||||
void SetSeaLevelRadius(double tt) { SeaLevelRadius = tt; }
|
||||
|
@ -588,6 +584,16 @@ public:
|
|||
VehicleRadius = GetRadius();
|
||||
UpdateLocationMatrices();
|
||||
}
|
||||
void SetLocation(const FGLocation& l) {
|
||||
VState.vLocation = l;
|
||||
VState.vInertialPosition = GetTec2i() * VState.vLocation;
|
||||
UpdateLocationMatrices();
|
||||
}
|
||||
void SetLocation(const FGColumnVector3& l) {
|
||||
VState.vLocation = l;
|
||||
VState.vInertialPosition = GetTec2i() * VState.vLocation;
|
||||
UpdateLocationMatrices();
|
||||
}
|
||||
|
||||
void RecomputeLocalTerrainRadius(void);
|
||||
|
||||
|
@ -604,6 +610,8 @@ public:
|
|||
double value;
|
||||
};
|
||||
|
||||
void DumpState(void);
|
||||
|
||||
private:
|
||||
|
||||
// state vector
|
||||
|
@ -612,6 +620,7 @@ private:
|
|||
|
||||
FGColumnVector3 vVel;
|
||||
FGColumnVector3 vPQRdot;
|
||||
FGColumnVector3 vPQRidot;
|
||||
FGColumnVector3 vUVWdot, vUVWidot;
|
||||
FGColumnVector3 vInertialVelocity;
|
||||
FGColumnVector3 vLocation;
|
||||
|
@ -633,7 +642,7 @@ private:
|
|||
FGMatrix33 Tl2i;
|
||||
|
||||
double LocalTerrainRadius, SeaLevelRadius, VehicleRadius;
|
||||
FGColumnVector3 LocalTerrainVelocity;
|
||||
FGColumnVector3 LocalTerrainVelocity, LocalTerrainAngularVelocity;
|
||||
eIntegrateType integrator_rotational_rate;
|
||||
eIntegrateType integrator_translational_rate;
|
||||
eIntegrateType integrator_rotational_position;
|
||||
|
|
|
@ -65,7 +65,7 @@ using namespace std;
|
|||
|
||||
namespace JSBSim {
|
||||
|
||||
static const char *IdSrc = "$Id: FGPropulsion.cpp,v 1.40 2010/09/07 00:40:03 jberndt Exp $";
|
||||
static const char *IdSrc = "$Id: FGPropulsion.cpp,v 1.41 2010/10/15 11:32:41 jberndt Exp $";
|
||||
static const char *IdHdr = ID_PROPULSION;
|
||||
|
||||
extern short debug_lvl;
|
||||
|
@ -295,29 +295,34 @@ bool FGPropulsion::Load(Element* el)
|
|||
document->SetParent(engine_element);
|
||||
|
||||
type = document->GetName();
|
||||
if (type == "piston_engine") {
|
||||
HavePistonEngine = true;
|
||||
if (!IsBound) bind();
|
||||
Engines.push_back(new FGPiston(FDMExec, document, numEngines));
|
||||
} else if (type == "turbine_engine") {
|
||||
HaveTurbineEngine = true;
|
||||
if (!IsBound) bind();
|
||||
Engines.push_back(new FGTurbine(FDMExec, document, numEngines));
|
||||
} else if (type == "turboprop_engine") {
|
||||
HaveTurboPropEngine = true;
|
||||
if (!IsBound) bind();
|
||||
Engines.push_back(new FGTurboProp(FDMExec, document, numEngines));
|
||||
} else if (type == "rocket_engine") {
|
||||
HaveRocketEngine = true;
|
||||
if (!IsBound) bind();
|
||||
Engines.push_back(new FGRocket(FDMExec, document, numEngines));
|
||||
} else if (type == "electric_engine") {
|
||||
HaveElectricEngine = true;
|
||||
if (!IsBound) bind();
|
||||
Engines.push_back(new FGElectric(FDMExec, document, numEngines));
|
||||
} else {
|
||||
cerr << "Unknown engine type: " << type << endl;
|
||||
exit(-5);
|
||||
try {
|
||||
if (type == "piston_engine") {
|
||||
HavePistonEngine = true;
|
||||
if (!IsBound) bind();
|
||||
Engines.push_back(new FGPiston(FDMExec, document, numEngines));
|
||||
} else if (type == "turbine_engine") {
|
||||
HaveTurbineEngine = true;
|
||||
if (!IsBound) bind();
|
||||
Engines.push_back(new FGTurbine(FDMExec, document, numEngines));
|
||||
} else if (type == "turboprop_engine") {
|
||||
HaveTurboPropEngine = true;
|
||||
if (!IsBound) bind();
|
||||
Engines.push_back(new FGTurboProp(FDMExec, document, numEngines));
|
||||
} else if (type == "rocket_engine") {
|
||||
HaveRocketEngine = true;
|
||||
if (!IsBound) bind();
|
||||
Engines.push_back(new FGRocket(FDMExec, document, numEngines));
|
||||
} else if (type == "electric_engine") {
|
||||
HaveElectricEngine = true;
|
||||
if (!IsBound) bind();
|
||||
Engines.push_back(new FGElectric(FDMExec, document, numEngines));
|
||||
} else {
|
||||
cerr << "Unknown engine type: " << type << endl;
|
||||
exit(-5);
|
||||
}
|
||||
} catch (std::string str) {
|
||||
cerr << endl << fgred << str << reset << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
FCS->AddThrottle();
|
||||
|
|
|
@ -54,7 +54,7 @@ using namespace std;
|
|||
|
||||
namespace JSBSim {
|
||||
|
||||
static const char *IdSrc = "$Id: FGEngine.cpp,v 1.39 2010/08/21 17:13:48 jberndt Exp $";
|
||||
static const char *IdSrc = "$Id: FGEngine.cpp,v 1.40 2010/10/15 11:32:41 jberndt Exp $";
|
||||
static const char *IdHdr = ID_ENGINE;
|
||||
|
||||
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
@ -109,7 +109,11 @@ FGEngine::FGEngine(FGFDMExec* exec, Element* engine_element, int engine_number)
|
|||
// Load thruster
|
||||
local_element = engine_element->GetParent()->FindElement("thruster");
|
||||
if (local_element) {
|
||||
if (!LoadThruster(local_element)) exit(-1);
|
||||
try {
|
||||
if (!LoadThruster(local_element)) exit(-1);
|
||||
} catch (std::string str) {
|
||||
throw("Error loading engine " + Name + ". " + str);
|
||||
}
|
||||
} else {
|
||||
cerr << "No thruster definition supplied with engine definition." << endl;
|
||||
}
|
||||
|
|
|
@ -48,7 +48,7 @@ using namespace std;
|
|||
|
||||
namespace JSBSim {
|
||||
|
||||
static const char *IdSrc = "$Id: FGPropeller.cpp,v 1.30 2010/05/02 15:10:07 jberndt Exp $";
|
||||
static const char *IdSrc = "$Id: FGPropeller.cpp,v 1.32 2010/10/21 03:27:40 jberndt Exp $";
|
||||
static const char *IdHdr = ID_PROPELLER;
|
||||
|
||||
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
@ -105,16 +105,20 @@ FGPropeller::FGPropeller(FGFDMExec* exec, Element* prop_element, int num)
|
|||
for (int i=0; i<2; i++) {
|
||||
table_element = prop_element->FindNextElement("table");
|
||||
name = table_element->GetAttributeValue("name");
|
||||
if (name == "C_THRUST") {
|
||||
cThrust = new FGTable(PropertyManager, table_element);
|
||||
} else if (name == "C_POWER") {
|
||||
cPower = new FGTable(PropertyManager, table_element);
|
||||
} else if (name == "CT_MACH") {
|
||||
CtMach = new FGTable(PropertyManager, table_element);
|
||||
} else if (name == "CP_MACH") {
|
||||
CpMach = new FGTable(PropertyManager, table_element);
|
||||
} else {
|
||||
cerr << "Unknown table type: " << name << " in propeller definition." << endl;
|
||||
try {
|
||||
if (name == "C_THRUST") {
|
||||
cThrust = new FGTable(PropertyManager, table_element);
|
||||
} else if (name == "C_POWER") {
|
||||
cPower = new FGTable(PropertyManager, table_element);
|
||||
} else if (name == "CT_MACH") {
|
||||
CtMach = new FGTable(PropertyManager, table_element);
|
||||
} else if (name == "CP_MACH") {
|
||||
CpMach = new FGTable(PropertyManager, table_element);
|
||||
} else {
|
||||
cerr << "Unknown table type: " << name << " in propeller definition." << endl;
|
||||
}
|
||||
} catch (std::string str) {
|
||||
throw("Error loading propeller table:" + name + ". " + str);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -334,7 +338,7 @@ double FGPropeller::GetPowerRequired(void)
|
|||
if (CL > 1.5) CL = 1.5;
|
||||
double BladeArea = Diameter * Diameter / 32.0 * numBlades;
|
||||
vTorque(eX) = -Sense*BladeArea*Diameter*Vel*Vel*rho*0.19*CL;
|
||||
PowerRequired = vTorque(eX)*0.2*M_PI;
|
||||
PowerRequired = fabs(vTorque(eX))*0.2*M_PI;
|
||||
}
|
||||
|
||||
return PowerRequired;
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <cassert>
|
||||
#include <simgear/structure/exception.hxx>
|
||||
|
||||
#include <FDM/fdm_shell.hxx>
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include <Airports/simple.hxx>
|
||||
#include <Airports/runways.hxx>
|
||||
#include <Main/fg_os.hxx> // fgGetKeyModifiers()
|
||||
#include <Navaids/routePath.hxx>
|
||||
|
||||
const char* RULER_LEGEND_KEY = "ruler-legend";
|
||||
|
||||
|
@ -657,77 +658,73 @@ void MapWidget::paintAircraftLocation(const SGGeod& aircraftPos)
|
|||
|
||||
void MapWidget::paintRoute()
|
||||
{
|
||||
if (_route->size() < 2) {
|
||||
if (_route->numWaypts() < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
// first pass, draw the actual line
|
||||
RoutePath path(_route->waypts());
|
||||
|
||||
// first pass, draw the actual lines
|
||||
glLineWidth(2.0);
|
||||
glBegin(GL_LINE_STRIP);
|
||||
|
||||
SGVec2d prev = project(_route->get_waypoint(0).get_target());
|
||||
glVertex2d(prev.x(), prev.y());
|
||||
|
||||
for (int w=1; w < _route->size(); ++w) {
|
||||
for (int w=0; w<_route->numWaypts(); ++w) {
|
||||
SGGeodVec gv(path.pathForIndex(w));
|
||||
if (gv.empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
SGVec2d p = project(_route->get_waypoint(w).get_target());
|
||||
|
||||
if (w < _route->currentWaypoint()) {
|
||||
if (w < _route->currentIndex()) {
|
||||
glColor4f(0.5, 0.5, 0.5, 0.7);
|
||||
} else {
|
||||
glColor4f(1.0, 0.0, 1.0, 1.0);
|
||||
}
|
||||
|
||||
glVertex2d(p.x(), p.y());
|
||||
flightgear::WayptRef wpt(_route->wayptAtIndex(w));
|
||||
if (wpt->flag(flightgear::WPT_MISS)) {
|
||||
glEnable(GL_LINE_STIPPLE);
|
||||
glLineStipple(1, 0x00FF);
|
||||
}
|
||||
|
||||
glBegin(GL_LINE_STRIP);
|
||||
for (unsigned int i=0; i<gv.size(); ++i) {
|
||||
SGVec2d p = project(gv[i]);
|
||||
glVertex2d(p.x(), p.y());
|
||||
}
|
||||
|
||||
glEnd();
|
||||
glDisable(GL_LINE_STIPPLE);
|
||||
}
|
||||
glEnd();
|
||||
|
||||
glLineWidth(1.0);
|
||||
// second pass, draw waypoint symbols and data
|
||||
for (int w=0; w < _route->size(); ++w) {
|
||||
const SGWayPoint& wpt(_route->get_waypoint(w));
|
||||
SGVec2d p = project(wpt.get_target());
|
||||
for (int w=0; w < _route->numWaypts(); ++w) {
|
||||
flightgear::WayptRef wpt(_route->wayptAtIndex(w));
|
||||
SGGeod g = path.positionForIndex(w);
|
||||
if (g == SGGeod()) {
|
||||
continue; // Vectors or similar
|
||||
}
|
||||
|
||||
SGVec2d p = project(g);
|
||||
glColor4f(1.0, 0.0, 1.0, 1.0);
|
||||
circleAtAlt(p, 8, 12, 5);
|
||||
|
||||
std::ostringstream legend;
|
||||
legend << wpt.get_id();
|
||||
if (wpt.get_target_alt() > -9990.0) {
|
||||
legend << '\n' << SGMiscd::roundToInt(wpt.get_target_alt()) << '\'';
|
||||
legend << wpt->ident();
|
||||
if (wpt->altitudeRestriction() != flightgear::RESTRICT_NONE) {
|
||||
legend << '\n' << SGMiscd::roundToInt(wpt->altitudeFt()) << '\'';
|
||||
}
|
||||
|
||||
if (wpt.get_speed() > 0.0) {
|
||||
legend << '\n' << SGMiscd::roundToInt(wpt.get_speed()) << "Kts";
|
||||
if (wpt->speedRestriction() != flightgear::RESTRICT_NONE) {
|
||||
legend << '\n' << SGMiscd::roundToInt(wpt->speedKts()) << "Kts";
|
||||
}
|
||||
|
||||
MapData* d = getOrCreateDataForKey(reinterpret_cast<void*>(w * 2));
|
||||
d->setText(legend.str());
|
||||
d->setLabel(wpt.get_id());
|
||||
d->setLabel(wpt->ident());
|
||||
d->setAnchor(p);
|
||||
d->setOffset(MapData::VALIGN_TOP | MapData::HALIGN_CENTER, 15);
|
||||
d->setPriority(w < _route->currentWaypoint() ? 9000 : 12000);
|
||||
d->setPriority(w < _route->currentIndex() ? 9000 : 12000);
|
||||
|
||||
if (w > 0) {
|
||||
SGVec2d legMid = (prev + p) * 0.5;
|
||||
std::ostringstream legLegend;
|
||||
|
||||
double track = wpt.get_track();
|
||||
if (_magneticHeadings) {
|
||||
track -= _magVar->get_magvar(); // show magnetic track for leg
|
||||
}
|
||||
|
||||
legLegend << SGMiscd::roundToInt(track) << " "
|
||||
<< SGMiscd::roundToInt(wpt.get_distance() * SG_METER_TO_NM) << "Nm";
|
||||
|
||||
MapData* ld = getOrCreateDataForKey(reinterpret_cast<void*>(w * 2 + 1));
|
||||
ld->setText(legLegend.str());
|
||||
ld->setAnchor(legMid);
|
||||
ld->setOffset(MapData::VALIGN_TOP | MapData::HALIGN_CENTER, 15);
|
||||
ld->setPriority(w < _route->currentWaypoint() ? 8000 : 11000);
|
||||
} // of draw leg data
|
||||
|
||||
prev = p;
|
||||
} // of second waypoint iteration
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
#include "WaypointList.hxx"
|
||||
|
||||
#include <algorithm>
|
||||
#include <boost/tuple/tuple.hpp>
|
||||
|
||||
#include <plib/puAux.h>
|
||||
|
||||
#include <simgear/route/waypoint.hxx>
|
||||
|
@ -16,14 +18,18 @@
|
|||
#include <Main/globals.hxx>
|
||||
#include <Main/fg_props.hxx>
|
||||
|
||||
#include <Navaids/positioned.hxx>
|
||||
#include <Autopilot/route_mgr.hxx>
|
||||
|
||||
using namespace flightgear;
|
||||
|
||||
enum {
|
||||
SCROLL_NO = 0,
|
||||
SCROLL_UP,
|
||||
SCROLL_DOWN
|
||||
};
|
||||
|
||||
static const double BLINK_TIME = 0.3;
|
||||
static const int DRAG_START_DISTANCE_PX = 5;
|
||||
|
||||
class RouteManagerWaypointModel :
|
||||
|
@ -48,37 +54,38 @@ public:
|
|||
// implement WaypointList::Model
|
||||
virtual unsigned int numWaypoints() const
|
||||
{
|
||||
return _rm->size();
|
||||
return _rm->numWaypts();
|
||||
}
|
||||
|
||||
virtual int currentWaypoint() const
|
||||
{
|
||||
return _rm->currentWaypoint();
|
||||
return _rm->currentIndex();
|
||||
}
|
||||
|
||||
virtual SGWayPoint waypointAt(unsigned int index) const
|
||||
virtual flightgear::Waypt* waypointAt(unsigned int index) const
|
||||
{
|
||||
return _rm->get_waypoint(index);
|
||||
if (index >= numWaypoints()) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return _rm->wayptAtIndex(index);
|
||||
}
|
||||
|
||||
virtual void deleteAt(unsigned int index)
|
||||
{
|
||||
_rm->pop_waypoint(index);
|
||||
}
|
||||
|
||||
virtual void setWaypointTargetAltitudeFt(unsigned int index, int altFt)
|
||||
{
|
||||
_rm->setWaypointTargetAltitudeFt(index, altFt);
|
||||
_rm->removeWayptAtIndex(index);
|
||||
}
|
||||
|
||||
virtual void moveWaypointToIndex(unsigned int srcIndex, unsigned int destIndex)
|
||||
{
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "moveWaypoint: from " << srcIndex << " to " << destIndex);
|
||||
if (destIndex > srcIndex) {
|
||||
--destIndex;
|
||||
}
|
||||
|
||||
SGWayPoint wp = _rm->pop_waypoint(srcIndex);
|
||||
_rm->add_waypoint(wp, destIndex);
|
||||
WayptRef w(_rm->removeWayptAtIndex(srcIndex));
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "wpt:" << w->ident());
|
||||
_rm->insertWayptAtIndex(w, destIndex);
|
||||
}
|
||||
|
||||
virtual void setUpdateCallback(SGCallback* cb)
|
||||
|
@ -129,13 +136,16 @@ WaypointList::WaypointList(int x, int y, int width, int height) :
|
|||
_showLatLon(false),
|
||||
_model(NULL),
|
||||
_updateCallback(NULL),
|
||||
_scrollCallback(NULL)
|
||||
_scrollCallback(NULL),
|
||||
_blink(false)
|
||||
{
|
||||
// pretend to be a list, so fgPopup doesn't mess with our mouse events
|
||||
type |= PUCLASS_LIST;
|
||||
setModel(new RouteManagerWaypointModel());
|
||||
setSize(width, height);
|
||||
setValue(-1);
|
||||
|
||||
_blinkTimer.stamp();
|
||||
}
|
||||
|
||||
WaypointList::~WaypointList()
|
||||
|
@ -230,6 +240,11 @@ void WaypointList::handleDrag(int x, int y)
|
|||
}
|
||||
|
||||
_dragSourceRow = rowForY(y - abox.min[1]);
|
||||
Waypt* wp = _model->waypointAt(_dragSourceRow);
|
||||
if (!wp || wp->flag(WPT_GENERATED)) {
|
||||
return; // don't allow generated points to be dragged
|
||||
}
|
||||
|
||||
_dragging = true;
|
||||
_dragScroll = SCROLL_NO;
|
||||
}
|
||||
|
@ -255,20 +270,26 @@ void WaypointList::doDrop(int x, int y)
|
|||
_dragging = false;
|
||||
puDeactivateWidget();
|
||||
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "doDrop");
|
||||
|
||||
if ((y < abox.min[1]) || (y >= abox.max[1])) {
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "y out of bounds:" << y);
|
||||
return;
|
||||
}
|
||||
|
||||
if (_dragSourceRow != _dragTargetRow) {
|
||||
_model->moveWaypointToIndex(_dragSourceRow, _dragTargetRow);
|
||||
|
||||
// keep row indexes linged up when moving an item down the list
|
||||
if (_dragSourceRow < _dragTargetRow) {
|
||||
--_dragTargetRow;
|
||||
}
|
||||
|
||||
setSelected(_dragTargetRow);
|
||||
if (_dragSourceRow == _dragTargetRow) {
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "source and target row match");
|
||||
return;
|
||||
}
|
||||
|
||||
_model->moveWaypointToIndex(_dragSourceRow, _dragTargetRow);
|
||||
|
||||
// keep row indexes linged up when moving an item down the list
|
||||
if (_dragSourceRow < _dragTargetRow) {
|
||||
--_dragTargetRow;
|
||||
}
|
||||
|
||||
setSelected(_dragTargetRow);
|
||||
}
|
||||
|
||||
void WaypointList::invokeDownCallback(void)
|
||||
|
@ -302,6 +323,12 @@ void WaypointList::draw( int dx, int dy )
|
|||
doDragScroll();
|
||||
}
|
||||
|
||||
double dt = (SGTimeStamp::now() - _blinkTimer).toSecs();
|
||||
if (dt > BLINK_TIME) {
|
||||
_blinkTimer.stamp();
|
||||
_blink = !_blink;
|
||||
}
|
||||
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
GLint sx = (int) abox.min[0],
|
||||
sy = abox.min[1];
|
||||
|
@ -321,6 +348,7 @@ void WaypointList::draw( int dx, int dy )
|
|||
|
||||
y -= (_scrollPx % rowHeight); // partially draw the first row
|
||||
|
||||
_arrowWidth = legendFont.getStringWidth(">");
|
||||
for ( ; row <= final; ++row, y += rowHeight) {
|
||||
drawRow(dx, dy, row, y);
|
||||
} // of row drawing iteration
|
||||
|
@ -343,6 +371,8 @@ void WaypointList::draw( int dx, int dy )
|
|||
|
||||
void WaypointList::drawRow(int dx, int dy, int rowIndex, int y)
|
||||
{
|
||||
flightgear::Waypt* wp(_model->waypointAt(rowIndex));
|
||||
|
||||
bool isSelected = (rowIndex == getSelected());
|
||||
bool isCurrent = (rowIndex == _model->currentWaypoint());
|
||||
bool isDragSource = (_dragging && (rowIndex == _dragSourceRow));
|
||||
|
@ -351,62 +381,100 @@ void WaypointList::drawRow(int dx, int dy, int rowIndex, int y)
|
|||
bkgBox.min[1] = abox.max[1] - y;
|
||||
bkgBox.max[1] = bkgBox.min[1] + rowHeightPx();
|
||||
|
||||
puColour currentColor;
|
||||
puSetColor(currentColor, 1.0, 1.0, 0.0, 0.5);
|
||||
puColour col;
|
||||
puFont* f = &legendFont;
|
||||
bool drawBox = false;
|
||||
|
||||
if (wp->flag(WPT_MISS)) {
|
||||
drawBox = true;
|
||||
puSetColor(col, 1.0, 0.0, 0.0, 0.3); // red
|
||||
} else if (wp->flag(WPT_ARRIVAL)) {
|
||||
drawBox = true;
|
||||
puSetColor(col, 0.0, 0.0, 0.0, 0.3);
|
||||
} else if (wp->flag(WPT_DEPARTURE)) {
|
||||
drawBox = true;
|
||||
puSetColor(col, 0.0, 0.0, 0.0, 0.3);
|
||||
}
|
||||
|
||||
if (isDragSource) {
|
||||
// draw later, on *top* of text string
|
||||
} else if (isCurrent) {
|
||||
bkgBox.draw(dx, dy, PUSTYLE_PLAIN, ¤tColor, false, 0);
|
||||
} else if (isSelected) { // -PLAIN means selected, apparently
|
||||
bkgBox.draw(dx, dy, -PUSTYLE_PLAIN, colour, false, 0);
|
||||
} else if (drawBox) {
|
||||
bkgBox.draw(dx, dy, PUSTYLE_PLAIN, &col, false, 0);
|
||||
}
|
||||
|
||||
if (isCurrent) {
|
||||
glColor4f (1.0, 0.5, 0.0, 1.0) ;
|
||||
} else {
|
||||
glColor4fv ( colour [ PUCOL_LEGEND ] ) ;
|
||||
}
|
||||
|
||||
int xx = dx + abox.min[0] + PUSTR_LGAP;
|
||||
int yy = dy + abox.max[1] - y ;
|
||||
yy += 4; // center text in row height
|
||||
|
||||
// row textual data
|
||||
const SGWayPoint wp(_model->waypointAt(rowIndex));
|
||||
char buffer[128];
|
||||
int count = ::snprintf(buffer, 128, "%03d %-5s", rowIndex, wp.get_id().c_str());
|
||||
|
||||
if (wp.get_name().size() > 0 && (wp.get_name() != wp.get_id())) {
|
||||
// append name if present, and different to id
|
||||
::snprintf(buffer + count, 128 - count, " (%s)", wp.get_name().c_str());
|
||||
if (isCurrent) {
|
||||
f->drawString(">", xx, yy);
|
||||
}
|
||||
|
||||
glColor4fv ( colour [ PUCOL_LEGEND ] ) ;
|
||||
drawClippedString(legendFont, buffer, xx, yy, 300);
|
||||
int x = xx;
|
||||
x += _arrowWidth + PUSTR_LGAP;
|
||||
|
||||
if (_showLatLon) {
|
||||
char ns = (wp.get_target_lat() > 0.0) ? 'N' : 'S';
|
||||
char ew = (wp.get_target_lon() > 0.0) ? 'E' : 'W';
|
||||
|
||||
::snprintf(buffer, 128 - count, "%4.2f%c %4.2f%c",
|
||||
fabs(wp.get_target_lon()), ew, fabs(wp.get_target_lat()), ns);
|
||||
} else {
|
||||
::snprintf(buffer, 128 - count, "%03.0f %5.1fnm",
|
||||
wp.get_track(), wp.get_distance() * SG_METER_TO_NM);
|
||||
// row textual data
|
||||
|
||||
char buffer[128];
|
||||
int count = ::snprintf(buffer, 128, "%03d %-5s", rowIndex, wp->ident().c_str());
|
||||
|
||||
FGPositioned* src = wp->source();
|
||||
if (src && !src->name().empty() && (src->name() != wp->ident())) {
|
||||
// append name if present, and different to id
|
||||
::snprintf(buffer + count, 128 - count, " (%s)", src->name().c_str());
|
||||
}
|
||||
|
||||
legendFont.drawString(buffer, xx + 300 + PUSTR_LGAP, yy);
|
||||
drawClippedString(legendFont, buffer, x, yy, 300);
|
||||
x += 300 + PUSTR_LGAP;
|
||||
|
||||
int altFt = (int) wp.get_target_alt() * SG_METER_TO_FEET;
|
||||
if (altFt > -9990) {
|
||||
int altHundredFt = (altFt + 50) / 100; // round to nearest 100ft
|
||||
if (_showLatLon) {
|
||||
SGGeod p(wp->position());
|
||||
char ns = (p.getLatitudeDeg() > 0.0) ? 'N' : 'S';
|
||||
char ew = (p.getLongitudeDeg() > 0.0) ? 'E' : 'W';
|
||||
|
||||
::snprintf(buffer, 128 - count, "%4.2f%c %4.2f%c",
|
||||
fabs(p.getLongitudeDeg()), ew, fabs(p.getLatitudeDeg()), ns);
|
||||
} else if (rowIndex > 0) {
|
||||
double courseDeg;
|
||||
double distanceM;
|
||||
Waypt* prev = _model->waypointAt(rowIndex - 1);
|
||||
boost::tie(courseDeg, distanceM) = wp->courseAndDistanceFrom(prev->position());
|
||||
|
||||
::snprintf(buffer, 128 - count, "%03.0f %5.1fnm",
|
||||
courseDeg, distanceM * SG_METER_TO_NM);
|
||||
}
|
||||
|
||||
f->drawString(buffer, x, yy);
|
||||
x += 100 + PUSTR_LGAP;
|
||||
|
||||
if (wp->altitudeRestriction() != RESTRICT_NONE) {
|
||||
int altHundredFt = (wp->altitudeFt() + 50) / 100; // round to nearest 100ft
|
||||
if (altHundredFt < 100) {
|
||||
count = ::snprintf(buffer, 128, "%d'", altHundredFt * 100);
|
||||
} else { // display as a flight-level
|
||||
count = ::snprintf(buffer, 128, "FL%d", altHundredFt);
|
||||
}
|
||||
|
||||
legendFont.drawString(buffer, xx + 400 + PUSTR_LGAP, yy);
|
||||
f->drawString(buffer, x, yy);
|
||||
} // of valid wp altitude
|
||||
x += 60 + PUSTR_LGAP;
|
||||
|
||||
if (wp->speedRestriction() != RESTRICT_NONE) {
|
||||
count = ::snprintf(buffer, 126, "%dKts", (int) wp->speedKts());
|
||||
f->drawString(buffer, x, yy);
|
||||
}
|
||||
|
||||
if (isDragSource) {
|
||||
puSetColor(currentColor, 1.0, 0.5, 0.0, 0.5);
|
||||
bkgBox.draw(dx, dy, PUSTYLE_PLAIN, ¤tColor, false, 0);
|
||||
puSetColor(col, 1.0, 0.5, 0.0, 0.5);
|
||||
bkgBox.draw(dx, dy, PUSTYLE_PLAIN, &col, false, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -613,22 +681,34 @@ int WaypointList::checkKey (int key, int updown )
|
|||
|
||||
case '-':
|
||||
if (getSelected() >= 0) {
|
||||
int newAlt = wayptAltFtHundreds(getSelected()) - 10;
|
||||
if (newAlt < 0) {
|
||||
_model->setWaypointTargetAltitudeFt(getSelected(), -9999);
|
||||
} else {
|
||||
_model->setWaypointTargetAltitudeFt(getSelected(), newAlt * 100);
|
||||
Waypt* wp = _model->waypointAt(getSelected());
|
||||
if (wp->flag(WPT_GENERATED)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (wp->altitudeRestriction() != RESTRICT_NONE) {
|
||||
int curAlt = (static_cast<int>(wp->altitudeFt()) + 50) / 100;
|
||||
if (curAlt <= 0) {
|
||||
wp->setAltitude(0, RESTRICT_NONE);
|
||||
} else {
|
||||
wp->setAltitude((curAlt - 10) * 100, wp->altitudeRestriction());
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case '=':
|
||||
if (getSelected() >= 0) {
|
||||
int newAlt = wayptAltFtHundreds(getSelected()) + 10;
|
||||
if (newAlt < 0) {
|
||||
_model->setWaypointTargetAltitudeFt(getSelected(), 0);
|
||||
flightgear::Waypt* wp = _model->waypointAt(getSelected());
|
||||
if (wp->flag(WPT_GENERATED)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (wp->altitudeRestriction() == RESTRICT_NONE) {
|
||||
wp->setAltitude(1000, RESTRICT_AT);
|
||||
} else {
|
||||
_model->setWaypointTargetAltitudeFt(getSelected(), newAlt * 100);
|
||||
int curAlt = (static_cast<int>(wp->altitudeFt()) + 50) / 100;
|
||||
wp->setAltitude((curAlt + 10) * 100, wp->altitudeRestriction());
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -636,6 +716,11 @@ int WaypointList::checkKey (int key, int updown )
|
|||
case 0x7f: // delete
|
||||
if (getSelected() >= 0) {
|
||||
int index = getSelected();
|
||||
Waypt* wp = _model->waypointAt(getSelected());
|
||||
if (wp->flag(WPT_GENERATED)) {
|
||||
break;
|
||||
}
|
||||
|
||||
_model->deleteAt(index);
|
||||
setSelected(index - 1);
|
||||
}
|
||||
|
@ -648,17 +733,6 @@ int WaypointList::checkKey (int key, int updown )
|
|||
return TRUE ;
|
||||
}
|
||||
|
||||
int WaypointList::wayptAltFtHundreds(int index) const
|
||||
{
|
||||
double alt = _model->waypointAt(index).get_target_alt();
|
||||
if (alt < -9990.0) {
|
||||
return -9999;
|
||||
}
|
||||
|
||||
int altFt = (int) alt * SG_METER_TO_FEET;
|
||||
return (altFt + 50) / 100; // round to nearest 100ft
|
||||
}
|
||||
|
||||
void WaypointList::modelUpdateCallback()
|
||||
{
|
||||
// local stuff
|
||||
|
|
|
@ -14,9 +14,12 @@
|
|||
|
||||
// forward decls
|
||||
class puaScrollBar;
|
||||
class SGWayPoint;
|
||||
class SGCallback;
|
||||
|
||||
namespace flightgear {
|
||||
class Waypt;
|
||||
}
|
||||
|
||||
class WaypointList : public puFrame, public GUI_ID
|
||||
{
|
||||
public:
|
||||
|
@ -71,14 +74,13 @@ public:
|
|||
|
||||
virtual unsigned int numWaypoints() const = 0;
|
||||
virtual int currentWaypoint() const = 0;
|
||||
virtual SGWayPoint waypointAt(unsigned int index) const = 0;
|
||||
virtual flightgear::Waypt* waypointAt(unsigned int index) const = 0;
|
||||
|
||||
// update notifications
|
||||
virtual void setUpdateCallback(SGCallback* cb) = 0;
|
||||
|
||||
// editing operations
|
||||
virtual void deleteAt(unsigned int index) = 0;
|
||||
virtual void setWaypointTargetAltitudeFt(unsigned int index, int altFt) = 0;
|
||||
virtual void moveWaypointToIndex(unsigned int srcIndex, unsigned int dstIndex) = 0;
|
||||
};
|
||||
|
||||
|
@ -121,9 +123,7 @@ private:
|
|||
int numFullyVisibleRows() const;
|
||||
int firstFullyVisibleRow() const;
|
||||
int lastFullyVisibleRow() const;
|
||||
|
||||
int wayptAltFtHundreds(int index) const;
|
||||
|
||||
|
||||
void modelUpdateCallback();
|
||||
|
||||
int _scrollPx; // scroll ammount (in pixels)
|
||||
|
@ -141,6 +141,10 @@ private:
|
|||
Model* _model;
|
||||
SGCallback* _updateCallback;
|
||||
SGCallback* _scrollCallback;
|
||||
|
||||
SGTimeStamp _blinkTimer;
|
||||
bool _blink;
|
||||
int _arrowWidth;
|
||||
};
|
||||
|
||||
class ScrolledWaypointList : public puGroup
|
||||
|
|
|
@ -1339,8 +1339,41 @@ fgList::update()
|
|||
|
||||
void fgComboBox::update()
|
||||
{
|
||||
if (_inHit) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::string curValue(getStringValue());
|
||||
fgValueList::update();
|
||||
newList(_list);
|
||||
int currentItem = puaComboBox::getCurrentItem();
|
||||
|
||||
|
||||
// look for the previous value, in the new list
|
||||
for (int i = 0; _list[i] != 0; i++) {
|
||||
if (_list[i] == curValue) {
|
||||
// don't set the current item again; this is important to avoid
|
||||
// recursion here if the combo callback ultimately causes another dialog-update
|
||||
if (i != currentItem) {
|
||||
puaComboBox::setCurrentItem(i);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
} // of list values iteration
|
||||
|
||||
// cound't find current item, default to first
|
||||
if (currentItem != 0) {
|
||||
puaComboBox::setCurrentItem(0);
|
||||
}
|
||||
}
|
||||
|
||||
int fgComboBox::checkHit(int b, int up, int x, int y)
|
||||
{
|
||||
_inHit = true;
|
||||
int r = puaComboBox::checkHit(b, up, x, y);
|
||||
_inHit = false;
|
||||
return r;
|
||||
}
|
||||
|
||||
// end of dialog.cxx
|
||||
|
|
|
@ -259,9 +259,17 @@ public:
|
|||
class fgComboBox : public fgValueList, public puaComboBox {
|
||||
public:
|
||||
fgComboBox(int x1, int y1, int x2, int y2, SGPropertyNode *p, bool editable) :
|
||||
fgValueList(p), puaComboBox(x1, y1, x2, y2, _list, editable) {}
|
||||
fgValueList(p),
|
||||
puaComboBox(x1, y1, x2, y2, _list, editable),
|
||||
_inHit(false)
|
||||
{}
|
||||
|
||||
void update();
|
||||
|
||||
virtual int checkHit(int b, int up, int x, int y);
|
||||
|
||||
private:
|
||||
bool _inHit;
|
||||
};
|
||||
|
||||
class fgSelectBox : public fgValueList, public puaSelectBox {
|
||||
|
|
|
@ -39,7 +39,6 @@
|
|||
|
||||
#include <plib/pu.h>
|
||||
|
||||
#include <Include/general.hxx>
|
||||
#include <Main/main.hxx>
|
||||
#include <Main/globals.hxx>
|
||||
#include <Main/fg_props.hxx>
|
||||
|
|
|
@ -10,14 +10,13 @@
|
|||
#include <iostream>
|
||||
#include <cstring>
|
||||
#include <sys/types.h>
|
||||
#include <plib/ul.h>
|
||||
|
||||
#include <plib/pu.h>
|
||||
#include <plib/ul.h>
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
#include <simgear/structure/exception.hxx>
|
||||
#include <simgear/props/props_io.hxx>
|
||||
#include <simgear/misc/sg_dir.hxx>
|
||||
|
||||
#include <boost/algorithm/string/case_conv.hpp>
|
||||
|
||||
|
@ -56,11 +55,8 @@ void
|
|||
NewGUI::init ()
|
||||
{
|
||||
setStyle();
|
||||
char path1[1024];
|
||||
char path2[1024];
|
||||
ulMakePath(path1, globals->get_fg_root().c_str(), "gui");
|
||||
ulMakePath(path2, path1, "dialogs");
|
||||
readDir(path2);
|
||||
SGPath p(globals->get_fg_root(), "gui/dialogs");
|
||||
readDir(p);
|
||||
_menubar->init();
|
||||
}
|
||||
|
||||
|
@ -233,19 +229,6 @@ NewGUI::setMenuBarVisible (bool visible)
|
|||
_menubar->hide();
|
||||
}
|
||||
|
||||
static bool
|
||||
test_extension (const char * path, const char * ext)
|
||||
{
|
||||
int pathlen = strlen(path);
|
||||
int extlen = strlen(ext);
|
||||
|
||||
for (int i = 1; i <= pathlen && i <= extlen; i++) {
|
||||
if (path[pathlen-i] != ext[extlen-i])
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
NewGUI::newDialog (SGPropertyNode* props)
|
||||
{
|
||||
|
@ -260,49 +243,31 @@ NewGUI::newDialog (SGPropertyNode* props)
|
|||
}
|
||||
|
||||
void
|
||||
NewGUI::readDir (const char * path)
|
||||
NewGUI::readDir (const SGPath& path)
|
||||
{
|
||||
ulDir * dir = ulOpenDir(path);
|
||||
|
||||
if (dir == 0) {
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "Failed to read GUI files from "
|
||||
<< path);
|
||||
return;
|
||||
simgear::Dir dir(path);
|
||||
simgear::PathList xmls = dir.children(simgear::Dir::TYPE_FILE, ".xml");
|
||||
|
||||
for (unsigned int i=0; i<xmls.size(); ++i) {
|
||||
SGPropertyNode * props = new SGPropertyNode;
|
||||
try {
|
||||
readProperties(xmls[i].str(), props);
|
||||
} catch (const sg_exception &) {
|
||||
SG_LOG(SG_INPUT, SG_ALERT, "Error parsing dialog "
|
||||
<< xmls[i].str());
|
||||
delete props;
|
||||
continue;
|
||||
}
|
||||
SGPropertyNode *nameprop = props->getNode("name");
|
||||
if (!nameprop) {
|
||||
SG_LOG(SG_INPUT, SG_WARN, "dialog " << xmls[i].str()
|
||||
<< " has no name; skipping.");
|
||||
delete props;
|
||||
continue;
|
||||
}
|
||||
string name = nameprop->getStringValue();
|
||||
_dialog_props[name] = props;
|
||||
}
|
||||
|
||||
for (ulDirEnt * dirEnt = ulReadDir(dir);
|
||||
dirEnt != 0;
|
||||
dirEnt = ulReadDir(dir)) {
|
||||
|
||||
char subpath[1024];
|
||||
|
||||
ulMakePath(subpath, path, dirEnt->d_name);
|
||||
|
||||
if (!dirEnt->d_isdir && test_extension(subpath, ".xml")) {
|
||||
SGPropertyNode * props = new SGPropertyNode;
|
||||
try {
|
||||
readProperties(subpath, props);
|
||||
} catch (const sg_exception &) {
|
||||
SG_LOG(SG_INPUT, SG_ALERT, "Error parsing dialog "
|
||||
<< subpath);
|
||||
delete props;
|
||||
continue;
|
||||
}
|
||||
SGPropertyNode *nameprop = props->getNode("name");
|
||||
if (!nameprop) {
|
||||
SG_LOG(SG_INPUT, SG_WARN, "dialog " << subpath
|
||||
<< " has no name; skipping.");
|
||||
delete props;
|
||||
continue;
|
||||
}
|
||||
string name = nameprop->getStringValue();
|
||||
if (_dialog_props[name])
|
||||
delete (SGPropertyNode *)_dialog_props[name];
|
||||
|
||||
_dialog_props[name] = props;
|
||||
}
|
||||
}
|
||||
ulCloseDir(dir);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -219,7 +219,7 @@ private:
|
|||
void clear_colors();
|
||||
|
||||
// Read all the configuration files in a directory.
|
||||
void readDir (const char * path);
|
||||
void readDir (const SGPath& path);
|
||||
|
||||
FGMenuBar * _menubar;
|
||||
FGDialog * _active_dialog;
|
||||
|
|
|
@ -4,5 +4,4 @@ EXTRA_DIST = \
|
|||
config.h-msvc71 \
|
||||
config.h-msvc8 \
|
||||
cmdargs.h \
|
||||
fg_typedefs.h \
|
||||
general.hxx
|
||||
fg_typedefs.h
|
|
@ -1,85 +0,0 @@
|
|||
// general.hxx -- a general house keeping data structure definition for
|
||||
// various info that might need to be accessible from all
|
||||
// parts of the sim.
|
||||
//
|
||||
// Written by Curtis Olson, started July 1997.
|
||||
//
|
||||
// Copyright (C) 1997 Curtis L. Olson - http://www.flightgear.org/~curt
|
||||
//
|
||||
// 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
// $Id$
|
||||
|
||||
|
||||
#ifndef _GENERAL_HXX
|
||||
#define _GENERAL_HXX
|
||||
|
||||
|
||||
#ifndef __cplusplus
|
||||
# error This library requires C++
|
||||
#endif
|
||||
|
||||
#include <simgear/structure/OSGVersion.hxx>
|
||||
#define FG_OSG_VERSION SG_OSG_VERSION
|
||||
|
||||
// #define FANCY_FRAME_COUNTER
|
||||
#ifdef FANCY_FRAME_COUNTER
|
||||
#define FG_FRAME_RATE_HISTORY 10
|
||||
#endif
|
||||
|
||||
|
||||
// the general house keeping structure definition
|
||||
class FGGeneral {
|
||||
// Info about OpenGL
|
||||
char *glVendor;
|
||||
char *glRenderer;
|
||||
char *glVersion;
|
||||
int glMaxTexSize;
|
||||
int glDepthBits;
|
||||
|
||||
// Last frame rate measurement
|
||||
int frame_rate;
|
||||
#ifdef FANCY_FRAME_COUNTER
|
||||
double frames[FG_FRAME_RATE_HISTORY];
|
||||
#endif
|
||||
|
||||
public:
|
||||
inline char* get_glVendor() { return glVendor; }
|
||||
inline void set_glVendor( char *str ) { glVendor = str; }
|
||||
inline char* get_glRenderer() const { return glRenderer; }
|
||||
inline void set_glRenderer( char *str ) { glRenderer = str; }
|
||||
inline char* get_glVersion() { return glVersion; }
|
||||
inline void set_glVersion( char *str ) { glVersion = str; }
|
||||
inline void set_glMaxTexSize( int i ) { glMaxTexSize = i; }
|
||||
inline int get_glMaxTexSize() const { return glMaxTexSize; }
|
||||
inline void set_glDepthBits( int d ) { glDepthBits = d; }
|
||||
inline int get_glDepthBits() const { return glDepthBits; }
|
||||
inline double get_frame_rate() const { return frame_rate; }
|
||||
#ifdef FANCY_FRAME_COUNTER
|
||||
inline double get_frame(int idx) const { return frames[idx]; }
|
||||
inline void set_frame( int idx, double value ) { frames[idx] = value; }
|
||||
inline void set_frame_rate( double rate ) { frame_rate = rate; }
|
||||
#else
|
||||
inline void set_frame_rate( int rate ) { frame_rate = rate; }
|
||||
#endif
|
||||
};
|
||||
|
||||
// general contains all the general house keeping parameters.
|
||||
extern FGGeneral general;
|
||||
|
||||
|
||||
#endif // _GENERAL_HXX
|
||||
|
||||
|
|
@ -27,7 +27,6 @@
|
|||
|
||||
#include <vector>
|
||||
#include <simgear/structure/SGBinding.hxx>
|
||||
#include <plib/ul.h>
|
||||
|
||||
#if defined( UL_WIN32 )
|
||||
#define TGT_PLATFORM "windows"
|
||||
|
|
|
@ -30,8 +30,7 @@
|
|||
|
||||
#include "FGDeviceConfigurationMap.hxx"
|
||||
|
||||
#include <plib/ul.h>
|
||||
|
||||
#include <simgear/misc/sg_dir.hxx>
|
||||
#include <simgear/props/props_io.hxx>
|
||||
#include <Main/globals.hxx>
|
||||
|
||||
|
@ -41,11 +40,8 @@ FGDeviceConfigurationMap::FGDeviceConfigurationMap( const char * relative_path,
|
|||
base(aBase),
|
||||
childname(aChildname)
|
||||
{
|
||||
SGPath path(globals->get_fg_root());
|
||||
path.append( relative_path );
|
||||
|
||||
int index = 1000;
|
||||
scan_dir( path, &index);
|
||||
scan_dir( SGPath(globals->get_fg_root(), relative_path), &index);
|
||||
|
||||
PropertyList childNodes = base->getChildren(childname);
|
||||
for (int k = (int)childNodes.size() - 1; k >= 0; k--) {
|
||||
|
@ -62,26 +58,22 @@ FGDeviceConfigurationMap::~FGDeviceConfigurationMap()
|
|||
base->removeChildren( childname );
|
||||
}
|
||||
|
||||
void FGDeviceConfigurationMap::scan_dir( SGPath & path, int *index)
|
||||
void FGDeviceConfigurationMap::scan_dir(const SGPath & path, int *index)
|
||||
{
|
||||
ulDir *dir = ulOpenDir(path.c_str());
|
||||
if (dir) {
|
||||
ulDirEnt* dent;
|
||||
while ((dent = ulReadDir(dir)) != 0) {
|
||||
if (dent->d_name[0] == '.')
|
||||
continue;
|
||||
simgear::Dir dir(path);
|
||||
simgear::PathList children = dir.children(simgear::Dir::TYPE_FILE |
|
||||
simgear::Dir::TYPE_DIR | simgear::Dir::NO_DOT_OR_DOTDOT);
|
||||
|
||||
SGPath p(path.str());
|
||||
p.append(dent->d_name);
|
||||
scan_dir(p, index);
|
||||
for (unsigned int c=0; c<children.size(); ++c) {
|
||||
SGPath path(children[c]);
|
||||
if (path.isDir()) {
|
||||
scan_dir(path, index);
|
||||
} else if (path.extension() == "xml") {
|
||||
SG_LOG(SG_INPUT, SG_DEBUG, "Reading joystick file " << path.str());
|
||||
SGPropertyNode_ptr n = base->getChild(childname, (*index)++, true);
|
||||
readProperties(path.str(), n);
|
||||
n->setStringValue("source", path.c_str());
|
||||
}
|
||||
ulCloseDir(dir);
|
||||
|
||||
} else if (path.extension() == "xml") {
|
||||
SG_LOG(SG_INPUT, SG_DEBUG, "Reading joystick file " << path.str());
|
||||
SGPropertyNode_ptr n = base->getChild(childname, (*index)++, true);
|
||||
readProperties(path.str(), n);
|
||||
n->setStringValue("source", path.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -30,16 +30,17 @@
|
|||
#endif
|
||||
|
||||
#include <simgear/props/props.hxx>
|
||||
#include <simgear/misc/sg_path.hxx>
|
||||
|
||||
#include <map>
|
||||
|
||||
class SGPath;
|
||||
|
||||
class FGDeviceConfigurationMap : public std::map<std::string,SGPropertyNode_ptr> {
|
||||
public:
|
||||
FGDeviceConfigurationMap ( const char * relative_path, SGPropertyNode_ptr base, const char * childname );
|
||||
virtual ~FGDeviceConfigurationMap();
|
||||
private:
|
||||
void scan_dir( SGPath & path, int *index);
|
||||
void scan_dir(const SGPath & path, int *index);
|
||||
SGPropertyNode_ptr base;
|
||||
const char * childname;
|
||||
};
|
||||
|
|
|
@ -66,7 +66,7 @@ bool FGEventSetting::Test()
|
|||
|
||||
static inline bool StartsWith( string & s, const char * cp )
|
||||
{
|
||||
return s.compare( 0, strlen(cp), cp ) == 0;
|
||||
return s.find( cp ) == 0;
|
||||
}
|
||||
|
||||
FGInputEvent * FGInputEvent::NewObject( FGInputDevice * device, SGPropertyNode_ptr node )
|
||||
|
@ -223,8 +223,8 @@ FGInputDevice::~FGInputDevice()
|
|||
if( nasal ) {
|
||||
SGPropertyNode_ptr nasalClose = nasal->getNode("close");
|
||||
if (nasalClose) {
|
||||
const char *s = nasalClose->getStringValue();
|
||||
nas->createModule(nasalModule.c_str(), nasalModule.c_str(), s, strlen(s), deviceNode );
|
||||
const string s = nasalClose->getStringValue();
|
||||
nas->createModule(nasalModule.c_str(), nasalModule.c_str(), s.c_str(), s.length(), deviceNode );
|
||||
}
|
||||
}
|
||||
nas->deleteModule(nasalModule.c_str());
|
||||
|
@ -253,10 +253,10 @@ void FGInputDevice::Configure( SGPropertyNode_ptr aDeviceNode )
|
|||
if (nasal) {
|
||||
SGPropertyNode_ptr open = nasal->getNode("open");
|
||||
if (open) {
|
||||
const char *s = open->getStringValue();
|
||||
const string s = open->getStringValue();
|
||||
FGNasalSys *nas = (FGNasalSys *)globals->get_subsystem("nasal");
|
||||
if (nas)
|
||||
nas->createModule(nasalModule.c_str(), nasalModule.c_str(), s, strlen(s), deviceNode );
|
||||
nas->createModule(nasalModule.c_str(), nasalModule.c_str(), s.c_str(), s.length(), deviceNode );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -29,6 +29,8 @@
|
|||
#include <poll.h>
|
||||
#include <linux/input.h>
|
||||
#include <dbus/dbus.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
|
||||
struct TypeCode {
|
||||
unsigned type;
|
||||
|
@ -238,7 +240,7 @@ static EventNameByType EVENT_NAME_BY_TYPE;
|
|||
|
||||
struct ltstr {
|
||||
bool operator()(const char * s1, const char * s2 ) const {
|
||||
return strcmp( s1, s2 ) < 0;
|
||||
return string(s1).compare( s2 ) < 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -115,14 +115,8 @@ HUD::~HUD()
|
|||
_scr_heightN->removeChangeListener(this);
|
||||
_unitsN->removeChangeListener(this);
|
||||
delete _font_renderer;
|
||||
delete _clip_box;
|
||||
|
||||
deque<Item *>::const_iterator it, end = _items.end();
|
||||
for (it = _items.begin(); it != end; ++it)
|
||||
delete *it;
|
||||
end = _ladders.end();
|
||||
for (it = _ladders.begin(); it != end; ++it)
|
||||
delete *it;
|
||||
|
||||
deinit();
|
||||
}
|
||||
|
||||
|
||||
|
@ -146,6 +140,27 @@ void HUD::init()
|
|||
_path->fireValueChanged();
|
||||
}
|
||||
|
||||
void HUD::deinit()
|
||||
{
|
||||
deque<Item *>::const_iterator it, end = _items.end();
|
||||
for (it = _items.begin(); it != end; ++it)
|
||||
delete *it;
|
||||
end = _ladders.end();
|
||||
for (it = _ladders.begin(); it != end; ++it)
|
||||
delete *it;
|
||||
|
||||
_items.clear();
|
||||
_ladders.clear();
|
||||
|
||||
delete _clip_box;
|
||||
_clip_box = NULL;
|
||||
}
|
||||
|
||||
void HUD::reinit()
|
||||
{
|
||||
deinit();
|
||||
_path->fireValueChanged();
|
||||
}
|
||||
|
||||
void HUD::update(double dt)
|
||||
{
|
||||
|
@ -186,27 +201,31 @@ void HUD::draw(osg::State&)
|
|||
|
||||
void HUD::draw3D()
|
||||
{
|
||||
using namespace osg;
|
||||
FGViewer* view = globals->get_current_view();
|
||||
|
||||
// Standard fgfs projection, with essentially meaningless clip
|
||||
// planes (we'll map the whole HUD plane to z=-1)
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
gluPerspective(view->get_v_fov(), 1.0 / view->get_aspect_ratio(), 0.1, 10);
|
||||
Matrixf proj
|
||||
= Matrixf::perspective(view->get_v_fov(), 1/view->get_aspect_ratio(),
|
||||
0.1, 10);
|
||||
glLoadMatrix(proj.ptr());
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
|
||||
// Standard fgfs view direction computation
|
||||
float lookat[3];
|
||||
Vec3f lookat;
|
||||
lookat[0] = -sin(SG_DEGREES_TO_RADIANS * view->getHeadingOffset_deg());
|
||||
lookat[1] = tan(SG_DEGREES_TO_RADIANS * view->getPitchOffset_deg());
|
||||
lookat[2] = -cos(SG_DEGREES_TO_RADIANS * view->getHeadingOffset_deg());
|
||||
if (fabs(lookat[1]) > 9999)
|
||||
lookat[1] = 9999; // FPU sanity
|
||||
gluLookAt(0, 0, 0, lookat[0], lookat[1], lookat[2], 0, 1, 0);
|
||||
Matrixf mv = Matrixf::lookAt(Vec3f(0.0, 0.0, 0.0), lookat,
|
||||
Vec3f(0.0, 1.0, 0.0));
|
||||
glLoadMatrix(mv.ptr());
|
||||
|
||||
// Map the -1:1 square to a 55.0x41.25 degree wide patch at z=1.
|
||||
// This is the default fgfs field of view, which the HUD files are
|
||||
|
@ -236,10 +255,11 @@ void HUD::draw3D()
|
|||
|
||||
void HUD::draw2D(GLfloat x_start, GLfloat y_start, GLfloat x_end, GLfloat y_end)
|
||||
{
|
||||
using namespace osg;
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
gluOrtho2D(x_start, x_end, y_start, y_end);
|
||||
Matrixf proj = Matrixf::ortho2D(x_start, x_end, y_start, y_end);
|
||||
glLoadMatrix(proj.ptr());
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
|
@ -323,8 +343,7 @@ int HUD::load(const char *file, float x, float y, int level, const string& inden
|
|||
const sgDebugPriority TREE = SG_INFO;
|
||||
const int MAXNEST = 10;
|
||||
|
||||
SGPath path(globals->get_fg_root());
|
||||
path.append(file);
|
||||
SGPath path(globals->resolve_maybe_aircraft_path(file));
|
||||
|
||||
if (!level) {
|
||||
SG_LOG(SG_INPUT, TREE, endl << "load " << file);
|
||||
|
|
|
@ -153,6 +153,8 @@ public:
|
|||
void init();
|
||||
void update(double);
|
||||
|
||||
void reinit();
|
||||
|
||||
// called from Main/renderer.cxx to draw 2D and 3D HUD
|
||||
void draw(osg::State&);
|
||||
|
||||
|
@ -195,6 +197,8 @@ protected:
|
|||
int level = 0, const std::string& indent = "");
|
||||
|
||||
private:
|
||||
void deinit();
|
||||
|
||||
void draw3D();
|
||||
void draw2D(GLfloat, GLfloat, GLfloat, GLfloat);
|
||||
|
||||
|
@ -595,7 +599,6 @@ private:
|
|||
double _default_heading;
|
||||
GLint _view[4];
|
||||
FGRunway* _runway;
|
||||
FGViewer* _cockpit_view;
|
||||
unsigned short _stipple_out; // stipple pattern of the outline of the runway
|
||||
unsigned short _stipple_center; // stipple pattern of the center line of the runway
|
||||
bool _draw_arrow; // draw arrow when runway is not visible in HUD
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
|
||||
#include <simgear/compiler.h>
|
||||
#include <simgear/math/sg_geodesy.hxx>
|
||||
#include <osg/GLU>
|
||||
#include <simgear/math/project.hxx>
|
||||
|
||||
#include <Main/globals.hxx>
|
||||
#include <Scenery/scenery.hxx>
|
||||
|
@ -49,7 +49,6 @@ HUD::Runway::Runway(HUD *hud, const SGPropertyNode *node, float x, float y) :
|
|||
_scale_dist(node->getDoubleValue("scale-dist-nm")),
|
||||
_default_pitch(fgGetDouble("/sim/view[0]/config/pitch-pitch-deg", 0.0)),
|
||||
_default_heading(fgGetDouble("/sim/view[0]/config/pitch-heading-deg", 0.0)),
|
||||
_cockpit_view(globals->get_viewmgr()->get_view(0)),
|
||||
_stipple_out(node->getIntValue("outer_stipple", 0xFFFF)),
|
||||
_stipple_center(node->getIntValue("center-stipple", 0xFFFF)),
|
||||
_draw_arrow(_arrow_scale > 0 ? true : false),
|
||||
|
@ -69,7 +68,6 @@ HUD::Runway::Runway(HUD *hud, const SGPropertyNode *node, float x, float y) :
|
|||
_top = _center_y + (_h / 2) + _y;
|
||||
}
|
||||
|
||||
|
||||
void HUD::Runway::draw()
|
||||
{
|
||||
_runway = get_active_runway();
|
||||
|
@ -87,17 +85,14 @@ void HUD::Runway::draw()
|
|||
double po = curr_view->getPitchOffset_deg();
|
||||
double ho = curr_view->getHeadingOffset_deg();
|
||||
|
||||
double yaw = -(_cockpit_view->getHeadingOffset_deg() - _default_heading) * SG_DEGREES_TO_RADIANS;
|
||||
double pitch = (_cockpit_view->getPitchOffset_deg() - _default_pitch) * SG_DEGREES_TO_RADIANS;
|
||||
FGViewer* cockpitView = globals->get_viewmgr()->get_view(0);
|
||||
|
||||
double yaw = -(cockpitView->getHeadingOffset_deg() - _default_heading) * SG_DEGREES_TO_RADIANS;
|
||||
double pitch = (cockpitView->getPitchOffset_deg() - _default_pitch) * SG_DEGREES_TO_RADIANS;
|
||||
//double roll = fgGetDouble("/sim/view[0]/config/roll-offset-deg",0.0) //TODO: adjust for default roll offset
|
||||
double sPitch = sin(pitch), cPitch = cos(pitch),
|
||||
sYaw = sin(yaw), cYaw = cos(yaw);
|
||||
|
||||
//Assuming that the "Cockpit View" is always at position zero!!!
|
||||
if (curr_view_id != 0) {
|
||||
globals->get_viewmgr()->set_view(0);
|
||||
globals->get_viewmgr()->copyToCurrent();
|
||||
}
|
||||
//Set the camera to the cockpit view to get the view of the runway from the cockpit
|
||||
// OSGFIXME
|
||||
// ssgSetCamera((sgVec4 *)_cockpit_view->get_VIEW());
|
||||
|
@ -129,8 +124,9 @@ void HUD::Runway::draw()
|
|||
//Calculate the 2D points via gluProject
|
||||
int result = GL_TRUE;
|
||||
for (int i = 0; i < 6; i++) {
|
||||
result = gluProject(_points3d[i][0], _points3d[i][1], _points3d[i][2], _mm,
|
||||
_pm, _view, &_points2d[i][0], &_points2d[i][1], &_points2d[i][2]);
|
||||
result = simgear::project(_points3d[i][0], _points3d[i][1], _points3d[i][2],
|
||||
_mm, _pm, _view,
|
||||
&_points2d[i][0], &_points2d[i][1], &_points2d[i][2]);
|
||||
}
|
||||
//set the line width based on our distance from the runway
|
||||
setLineWidth();
|
||||
|
@ -151,15 +147,6 @@ void HUD::Runway::draw()
|
|||
drawArrow(); //draw indication arrow
|
||||
}
|
||||
|
||||
//Restore the current view and any offsets
|
||||
if (curr_view_id != 0) {
|
||||
globals->get_viewmgr()->set_view(curr_view_id);
|
||||
globals->get_viewmgr()->copyToCurrent();
|
||||
curr_view->setHeadingOffset_deg(ho);
|
||||
curr_view->setPitchOffset_deg(po);
|
||||
curr_view->setGoalHeadingOffset_deg(gho);
|
||||
curr_view->setGoalPitchOffset_deg(gpo);
|
||||
}
|
||||
//Set the camera back to the current view
|
||||
// OSGFIXME
|
||||
// ssgSetCamera((sgVec4 *)curr_view);
|
||||
|
@ -229,7 +216,8 @@ bool HUD::Runway::drawLine(const sgdVec3& a1, const sgdVec3& a2, const sgdVec3&
|
|||
sgdVec3 newPt;
|
||||
sgdCopyVec3(newPt, a1);
|
||||
sgdAddVec3(newPt, vec);
|
||||
if (gluProject(newPt[0], newPt[1], newPt[2], _mm, _pm, _view, &p2[0], &p2[1], &p2[2])
|
||||
if (simgear::project(newPt[0], newPt[1], newPt[2], _mm, _pm, _view,
|
||||
&p2[0], &p2[1], &p2[2])
|
||||
&& (p2[2] > 0 && p2[2] < 1.0)) {
|
||||
boundPoint(p1, p2);
|
||||
glBegin(GL_LINES);
|
||||
|
@ -245,7 +233,8 @@ bool HUD::Runway::drawLine(const sgdVec3& a1, const sgdVec3& a2, const sgdVec3&
|
|||
sgdVec3 newPt;
|
||||
sgdCopyVec3(newPt, a2);
|
||||
sgdAddVec3(newPt, vec);
|
||||
if (gluProject(newPt[0], newPt[1], newPt[2], _mm, _pm, _view, &p1[0], &p1[1], &p1[2])
|
||||
if (simgear::project(newPt[0], newPt[1], newPt[2], _mm, _pm, _view,
|
||||
&p1[0], &p1[1], &p1[2])
|
||||
&& (p1[2] > 0 && p1[2] < 1.0)) {
|
||||
boundPoint(p2, p1);
|
||||
glBegin(GL_LINES);
|
||||
|
|
|
@ -31,7 +31,8 @@ libInstrumentation_a_SOURCES = \
|
|||
tacan.cxx tacan.hxx mk_viii.cxx mk_viii.hxx \
|
||||
dclgps.cxx dclgps.hxx \
|
||||
render_area_2d.cxx render_area_2d.hxx \
|
||||
groundradar.cxx groundradar.hxx \
|
||||
agradar.cxx agradar.hxx rad_alt.cxx rad_alt.hxx
|
||||
groundradar.cxx groundradar.hxx \
|
||||
agradar.cxx agradar.hxx rad_alt.cxx rad_alt.hxx \
|
||||
rnav_waypt_controller.cxx rnav_waypt_controller.hxx
|
||||
|
||||
INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/src -I$(top_builddir)/src
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
|
||||
#include "gps.hxx"
|
||||
|
||||
#include <boost/tuple/tuple.hpp>
|
||||
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <cstring>
|
||||
|
@ -17,6 +19,7 @@
|
|||
#include "Main/globals.hxx" // for get_subsystem
|
||||
#include "Main/util.hxx" // for fgLowPass
|
||||
#include "Navaids/positioned.hxx"
|
||||
#include <Navaids/waypoint.hxx>
|
||||
#include "Navaids/navrecord.hxx"
|
||||
#include "Airports/simple.hxx"
|
||||
#include "Airports/runways.hxx"
|
||||
|
@ -29,6 +32,7 @@
|
|||
|
||||
using std::auto_ptr;
|
||||
using std::string;
|
||||
using namespace flightgear;
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
|
@ -227,6 +231,9 @@ GPS::GPS ( SGPropertyNode *node) :
|
|||
string branch = "/instrumentation/" + _name;
|
||||
_gpsNode = fgGetNode(branch.c_str(), _num, true );
|
||||
_scratchNode = _gpsNode->getChild("scratch", 0, true);
|
||||
|
||||
SGPropertyNode *wp_node = _gpsNode->getChild("wp", 0, true);
|
||||
_currentWayptNode = wp_node->getChild("wp", 1, true);
|
||||
}
|
||||
|
||||
GPS::~GPS ()
|
||||
|
@ -255,17 +262,9 @@ GPS::init ()
|
|||
_northSouthVelocity = _gpsNode->getChild("ns-velocity-msec", 0, true);
|
||||
|
||||
// waypoints
|
||||
SGPropertyNode *wp_node = _gpsNode->getChild("wp", 0, true);
|
||||
SGPropertyNode *wp1_node = wp_node->getChild("wp", 1, true);
|
||||
|
||||
// for compatability, alias selected course down to wp/wp[1]/desired-course-deg
|
||||
SGPropertyNode* wp1Crs = wp1_node->getChild("desired-course-deg", 0, true);
|
||||
SGPropertyNode* wp1Crs = _currentWayptNode->getChild("desired-course-deg", 0, true);
|
||||
wp1Crs->alias(_gpsNode->getChild("desired-course-deg", 0, true));
|
||||
|
||||
// _true_wp1_bearing_error_node =
|
||||
// wp1_node->getChild("true-bearing-error-deg", 0, true);
|
||||
// _magnetic_wp1_bearing_error_node =
|
||||
// wp1_node->getChild("magnetic-bearing-error-deg", 0, true);
|
||||
|
||||
_tracking_bug_node = _gpsNode->getChild("tracking-bug", 0, true);
|
||||
|
||||
|
@ -299,10 +298,10 @@ GPS::init ()
|
|||
|
||||
// navradio slaving properties
|
||||
SGPropertyNode* toFlag = _gpsNode->getChild("to-flag", 0, true);
|
||||
toFlag->alias(wp1_node->getChild("to-flag"));
|
||||
toFlag->alias(_currentWayptNode->getChild("to-flag"));
|
||||
|
||||
SGPropertyNode* fromFlag = _gpsNode->getChild("from-flag", 0, true);
|
||||
fromFlag->alias(wp1_node->getChild("from-flag"));
|
||||
fromFlag->alias(_currentWayptNode->getChild("from-flag"));
|
||||
|
||||
// autopilot drive properties
|
||||
_apDrivingFlag = fgGetNode("/autopilot/settings/gps-driving-true-heading", true);
|
||||
|
@ -357,49 +356,39 @@ GPS::bind()
|
|||
tie(_scratchNode, "mag-bearing-deg", SGRawValueMethods<GPS, double>(*this, &GPS::getScratchMagBearing, NULL));
|
||||
tie(_scratchNode, "has-next", SGRawValueMethods<GPS, bool>(*this, &GPS::getScratchHasNext, NULL));
|
||||
_scratchValid = false;
|
||||
|
||||
// waypoint data (including various historical things)
|
||||
SGPropertyNode *wp_node = _gpsNode->getChild("wp", 0, true);
|
||||
SGPropertyNode *wp0_node = wp_node->getChild("wp", 0, true);
|
||||
SGPropertyNode *wp1_node = wp_node->getChild("wp", 1, true);
|
||||
|
||||
tieSGGeodReadOnly(wp0_node, _wp0_position, "longitude-deg", "latitude-deg", "altitude-ft");
|
||||
tie(wp0_node, "ID", SGRawValueMethods<GPS, const char*>
|
||||
(*this, &GPS::getWP0Ident, NULL));
|
||||
tie(wp0_node, "name", SGRawValueMethods<GPS, const char*>
|
||||
(*this, &GPS::getWP0Name, NULL));
|
||||
|
||||
tieSGGeodReadOnly(wp1_node, _wp1_position, "longitude-deg", "latitude-deg", "altitude-ft");
|
||||
tie(wp1_node, "ID", SGRawValueMethods<GPS, const char*>
|
||||
(*this, &GPS::getWP1Ident, NULL));
|
||||
tie(wp1_node, "name", SGRawValueMethods<GPS, const char*>
|
||||
(*this, &GPS::getWP1Name, NULL));
|
||||
|
||||
tie(wp1_node, "distance-nm", SGRawValueMethods<GPS, double>
|
||||
SGPropertyNode *wp_node = _gpsNode->getChild("wp", 0, true);
|
||||
SGPropertyNode* wp0_node = wp_node->getChild("wp", 0, true);
|
||||
|
||||
tieSGGeodReadOnly(wp0_node, _wp0_position, "longitude-deg", "latitude-deg", "altitude-ft");
|
||||
tie(_currentWayptNode, "ID", SGRawValueMethods<GPS, const char*>
|
||||
(*this, &GPS::getWP1Ident, NULL));
|
||||
|
||||
tie(_currentWayptNode, "distance-nm", SGRawValueMethods<GPS, double>
|
||||
(*this, &GPS::getWP1Distance, NULL));
|
||||
tie(wp1_node, "bearing-true-deg", SGRawValueMethods<GPS, double>
|
||||
tie(_currentWayptNode, "bearing-true-deg", SGRawValueMethods<GPS, double>
|
||||
(*this, &GPS::getWP1Bearing, NULL));
|
||||
tie(wp1_node, "bearing-mag-deg", SGRawValueMethods<GPS, double>
|
||||
tie(_currentWayptNode, "bearing-mag-deg", SGRawValueMethods<GPS, double>
|
||||
(*this, &GPS::getWP1MagBearing, NULL));
|
||||
tie(wp1_node, "TTW-sec", SGRawValueMethods<GPS, double>
|
||||
tie(_currentWayptNode, "TTW-sec", SGRawValueMethods<GPS, double>
|
||||
(*this, &GPS::getWP1TTW, NULL));
|
||||
tie(wp1_node, "TTW", SGRawValueMethods<GPS, const char*>
|
||||
tie(_currentWayptNode, "TTW", SGRawValueMethods<GPS, const char*>
|
||||
(*this, &GPS::getWP1TTWString, NULL));
|
||||
|
||||
tie(wp1_node, "course-deviation-deg", SGRawValueMethods<GPS, double>
|
||||
tie(_currentWayptNode, "course-deviation-deg", SGRawValueMethods<GPS, double>
|
||||
(*this, &GPS::getWP1CourseDeviation, NULL));
|
||||
tie(wp1_node, "course-error-nm", SGRawValueMethods<GPS, double>
|
||||
tie(_currentWayptNode, "course-error-nm", SGRawValueMethods<GPS, double>
|
||||
(*this, &GPS::getWP1CourseErrorNm, NULL));
|
||||
tie(wp1_node, "to-flag", SGRawValueMethods<GPS, bool>
|
||||
tie(_currentWayptNode, "to-flag", SGRawValueMethods<GPS, bool>
|
||||
(*this, &GPS::getWP1ToFlag, NULL));
|
||||
tie(wp1_node, "from-flag", SGRawValueMethods<GPS, bool>
|
||||
tie(_currentWayptNode, "from-flag", SGRawValueMethods<GPS, bool>
|
||||
(*this, &GPS::getWP1FromFlag, NULL));
|
||||
|
||||
// leg properties (only valid in DTO/LEG modes, not OBS)
|
||||
tie(wp_node, "leg-distance-nm", SGRawValueMethods<GPS, double>(*this, &GPS::getLegDistance, NULL));
|
||||
tie(wp_node, "leg-true-course-deg", SGRawValueMethods<GPS, double>(*this, &GPS::getLegCourse, NULL));
|
||||
tie(wp_node, "leg-mag-course-deg", SGRawValueMethods<GPS, double>(*this, &GPS::getLegMagCourse, NULL));
|
||||
tie(wp_node, "alt-dist-ratio", SGRawValueMethods<GPS, double>(*this, &GPS::getAltDistanceRatio, NULL));
|
||||
|
||||
// navradio slaving properties
|
||||
tie(_gpsNode, "cdi-deflection", SGRawValueMethods<GPS,double>
|
||||
|
@ -426,12 +415,11 @@ GPS::clearOutput()
|
|||
_last_vertical_speed = 0.0;
|
||||
_last_true_track = 0.0;
|
||||
_lastEWVelocity = _lastNSVelocity = 0.0;
|
||||
_currentWaypt = _prevWaypt = NULL;
|
||||
_legDistanceNm = -1.0;
|
||||
|
||||
_raim_node->setDoubleValue(0.0);
|
||||
_indicated_pos = SGGeod();
|
||||
_wp1DistanceM = 0.0;
|
||||
_wp1TrueBearing = 0.0;
|
||||
_wp1_position = SGGeod();
|
||||
_odometer_node->setDoubleValue(0);
|
||||
_trip_odometer_node->setDoubleValue(0);
|
||||
_tracking_bug_node->setDoubleValue(0);
|
||||
|
@ -455,61 +443,28 @@ GPS::update (double delta_time_sec)
|
|||
if (delta_time_sec <= 0.0) {
|
||||
return; // paused, don't bother
|
||||
}
|
||||
// TODO: Add noise and other errors.
|
||||
/*
|
||||
|
||||
// Bias and random error
|
||||
double random_factor = sg_random();
|
||||
double random_error = 1.4;
|
||||
double error_radius = 5.1;
|
||||
double bias_max_radius = 5.1;
|
||||
double random_max_radius = 1.4;
|
||||
|
||||
bias_length += (random_factor-0.5) * 1.0e-3;
|
||||
if (bias_length <= 0.0) bias_length = 0.0;
|
||||
else if (bias_length >= bias_max_radius) bias_length = bias_max_radius;
|
||||
bias_angle += (random_factor-0.5) * 1.0e-3;
|
||||
if (bias_angle <= 0.0) bias_angle = 0.0;
|
||||
else if (bias_angle >= 360.0) bias_angle = 360.0;
|
||||
|
||||
double random_length = random_factor * random_max_radius;
|
||||
double random_angle = random_factor * 360.0;
|
||||
|
||||
double bias_x = bias_length * cos(bias_angle * SG_PI / 180.0);
|
||||
double bias_y = bias_length * sin(bias_angle * SG_PI / 180.0);
|
||||
double random_x = random_length * cos(random_angle * SG_PI / 180.0);
|
||||
double random_y = random_length * sin(random_angle * SG_PI / 180.0);
|
||||
double error_x = bias_x + random_x;
|
||||
double error_y = bias_y + random_y;
|
||||
double error_length = sqrt(error_x*error_x + error_y*error_y);
|
||||
double error_angle = atan(error_y / error_x) * 180.0 / SG_PI;
|
||||
|
||||
double lat2;
|
||||
double lon2;
|
||||
double az2;
|
||||
geo_direct_wgs_84 ( altitude_m, latitude_deg,
|
||||
longitude_deg, error_angle,
|
||||
error_length, &lat2, &lon2,
|
||||
&az2 );
|
||||
//cout << lat2 << " " << lon2 << endl;
|
||||
printf("%f %f \n", bias_length, bias_angle);
|
||||
printf("%3.7f %3.7f \n", lat2, lon2);
|
||||
printf("%f %f \n", error_length, error_angle);
|
||||
|
||||
*/
|
||||
|
||||
_raim_node->setDoubleValue(1.0);
|
||||
_indicated_pos = _position.get();
|
||||
updateBasicData(delta_time_sec);
|
||||
|
||||
if (_dataValid) {
|
||||
if (_mode != "obs") {
|
||||
updateTurn();
|
||||
}
|
||||
if (_wayptController.get()) {
|
||||
_wayptController->update();
|
||||
SGGeod p(_wayptController->position());
|
||||
_currentWayptNode->setDoubleValue("longitude-deg", p.getLongitudeDeg());
|
||||
_currentWayptNode->setDoubleValue("latitude-deg", p.getLatitudeDeg());
|
||||
_currentWayptNode->setDoubleValue("altitude-ft", p.getElevationFt());
|
||||
|
||||
updateWaypoints();
|
||||
_desiredCourse = getLegMagCourse();
|
||||
|
||||
updateTurn();
|
||||
updateRouteData();
|
||||
}
|
||||
|
||||
|
||||
updateTrackingBug();
|
||||
updateReferenceNavaid(delta_time_sec);
|
||||
updateRouteData();
|
||||
driveAutopilot();
|
||||
}
|
||||
|
||||
|
@ -538,6 +493,49 @@ GPS::update (double delta_time_sec)
|
|||
_lastPosValid = true;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// implement the RNAV interface
|
||||
SGGeod GPS::position()
|
||||
{
|
||||
if (!_dataValid) {
|
||||
return SGGeod();
|
||||
}
|
||||
|
||||
return _indicated_pos;
|
||||
}
|
||||
|
||||
double GPS::trackDeg()
|
||||
{
|
||||
return _last_true_track;
|
||||
}
|
||||
|
||||
double GPS::groundSpeedKts()
|
||||
{
|
||||
return _last_speed_kts;
|
||||
}
|
||||
|
||||
double GPS::vspeedFPM()
|
||||
{
|
||||
return _last_vertical_speed;
|
||||
}
|
||||
|
||||
double GPS::magvarDeg()
|
||||
{
|
||||
return _magvar_node->getDoubleValue();
|
||||
}
|
||||
|
||||
double GPS::overflightArmDistanceM()
|
||||
{
|
||||
return _config.overflightArmDistanceNm() * SG_NM_TO_METER;
|
||||
}
|
||||
|
||||
double GPS::selectedMagCourse()
|
||||
{
|
||||
return _selectedCourse;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void
|
||||
GPS::updateBasicData(double dt)
|
||||
{
|
||||
|
@ -601,13 +599,6 @@ GPS::updateTrackingBug()
|
|||
_magnetic_bug_error_node->setDoubleValue(magnetic_bug_error);
|
||||
}
|
||||
|
||||
void
|
||||
GPS::updateWaypoints()
|
||||
{
|
||||
double az2;
|
||||
SGGeodesy::inverse(_indicated_pos, _wp1_position, _wp1TrueBearing, az2,_wp1DistanceM);
|
||||
}
|
||||
|
||||
void GPS::updateReferenceNavaid(double dt)
|
||||
{
|
||||
if (!_ref_navaid_set) {
|
||||
|
@ -690,7 +681,9 @@ void GPS::routeActivated()
|
|||
}
|
||||
} else if (_mode == "leg") {
|
||||
SG_LOG(SG_INSTR, SG_INFO, "GPS::route deactivated, switching to OBS mode");
|
||||
selectOBSMode();
|
||||
// select OBS mode, but keep current waypoint-as is
|
||||
_mode = "obs";
|
||||
wp1Changed();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -701,8 +694,8 @@ void GPS::routeManagerSequenced()
|
|||
return;
|
||||
}
|
||||
|
||||
int index = _routeMgr->currentWaypoint(),
|
||||
count = _routeMgr->size();
|
||||
int index = _routeMgr->currentIndex(),
|
||||
count = _routeMgr->numWaypts();
|
||||
if ((index < 0) || (index >= count)) {
|
||||
SG_LOG(SG_INSTR, SG_ALERT, "GPS: malformed route, index=" << index);
|
||||
return;
|
||||
|
@ -711,17 +704,15 @@ void GPS::routeManagerSequenced()
|
|||
SG_LOG(SG_INSTR, SG_INFO, "GPS waypoint index is now " << index);
|
||||
|
||||
if (index > 0) {
|
||||
SGWayPoint wp0(_routeMgr->get_waypoint(index - 1));
|
||||
_wp0Ident = wp0.get_id();
|
||||
_wp0Name = wp0.get_name();
|
||||
_wp0_position = wp0.get_target();
|
||||
|
||||
_prevWaypt = _routeMgr->previousWaypt();
|
||||
if (_prevWaypt->flag(WPT_DYNAMIC)) {
|
||||
_wp0_position = _indicated_pos;
|
||||
} else {
|
||||
_wp0_position = _prevWaypt->position();
|
||||
}
|
||||
}
|
||||
|
||||
SGWayPoint wp1(_routeMgr->get_waypoint(index));
|
||||
_wp1Ident = wp1.get_id();
|
||||
_wp1Name = wp1.get_name();
|
||||
_wp1_position = wp1.get_target();
|
||||
_currentWaypt = _routeMgr->currentWaypt();
|
||||
|
||||
_desiredCourse = getLegMagCourse();
|
||||
_desiredCourseNode->fireValueChanged();
|
||||
|
@ -745,8 +736,8 @@ void GPS::routeFinished()
|
|||
}
|
||||
|
||||
SG_LOG(SG_INSTR, SG_INFO, "GPS route finished, reverting to OBS");
|
||||
// select OBS mode, but keep current waypoint-as is
|
||||
_mode = "obs";
|
||||
_wp0_position = _indicated_pos;
|
||||
wp1Changed();
|
||||
}
|
||||
|
||||
|
@ -800,7 +791,7 @@ void GPS::updateTurn()
|
|||
double deviationNm = (distanceM * SG_METER_TO_NM) - _turnRadius;
|
||||
double deviationDeg = desiredCourse - getMagTrack();
|
||||
deviationNm = copysign(deviationNm, deviationDeg);
|
||||
// FXIME
|
||||
// FIXME
|
||||
//_wp1_course_deviation_node->setDoubleValue(deviationDeg);
|
||||
//_wp1_course_error_nm_node->setDoubleValue(deviationNm);
|
||||
//_cdiDeflectionNode->setDoubleValue(deviationDeg);
|
||||
|
@ -809,26 +800,29 @@ void GPS::updateTurn()
|
|||
|
||||
void GPS::updateOverflight()
|
||||
{
|
||||
if ((_wp1DistanceM * SG_METER_TO_NM) > _config.overflightArmDistanceNm()) {
|
||||
if (!_wayptController->isDone()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (getWP1ToFlag()) {
|
||||
return; // still heading towards the WP
|
||||
}
|
||||
|
||||
if (_mode == "dto") {
|
||||
SG_LOG(SG_INSTR, SG_INFO, "GPS DTO reached destination point");
|
||||
|
||||
// check for wp1 being on active route - resume leg mode
|
||||
if (_routeMgr->isRouteActive()) {
|
||||
int index = _routeMgr->findWaypoint(_wp1_position);
|
||||
int index = _routeMgr->findWayptIndex(_currentWaypt->position());
|
||||
if (index >= 0) {
|
||||
SG_LOG(SG_INSTR, SG_INFO, "GPS DTO, resuming LEG mode at wp:" << index);
|
||||
_mode = "leg";
|
||||
_routeMgr->jumpToIndex(index);
|
||||
}
|
||||
}
|
||||
|
||||
if (_mode == "dto") {
|
||||
// if we didn't enter leg mode, drop back to OBS mode
|
||||
// select OBS mode, but keep current waypoint-as is
|
||||
_mode = "obs";
|
||||
wp1Changed();
|
||||
}
|
||||
} else if (_mode == "leg") {
|
||||
SG_LOG(SG_INSTR, SG_INFO, "GPS doing overflight sequencing");
|
||||
_routeMgr->sequence();
|
||||
|
@ -867,8 +861,8 @@ void GPS::computeTurnData()
|
|||
return;
|
||||
}
|
||||
|
||||
int curIndex = _routeMgr->currentWaypoint();
|
||||
if ((curIndex + 1) >= _routeMgr->size()) {
|
||||
WayptRef next = _routeMgr->nextWaypt();
|
||||
if (!next || next->flag(WPT_DYNAMIC)) {
|
||||
_anticipateTurn = false;
|
||||
return;
|
||||
}
|
||||
|
@ -880,11 +874,9 @@ void GPS::computeTurnData()
|
|||
|
||||
_turnStartBearing = _desiredCourse;
|
||||
// compute next leg course
|
||||
SGWayPoint wp1(_routeMgr->get_waypoint(curIndex)),
|
||||
wp2(_routeMgr->get_waypoint(curIndex + 1));
|
||||
double crs, dist;
|
||||
wp2.CourseAndDistance(wp1, &crs, &dist);
|
||||
|
||||
boost::tie(crs, dist) = next->courseAndDistanceFrom(_currentWaypt->position());
|
||||
|
||||
|
||||
// compute offset bearing
|
||||
_turnAngle = crs - _turnStartBearing;
|
||||
|
@ -897,9 +889,9 @@ void GPS::computeTurnData()
|
|||
", out=" << crs << "; turnAngle=" << _turnAngle << ", median=" << median
|
||||
<< ", offset=" << offsetBearing);
|
||||
|
||||
SG_LOG(SG_INSTR, SG_INFO, "next leg is now:" << wp1.get_id() << "->" << wp2.get_id());
|
||||
SG_LOG(SG_INSTR, SG_INFO, "next leg is now:" << _currentWaypt->ident() << "->" << next->ident());
|
||||
|
||||
_turnPt = _wp1_position;
|
||||
_turnPt = _currentWaypt->position();
|
||||
_anticipateTurn = true;
|
||||
}
|
||||
|
||||
|
@ -945,10 +937,10 @@ double GPS::computeTurnRadiusNm(double aGroundSpeedKts) const
|
|||
|
||||
void GPS::updateRouteData()
|
||||
{
|
||||
double totalDistance = _wp1DistanceM * SG_METER_TO_NM;
|
||||
double totalDistance = _wayptController->distanceToWayptM() * SG_METER_TO_NM;
|
||||
// walk all waypoints from wp2 to route end, and sum
|
||||
for (int i=_routeMgr->currentWaypoint()+1; i<_routeMgr->size(); ++i) {
|
||||
totalDistance += _routeMgr->get_waypoint(i).get_distance();
|
||||
for (int i=_routeMgr->currentIndex()+1; i<_routeMgr->numWaypts(); ++i) {
|
||||
//totalDistance += _routeMgr->get_waypoint(i).get_distance();
|
||||
}
|
||||
|
||||
_routeDistanceNm->setDoubleValue(totalDistance * SG_METER_TO_NM);
|
||||
|
@ -979,13 +971,36 @@ void GPS::driveAutopilot()
|
|||
|
||||
void GPS::wp1Changed()
|
||||
{
|
||||
if (_mode == "leg") {
|
||||
_wayptController.reset(WayptController::createForWaypt(this, _currentWaypt));
|
||||
} else if (_mode == "obs") {
|
||||
_wayptController.reset(new OBSController(this, _currentWaypt));
|
||||
} else if (_mode == "dto") {
|
||||
_wayptController.reset(new DirectToController(this, _currentWaypt, _wp0_position));
|
||||
}
|
||||
|
||||
_wayptController->init();
|
||||
|
||||
if (_mode == "obs") {
|
||||
_legDistanceNm = -1.0;
|
||||
} else {
|
||||
_wayptController->update();
|
||||
_legDistanceNm = _wayptController->distanceToWayptM() * SG_METER_TO_NM;
|
||||
}
|
||||
|
||||
if (!_config.driveAutopilot()) {
|
||||
return;
|
||||
}
|
||||
|
||||
double altFt = _wp1_position.getElevationFt();
|
||||
if (altFt > -9990.0) {
|
||||
_apTargetAltitudeFt->setDoubleValue(altFt);
|
||||
RouteRestriction ar = _currentWaypt->altitudeRestriction();
|
||||
double restrictAlt = _currentWaypt->altitudeFt();
|
||||
double alt = _indicated_pos.getElevationFt();
|
||||
if ((ar == RESTRICT_AT) ||
|
||||
((ar == RESTRICT_ABOVE) && (alt < restrictAlt)) ||
|
||||
((ar == RESTRICT_BELOW) && (alt > restrictAlt)))
|
||||
{
|
||||
SG_LOG(SG_AUTOPILOT, SG_INFO, "current waypt has altitude set, setting on AP");
|
||||
_apTargetAltitudeFt->setDoubleValue(restrictAlt);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1011,16 +1026,16 @@ double GPS::getLegDistance() const
|
|||
return -1;
|
||||
}
|
||||
|
||||
return SGGeodesy::distanceNm(_wp0_position, _wp1_position);
|
||||
return _legDistanceNm;
|
||||
}
|
||||
|
||||
double GPS::getLegCourse() const
|
||||
{
|
||||
if (!_dataValid) {
|
||||
if (!_dataValid || !_wayptController.get()) {
|
||||
return -9999.0;
|
||||
}
|
||||
|
||||
return SGGeodesy::courseDeg(_wp0_position, _wp1_position);
|
||||
return _wayptController->targetTrackDeg();
|
||||
}
|
||||
|
||||
double GPS::getLegMagCourse() const
|
||||
|
@ -1034,21 +1049,6 @@ double GPS::getLegMagCourse() const
|
|||
return m;
|
||||
}
|
||||
|
||||
double GPS::getAltDistanceRatio() const
|
||||
{
|
||||
if (!_dataValid || (_mode == "obs")) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
double dist = SGGeodesy::distanceM(_wp0_position, _wp1_position);
|
||||
if ( dist <= 0.0 ) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
double alt_difference_m = _wp0_position.getElevationM() - _wp1_position.getElevationM();
|
||||
return alt_difference_m / dist;
|
||||
}
|
||||
|
||||
double GPS::getMagTrack() const
|
||||
{
|
||||
if (!_dataValid) {
|
||||
|
@ -1086,16 +1086,12 @@ const char* GPS::getWP0Ident() const
|
|||
return "";
|
||||
}
|
||||
|
||||
return _wp0Ident.c_str();
|
||||
return _prevWaypt->ident().c_str();
|
||||
}
|
||||
|
||||
const char* GPS::getWP0Name() const
|
||||
{
|
||||
if (!_dataValid || (_mode != "leg")) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return _wp0Name.c_str();
|
||||
return "";
|
||||
}
|
||||
|
||||
const char* GPS::getWP1Ident() const
|
||||
|
@ -1104,56 +1100,49 @@ const char* GPS::getWP1Ident() const
|
|||
return "";
|
||||
}
|
||||
|
||||
return _wp1Ident.c_str();
|
||||
return _currentWaypt->ident().c_str();
|
||||
}
|
||||
|
||||
const char* GPS::getWP1Name() const
|
||||
{
|
||||
if (!_dataValid) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return _wp1Name.c_str();
|
||||
return "";
|
||||
}
|
||||
|
||||
double GPS::getWP1Distance() const
|
||||
{
|
||||
if (!_dataValid) {
|
||||
if (!_dataValid || !_wayptController.get()) {
|
||||
return -1.0;
|
||||
}
|
||||
|
||||
return _wp1DistanceM * SG_METER_TO_NM;
|
||||
return _wayptController->distanceToWayptM() * SG_METER_TO_NM;
|
||||
}
|
||||
|
||||
double GPS::getWP1TTW() const
|
||||
{
|
||||
if (!_dataValid) {
|
||||
if (!_dataValid || !_wayptController.get()) {
|
||||
return -1.0;
|
||||
}
|
||||
|
||||
if (_last_speed_kts < 1.0) {
|
||||
return -1.0;
|
||||
}
|
||||
|
||||
return (getWP1Distance() / _last_speed_kts) * 3600.0;
|
||||
return _wayptController->timeToWaypt();
|
||||
}
|
||||
|
||||
const char* GPS::getWP1TTWString() const
|
||||
{
|
||||
if (!_dataValid) {
|
||||
double t = getWP1TTW();
|
||||
if (t <= 0.0) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return makeTTWString(getWP1TTW());
|
||||
return makeTTWString(t);
|
||||
}
|
||||
|
||||
double GPS::getWP1Bearing() const
|
||||
{
|
||||
if (!_dataValid) {
|
||||
if (!_dataValid || !_wayptController.get()) {
|
||||
return -9999.0;
|
||||
}
|
||||
|
||||
return _wp1TrueBearing;
|
||||
return _wayptController->trueBearingDeg();
|
||||
}
|
||||
|
||||
double GPS::getWP1MagBearing() const
|
||||
|
@ -1162,56 +1151,41 @@ double GPS::getWP1MagBearing() const
|
|||
return -9999.0;
|
||||
}
|
||||
|
||||
double magBearing = _wp1TrueBearing - _magvar_node->getDoubleValue();
|
||||
double magBearing = _wayptController->trueBearingDeg() - _magvar_node->getDoubleValue();
|
||||
SG_NORMALIZE_RANGE(magBearing, 0.0, 360.0);
|
||||
return magBearing;
|
||||
}
|
||||
|
||||
double GPS::getWP1CourseDeviation() const
|
||||
{
|
||||
if (!_dataValid) {
|
||||
if (!_dataValid || !_wayptController.get()) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
double dev = getWP1MagBearing() - _desiredCourse;
|
||||
SG_NORMALIZE_RANGE(dev, -180.0, 180.0);
|
||||
|
||||
if (fabs(dev) > 90.0) {
|
||||
// When the course is away from the waypoint,
|
||||
// it makes sense to change the sign of the deviation.
|
||||
dev *= -1.0;
|
||||
SG_NORMALIZE_RANGE(dev, -90.0, 90.0);
|
||||
}
|
||||
|
||||
return dev;
|
||||
|
||||
return _wayptController->courseDeviationDeg();
|
||||
}
|
||||
|
||||
double GPS::getWP1CourseErrorNm() const
|
||||
{
|
||||
if (!_dataValid) {
|
||||
if (!_dataValid || !_wayptController.get()) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
double radDev = getWP1CourseDeviation() * SG_DEGREES_TO_RADIANS;
|
||||
double course_error_m = sin(radDev) * _wp1DistanceM;
|
||||
return course_error_m * SG_METER_TO_NM;
|
||||
return _wayptController->xtrackErrorNm();
|
||||
}
|
||||
|
||||
bool GPS::getWP1ToFlag() const
|
||||
{
|
||||
if (!_dataValid) {
|
||||
if (!_dataValid || !_wayptController.get()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
double dev = getWP1MagBearing() - _desiredCourse;
|
||||
SG_NORMALIZE_RANGE(dev, -180.0, 180.0);
|
||||
|
||||
return (fabs(dev) < 90.0);
|
||||
return _wayptController->toFlag();
|
||||
}
|
||||
|
||||
bool GPS::getWP1FromFlag() const
|
||||
{
|
||||
if (!_dataValid) {
|
||||
if (!_dataValid || !_wayptController.get()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1278,9 +1252,9 @@ void GPS::setCommand(const char* aCmd)
|
|||
defineWaypoint();
|
||||
} else if (!strcmp(aCmd, "route-insert-before")) {
|
||||
int index = _scratchNode->getIntValue("index");
|
||||
if (index < 0 || (_routeMgr->size() == 0)) {
|
||||
index = _routeMgr->size();
|
||||
} else if (index >= _routeMgr->size()) {
|
||||
if (index < 0 || (_routeMgr->numWaypts() == 0)) {
|
||||
index = _routeMgr->numWaypts();
|
||||
} else if (index >= _routeMgr->numWaypts()) {
|
||||
SG_LOG(SG_INSTR, SG_WARN, "GPS:route-insert-before, bad index:" << index);
|
||||
return;
|
||||
}
|
||||
|
@ -1288,9 +1262,9 @@ void GPS::setCommand(const char* aCmd)
|
|||
insertWaypointAtIndex(index);
|
||||
} else if (!strcmp(aCmd, "route-insert-after")) {
|
||||
int index = _scratchNode->getIntValue("index");
|
||||
if (index < 0 || (_routeMgr->size() == 0)) {
|
||||
index = _routeMgr->size();
|
||||
} else if (index >= _routeMgr->size()) {
|
||||
if (index < 0 || (_routeMgr->numWaypts() == 0)) {
|
||||
index = _routeMgr->numWaypts();
|
||||
} else if (index >= _routeMgr->numWaypts()) {
|
||||
SG_LOG(SG_INSTR, SG_WARN, "GPS:route-insert-after, bad index:" << index);
|
||||
return;
|
||||
} else {
|
||||
|
@ -1301,8 +1275,8 @@ void GPS::setCommand(const char* aCmd)
|
|||
} else if (!strcmp(aCmd, "route-delete")) {
|
||||
int index = _scratchNode->getIntValue("index");
|
||||
if (index < 0) {
|
||||
index = _routeMgr->size();
|
||||
} else if (index >= _routeMgr->size()) {
|
||||
index = _routeMgr->numWaypts();
|
||||
} else if (index >= _routeMgr->numWaypts()) {
|
||||
SG_LOG(SG_INSTR, SG_WARN, "GPS:route-delete, bad index:" << index);
|
||||
return;
|
||||
}
|
||||
|
@ -1332,18 +1306,16 @@ bool GPS::isScratchPositionValid() const
|
|||
}
|
||||
|
||||
void GPS::directTo()
|
||||
{
|
||||
_wp0_position = _indicated_pos;
|
||||
|
||||
if (isScratchPositionValid()) {
|
||||
_wp1Ident = _scratchNode->getStringValue("ident");
|
||||
_wp1Name = _scratchNode->getStringValue("name");
|
||||
_wp1_position = _scratchPos;
|
||||
{
|
||||
if (!isScratchPositionValid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
_prevWaypt = NULL;
|
||||
_wp0_position = _indicated_pos;
|
||||
_currentWaypt = new BasicWaypt(_scratchPos, _scratchNode->getStringValue("ident"), NULL);
|
||||
_mode = "dto";
|
||||
_desiredCourse = getLegMagCourse();
|
||||
_desiredCourseNode->fireValueChanged();
|
||||
|
||||
clearScratch();
|
||||
wp1Changed();
|
||||
}
|
||||
|
@ -1359,8 +1331,8 @@ void GPS::loadRouteWaypoint()
|
|||
int index = _scratchNode->getIntValue("index", -9999);
|
||||
clearScratch();
|
||||
|
||||
if ((index < 0) || (index >= _routeMgr->size())) { // no index supplied, use current wp
|
||||
index = _routeMgr->currentWaypoint();
|
||||
if ((index < 0) || (index >= _routeMgr->numWaypts())) { // no index supplied, use current wp
|
||||
index = _routeMgr->currentIndex();
|
||||
}
|
||||
|
||||
_searchIsRoute = true;
|
||||
|
@ -1370,18 +1342,16 @@ void GPS::loadRouteWaypoint()
|
|||
void GPS::setScratchFromRouteWaypoint(int aIndex)
|
||||
{
|
||||
assert(_searchIsRoute);
|
||||
if ((aIndex < 0) || (aIndex >= _routeMgr->size())) {
|
||||
if ((aIndex < 0) || (aIndex >= _routeMgr->numWaypts())) {
|
||||
SG_LOG(SG_INSTR, SG_WARN, "GPS:setScratchFromRouteWaypoint: route-index out of bounds");
|
||||
return;
|
||||
}
|
||||
|
||||
_searchResultIndex = aIndex;
|
||||
SGWayPoint wp(_routeMgr->get_waypoint(aIndex));
|
||||
_scratchNode->setStringValue("name", wp.get_name());
|
||||
_scratchNode->setStringValue("ident", wp.get_id());
|
||||
_scratchPos = wp.get_target();
|
||||
WayptRef wp = _routeMgr->wayptAtIndex(aIndex);
|
||||
_scratchNode->setStringValue("ident", wp->ident());
|
||||
_scratchPos = wp->position();
|
||||
_scratchValid = true;
|
||||
_scratchNode->setDoubleValue("course", wp.get_track());
|
||||
_scratchNode->setIntValue("index", aIndex);
|
||||
}
|
||||
|
||||
|
@ -1476,9 +1446,9 @@ void GPS::search()
|
|||
|
||||
auto_ptr<FGPositioned::Filter> f(createFilter(_searchType));
|
||||
if (_searchNames) {
|
||||
_searchResults = FGPositioned::findAllWithName(_searchQuery, f.get());
|
||||
_searchResults = FGPositioned::findAllWithName(_searchQuery, f.get(), _searchExact);
|
||||
} else {
|
||||
_searchResults = FGPositioned::findAllWithIdent(_searchQuery, f.get());
|
||||
_searchResults = FGPositioned::findAllWithIdent(_searchQuery, f.get(), _searchExact);
|
||||
}
|
||||
|
||||
bool orderByRange = _scratchNode->getBoolValue("order-by-distance", true);
|
||||
|
@ -1498,7 +1468,7 @@ bool GPS::getScratchHasNext() const
|
|||
{
|
||||
int lastResult;
|
||||
if (_searchIsRoute) {
|
||||
lastResult = _routeMgr->size() - 1;
|
||||
lastResult = _routeMgr->numWaypts() - 1;
|
||||
} else {
|
||||
lastResult = (int) _searchResults.size() - 1;
|
||||
}
|
||||
|
@ -1584,14 +1554,14 @@ void GPS::addAirportToScratch(FGAirport* aAirport)
|
|||
|
||||
void GPS::selectOBSMode()
|
||||
{
|
||||
if (isScratchPositionValid()) {
|
||||
_wp1Ident = _scratchNode->getStringValue("ident");
|
||||
_wp1Name = _scratchNode->getStringValue("name");
|
||||
_wp1_position = _scratchPos;
|
||||
if (!isScratchPositionValid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
SG_LOG(SG_INSTR, SG_INFO, "GPS switching to OBS mode");
|
||||
_mode = "obs";
|
||||
|
||||
_currentWaypt = new BasicWaypt(_scratchPos, _scratchNode->getStringValue("ident"), NULL);
|
||||
_wp0_position = _indicated_pos;
|
||||
wp1Changed();
|
||||
}
|
||||
|
@ -1680,7 +1650,7 @@ void GPS::defineWaypoint()
|
|||
void GPS::insertWaypointAtIndex(int aIndex)
|
||||
{
|
||||
// note we do allow index = routeMgr->size(), that's an append
|
||||
if ((aIndex < 0) || (aIndex > _routeMgr->size())) {
|
||||
if ((aIndex < 0) || (aIndex > _routeMgr->numWaypts())) {
|
||||
throw sg_range_exception("GPS::insertWaypointAtIndex: index out of bounds");
|
||||
}
|
||||
|
||||
|
@ -1690,18 +1660,18 @@ void GPS::insertWaypointAtIndex(int aIndex)
|
|||
}
|
||||
|
||||
string ident = _scratchNode->getStringValue("ident");
|
||||
string name = _scratchNode->getStringValue("name");
|
||||
|
||||
_routeMgr->add_waypoint(SGWayPoint(_scratchPos, ident, name), aIndex);
|
||||
|
||||
WayptRef wpt = new BasicWaypt(_scratchPos, ident, NULL);
|
||||
_routeMgr->insertWayptAtIndex(wpt, aIndex);
|
||||
}
|
||||
|
||||
void GPS::removeWaypointAtIndex(int aIndex)
|
||||
{
|
||||
if ((aIndex < 0) || (aIndex >= _routeMgr->size())) {
|
||||
if ((aIndex < 0) || (aIndex >= _routeMgr->numWaypts())) {
|
||||
throw sg_range_exception("GPS::removeWaypointAtIndex: index out of bounds");
|
||||
}
|
||||
|
||||
_routeMgr->pop_waypoint(aIndex);
|
||||
_routeMgr->removeWayptAtIndex(aIndex);
|
||||
}
|
||||
|
||||
void GPS::tieSGGeod(SGPropertyNode* aNode, SGGeod& aRef,
|
||||
|
|
|
@ -8,12 +8,14 @@
|
|||
#define __INSTRUMENTS_GPS_HXX 1
|
||||
|
||||
#include <cassert>
|
||||
#include <memory>
|
||||
|
||||
#include <simgear/props/props.hxx>
|
||||
#include <simgear/structure/subsystem_mgr.hxx>
|
||||
#include <simgear/math/SGMath.hxx>
|
||||
|
||||
#include "Navaids/positioned.hxx"
|
||||
#include <Navaids/positioned.hxx>
|
||||
#include <Instrumentation/rnav_waypt_controller.hxx>
|
||||
|
||||
// forward decls
|
||||
class SGRoute;
|
||||
|
@ -73,20 +75,29 @@ private:
|
|||
* /instrumentation/gps/magnetic-bug-error-deg
|
||||
|
||||
*/
|
||||
class GPS : public SGSubsystem
|
||||
class GPS : public SGSubsystem, public flightgear::RNAV
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
GPS (SGPropertyNode *node);
|
||||
GPS ();
|
||||
virtual ~GPS ();
|
||||
|
||||
// SGSubsystem interface
|
||||
virtual void init ();
|
||||
virtual void update (double delta_time_sec);
|
||||
|
||||
virtual void bind();
|
||||
virtual void unbind();
|
||||
|
||||
// RNAV interface
|
||||
virtual SGGeod position();
|
||||
virtual double trackDeg();
|
||||
virtual double groundSpeedKts();
|
||||
virtual double vspeedFPM();
|
||||
virtual double magvarDeg();
|
||||
virtual double selectedMagCourse();
|
||||
virtual double overflightArmDistanceM();
|
||||
|
||||
private:
|
||||
friend class GPSListener;
|
||||
friend class SearchFilter;
|
||||
|
@ -188,7 +199,6 @@ private:
|
|||
void clearOutput();
|
||||
|
||||
void updateBasicData(double dt);
|
||||
void updateWaypoints();
|
||||
|
||||
void updateTrackingBug();
|
||||
void updateReferenceNavaid(double dt);
|
||||
|
@ -275,7 +285,6 @@ private:
|
|||
double getLegDistance() const;
|
||||
double getLegCourse() const;
|
||||
double getLegMagCourse() const;
|
||||
double getAltDistanceRatio() const;
|
||||
|
||||
double getTrueTrack() const { return _last_true_track; }
|
||||
double getMagTrack() const;
|
||||
|
@ -325,6 +334,7 @@ private:
|
|||
|
||||
// members
|
||||
SGPropertyNode_ptr _gpsNode;
|
||||
SGPropertyNode_ptr _currentWayptNode;
|
||||
SGPropertyNode_ptr _magvar_node;
|
||||
SGPropertyNode_ptr _serviceable_node;
|
||||
SGPropertyNode_ptr _electrical_node;
|
||||
|
@ -379,10 +389,8 @@ private:
|
|||
|
||||
SGGeodProperty _position;
|
||||
SGGeod _wp0_position;
|
||||
SGGeod _wp1_position;
|
||||
SGGeod _indicated_pos;
|
||||
std::string _wp0Ident, _wp0Name, _wp1Ident, _wp1Name;
|
||||
double _wp1DistanceM, _wp1TrueBearing;
|
||||
double _legDistanceNm;
|
||||
|
||||
// scratch data
|
||||
SGGeod _scratchPos;
|
||||
|
@ -410,7 +418,11 @@ private:
|
|||
SGGeod _turnPt;
|
||||
SGGeod _turnCentre;
|
||||
|
||||
std::auto_ptr<flightgear::WayptController> _wayptController;
|
||||
|
||||
SGPropertyNode_ptr _realismSimpleGps; ///< should the GPS be simple or realistic?
|
||||
flightgear::WayptRef _prevWaypt;
|
||||
flightgear::WayptRef _currentWaypt;
|
||||
|
||||
// autopilot drive properties
|
||||
SGPropertyNode_ptr _apDrivingFlag;
|
||||
|
|
|
@ -55,7 +55,8 @@ FGInstrumentMgr::FGInstrumentMgr () :
|
|||
_explicitGps(false)
|
||||
{
|
||||
set_subsystem("od_gauge", new FGODGauge);
|
||||
set_subsystem("hud", new HUD);
|
||||
|
||||
globals->add_subsystem("hud", new HUD, SGSubsystemMgr::DISPLAY);
|
||||
}
|
||||
|
||||
FGInstrumentMgr::~FGInstrumentMgr ()
|
||||
|
|
|
@ -362,6 +362,7 @@ MK_VIII::SystemHandler::update ()
|
|||
if (replay_state != last_replay_state)
|
||||
{
|
||||
mk->alert_handler.reposition();
|
||||
mk->io_handler.reposition();
|
||||
|
||||
last_replay_state = replay_state;
|
||||
state = STATE_REPOSITION;
|
||||
|
@ -1065,6 +1066,7 @@ MK_VIII::IOHandler::boot ()
|
|||
mk_doutput(glideslope_cancel) = power_saved.glideslope_cancel;
|
||||
|
||||
altitude_samples.clear();
|
||||
reset_terrain_clearance();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1364,6 +1366,12 @@ MK_VIII::IOHandler::reset_terrain_clearance ()
|
|||
update_terrain_clearance();
|
||||
}
|
||||
|
||||
void
|
||||
MK_VIII::IOHandler::reposition ()
|
||||
{
|
||||
reset_terrain_clearance();
|
||||
}
|
||||
|
||||
void
|
||||
MK_VIII::IOHandler::handle_input_fault (bool test, FaultHandler::Fault fault)
|
||||
{
|
||||
|
|
|
@ -609,6 +609,7 @@ public:
|
|||
void update_egpws_alert_discrete_2 ();
|
||||
void update_egpwc_alert_discrete_3 ();
|
||||
void update_outputs ();
|
||||
void reposition ();
|
||||
|
||||
void update_lamps ();
|
||||
void set_lamp (Lamp lamp);
|
||||
|
@ -639,7 +640,7 @@ public:
|
|||
|
||||
public:
|
||||
inline TerrainClearanceFilter ()
|
||||
: value(0) {}
|
||||
: value(0.0), last_update(-1.0) {}
|
||||
|
||||
double update (double agl);
|
||||
void reset ();
|
||||
|
|
|
@ -390,6 +390,7 @@ void FGNavRadio::clearOutputs()
|
|||
|
||||
_dmeInRange = false;
|
||||
_operable = false;
|
||||
_navaid = NULL;
|
||||
}
|
||||
|
||||
void FGNavRadio::updateReceiver(double dt)
|
||||
|
|
699
src/Instrumentation/rnav_waypt_controller.cxx
Normal file
699
src/Instrumentation/rnav_waypt_controller.cxx
Normal file
|
@ -0,0 +1,699 @@
|
|||
// rnav_waypt_controller.cxx - Waypoint-specific behaviours for RNAV systems
|
||||
// Written by James Turner, started 2009.
|
||||
//
|
||||
// Copyright (C) 2009 Curtis L. Olson
|
||||
//
|
||||
// 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
#include "rnav_waypt_controller.hxx"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include <simgear/sg_inlines.h>
|
||||
#include <simgear/structure/exception.hxx>
|
||||
|
||||
#include <Airports/runways.hxx>
|
||||
|
||||
namespace flightgear
|
||||
{
|
||||
|
||||
const double KNOTS_TO_METRES_PER_SECOND = SG_NM_TO_METER / 3600.0;
|
||||
|
||||
double pmod(double x, double y)
|
||||
{
|
||||
if (x < 0.0) {
|
||||
return -fmod(x, y);
|
||||
} else {
|
||||
return fmod(x,y);
|
||||
}
|
||||
}
|
||||
|
||||
// implementation of
|
||||
// http://williams.best.vwh.net/avform.htm#Intersection
|
||||
bool geocRadialIntersection(const SGGeoc& a, double r1, const SGGeoc& b, double r2, SGGeoc& result)
|
||||
{
|
||||
double crs13 = r1 * SG_DEGREES_TO_RADIANS;
|
||||
double crs23 = r2 * SG_DEGREES_TO_RADIANS;
|
||||
double dst12 = SGGeodesy::distanceRad(a, b);
|
||||
|
||||
//IF sin(lon2-lon1)<0
|
||||
// crs12=acos((sin(lat2)-sin(lat1)*cos(dst12))/(sin(dst12)*cos(lat1)))
|
||||
// crs21=2.*pi-acos((sin(lat1)-sin(lat2)*cos(dst12))/(sin(dst12)*cos(lat2)))
|
||||
// ELSE
|
||||
// crs12=2.*pi-acos((sin(lat2)-sin(lat1)*cos(dst12))/(sin(dst12)*cos(lat1)))
|
||||
// crs21=acos((sin(lat1)-sin(lat2)*cos(dst12))/(sin(dst12)*cos(lat2)))
|
||||
// ENDIF
|
||||
|
||||
|
||||
// double diffLon = b.getLongitudeRad() - a.getLongitudeRad();
|
||||
|
||||
double sinLat1 = sin(a.getLatitudeRad());
|
||||
double cosLat1 = cos(a.getLatitudeRad());
|
||||
// double sinLat2 = sin(b.getLatitudeRad());
|
||||
//double cosLat2 = cos(b.getLatitudeRad());
|
||||
double sinDst12 = sin(dst12);
|
||||
double cosDst12 = cos(dst12);
|
||||
|
||||
double crs12 = SGGeodesy::courseRad(a, b),
|
||||
crs21 = SGGeodesy::courseRad(b, a);
|
||||
|
||||
double degCrs12 = crs12 * SG_RADIANS_TO_DEGREES;
|
||||
double degCrs21 = crs21 * SG_RADIANS_TO_DEGREES;
|
||||
|
||||
/*
|
||||
if (sin(diffLon) < 0.0) {
|
||||
crs12 = acos((sinLat2 - sinLat1 * cosDst12) / (sinDst12 * cosLat1));
|
||||
crs21 = SGMiscd::twopi() - acos((sinLat1 - sinLat2*cosDst12)/(sinDst12*cosLat2));
|
||||
} else {
|
||||
crs12 = SGMiscd::twopi() - acos((sinLat2 - sinLat1 * cosDst12)/(sinDst12 * cosLat1));
|
||||
crs21 = acos((sinLat1 - sinLat2 * cosDst12)/(sinDst12 * cosLat2));
|
||||
}
|
||||
*/
|
||||
|
||||
double ang1 = SGMiscd::normalizeAngle2(crs13-crs12);
|
||||
double ang2 = SGMiscd::normalizeAngle2(crs21-crs23);
|
||||
|
||||
if ((sin(ang1) == 0.0) && (sin(ang2) == 0.0)) {
|
||||
SG_LOG(SG_GENERAL, SG_WARN, "geocRadialIntersection: infinity of intersections");
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((sin(ang1)*sin(ang2))<0.0) {
|
||||
SG_LOG(SG_GENERAL, SG_WARN, "geocRadialIntersection: intersection ambiguous");
|
||||
return false;
|
||||
}
|
||||
|
||||
ang1 = fabs(ang1);
|
||||
ang2 = fabs(ang2);
|
||||
|
||||
//ang3=acos(-cos(ang1)*cos(ang2)+sin(ang1)*sin(ang2)*cos(dst12))
|
||||
//dst13=atan2(sin(dst12)*sin(ang1)*sin(ang2),cos(ang2)+cos(ang1)*cos(ang3))
|
||||
//lat3=asin(sin(lat1)*cos(dst13)+cos(lat1)*sin(dst13)*cos(crs13))
|
||||
|
||||
//lon3=mod(lon1-dlon+pi,2*pi)-pi
|
||||
|
||||
double ang3 = acos(-cos(ang1) * cos(ang2) + sin(ang1) * sin(ang2) * cosDst12);
|
||||
double dst13 = atan2(sinDst12 * sin(ang1) * sin(ang2), cos(ang2) + cos(ang1)*cos(ang3));
|
||||
|
||||
SGGeoc pt3;
|
||||
SGGeodesy::advanceRadM(a, crs13, dst13 * SG_RAD_TO_NM * SG_NM_TO_METER, pt3);
|
||||
|
||||
double lat3 = asin(sinLat1 * cos(dst13) + cosLat1 * sin(dst13) * cos(crs13));
|
||||
|
||||
//dlon=atan2(sin(crs13)*sin(dst13)*cos(lat1),cos(dst13)-sin(lat1)*sin(lat3))
|
||||
double dlon = atan2(sin(crs13)*sin(dst13)*cosLat1, cos(dst13)- (sinLat1 * sin(lat3)));
|
||||
double lon3 = SGMiscd::normalizeAngle(-a.getLongitudeRad()-dlon);
|
||||
|
||||
result = SGGeoc::fromRadM(-lon3, lat3, a.getRadiusM());
|
||||
//result = pt3;
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
WayptController::~WayptController()
|
||||
{
|
||||
}
|
||||
|
||||
void WayptController::init()
|
||||
{
|
||||
}
|
||||
|
||||
void WayptController::setDone()
|
||||
{
|
||||
if (_isDone) {
|
||||
SG_LOG(SG_AUTOPILOT, SG_WARN, "already done @ WayptController::setDone");
|
||||
}
|
||||
|
||||
_isDone = true;
|
||||
}
|
||||
|
||||
double WayptController::timeToWaypt() const
|
||||
{
|
||||
double gs = _rnav->groundSpeedKts();
|
||||
if (gs < 1.0) {
|
||||
return -1.0; // stationary
|
||||
}
|
||||
|
||||
gs*= KNOTS_TO_METRES_PER_SECOND;
|
||||
return (distanceToWayptM() / gs);
|
||||
}
|
||||
|
||||
//////////////
|
||||
|
||||
class BasicWayptCtl : public WayptController
|
||||
{
|
||||
public:
|
||||
BasicWayptCtl(RNAV* aRNAV, const WayptRef& aWpt) :
|
||||
WayptController(aRNAV, aWpt)
|
||||
{
|
||||
if (aWpt->flag(WPT_DYNAMIC)) {
|
||||
throw sg_exception("BasicWayptCtrl doesn't work with dynamic waypoints");
|
||||
}
|
||||
}
|
||||
|
||||
virtual void init()
|
||||
{
|
||||
_targetTrack = SGGeodesy::courseDeg(_rnav->position(), _waypt->position());
|
||||
}
|
||||
|
||||
virtual void update()
|
||||
{
|
||||
double brg, az2;
|
||||
SGGeodesy::inverse(_rnav->position(), _waypt->position(), brg, az2, _distanceM);
|
||||
_courseDev = brg - _targetTrack;
|
||||
SG_NORMALIZE_RANGE(_courseDev, -180.0, 180.0);
|
||||
|
||||
if ((fabs(_courseDev) > 90.0) && (_distanceM < _rnav->overflightArmDistanceM())) {
|
||||
setDone();
|
||||
}
|
||||
}
|
||||
|
||||
virtual double distanceToWayptM() const
|
||||
{
|
||||
return _distanceM;
|
||||
}
|
||||
|
||||
virtual double xtrackErrorNm() const
|
||||
{
|
||||
double x = sin(courseDeviationDeg() * SG_DEGREES_TO_RADIANS) * _distanceM;
|
||||
return x * SG_METER_TO_NM;
|
||||
}
|
||||
|
||||
virtual bool toFlag() const
|
||||
{
|
||||
return (fabs(_courseDev) < 90.0);
|
||||
}
|
||||
|
||||
virtual double courseDeviationDeg() const
|
||||
{
|
||||
return _courseDev;
|
||||
}
|
||||
|
||||
virtual double trueBearingDeg() const
|
||||
{
|
||||
return SGGeodesy::courseDeg(_rnav->position(), _waypt->position());
|
||||
}
|
||||
|
||||
virtual SGGeod position() const
|
||||
{
|
||||
return _waypt->position();
|
||||
}
|
||||
|
||||
private:
|
||||
double _distanceM;
|
||||
double _courseDev;
|
||||
};
|
||||
|
||||
/**
|
||||
* Special controller for runways. For runways, we want very narrow deviation
|
||||
* contraints, and to understand that any point along the paved area is
|
||||
* equivalent to being 'at' the runway.
|
||||
*/
|
||||
class RunwayCtl : public WayptController
|
||||
{
|
||||
public:
|
||||
RunwayCtl(RNAV* aRNAV, const WayptRef& aWpt) :
|
||||
WayptController(aRNAV, aWpt)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void init()
|
||||
{
|
||||
_runway = static_cast<RunwayWaypt*>(_waypt.get())->runway();
|
||||
_targetTrack = _runway->headingDeg();
|
||||
}
|
||||
|
||||
virtual void update()
|
||||
{
|
||||
double brg, az2;
|
||||
// use the far end of the runway for course deviation calculations.
|
||||
// this should do the correct thing both for takeoffs (including entering
|
||||
// the runway at a taxiway after the threshold) and also landings.
|
||||
// seperately compute the distance to the threshold for timeToWaypt calc
|
||||
SGGeodesy::inverse(_rnav->position(), _runway->end(), brg, az2, _distanceM);
|
||||
double _courseDev = brg - _targetTrack;
|
||||
SG_NORMALIZE_RANGE(_courseDev, -180.0, 180.0);
|
||||
|
||||
if (fabs(_courseDev) > 90.0) {
|
||||
setDone();
|
||||
}
|
||||
}
|
||||
|
||||
virtual double distanceToWayptM() const
|
||||
{
|
||||
return SGGeodesy::distanceM(_rnav->position(), _runway->threshold());
|
||||
}
|
||||
|
||||
virtual double xtrackErrorNm() const
|
||||
{
|
||||
double x = sin(_courseDev * SG_RADIANS_TO_DEGREES) * _distanceM;
|
||||
return x * SG_METER_TO_NM;
|
||||
}
|
||||
|
||||
virtual double courseDeviationDeg() const
|
||||
{
|
||||
return _courseDev;
|
||||
}
|
||||
|
||||
virtual double trueBearingDeg() const
|
||||
{
|
||||
// as in update(), use runway->end here, so the value remains
|
||||
// sensible whether taking off or landing.
|
||||
return SGGeodesy::courseDeg(_rnav->position(), _runway->end());
|
||||
}
|
||||
|
||||
virtual SGGeod position() const
|
||||
{
|
||||
return _runway->threshold();
|
||||
}
|
||||
private:
|
||||
FGRunway* _runway;
|
||||
double _distanceM;
|
||||
double _courseDev;
|
||||
};
|
||||
|
||||
class ConstHdgToAltCtl : public WayptController
|
||||
{
|
||||
public:
|
||||
ConstHdgToAltCtl(RNAV* aRNAV, const WayptRef& aWpt) :
|
||||
WayptController(aRNAV, aWpt)
|
||||
|
||||
{
|
||||
if (_waypt->type() != "hdgToAlt") {
|
||||
throw sg_exception("invalid waypoint type", "ConstHdgToAltCtl ctor");
|
||||
}
|
||||
|
||||
if (_waypt->altitudeRestriction() == RESTRICT_NONE) {
|
||||
throw sg_exception("invalid waypoint alt restriction", "ConstHdgToAltCtl ctor");
|
||||
}
|
||||
}
|
||||
|
||||
virtual void init()
|
||||
{
|
||||
HeadingToAltitude* w = (HeadingToAltitude*) _waypt.get();
|
||||
_targetTrack = w->headingDegMagnetic() + _rnav->magvarDeg();
|
||||
}
|
||||
|
||||
virtual void update()
|
||||
{
|
||||
double curAlt = _rnav->position().getElevationFt();
|
||||
|
||||
switch (_waypt->altitudeRestriction()) {
|
||||
case RESTRICT_AT: {
|
||||
double d = curAlt - _waypt->altitudeFt();
|
||||
if (fabs(d) < 50.0) {
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "ConstHdgToAltCtl, reached target altitude " << _waypt->altitudeFt());
|
||||
setDone();
|
||||
}
|
||||
} break;
|
||||
|
||||
case RESTRICT_ABOVE:
|
||||
if (curAlt >= _waypt->altitudeFt()) {
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "ConstHdgToAltCtl, above target altitude " << _waypt->altitudeFt());
|
||||
setDone();
|
||||
}
|
||||
break;
|
||||
|
||||
case RESTRICT_BELOW:
|
||||
if (curAlt <= _waypt->altitudeFt()) {
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "ConstHdgToAltCtl, below target altitude " << _waypt->altitudeFt());
|
||||
setDone();
|
||||
}
|
||||
break;
|
||||
|
||||
case RESTRICT_NONE:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
virtual double timeToWaypt() const
|
||||
{
|
||||
double d = fabs(_rnav->position().getElevationFt() - _waypt->altitudeFt());
|
||||
return (d / _rnav->vspeedFPM()) * 60.0; // low pass filter here, probably
|
||||
}
|
||||
|
||||
virtual double distanceToWayptM() const
|
||||
{
|
||||
double gsMsec = _rnav->groundSpeedKts() * KNOTS_TO_METRES_PER_SECOND;
|
||||
return timeToWaypt() * gsMsec;
|
||||
}
|
||||
|
||||
virtual SGGeod position() const
|
||||
{
|
||||
SGGeod p;
|
||||
double az2;
|
||||
SGGeodesy::direct(_rnav->position(), _targetTrack, distanceToWayptM(), p, az2);
|
||||
return p;
|
||||
}
|
||||
};
|
||||
|
||||
class InterceptCtl : public WayptController
|
||||
{
|
||||
public:
|
||||
InterceptCtl(RNAV* aRNAV, const WayptRef& aWpt) :
|
||||
WayptController(aRNAV, aWpt)
|
||||
|
||||
{
|
||||
if (_waypt->type() != "radialIntercept") {
|
||||
throw sg_exception("invalid waypoint type", "InterceptCtl ctor");
|
||||
}
|
||||
}
|
||||
|
||||
virtual void init()
|
||||
{
|
||||
RadialIntercept* w = (RadialIntercept*) _waypt.get();
|
||||
_trueRadial = w->radialDegMagnetic() + _rnav->magvarDeg();
|
||||
_targetTrack = w->courseDegMagnetic() + _rnav->magvarDeg();
|
||||
}
|
||||
|
||||
virtual void update()
|
||||
{
|
||||
// note we want the outbound radial from the waypt, hence the ordering
|
||||
// of arguments to courseDeg
|
||||
double r = SGGeodesy::courseDeg(_waypt->position(), _rnav->position());
|
||||
SG_LOG(SG_AUTOPILOT, SG_INFO, "current radial=" << r);
|
||||
if (fabs(r - _trueRadial) < 0.5) {
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "InterceptCtl, intercepted radial " << _trueRadial);
|
||||
setDone();
|
||||
}
|
||||
}
|
||||
|
||||
virtual double distanceToWayptM() const
|
||||
{
|
||||
return SGGeodesy::distanceM(_rnav->position(), position());
|
||||
}
|
||||
|
||||
virtual SGGeod position() const
|
||||
{
|
||||
SGGeoc c;
|
||||
geocRadialIntersection(SGGeoc::fromGeod(_rnav->position()), _rnav->trackDeg(),
|
||||
SGGeoc::fromGeod(_waypt->position()), _trueRadial, c);
|
||||
return SGGeod::fromGeoc(c);
|
||||
}
|
||||
private:
|
||||
double _trueRadial;
|
||||
};
|
||||
|
||||
class DMEInterceptCtl : public WayptController
|
||||
{
|
||||
public:
|
||||
DMEInterceptCtl(RNAV* aRNAV, const WayptRef& aWpt) :
|
||||
WayptController(aRNAV, aWpt)
|
||||
|
||||
{
|
||||
if (_waypt->type() != "dmeIntercept") {
|
||||
throw sg_exception("invalid waypoint type", "DMEInterceptCtl ctor");
|
||||
}
|
||||
}
|
||||
|
||||
virtual void init()
|
||||
{
|
||||
_dme = (DMEIntercept*) _waypt.get();
|
||||
_targetTrack = _dme->courseDegMagnetic() + _rnav->magvarDeg();
|
||||
}
|
||||
|
||||
virtual void update()
|
||||
{
|
||||
_distanceNm = SGGeodesy::distanceNm(_rnav->position(), _dme->position());
|
||||
double d = fabs(_distanceNm - _dme->dmeDistanceNm());
|
||||
if (d < 0.1) {
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "DMEInterceptCtl, intercepted DME " << _dme->dmeDistanceNm());
|
||||
setDone();
|
||||
}
|
||||
}
|
||||
|
||||
virtual double distanceToWayptM() const
|
||||
{
|
||||
return fabs(_distanceNm - _dme->dmeDistanceNm()) * SG_NM_TO_METER;
|
||||
}
|
||||
|
||||
virtual SGGeod position() const
|
||||
{
|
||||
SGGeod p;
|
||||
double az2;
|
||||
SGGeodesy::direct(_rnav->position(), _targetTrack, distanceToWayptM(), p, az2);
|
||||
return p;
|
||||
}
|
||||
|
||||
private:
|
||||
DMEIntercept* _dme;
|
||||
double _distanceNm;
|
||||
};
|
||||
|
||||
class HoldCtl : public WayptController
|
||||
{
|
||||
public:
|
||||
HoldCtl(RNAV* aRNAV, const WayptRef& aWpt) :
|
||||
WayptController(aRNAV, aWpt)
|
||||
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
virtual void init()
|
||||
{
|
||||
}
|
||||
|
||||
virtual void update()
|
||||
{
|
||||
// fly inbound / outbound sides, or execute the turn
|
||||
#if 0
|
||||
if (inTurn) {
|
||||
|
||||
targetTrack += dt * turnRateSec * turnDirection;
|
||||
if (inbound) {
|
||||
if .. targetTrack has passed inbound radial, doen with this turn
|
||||
} else {
|
||||
if target track has passed reciprocal radial done with turn
|
||||
}
|
||||
} else {
|
||||
check time / distance elapsed
|
||||
|
||||
if (sideDone) {
|
||||
inTurn = true;
|
||||
inbound = !inbound;
|
||||
nextHeading = inbound;
|
||||
if (!inbound) {
|
||||
nextHeading += 180.0;
|
||||
SG_NORMALIZE_RANGE(nextHeading, 0.0, 360.0);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
setDone();
|
||||
}
|
||||
|
||||
virtual double distanceToWayptM() const
|
||||
{
|
||||
return -1.0;
|
||||
}
|
||||
|
||||
virtual SGGeod position() const
|
||||
{
|
||||
return _waypt->position();
|
||||
}
|
||||
};
|
||||
|
||||
class VectorsCtl : public WayptController
|
||||
{
|
||||
public:
|
||||
VectorsCtl(RNAV* aRNAV, const WayptRef& aWpt) :
|
||||
WayptController(aRNAV, aWpt)
|
||||
|
||||
{
|
||||
}
|
||||
|
||||
virtual void init()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
virtual void update()
|
||||
{
|
||||
setDone();
|
||||
}
|
||||
|
||||
virtual double distanceToWayptM() const
|
||||
{
|
||||
return -1.0;
|
||||
}
|
||||
|
||||
virtual SGGeod position() const
|
||||
{
|
||||
return _waypt->position();
|
||||
}
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DirectToController::DirectToController(RNAV* aRNAV, const WayptRef& aWpt, const SGGeod& aOrigin) :
|
||||
WayptController(aRNAV, aWpt),
|
||||
_origin(aOrigin)
|
||||
{
|
||||
}
|
||||
|
||||
void DirectToController::init()
|
||||
{
|
||||
if (_waypt->flag(WPT_DYNAMIC)) {
|
||||
throw sg_exception("can't direct-to a dynamic waypoint");
|
||||
}
|
||||
|
||||
_targetTrack = SGGeodesy::courseDeg(_origin, _waypt->position());
|
||||
}
|
||||
|
||||
void DirectToController::update()
|
||||
{
|
||||
double brg, az2;
|
||||
SGGeodesy::inverse(_rnav->position(), _waypt->position(), brg, az2, _distanceM);
|
||||
_courseDev = brg - _targetTrack;
|
||||
SG_NORMALIZE_RANGE(_courseDev, -180.0, 180.0);
|
||||
|
||||
if ((fabs(_courseDev) > 90.0) && (_distanceM < _rnav->overflightArmDistanceM())) {
|
||||
setDone();
|
||||
}
|
||||
}
|
||||
|
||||
double DirectToController::distanceToWayptM() const
|
||||
{
|
||||
return _distanceM;
|
||||
}
|
||||
|
||||
double DirectToController::xtrackErrorNm() const
|
||||
{
|
||||
double x = sin(courseDeviationDeg() * SG_DEGREES_TO_RADIANS) * _distanceM;
|
||||
return x * SG_METER_TO_NM;
|
||||
}
|
||||
|
||||
double DirectToController::courseDeviationDeg() const
|
||||
{
|
||||
return _courseDev;
|
||||
}
|
||||
|
||||
double DirectToController::trueBearingDeg() const
|
||||
{
|
||||
return SGGeodesy::courseDeg(_rnav->position(), _waypt->position());
|
||||
}
|
||||
|
||||
SGGeod DirectToController::position() const
|
||||
{
|
||||
return _waypt->position();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
OBSController::OBSController(RNAV* aRNAV, const WayptRef& aWpt) :
|
||||
WayptController(aRNAV, aWpt)
|
||||
{
|
||||
}
|
||||
|
||||
void OBSController::init()
|
||||
{
|
||||
if (_waypt->flag(WPT_DYNAMIC)) {
|
||||
throw sg_exception("can't use a dynamic waypoint for OBS mode");
|
||||
}
|
||||
|
||||
_targetTrack = _rnav->selectedMagCourse() + _rnav->magvarDeg();
|
||||
}
|
||||
|
||||
void OBSController::update()
|
||||
{
|
||||
_targetTrack = _rnav->selectedMagCourse() + _rnav->magvarDeg();
|
||||
double brg, az2;
|
||||
SGGeodesy::inverse(_rnav->position(), _waypt->position(), brg, az2, _distanceM);
|
||||
_courseDev = brg - _targetTrack;
|
||||
SG_NORMALIZE_RANGE(_courseDev, -180.0, 180.0);
|
||||
}
|
||||
|
||||
bool OBSController::toFlag() const
|
||||
{
|
||||
return (fabs(_courseDev) < 90.0);
|
||||
}
|
||||
|
||||
double OBSController::distanceToWayptM() const
|
||||
{
|
||||
return _distanceM;
|
||||
}
|
||||
|
||||
double OBSController::xtrackErrorNm() const
|
||||
{
|
||||
double x = sin(_courseDev * SG_DEGREES_TO_RADIANS) * _distanceM;
|
||||
return x * SG_METER_TO_NM;
|
||||
}
|
||||
|
||||
double OBSController::courseDeviationDeg() const
|
||||
{
|
||||
// if (fabs(_courseDev) > 90.0) {
|
||||
// double d = -_courseDev;
|
||||
// SG_NORMALIZE_RANGE(d, -90.0, 90.0);
|
||||
// return d;
|
||||
//}
|
||||
|
||||
return _courseDev;
|
||||
}
|
||||
|
||||
double OBSController::trueBearingDeg() const
|
||||
{
|
||||
return SGGeodesy::courseDeg(_rnav->position(), _waypt->position());
|
||||
}
|
||||
|
||||
SGGeod OBSController::position() const
|
||||
{
|
||||
return _waypt->position();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
WayptController* WayptController::createForWaypt(RNAV* aRNAV, const WayptRef& aWpt)
|
||||
{
|
||||
if (!aWpt) {
|
||||
throw sg_exception("Passed null waypt", "WayptController::createForWaypt");
|
||||
}
|
||||
|
||||
const std::string& wty(aWpt->type());
|
||||
if (wty == "runway") {
|
||||
return new RunwayCtl(aRNAV, aWpt);
|
||||
}
|
||||
|
||||
if (wty == "radialIntercept") {
|
||||
return new InterceptCtl(aRNAV, aWpt);
|
||||
}
|
||||
|
||||
if (wty == "dmeIntercept") {
|
||||
return new DMEInterceptCtl(aRNAV, aWpt);
|
||||
}
|
||||
|
||||
if (wty == "hdgToAlt") {
|
||||
return new ConstHdgToAltCtl(aRNAV, aWpt);
|
||||
}
|
||||
|
||||
if (wty == "vectors") {
|
||||
return new VectorsCtl(aRNAV, aWpt);
|
||||
}
|
||||
|
||||
if (wty == "hold") {
|
||||
return new HoldCtl(aRNAV, aWpt);
|
||||
}
|
||||
|
||||
return new BasicWayptCtl(aRNAV, aWpt);
|
||||
}
|
||||
|
||||
} // of namespace flightgear
|
||||
|
193
src/Instrumentation/rnav_waypt_controller.hxx
Normal file
193
src/Instrumentation/rnav_waypt_controller.hxx
Normal file
|
@ -0,0 +1,193 @@
|
|||
// rnav_waypt_controller.hxx - Waypoint-specific behaviours for RNAV systems
|
||||
// Written by James Turner, started 2009.
|
||||
//
|
||||
// Copyright (C) 2009 Curtis L. Olson
|
||||
//
|
||||
// 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
#ifndef FG_WAYPT_CONTROLLER_HXX
|
||||
#define FG_WAYPT_CONTROLLER_HXX
|
||||
|
||||
#include <Navaids/waypoint.hxx>
|
||||
|
||||
namespace flightgear
|
||||
{
|
||||
|
||||
/**
|
||||
* Abstract RNAV interface, for devices which implement an RNAV
|
||||
* system - INS / GPS / FMS
|
||||
*/
|
||||
class RNAV
|
||||
{
|
||||
public:
|
||||
virtual SGGeod position() = 0;
|
||||
|
||||
/**
|
||||
* True track in degrees
|
||||
*/
|
||||
virtual double trackDeg() = 0;
|
||||
|
||||
/**
|
||||
* Ground speed (along the track) in knots
|
||||
*/
|
||||
virtual double groundSpeedKts() = 0;
|
||||
|
||||
/**
|
||||
* Vertical speed in ft/minute
|
||||
*/
|
||||
virtual double vspeedFPM()= 0;
|
||||
|
||||
/**
|
||||
* Magnetic variation at current position
|
||||
*/
|
||||
virtual double magvarDeg() = 0;
|
||||
|
||||
/**
|
||||
* device selected course (eg, from autopilot / MCP / OBS) in degrees
|
||||
*/
|
||||
virtual double selectedMagCourse() = 0;
|
||||
|
||||
/**
|
||||
* minimum distance to a waypoint for overflight sequencing.
|
||||
*/
|
||||
virtual double overflightArmDistanceM() = 0;
|
||||
};
|
||||
|
||||
class WayptController
|
||||
{
|
||||
public:
|
||||
virtual ~WayptController();
|
||||
|
||||
virtual void init();
|
||||
|
||||
virtual void update() = 0;
|
||||
|
||||
/**
|
||||
* Compute time until the waypoint is done
|
||||
*/
|
||||
virtual double timeToWaypt() const;
|
||||
|
||||
/**
|
||||
* Compute distance until the waypoint is done
|
||||
*/
|
||||
virtual double distanceToWayptM() const = 0;
|
||||
|
||||
/**
|
||||
* Bearing to the waypoint, if this value is meaningful.
|
||||
* Default implementation returns the target track
|
||||
*/
|
||||
virtual double trueBearingDeg() const
|
||||
{ return _targetTrack; }
|
||||
|
||||
virtual double targetTrackDeg() const
|
||||
{ return _targetTrack; }
|
||||
|
||||
virtual double xtrackErrorNm() const
|
||||
{ return 0.0; }
|
||||
|
||||
virtual double courseDeviationDeg() const
|
||||
{ return 0.0; }
|
||||
|
||||
/**
|
||||
* Position associated with the waypt. For static waypoints, this is
|
||||
* simply the waypoint position itself; for dynamic points, it's the
|
||||
* estimated location at which the controller will be done.
|
||||
*/
|
||||
virtual SGGeod position() const = 0;
|
||||
|
||||
/**
|
||||
* Is this controller finished?
|
||||
*/
|
||||
bool isDone() const
|
||||
{ return _isDone; }
|
||||
|
||||
/**
|
||||
* to/from flag - true = to, false = from. Defaults to 'true' because
|
||||
* nearly all waypoint controllers become done as soon as this value would
|
||||
* become false.
|
||||
*/
|
||||
virtual bool toFlag() const
|
||||
{ return true; }
|
||||
|
||||
/**
|
||||
* Static factory method, given a waypoint, return a controller bound
|
||||
* to it, of the appropriate type
|
||||
*/
|
||||
static WayptController* createForWaypt(RNAV* rnav, const WayptRef& aWpt);
|
||||
protected:
|
||||
WayptController(RNAV* aRNAV, const WayptRef& aWpt) :
|
||||
_waypt(aWpt),
|
||||
_rnav(aRNAV),
|
||||
_isDone(false)
|
||||
{ }
|
||||
|
||||
WayptRef _waypt;
|
||||
double _targetTrack;
|
||||
RNAV* _rnav;
|
||||
|
||||
void setDone();
|
||||
private:
|
||||
bool _isDone;
|
||||
};
|
||||
|
||||
/**
|
||||
* Controller supports 'directTo' (DTO) navigation to a waypoint. This
|
||||
* creates a course from a starting point, to the waypoint, and reports
|
||||
* deviation from that course.
|
||||
*
|
||||
* The controller is done when the waypoint is reached (to/from goes to 'from')
|
||||
*/
|
||||
class DirectToController : public WayptController
|
||||
{
|
||||
public:
|
||||
DirectToController(RNAV* aRNAV, const WayptRef& aWpt, const SGGeod& aOrigin);
|
||||
|
||||
virtual void init();
|
||||
virtual void update();
|
||||
virtual double distanceToWayptM() const;
|
||||
virtual double xtrackErrorNm() const;
|
||||
virtual double courseDeviationDeg() const;
|
||||
virtual double trueBearingDeg() const;
|
||||
virtual SGGeod position() const;
|
||||
private:
|
||||
SGGeod _origin;
|
||||
double _distanceM;
|
||||
double _courseDev;
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class OBSController : public WayptController
|
||||
{
|
||||
public:
|
||||
OBSController(RNAV* aRNAV, const WayptRef& aWpt);
|
||||
|
||||
virtual void init();
|
||||
virtual void update();
|
||||
virtual double distanceToWayptM() const;
|
||||
virtual double xtrackErrorNm() const;
|
||||
virtual double courseDeviationDeg() const;
|
||||
virtual double trueBearingDeg() const;
|
||||
virtual bool toFlag() const;
|
||||
virtual SGGeod position() const;
|
||||
private:
|
||||
double _distanceM;
|
||||
double _courseDev;
|
||||
};
|
||||
|
||||
} // of namespace flightgear
|
||||
|
||||
#endif
|
|
@ -1,4 +1,9 @@
|
|||
|
||||
#include <fstream>
|
||||
|
||||
#include <simgear/misc/sg_path.hxx>
|
||||
#include <simgear/structure/exception.hxx>
|
||||
|
||||
#include <Main/fg_init.hxx>
|
||||
#include <Main/globals.hxx>
|
||||
#include <Main/fg_props.hxx>
|
||||
|
@ -6,8 +11,12 @@
|
|||
#include <Instrumentation/gps.hxx>
|
||||
#include <Autopilot/route_mgr.hxx>
|
||||
#include <Environment/environment_mgr.hxx>
|
||||
#include <Navaids/airways.hxx>
|
||||
#include <Navaids/waypoint.hxx>
|
||||
#include <Navaids/procedure.hxx>
|
||||
|
||||
using std::string;
|
||||
using namespace flightgear;
|
||||
|
||||
char *homedir = ::getenv( "HOME" );
|
||||
char *hostname = ::getenv( "HOSTNAME" );
|
||||
|
@ -45,6 +54,16 @@ void printScratch(SGPropertyNode* scratch)
|
|||
}
|
||||
}
|
||||
|
||||
void printRoute(const WayptVec& aRoute)
|
||||
{
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "route size=" << aRoute.size());
|
||||
for (unsigned int r=0; r<aRoute.size();++r) {
|
||||
Waypt* w = aRoute[r];
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "\t" << r << ": " << w->ident() << " "
|
||||
<< w->owner()->ident());
|
||||
}
|
||||
}
|
||||
|
||||
void createDummyRoute(FGRouteMgr* rm)
|
||||
{
|
||||
SGPropertyNode* rmInput = fgGetNode("/autopilot/route-manager/input", true);
|
||||
|
@ -59,6 +78,8 @@ void createDummyRoute(FGRouteMgr* rm)
|
|||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
|
||||
try{
|
||||
globals = new FGGlobals;
|
||||
|
||||
fgInitFGRoot(argc, argv);
|
||||
|
@ -69,6 +90,9 @@ int main(int argc, char* argv[])
|
|||
|
||||
|
||||
fgInitNav();
|
||||
fgSetDouble("/environment/magnetic-variation-deg", 0.0);
|
||||
|
||||
Airway::load();
|
||||
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "hello world!");
|
||||
|
||||
|
@ -94,12 +118,15 @@ int main(int argc, char* argv[])
|
|||
// globals->add_subsystem("environment", envMgr);
|
||||
// envMgr->init();
|
||||
|
||||
fgSetBool("/sim/realism/simple-gps", true);
|
||||
|
||||
// _realismSimpleGps
|
||||
|
||||
SGPropertyNode* nd = fgGetNode("/instrumentation/gps", true);
|
||||
GPS* gps = new GPS(nd);
|
||||
globals->add_subsystem("gps", gps);
|
||||
|
||||
|
||||
|
||||
const FGAirport* egph = fgFindAirportID("EGPH");
|
||||
testSetPosition(egph->geod());
|
||||
|
||||
// startup the route manager
|
||||
|
@ -116,6 +143,7 @@ int main(int argc, char* argv[])
|
|||
// update a few times
|
||||
gps->update(0.05);
|
||||
gps->update(0.05);
|
||||
gps->update(0.05);
|
||||
|
||||
scratch->setStringValue("query", "TL");
|
||||
scratch->setStringValue("type", "Vor");
|
||||
|
@ -221,7 +249,105 @@ int main(int argc, char* argv[])
|
|||
nd->setStringValue("command", "define-user-wpt");
|
||||
printScratch(scratch);
|
||||
|
||||
// airways
|
||||
FGPositioned::TypeFilter vorFilt(FGPositioned::VOR);
|
||||
FGPositionedRef tla = FGPositioned::findClosestWithIdent("TLA", pos, &vorFilt);
|
||||
FGPositionedRef big = FGPositioned::findClosestWithIdent("BIG", pos, &vorFilt);
|
||||
FGPositionedRef pol = FGPositioned::findClosestWithIdent("POL", pos, &vorFilt);
|
||||
|
||||
const FGAirport* eddm = fgFindAirportID("EDDM");
|
||||
FGPositionedRef mun = FGPositioned::findClosestWithIdent("MUN",
|
||||
eddm->geod(), &vorFilt);
|
||||
|
||||
const FGAirport* ksfo = fgFindAirportID("KSFO");
|
||||
FGPositionedRef sfo = FGPositioned::findClosestWithIdent("SFO",
|
||||
ksfo->geod(), &vorFilt);
|
||||
|
||||
|
||||
WayptRef awy1 = new NavaidWaypoint(tla, NULL);
|
||||
WayptRef awy2 = new NavaidWaypoint(big, NULL);
|
||||
WayptRef awy3 = new NavaidWaypoint(pol, NULL);
|
||||
WayptRef awy4 = new NavaidWaypoint(mun, NULL);
|
||||
WayptRef awy5 = new NavaidWaypoint(sfo, NULL);
|
||||
|
||||
WayptRef awy6 = new NavaidWaypoint(
|
||||
(FGPositioned*) fgFindAirportID("KJFK"), NULL);
|
||||
|
||||
SGPath p("/Users/jmt/Desktop/airways.kml");
|
||||
std::fstream f;
|
||||
f.open(p.str().c_str(), fstream::out | fstream::trunc);
|
||||
|
||||
// pre-amble
|
||||
f << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
||||
"<kml xmlns=\"http://www.opengis.net/kml/2.2\">\n"
|
||||
"<Document>\n";
|
||||
|
||||
WayptVec route;
|
||||
Airway::highLevel()->route(awy1, awy3, route);
|
||||
Route::dumpRouteToLineString("egph-egcc", route, f);
|
||||
|
||||
Airway::lowLevel()->route(awy1, awy2, route);
|
||||
Route::dumpRouteToLineString("egph-big", route, f);
|
||||
|
||||
Airway::lowLevel()->route(awy2, awy4, route);
|
||||
Route::dumpRouteToLineString("big-mun", route, f);
|
||||
|
||||
Airway::highLevel()->route(awy4, awy5, route);
|
||||
Route::dumpRouteToLineString("mun-sfo", route, f);
|
||||
|
||||
Airway::lowLevel()->route(awy5, awy6, route);
|
||||
Route::dumpRouteToLineString("sfo-jfk", route, f);
|
||||
|
||||
// post-amble
|
||||
f << "</Document>\n"
|
||||
"</kml>" << endl;
|
||||
f.close();
|
||||
|
||||
// procedures
|
||||
SGPath op("/Users/jmt/Desktop/procedures.kml");
|
||||
f.open(op.str().c_str(), fstream::out | fstream::trunc);
|
||||
|
||||
FGAirport* eham = (FGAirport*) fgFindAirportID("EHAM");
|
||||
FGPositioned::TypeFilter fixFilt(FGPositioned::FIX);
|
||||
|
||||
WayptVec approach;
|
||||
FGPositionedRef redfa = FGPositioned::findClosestWithIdent("REDFA",
|
||||
eham->geod(), &fixFilt);
|
||||
bool ok = eham->buildApproach(new NavaidWaypoint(redfa, NULL),
|
||||
eham->getRunwayByIdent("18R"), approach);
|
||||
if (!ok ) {
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "failed to build approach");
|
||||
}
|
||||
|
||||
|
||||
FGAirport* egll = (FGAirport*) fgFindAirportID("EGLL");
|
||||
WayptVec approach2;
|
||||
ok = egll->buildApproach(new NavaidWaypoint(big, NULL),
|
||||
egll->getRunwayByIdent("27R"), approach2);
|
||||
if (!ok ) {
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "failed to build approach");
|
||||
}
|
||||
|
||||
// pre-amble
|
||||
f << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
||||
"<kml xmlns=\"http://www.opengis.net/kml/2.2\">\n"
|
||||
"<Document>\n";
|
||||
|
||||
Route::dumpRouteToLineString("REDFA 18R", approach, f);
|
||||
Route::dumpRouteToLineString("EGLL 27R", approach2, f);
|
||||
|
||||
// post-amble
|
||||
f << "</Document>\n"
|
||||
"</kml>" << endl;
|
||||
f.close();
|
||||
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
|
||||
|
||||
|
||||
} catch (sg_exception& ex) {
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "exception:" << ex.getFormattedMessage());
|
||||
}
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
|
|
@ -58,7 +58,6 @@ using std::setfill;
|
|||
#include <Cockpit/panel.hxx>
|
||||
#include <Cockpit/hud.hxx>
|
||||
|
||||
#include <Include/general.hxx>
|
||||
#include "instrument_mgr.hxx"
|
||||
#include "od_gauge.hxx"
|
||||
#include "wxradar.hxx"
|
||||
|
@ -123,10 +122,9 @@ wxRadarBg::init ()
|
|||
"Aircraft/Instruments/Textures/od_wxradar.rgb");
|
||||
_resultTexture = FGTextureManager::createTexture(_texture_path.c_str(), false);
|
||||
|
||||
SGPath tpath(globals->get_fg_root());
|
||||
string path = _Instrument->getStringValue("echo-texture-path",
|
||||
"Aircraft/Instruments/Textures/wxecho.rgb");
|
||||
tpath.append(path);
|
||||
SGPath tpath = globals->resolve_aircraft_path(path);
|
||||
|
||||
// no mipmap or else alpha will mix with pixels on the border of shapes, ruining the effect
|
||||
_wxEcho = SGLoadTexture2D(tpath, false, false);
|
||||
|
|
|
@ -24,11 +24,9 @@ endif
|
|||
|
||||
if HAVE_FRAMEWORK_PLIB
|
||||
fgfs_PLIB_FW = $(plib_FRAMEWORK)
|
||||
metar_PLIB_FW = $(plib_FRAMEWORK)
|
||||
else
|
||||
fgfs_PLIB_LIBS = -lplibpuaux -lplibpu -lplibfnt -lplibjs -lplibnet \
|
||||
fgfs_PLIB_LIBS = -lplibpuaux -lplibpu -lplibfnt -lplibjs \
|
||||
-lplibsg -lplibul
|
||||
metar_PLIB_LIBS = -lplibnet -lplibul
|
||||
endif
|
||||
|
||||
if HAVE_FRAMEWORK_OSG
|
||||
|
@ -133,9 +131,8 @@ metar_SOURCES = metar_main.cxx
|
|||
|
||||
metar_LDADD = \
|
||||
-lsgenvironment -lsgio -lsgbucket -lsgmisc -lsgstructure -lsgdebug \
|
||||
$(metar_PLIB_LIBS) $(network_LIBS) \
|
||||
$(network_LIBS) \
|
||||
-lz $(base_LIBS)
|
||||
|
||||
metar_LDFLAGS = $(metar_PLIB_FW)
|
||||
|
||||
INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/src
|
||||
|
|
|
@ -241,6 +241,8 @@ int main ( int argc, char **argv ) {
|
|||
fgviewerMain(argc, argv);
|
||||
else
|
||||
fgMainInit(argc, argv);
|
||||
|
||||
|
||||
} catch (const sg_throwable &t) {
|
||||
// We must use cerr rather than
|
||||
// logging, since logging may be
|
||||
|
|
|
@ -211,7 +211,8 @@ do_exit (const SGPropertyNode * arg)
|
|||
SG_LOG(SG_INPUT, SG_DEBUG, "Finished Saving user settings");
|
||||
}
|
||||
}
|
||||
fgExit(arg->getIntValue("status", 0));
|
||||
|
||||
fgOSExit(arg->getIntValue("status", 0));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -391,9 +392,11 @@ static bool
|
|||
do_panel_load (const SGPropertyNode * arg)
|
||||
{
|
||||
string panel_path =
|
||||
arg->getStringValue("path",
|
||||
fgGetString("/sim/panel/path",
|
||||
"Panels/Default/default.xml"));
|
||||
arg->getStringValue("path", fgGetString("/sim/panel/path"));
|
||||
if (panel_path.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
FGPanel * new_panel = fgReadPanel(panel_path);
|
||||
if (new_panel == 0) {
|
||||
SG_LOG(SG_INPUT, SG_ALERT,
|
||||
|
@ -555,15 +558,9 @@ do_tile_cache_reload (const SGPropertyNode * arg)
|
|||
if ( !freeze ) {
|
||||
fgSetBool("/sim/freeze/master", true);
|
||||
}
|
||||
if ( globals->get_tile_mgr()->init() ) {
|
||||
// Load the local scenery data
|
||||
double visibility_meters = fgGetDouble("/environment/visibility-m");
|
||||
globals->get_tile_mgr()->update( visibility_meters );
|
||||
} else {
|
||||
SG_LOG( SG_GENERAL, SG_ALERT,
|
||||
"Error in Tile Manager initialization!" );
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
globals->get_subsystem("tile-manager")->reinit();
|
||||
|
||||
if ( !freeze ) {
|
||||
fgSetBool("/sim/freeze/master", false);
|
||||
}
|
||||
|
@ -1240,8 +1237,6 @@ do_presets_commit (const SGPropertyNode * arg)
|
|||
|
||||
fgReInitSubsystems();
|
||||
|
||||
globals->get_tile_mgr()->update( fgGetDouble("/environment/visibility-m") );
|
||||
|
||||
#if 0
|
||||
if ( ! fgGetBool("/sim/presets/onground") ) {
|
||||
fgSetBool( "/sim/freeze/master", true );
|
||||
|
|
|
@ -58,6 +58,8 @@
|
|||
#include <simgear/structure/event_mgr.hxx>
|
||||
#include <simgear/misc/sg_path.hxx>
|
||||
#include <simgear/misc/sg_dir.hxx>
|
||||
#include <simgear/misc/sgstream.hxx>
|
||||
|
||||
#include <simgear/misc/interpolator.hxx>
|
||||
#include <simgear/scene/material/matlib.hxx>
|
||||
#include <simgear/scene/model/particles.hxx>
|
||||
|
@ -88,16 +90,17 @@
|
|||
#include <Cockpit/panel_io.hxx>
|
||||
|
||||
#include <GUI/new_gui.hxx>
|
||||
#include <Include/general.hxx>
|
||||
#include <Input/input.hxx>
|
||||
#include <Instrumentation/instrument_mgr.hxx>
|
||||
#include <Model/acmodel.hxx>
|
||||
#include <Model/modelmgr.hxx>
|
||||
#include <AIModel/submodel.hxx>
|
||||
#include <AIModel/AIManager.hxx>
|
||||
#include <Navaids/navdb.hxx>
|
||||
#include <Navaids/navlist.hxx>
|
||||
#include <Navaids/fix.hxx>
|
||||
#include <Navaids/fixlist.hxx>
|
||||
#include <Navaids/airways.hxx>
|
||||
#include <Scenery/scenery.hxx>
|
||||
#include <Scenery/tilemgr.hxx>
|
||||
#include <Scripting/NasalSys.hxx>
|
||||
|
@ -1072,15 +1075,8 @@ fgInitNav ()
|
|||
fixlist.init( p_fix ); // adds fixes to the DB in positioned.cxx
|
||||
|
||||
SG_LOG(SG_GENERAL, SG_INFO, " Airways");
|
||||
SGPath p_awy( globals->get_fg_root() );
|
||||
p_awy.append( "Navaids/awy.dat" );
|
||||
FGAirwayNetwork *awyNet = new FGAirwayNetwork;
|
||||
//cerr << "Loading Airways" << endl;
|
||||
awyNet->load (p_awy );
|
||||
awyNet->init();
|
||||
//cerr << "initializing airways" << endl;
|
||||
globals->set_airwaynet( awyNet );
|
||||
|
||||
flightgear::Airway::load();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1263,14 +1259,6 @@ bool fgInitGeneral() {
|
|||
return true;
|
||||
}
|
||||
|
||||
// Initialize view parameters
|
||||
void fgInitView() {
|
||||
// force update of model so that viewer can get some data...
|
||||
globals->get_aircraft_model()->update(0);
|
||||
// run update for current view so that data is current...
|
||||
globals->get_viewmgr()->update(0);
|
||||
}
|
||||
|
||||
// This is the top level init routine which calls all the other
|
||||
// initialization routines. If you are adding a subsystem to flight
|
||||
// gear, its initialization call should located in this routine.
|
||||
|
@ -1322,15 +1310,6 @@ bool fgInitSubsystems() {
|
|||
// Initialize the scenery management subsystem.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
if ( globals->get_tile_mgr()->init() ) {
|
||||
// Load the local scenery data
|
||||
double visibility_meters = fgGetDouble("/environment/visibility-m");
|
||||
globals->get_tile_mgr()->update( visibility_meters );
|
||||
} else {
|
||||
SG_LOG( SG_GENERAL, SG_ALERT, "Error in Tile Manager initialization!" );
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
globals->get_scenery()->get_scene_graph()
|
||||
->addChild(simgear::Particles::getCommonRoot());
|
||||
simgear::GlobalParticleCallback::setSwitch(fgGetNode("/sim/rendering/particles", true));
|
||||
|
@ -1362,12 +1341,6 @@ bool fgInitSubsystems() {
|
|||
|
||||
globals->add_subsystem( "xml-autopilot", FGXMLAutopilotGroup::createInstance(), SGSubsystemMgr::FDM );
|
||||
globals->add_subsystem( "route-manager", new FGRouteMgr );
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Initialize the view manager subsystem.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
fgInitView();
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Initialize the Input-Output subsystem
|
||||
|
@ -1386,23 +1359,12 @@ bool fgInitSubsystems() {
|
|||
|
||||
globals->add_subsystem("gui", new NewGUI, SGSubsystemMgr::INIT);
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Initialize the lighting subsystem.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
globals->add_subsystem("lighting", new FGLight, SGSubsystemMgr::DISPLAY);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Initialize the 2D cloud subsystem.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
fgGetBool("/sim/rendering/bump-mapping", false);
|
||||
|
||||
#ifdef ENABLE_AUDIO_SUPPORT
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Initialize the sound-effects subsystem.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
globals->add_subsystem("voice", new FGVoiceMgr, SGSubsystemMgr::DISPLAY);
|
||||
#endif
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Initialise the ATC Manager
|
||||
|
@ -1418,6 +1380,14 @@ bool fgInitSubsystems() {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
globals->add_subsystem("atis", new FGAtisManager, SGSubsystemMgr::POST_FDM);
|
||||
#endif
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Initialize multiplayer subsystem
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
globals->add_subsystem("mp", new FGMultiplayMgr, SGSubsystemMgr::POST_FDM);
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Initialise the AI Model Manager
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
@ -1444,20 +1414,20 @@ bool fgInitSubsystems() {
|
|||
// Add a new 2D panel.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
string panel_path = fgGetString("/sim/panel/path",
|
||||
"Panels/Default/default.xml");
|
||||
|
||||
globals->set_current_panel( fgReadPanel(panel_path) );
|
||||
if (globals->get_current_panel() == 0) {
|
||||
string panel_path(fgGetString("/sim/panel/path"));
|
||||
if (!panel_path.empty()) {
|
||||
FGPanel* p = fgReadPanel(panel_path);
|
||||
if (p) {
|
||||
globals->set_current_panel(p);
|
||||
p->init();
|
||||
p->bind();
|
||||
SG_LOG( SG_INPUT, SG_INFO, "Loaded new panel from " << panel_path );
|
||||
} else {
|
||||
SG_LOG( SG_INPUT, SG_ALERT,
|
||||
"Error reading new panel from " << panel_path );
|
||||
} else {
|
||||
SG_LOG( SG_INPUT, SG_INFO, "Loaded new panel from " << panel_path );
|
||||
globals->get_current_panel()->init();
|
||||
globals->get_current_panel()->bind();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Initialize the controls subsystem.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
@ -1478,7 +1448,37 @@ bool fgInitSubsystems() {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
globals->add_subsystem("replay", new FGReplay);
|
||||
|
||||
#ifdef ENABLE_AUDIO_SUPPORT
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Initialize the sound-effects subsystem.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
globals->add_subsystem("voice", new FGVoiceMgr, SGSubsystemMgr::DISPLAY);
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Initialize the lighting subsystem.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
globals->add_subsystem("lighting", new FGLight, SGSubsystemMgr::DISPLAY);
|
||||
|
||||
// ordering here is important : Nasal (via events), then models, then views
|
||||
globals->add_subsystem("events", globals->get_event_mgr(), SGSubsystemMgr::DISPLAY);
|
||||
|
||||
FGAircraftModel* acm = new FGAircraftModel;
|
||||
globals->set_aircraft_model(acm);
|
||||
globals->add_subsystem("aircraft-model", acm, SGSubsystemMgr::DISPLAY);
|
||||
|
||||
FGModelMgr* mm = new FGModelMgr;
|
||||
globals->set_model_mgr(mm);
|
||||
globals->add_subsystem("model-manager", mm, SGSubsystemMgr::DISPLAY);
|
||||
|
||||
FGViewMgr *viewmgr = new FGViewMgr;
|
||||
globals->set_viewmgr( viewmgr );
|
||||
globals->add_subsystem("view-manager", viewmgr, SGSubsystemMgr::DISPLAY);
|
||||
|
||||
globals->add_subsystem("tile-manager", globals->get_tile_mgr(),
|
||||
SGSubsystemMgr::DISPLAY);
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Bind and initialize subsystems.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
@ -1486,13 +1486,6 @@ bool fgInitSubsystems() {
|
|||
globals->get_subsystem_mgr()->bind();
|
||||
globals->get_subsystem_mgr()->init();
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Initialize multiplayer subsystem
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
globals->set_multiplayer_mgr(new FGMultiplayMgr);
|
||||
globals->get_multiplayer_mgr()->init();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Initialize the Nasal interpreter.
|
||||
// Do this last, so that the loaded scripts see initialized state
|
||||
|
@ -1549,12 +1542,11 @@ void fgReInitSubsystems()
|
|||
// reload offsets from config defaults
|
||||
globals->get_viewmgr()->reinit();
|
||||
|
||||
fgInitView();
|
||||
|
||||
globals->get_controls()->reset_all();
|
||||
|
||||
globals->get_subsystem("time")->reinit();
|
||||
|
||||
globals->get_subsystem("tile-manager")->reinit();
|
||||
|
||||
if ( !freeze ) {
|
||||
fgSetBool("/sim/freeze/master", false);
|
||||
}
|
||||
|
@ -1581,7 +1573,6 @@ void doSimulatorReset(void) // from gui_local.cxx -- TODO merge with fgReInitSu
|
|||
|
||||
fgReInitSubsystems();
|
||||
|
||||
globals->get_tile_mgr()->update(fgGetDouble("/environment/visibility-m"));
|
||||
fgSetBool("/sim/signals/reinit", false);
|
||||
|
||||
if (!freeze)
|
||||
|
|
|
@ -60,7 +60,7 @@ enum { KEYMOD_NONE = 0,
|
|||
void fgOSInit(int* argc, char** argv);
|
||||
void fgOSOpenWindow(bool stencil);
|
||||
void fgOSFullScreen();
|
||||
void fgOSMainLoop();
|
||||
int fgOSMainLoop();
|
||||
void fgOSExit(int code);
|
||||
|
||||
void fgSetMouseCursor(int cursor);
|
||||
|
@ -69,8 +69,6 @@ void fgWarpMouse(int x, int y);
|
|||
|
||||
int fgGetKeyModifiers();
|
||||
|
||||
void fgRequestRedraw();
|
||||
|
||||
//
|
||||
// Callbacks and registration API
|
||||
//
|
||||
|
|
|
@ -64,9 +64,5 @@ void fgRegisterMouseMotionHandler(fgMouseMotionHandler func)
|
|||
globals->get_renderer()->getEventHandler()->setMouseMotionHandler(func);
|
||||
}
|
||||
|
||||
// Redraw "happens" every frame whether you want it or not.
|
||||
void fgRequestRedraw()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -46,7 +46,6 @@
|
|||
#include <osgViewer/ViewerEventHandlers>
|
||||
#include <osgViewer/Viewer>
|
||||
|
||||
#include <Include/general.hxx>
|
||||
#include <Scenery/scenery.hxx>
|
||||
#include "fg_os.hxx"
|
||||
#include "fg_props.hxx"
|
||||
|
@ -271,7 +270,7 @@ void fgOSExit(int code)
|
|||
status = code;
|
||||
}
|
||||
|
||||
void fgOSMainLoop()
|
||||
int fgOSMainLoop()
|
||||
{
|
||||
ref_ptr<FGEventHandler> manipulator
|
||||
= globals->get_renderer()->getEventHandler();
|
||||
|
@ -287,11 +286,16 @@ void fgOSMainLoop()
|
|||
(*drawFunc)();
|
||||
viewer->frame();
|
||||
}
|
||||
fgExit(status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int fgGetKeyModifiers()
|
||||
{
|
||||
if (!globals->get_renderer()) { // happens during shutdown
|
||||
return 0;
|
||||
}
|
||||
|
||||
return globals->get_renderer()->getEventHandler()->getCurrentModifiers();
|
||||
}
|
||||
|
||||
|
|
|
@ -45,7 +45,6 @@
|
|||
#include <Model/acmodel.hxx>
|
||||
#include <Model/modelmgr.hxx>
|
||||
#include <MultiPlayer/multiplaymgr.hxx>
|
||||
#include <Navaids/awynet.hxx>
|
||||
#include <Scenery/scenery.hxx>
|
||||
#include <Scenery/tilemgr.hxx>
|
||||
#include <Navaids/navlist.hxx>
|
||||
|
@ -149,9 +148,7 @@ FGGlobals::FGGlobals() :
|
|||
dmelist( NULL ),
|
||||
tacanlist( NULL ),
|
||||
carrierlist( NULL ),
|
||||
channellist( NULL ),
|
||||
airwaynet( NULL ),
|
||||
multiplayer_mgr( NULL )
|
||||
channellist( NULL )
|
||||
{
|
||||
simgear::ResourceManager::instance()->addProvider(new AircraftResourceProvider());
|
||||
}
|
||||
|
@ -161,23 +158,21 @@ FGGlobals::FGGlobals() :
|
|||
FGGlobals::~FGGlobals()
|
||||
{
|
||||
delete renderer;
|
||||
renderer = NULL;
|
||||
|
||||
// The AIModels manager performs a number of actions upon
|
||||
// Shutdown that implicitly assume that other subsystems
|
||||
// are still operational (Due to the dynamic allocation and
|
||||
// deallocation of AIModel objects. To ensure we can safely
|
||||
// shut down all subsystems, make sure we take down the
|
||||
// AIModels system first.
|
||||
subsystem_mgr->get_group(SGSubsystemMgr::GENERAL)->remove_subsystem("ai_model");
|
||||
// FGInput (FGInputEvent) and FGDialog calls get_subsystem() in their destructors,
|
||||
// which is not safe since some subsystem are already deleted but can be referred.
|
||||
// So these subsystems must be deleted prior to deleting subsystem_mgr unless
|
||||
// ~SGSubsystemGroup and SGSubsystemMgr::get_subsystem are changed not to refer to
|
||||
// deleted subsystems.
|
||||
subsystem_mgr->get_group(SGSubsystemMgr::GENERAL)->remove_subsystem("input");
|
||||
subsystem_mgr->get_group(SGSubsystemMgr::GENERAL)->remove_subsystem("gui");
|
||||
SGSubsystem* ai = subsystem_mgr->remove("ai_model");
|
||||
ai->unbind();
|
||||
delete ai;
|
||||
|
||||
subsystem_mgr->unbind();
|
||||
delete subsystem_mgr;
|
||||
delete event_mgr;
|
||||
|
||||
delete time_params;
|
||||
delete mag;
|
||||
delete matlib;
|
||||
|
@ -186,14 +181,9 @@ FGGlobals::~FGGlobals()
|
|||
|
||||
delete ATC_mgr;
|
||||
delete controls;
|
||||
delete viewmgr;
|
||||
|
||||
// delete commands;
|
||||
delete acmodel;
|
||||
delete model_mgr;
|
||||
delete channel_options_list;
|
||||
delete initial_waypoints;
|
||||
delete tile_mgr;
|
||||
delete scenery;
|
||||
delete fontcache;
|
||||
|
||||
|
@ -204,8 +194,6 @@ FGGlobals::~FGGlobals()
|
|||
delete tacanlist;
|
||||
delete carrierlist;
|
||||
delete channellist;
|
||||
delete airwaynet;
|
||||
delete multiplayer_mgr;
|
||||
|
||||
soundmgr->unbind();
|
||||
delete soundmgr;
|
||||
|
|
|
@ -60,13 +60,10 @@ class FGAircraftModel;
|
|||
class FGControls;
|
||||
class FGFlightPlanDispatcher;
|
||||
class FGNavList;
|
||||
class FGAirwayNetwork;
|
||||
class FGTACANList;
|
||||
class FGLight;
|
||||
class FGModelMgr;
|
||||
class FGRouteMgr;
|
||||
class FGScenery;
|
||||
class FGMultiplayMgr;
|
||||
class FGPanel;
|
||||
class FGTileMgr;
|
||||
class FGViewMgr;
|
||||
|
@ -173,10 +170,6 @@ private:
|
|||
FGNavList *tacanlist;
|
||||
FGNavList *carrierlist;
|
||||
FGTACANList *channellist;
|
||||
FGAirwayNetwork *airwaynet;
|
||||
|
||||
//Mulitplayer managers
|
||||
FGMultiplayMgr *multiplayer_mgr;
|
||||
|
||||
/// roots of Aircraft trees
|
||||
string_list fg_aircraft_dirs;
|
||||
|
@ -289,13 +282,6 @@ public:
|
|||
model_mgr = mgr;
|
||||
}
|
||||
|
||||
inline FGMultiplayMgr *get_multiplayer_mgr () { return multiplayer_mgr; }
|
||||
|
||||
inline void set_multiplayer_mgr (FGMultiplayMgr * mgr)
|
||||
{
|
||||
multiplayer_mgr = mgr;
|
||||
}
|
||||
|
||||
inline string_list *get_channel_options_list () {
|
||||
return channel_options_list;
|
||||
}
|
||||
|
@ -334,10 +320,6 @@ public:
|
|||
inline FGTACANList *get_channellist() const { return channellist; }
|
||||
inline void set_channellist( FGTACANList *c ) { channellist = c; }
|
||||
|
||||
inline FGAirwayNetwork *get_airwaynet() const { return airwaynet; }
|
||||
inline void set_airwaynet( FGAirwayNetwork *a ) { airwaynet = a; }
|
||||
|
||||
|
||||
/**
|
||||
* Save the current state as the initial state.
|
||||
*/
|
||||
|
|
|
@ -48,14 +48,13 @@
|
|||
#include <simgear/props/props.hxx>
|
||||
#include <simgear/timing/sg_time.hxx>
|
||||
#include <simgear/math/sg_random.h>
|
||||
#include <simgear/io/raw_socket.hxx>
|
||||
|
||||
#include <Time/light.hxx>
|
||||
#include <Include/general.hxx>
|
||||
#include <Aircraft/replay.hxx>
|
||||
#include <Cockpit/cockpit.hxx>
|
||||
#include <Cockpit/hud.hxx>
|
||||
#include <Model/panelnode.hxx>
|
||||
#include <Model/modelmgr.hxx>
|
||||
#include <Model/acmodel.hxx>
|
||||
#include <Scenery/scenery.hxx>
|
||||
#include <Scenery/tilemgr.hxx>
|
||||
|
@ -87,9 +86,6 @@ using namespace flightgear;
|
|||
|
||||
using std::cerr;
|
||||
|
||||
// This is a record containing a bit of global housekeeping information
|
||||
FGGeneral general;
|
||||
|
||||
// Specify our current idle function state. This is used to run all
|
||||
// our initializations out of the idle callback so that we can get a
|
||||
// splash screen up and running right away.
|
||||
|
@ -136,11 +132,6 @@ static void fgMainLoop( void ) {
|
|||
// compute simulated time (allowing for pause, warp, etc) and
|
||||
// real elapsed time
|
||||
timeMgr->computeTimeDeltas(sim_dt, real_dt);
|
||||
|
||||
if (globals->get_warp_delta() != 0) {
|
||||
FGLight *l = (FGLight *)(globals->get_subsystem("lighting"));
|
||||
l->update( 0.5 );
|
||||
}
|
||||
|
||||
// update magvar model
|
||||
globals->get_mag()->update( longitude->getDoubleValue()
|
||||
|
@ -150,11 +141,6 @@ static void fgMainLoop( void ) {
|
|||
altitude->getDoubleValue() * SG_FEET_TO_METER,
|
||||
globals->get_time_params()->getJD() );
|
||||
|
||||
|
||||
// Update any multiplayer's network queues, the AIMultiplayer
|
||||
// implementation is an AI model and depends on that
|
||||
globals->get_multiplayer_mgr()->Update();
|
||||
|
||||
#if ENABLE_ATCDCL
|
||||
// Run ATC subsystem
|
||||
if (fgGetBool("/sim/atc/enabled"))
|
||||
|
@ -162,30 +148,6 @@ static void fgMainLoop( void ) {
|
|||
#endif
|
||||
|
||||
globals->get_subsystem_mgr()->update(sim_dt);
|
||||
globals->get_aircraft_model()->update(sim_dt);
|
||||
|
||||
//
|
||||
// Tile Manager updates - see if we need to load any new scenery tiles.
|
||||
// this code ties together the fdm, viewer and scenery classes...
|
||||
// we may want to move this to its own class at some point
|
||||
//
|
||||
double visibility_meters = fgGetDouble("/environment/visibility-m");
|
||||
globals->get_tile_mgr()->prep_ssg_nodes( visibility_meters );
|
||||
|
||||
// update tile manager for view...
|
||||
SGVec3d viewPos = globals->get_current_view()->get_view_pos();
|
||||
SGGeod geodViewPos = SGGeod::fromCart(viewPos);
|
||||
globals->get_tile_mgr()->update(geodViewPos, visibility_meters);
|
||||
|
||||
// run Nasal's settimer() loops right before the view manager
|
||||
globals->get_event_mgr()->update(sim_dt);
|
||||
|
||||
// pick up model coordidnates that Nasal code may have set relative to the
|
||||
// aircraft's
|
||||
globals->get_model_mgr()->update(sim_dt);
|
||||
|
||||
// update the view angle as late as possible, but before sound calculations
|
||||
globals->get_viewmgr()->update(real_dt);
|
||||
|
||||
// Update the sound manager last so it can use the CPU while the GPU
|
||||
// is processing the scenery (doubled the frame-rate for me) -EMH-
|
||||
|
@ -238,7 +200,6 @@ static void fgMainLoop( void ) {
|
|||
SGRawValueFunctions<const char *>(0, fgSetNewSoundDevice), false);
|
||||
}
|
||||
simgear::AtomicChangeListener::fireChangeListeners();
|
||||
fgRequestRedraw();
|
||||
|
||||
SG_LOG( SG_ALL, SG_DEBUG, "" );
|
||||
}
|
||||
|
@ -278,21 +239,23 @@ struct GeneralInitOperation : public GraphicsContextOperation
|
|||
}
|
||||
void run(osg::GraphicsContext* gc)
|
||||
{
|
||||
general.set_glVendor( (char *)glGetString ( GL_VENDOR ) );
|
||||
general.set_glRenderer( (char *)glGetString ( GL_RENDERER ) );
|
||||
general.set_glVersion( (char *)glGetString ( GL_VERSION ) );
|
||||
SG_LOG( SG_GENERAL, SG_INFO, general.get_glVendor() );
|
||||
SG_LOG( SG_GENERAL, SG_INFO, general.get_glRenderer() );
|
||||
SG_LOG( SG_GENERAL, SG_INFO, general.get_glVersion() );
|
||||
SGPropertyNode* simRendering = fgGetNode("/sim/rendering");
|
||||
|
||||
simRendering->setStringValue("gl-vendor", (char*) glGetString(GL_VENDOR));
|
||||
SG_LOG( SG_GENERAL, SG_INFO, glGetString(GL_VENDOR));
|
||||
|
||||
simRendering->setStringValue("gl-renderer", (char*) glGetString(GL_RENDERER));
|
||||
SG_LOG( SG_GENERAL, SG_INFO, glGetString(GL_RENDERER));
|
||||
|
||||
simRendering->setStringValue("gl-version", (char*) glGetString(GL_VERSION));
|
||||
SG_LOG( SG_GENERAL, SG_INFO, glGetString(GL_VERSION));
|
||||
|
||||
GLint tmp;
|
||||
glGetIntegerv( GL_MAX_TEXTURE_SIZE, &tmp );
|
||||
general.set_glMaxTexSize( tmp );
|
||||
SG_LOG ( SG_GENERAL, SG_INFO, "Max texture size = " << tmp );
|
||||
simRendering->setIntValue("max-texture-size", tmp);
|
||||
|
||||
glGetIntegerv( GL_DEPTH_BITS, &tmp );
|
||||
general.set_glDepthBits( tmp );
|
||||
SG_LOG ( SG_GENERAL, SG_INFO, "Depth buffer bits = " << tmp );
|
||||
simRendering->setIntValue("depth-buffer-bits", tmp);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -402,35 +365,12 @@ static void fgIdleFunction ( void ) {
|
|||
globals->set_tile_mgr( new FGTileMgr );
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Initialize the general model subsystem.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
globals->set_model_mgr(new FGModelMgr);
|
||||
globals->get_model_mgr()->init();
|
||||
globals->get_model_mgr()->bind();
|
||||
fgSplashProgress("loading aircraft");
|
||||
|
||||
|
||||
} else if ( idle_state == 5 ) {
|
||||
idle_state++;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Initialize the 3D aircraft model subsystem (has a dependency on
|
||||
// the scenery subsystem.)
|
||||
////////////////////////////////////////////////////////////////////
|
||||
FGAircraftModel* acm = new FGAircraftModel;
|
||||
globals->set_aircraft_model(acm);
|
||||
//globals->add_subsystem("aircraft-model", acm);
|
||||
acm->init();
|
||||
acm->bind();
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Initialize the view manager subsystem.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
FGViewMgr *viewmgr = new FGViewMgr;
|
||||
globals->set_viewmgr( viewmgr );
|
||||
viewmgr->init();
|
||||
viewmgr->bind();
|
||||
fgSplashProgress("generating sky elements");
|
||||
|
||||
|
||||
|
@ -576,7 +516,7 @@ static void upper_case_property(const char *name)
|
|||
|
||||
|
||||
// Main top level initialization
|
||||
bool fgMainInit( int argc, char **argv ) {
|
||||
int fgMainInit( int argc, char **argv ) {
|
||||
|
||||
// set default log levels
|
||||
sglog().setLogLevels( SG_ALL, SG_ALERT );
|
||||
|
@ -649,8 +589,8 @@ bool fgMainInit( int argc, char **argv ) {
|
|||
fgRegisterIdleHandler( &fgIdleFunction );
|
||||
fgRegisterDrawHandler( &FGRenderer::update );
|
||||
|
||||
// Initialize plib net interface
|
||||
netInit( &argc, argv );
|
||||
// Initialize sockets (WinSock needs this)
|
||||
simgear::Socket::initSockets();
|
||||
|
||||
// Clouds3D requires an alpha channel
|
||||
fgOSOpenWindow(true /* request stencil buffer */);
|
||||
|
@ -660,11 +600,14 @@ bool fgMainInit( int argc, char **argv ) {
|
|||
fgSplashInit();
|
||||
|
||||
// pass control off to the master event handler
|
||||
fgOSMainLoop();
|
||||
|
||||
// we never actually get here ... but to avoid compiler warnings,
|
||||
// etc.
|
||||
return false;
|
||||
int result = fgOSMainLoop();
|
||||
|
||||
// clean up here; ensure we null globals to avoid
|
||||
// confusing the atexit() handler
|
||||
delete globals;
|
||||
globals = NULL;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue