1
0
Fork 0

Merge branch 'next' of D:\Git_New\flightgear into next

This commit is contained in:
Vivian Meazza 2010-10-28 17:35:03 +01:00
commit 02fb83c774
143 changed files with 11811 additions and 6824 deletions

View file

@ -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

View file

@ -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"
>

View file

@ -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;

View file

@ -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);

View file

@ -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"

View file

@ -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,

View file

@ -23,6 +23,8 @@
#endif
#include <simgear/math/sg_geodesy.hxx>
#include <Airports/simple.hxx>
#include <Airports/runways.hxx>
#include <Airports/dynamics.hxx>

View file

@ -34,7 +34,7 @@
#include <Traffic/TrafficMgr.hxx>
#include <Airports/groundnetwork.hxx>
#include <Airports/dynamics.hxx>
#include <Airports/simple.hxx>
using std::sort;

View file

@ -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>

View file

@ -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>

View file

@ -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;
}

View file

@ -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

View file

@ -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);
};

View file

@ -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 )
{

View file

@ -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

View file

@ -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 );

View file

@ -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;

View file

@ -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

View file

@ -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;
};

View file

@ -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 )

View file

@ -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();

View file

@ -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);

View file

@ -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();

View file

@ -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
/* -------------------------------------------------------------------------------- */

View file

@ -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 );

View file

@ -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;

View file

@ -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;

View file

@ -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*);

View file

@ -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;
}
}
}
}

View file

@ -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

View file

@ -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]));

View file

@ -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;

View file

@ -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

View file

@ -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;
}

View file

@ -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)

View file

@ -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:

View file

@ -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;

View file

@ -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();

View file

@ -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;

View file

@ -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));

View file

@ -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. */

View file

@ -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();

View file

@ -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;

View file

@ -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 {

View file

@ -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();

View file

@ -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 */

View file

@ -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);

View file

@ -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

View file

@ -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",

View file

@ -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;

View file

@ -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;
}

View file

@ -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);

View file

@ -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;

View file

@ -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;

View file

@ -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();

View file

@ -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;
}

View file

@ -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;

View file

@ -24,6 +24,7 @@
# include <config.h>
#endif
#include <cassert>
#include <simgear/structure/exception.hxx>
#include <FDM/fdm_shell.hxx>

View file

@ -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
}

View file

@ -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, &currentColor, 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, &currentColor, 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

View file

@ -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

View file

@ -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

View file

@ -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 {

View file

@ -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>

View file

@ -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);
}

View file

@ -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;

View file

@ -4,5 +4,4 @@ EXTRA_DIST = \
config.h-msvc71 \
config.h-msvc8 \
cmdargs.h \
fg_typedefs.h \
general.hxx
fg_typedefs.h

View file

@ -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

View file

@ -27,7 +27,6 @@
#include <vector>
#include <simgear/structure/SGBinding.hxx>
#include <plib/ul.h>
#if defined( UL_WIN32 )
#define TGT_PLATFORM "windows"

View file

@ -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());
}
}

View file

@ -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;
};

View file

@ -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 );
}
}

View file

@ -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;
}
};

View file

@ -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);

View 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

View file

@ -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);

View file

@ -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

View file

@ -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,

View file

@ -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;

View file

@ -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 ()

View file

@ -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)
{

View file

@ -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 ();

View file

@ -390,6 +390,7 @@ void FGNavRadio::clearOutputs()
_dmeInRange = false;
_operable = false;
_navaid = NULL;
}
void FGNavRadio::updateReceiver(double dt)

View 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

View 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

View file

@ -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;
}

View file

@ -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);

View file

@ -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

View file

@ -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

View file

@ -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 );

View file

@ -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)

View file

@ -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
//

View file

@ -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()
{
}

View file

@ -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();
}

View file

@ -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;

View file

@ -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.
*/

View file

@ -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