1
0
Fork 0

Curt Olson:

Autopilot overhaul.
This commit is contained in:
curt 2004-01-31 19:47:45 +00:00
parent 5a9c5d80c8
commit da5ea10d5d
25 changed files with 1563 additions and 190 deletions

View file

@ -40,7 +40,6 @@
#include <Cockpit/hud.hxx>
#include <Cockpit/panel_io.hxx>
#include <Model/acmodel.hxx>
#include <Autopilot/newauto.hxx>
#include "aircraft.hxx"
@ -228,9 +227,9 @@ fgLoadAircraft (const SGPropertyNode * arg)
//
globals->get_viewmgr()->reinit();
globals->get_controls()->reset_all();
globals->get_autopilot()->reset();
globals->get_aircraft_model()->reinit();
globals->get_subsystem("fx")->reinit();
globals->get_subsystem("xml-autopilot")->reinit();
fgReInitSubsystems();

View file

@ -2,6 +2,7 @@ noinst_LIBRARIES = libAutopilot.a
libAutopilot_a_SOURCES = \
auto_gui.cxx auto_gui.hxx \
newauto.cxx newauto.hxx
route_mgr.cxx route_mgr.hxx \
xmlauto.cxx xmlauto.hxx
INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/src

View file

@ -28,8 +28,6 @@
#include <simgear/compiler.h>
#include <simgear/route/route.hxx>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
@ -55,7 +53,8 @@
#include <Navaids/fixlist.hxx>
#include "auto_gui.hxx"
#include "newauto.hxx"
#include "route_mgr.hxx"
#include "xmlauto.hxx"
SG_USING_STD(string);
@ -206,27 +205,25 @@ void ApHeadingDialog_OK (puObject *me)
if( strlen(c) ) {
double NewHeading;
if( scan_number( c, &NewHeading ) )
{
if ( !globals->get_autopilot()->get_HeadingEnabled() ) {
globals->get_autopilot()->set_HeadingEnabled( true );
}
globals->get_autopilot()->HeadingSet( NewHeading );
} else {
error = 1;
s = c;
s += " is not a valid number.";
}
if( scan_number( c, &NewHeading ) ) {
fgSetString( "/autopilot/locks/heading", "dg-heading-hold" );
fgSetDouble( "/autopilot/settings/heading-bug-deg",
NewHeading );
} else {
error = 1;
s = c;
s += " is not a valid number.";
}
}
ApHeadingDialog_Cancel(me);
if( error ) mkDialog(s.c_str());
if ( error ) mkDialog(s.c_str());
}
void NewHeading(puObject *cb)
{
// string ApHeadingLabel( "Enter New Heading" );
// ApHeadingDialogMessage -> setLabel(ApHeadingLabel.c_str());
float heading = globals->get_autopilot()->get_DGTargetHeading();
float heading = fgGetDouble( "/autopilot/settings/heading-bug-deg" );
while ( heading < 0.0 ) { heading += 360.0; }
ApHeadingDialogInput -> setValue ( heading );
ApHeadingDialogInput -> acceptInput();
@ -281,19 +278,16 @@ void ApAltitudeDialog_OK (puObject *me)
char *c;
ApAltitudeDialogInput->getValue( &c );
if( strlen( c ) ) {
if ( strlen( c ) ) {
double NewAltitude;
if( scan_number( c, &NewAltitude) )
{
if ( !globals->get_autopilot()->get_AltitudeEnabled() ) {
globals->get_autopilot()->set_AltitudeEnabled( true );
}
globals->get_autopilot()->AltitudeSet( NewAltitude );
} else {
error = 1;
s = c;
s += " is not a valid number.";
}
if ( scan_number( c, &NewAltitude) ) {
fgSetString( "/autopilot/locks/altitude", "altitude-hold" );
fgSetDouble( "/autopilot/settings/altitude-ft", NewAltitude );
} else {
error = 1;
s = c;
s += " is not a valid number.";
}
}
ApAltitudeDialog_Cancel(me);
if( error ) mkDialog(s.c_str());
@ -301,7 +295,8 @@ void ApAltitudeDialog_OK (puObject *me)
void NewAltitude(puObject *cb)
{
float altitude = globals->get_autopilot()->get_TargetAltitude() * SG_METER_TO_FEET;
float altitude = fgGetDouble("/autopilot/settings/altitude-ft")
* SG_METER_TO_FEET;
ApAltitudeDialogInput -> setValue( altitude );
ApAltitudeDialogInput -> acceptInput();
FG_PUSH_PUI_DIALOG( ApAltitudeDialog );
@ -361,8 +356,9 @@ static void maxroll_adj( puObject *hs ) {
hs-> getValue ( &val ) ;
SG_CLAMP_RANGE ( val, 0.1f, 1.0f ) ;
// printf ( "maxroll_adj( %p ) %f %f\n", hs, val, MaxRollAdjust * val ) ;
globals->get_autopilot()->set_MaxRoll( MaxRollAdjust * val );
sprintf( SliderText[ 0 ], "%05.2f", globals->get_autopilot()->get_MaxRoll() );
fgSetDouble( "/autopilot/config/max-roll-deg", MaxRollAdjust * val );
sprintf( SliderText[ 0 ], "%05.2f",
fgGetDouble("/autopilot/config/max-roll-deg") );
APAdjustMaxRollText -> setLabel ( SliderText[ 0 ] ) ;
}
@ -372,8 +368,9 @@ static void rollout_adj( puObject *hs ) {
hs-> getValue ( &val ) ;
SG_CLAMP_RANGE ( val, 0.1f, 1.0f ) ;
// printf ( "rollout_adj( %p ) %f %f\n", hs, val, RollOutAdjust * val ) ;
globals->get_autopilot()->set_RollOut( RollOutAdjust * val );
sprintf( SliderText[ 1 ], "%05.2f", globals->get_autopilot()->get_RollOut() );
fgSetDouble( "/autopilot/config/roll-out-deg", RollOutAdjust * val );
sprintf( SliderText[ 1 ], "%05.2f",
fgGetDouble("/autopilot/config/roll-out-deg") );
APAdjustRollOutText -> setLabel ( SliderText[ 1 ] );
}
@ -383,8 +380,9 @@ static void maxaileron_adj( puObject *hs ) {
hs-> getValue ( &val ) ;
SG_CLAMP_RANGE ( val, 0.1f, 1.0f ) ;
// printf ( "maxaileron_adj( %p ) %f %f\n", hs, val, MaxAileronAdjust * val ) ;
globals->get_autopilot()->set_MaxAileron( MaxAileronAdjust * val );
sprintf( SliderText[ 3 ], "%05.2f", globals->get_autopilot()->get_MaxAileron() );
fgSetDouble( "/autopilot/config/max-aileron", MaxAileronAdjust * val );
sprintf( SliderText[ 3 ], "%05.2f",
fgGetDouble("/autopilot/config/max-aileron") );
APAdjustMaxAileronText -> setLabel ( SliderText[ 3 ] );
}
@ -394,8 +392,10 @@ static void rolloutsmooth_adj( puObject *hs ) {
hs -> getValue ( &val ) ;
SG_CLAMP_RANGE ( val, 0.1f, 1.0f ) ;
// printf ( "rolloutsmooth_adj( %p ) %f %f\n", hs, val, RollOutSmoothAdjust * val ) ;
globals->get_autopilot()->set_RollOutSmooth( RollOutSmoothAdjust * val );
sprintf( SliderText[ 2 ], "%5.2f", globals->get_autopilot()->get_RollOutSmooth() );
fgSetDouble( "/autopilot/config/roll-out-smooth-deg",
RollOutSmoothAdjust * val );
sprintf( SliderText[ 2 ], "%5.2f",
fgGetDouble("/autopilot/config/roll-out-smooth-deg") );
APAdjustRollOutSmoothText-> setLabel ( SliderText[ 2 ] );
}
@ -406,19 +406,21 @@ static void goAwayAPAdjust (puObject *)
}
void cancelAPAdjust( puObject *self ) {
globals->get_autopilot()->set_MaxRoll( TmpMaxRollValue );
globals->get_autopilot()->set_RollOut( TmpRollOutValue );
globals->get_autopilot()->set_MaxAileron( TmpMaxAileronValue );
globals->get_autopilot()->set_RollOutSmooth( TmpRollOutSmoothValue );
fgSetDouble( "/autopilot/config/max-roll-deg", TmpMaxRollValue );
fgSetDouble( "/autopilot/config/roll-out-deg", TmpRollOutValue );
fgSetDouble( "/autopilot/config/max-aileron", TmpMaxAileronValue );
fgSetDouble( "/autopilot/config/roll-out-smooth-deg",
TmpRollOutSmoothValue );
goAwayAPAdjust(self);
}
void resetAPAdjust( puObject *self ) {
globals->get_autopilot()->set_MaxRoll( MaxRollAdjust / 2 );
globals->get_autopilot()->set_RollOut( RollOutAdjust / 2 );
globals->get_autopilot()->set_MaxAileron( MaxAileronAdjust / 2 );
globals->get_autopilot()->set_RollOutSmooth( RollOutSmoothAdjust / 2 );
fgSetDouble( "/autopilot/config/max-roll-deg", MaxRollAdjust / 2 );
fgSetDouble( "/autopilot/config/roll-out-deg", RollOutAdjust / 2 );
fgSetDouble( "/autopilot/config/max-aileron", MaxAileronAdjust / 2 );
fgSetDouble( "/autopilot/config/roll-out-smooth-deg",
RollOutSmoothAdjust / 2 );
FG_POP_PUI_DIALOG( APAdjustDialog );
@ -426,15 +428,18 @@ void resetAPAdjust( puObject *self ) {
}
void fgAPAdjust( puObject *self ) {
TmpMaxRollValue = globals->get_autopilot()->get_MaxRoll();
TmpRollOutValue = globals->get_autopilot()->get_RollOut();
TmpMaxAileronValue = globals->get_autopilot()->get_MaxAileron();
TmpRollOutSmoothValue = globals->get_autopilot()->get_RollOutSmooth();
TmpMaxRollValue = fgGetDouble("/autopilot/config/max-roll-deg");
TmpRollOutValue = fgGetDouble("/autopilot/config/roll-out-deg");
TmpMaxAileronValue = fgGetDouble("/autopilot/config/max-aileron");
TmpRollOutSmoothValue = fgGetDouble("/autopilot/config/roll-out-smooth-deg");
MaxRollValue = globals->get_autopilot()->get_MaxRoll() / MaxRollAdjust;
RollOutValue = globals->get_autopilot()->get_RollOut() / RollOutAdjust;
MaxAileronValue = globals->get_autopilot()->get_MaxAileron() / MaxAileronAdjust;
RollOutSmoothValue = globals->get_autopilot()->get_RollOutSmooth()
MaxRollValue = fgGetDouble("/autopilot/config/max-roll-deg")
/ MaxRollAdjust;
RollOutValue = fgGetDouble("/autopilot/config/roll-out-deg")
/ RollOutAdjust;
MaxAileronValue = fgGetDouble("/autopilot/config/max-aileron")
/ MaxAileronAdjust;
RollOutSmoothValue = fgGetDouble("/autopilot/config/roll-out-smooth-deg")
/ RollOutSmoothAdjust;
APAdjustHS0-> setValue ( MaxRollValue ) ;
@ -470,20 +475,22 @@ void fgAPAdjustInit() {
int slider_value_x = 160;
float slider_delta = 0.1f;
TmpMaxRollValue = globals->get_autopilot()->get_MaxRoll();
TmpRollOutValue = globals->get_autopilot()->get_RollOut();
TmpMaxAileronValue = globals->get_autopilot()->get_MaxAileron();
TmpRollOutSmoothValue = globals->get_autopilot()->get_RollOutSmooth();
TmpMaxRollValue = fgGetDouble("/autopilot/config/max-roll-deg");
TmpRollOutValue = fgGetDouble("/autopilot/config/roll-out-deg");
TmpMaxAileronValue = fgGetDouble("/autopilot/config/max-aileron");
TmpRollOutSmoothValue = fgGetDouble("/autopilot/config/roll-out-smooth-deg");
MaxRollAdjust = 2 * fgGetDouble("/autopilot/config/max-roll-deg");
RollOutAdjust = 2 * fgGetDouble("/autopilot/config/roll-out-deg");
MaxAileronAdjust = 2 * fgGetDouble("/autopilot/config/max-aileron");
RollOutSmoothAdjust = 2 * fgGetDouble("/autopilot/config/roll-out-smooth-deg");
MaxRollAdjust = 2 * globals->get_autopilot()->get_MaxRoll();
RollOutAdjust = 2 * globals->get_autopilot()->get_RollOut();
MaxAileronAdjust = 2 * globals->get_autopilot()->get_MaxAileron();
RollOutSmoothAdjust = 2 * globals->get_autopilot()->get_RollOutSmooth();
MaxRollValue = globals->get_autopilot()->get_MaxRoll() / MaxRollAdjust;
RollOutValue = globals->get_autopilot()->get_RollOut() / RollOutAdjust;
MaxAileronValue = globals->get_autopilot()->get_MaxAileron() / MaxAileronAdjust;
RollOutSmoothValue = globals->get_autopilot()->get_RollOutSmooth()
MaxRollValue = fgGetDouble("/autopilot/config/max-roll-deg")
/ MaxRollAdjust;
RollOutValue = fgGetDouble("/autopilot/config/roll-out-deg")
/ RollOutAdjust;
MaxAileronValue = fgGetDouble("/autopilot/config/max-aileron")
/ MaxAileronAdjust;
RollOutSmoothValue = fgGetDouble("/autopilot/config/roll-out-smooth-deg")
/ RollOutSmoothAdjust;
puGetDefaultFonts ( &APAdjustLegendFont, &APAdjustLabelFont );
@ -510,7 +517,8 @@ void fgAPAdjustInit() {
APAdjustHS0-> setCBMode ( PUSLIDER_DELTA ) ;
APAdjustHS0-> setCallback ( maxroll_adj ) ;
sprintf( SliderText[ 0 ], "%05.2f", globals->get_autopilot()->get_MaxRoll() );
sprintf( SliderText[ 0 ], "%05.2f",
fgGetDouble("/autopilot/config/max-roll-deg") );
APAdjustMaxRollTitle = new puText ( slider_title_x, slider_y ) ;
APAdjustMaxRollTitle-> setDefaultValue ( "MaxRoll" ) ;
APAdjustMaxRollTitle-> getDefaultValue ( &s ) ;
@ -527,7 +535,8 @@ void fgAPAdjustInit() {
APAdjustHS1-> setCBMode ( PUSLIDER_DELTA ) ;
APAdjustHS1-> setCallback ( rollout_adj ) ;
sprintf( SliderText[ 1 ], "%05.2f", globals->get_autopilot()->get_RollOut() );
sprintf( SliderText[ 1 ], "%05.2f",
fgGetDouble("/autopilot/config/roll-out-deg") );
APAdjustRollOutTitle = new puText ( slider_title_x, slider_y ) ;
APAdjustRollOutTitle-> setDefaultValue ( "AdjustRollOut" ) ;
APAdjustRollOutTitle-> getDefaultValue ( &s ) ;
@ -545,7 +554,7 @@ void fgAPAdjustInit() {
APAdjustHS2-> setCallback ( rolloutsmooth_adj ) ;
sprintf( SliderText[ 2 ], "%5.2f",
globals->get_autopilot()->get_RollOutSmooth() );
fgGetDouble("/autopilot/config/roll-out-smooth-deg") );
APAdjustRollOutSmoothTitle = new puText ( slider_title_x, slider_y ) ;
APAdjustRollOutSmoothTitle-> setDefaultValue ( "RollOutSmooth" ) ;
APAdjustRollOutSmoothTitle-> getDefaultValue ( &s ) ;
@ -563,7 +572,7 @@ void fgAPAdjustInit() {
APAdjustHS3-> setCallback ( maxaileron_adj ) ;
sprintf( SliderText[ 3 ], "%05.2f",
globals->get_autopilot()->get_MaxAileron() );
fgGetDouble("/autopilot/config/max-aileron") );
APAdjustMaxAileronTitle = new puText ( slider_title_x, slider_y ) ;
APAdjustMaxAileronTitle-> setDefaultValue ( "MaxAileron" ) ;
APAdjustMaxAileronTitle-> getDefaultValue ( &s ) ;
@ -648,42 +657,40 @@ int NewWaypoint( string Tgt_Alt )
TgtAptId = Tgt_Alt;
}
FGRouteMgr *rm = (FGRouteMgr *)globals->get_subsystem("route-manager");
if ( fgFindAirportID( TgtAptId, &a ) ) {
SG_LOG( SG_GENERAL, SG_INFO,
"Adding waypoint (airport) = " << TgtAptId );
SG_LOG( SG_GENERAL, SG_INFO,
"Adding waypoint (airport) = " << TgtAptId );
sprintf( NewTgtAirportId, "%s", TgtAptId.c_str() );
sprintf( NewTgtAirportId, "%s", TgtAptId.c_str() );
SGWayPoint wp( a.longitude, a.latitude, alt,
SGWayPoint::WGS84, TgtAptId );
globals->get_route()->add_waypoint( wp );
SGWayPoint wp( a.longitude, a.latitude, alt,
SGWayPoint::WGS84, TgtAptId );
rm->add_waypoint( wp );
/* and turn on the autopilot */
globals->get_autopilot()->set_HeadingEnabled( true );
globals->get_autopilot()->set_HeadingMode( FGAutopilot::FG_HEADING_WAYPOINT
);
/* and turn on the autopilot */
fgSetString( "/autopilot/locks/heading", "true-heading-hold" );
return 1;
return 1;
} else if ( current_fixlist->query( TgtAptId, &f ) )
{
SG_LOG( SG_GENERAL, SG_INFO,
"Adding waypoint (fix) = " << TgtAptId );
} else if ( current_fixlist->query( TgtAptId, &f ) ) {
SG_LOG( SG_GENERAL, SG_INFO,
"Adding waypoint (fix) = " << TgtAptId );
sprintf( NewTgtAirportId, "%s", TgtAptId.c_str() );
sprintf( NewTgtAirportId, "%s", TgtAptId.c_str() );
SGWayPoint wp( f.get_lon(), f.get_lat(), alt,
SGWayPoint::WGS84, TgtAptId );
globals->get_route()->add_waypoint( wp );
/* and turn on the autopilot */
globals->get_autopilot()->set_HeadingEnabled( true );
globals->get_autopilot()->set_HeadingMode( FGAutopilot::FG_HEADING_WAYPOINT );
return 2;
SGWayPoint wp( f.get_lon(), f.get_lat(), alt,
SGWayPoint::WGS84, TgtAptId );
rm->add_waypoint( wp );
/* and turn on the autopilot */
fgSetString( "/autopilot/locks/heading", "true-heading-hold" );
return 2;
} else {
return 0;
}
else return 0;
}
@ -743,11 +750,16 @@ void AddWayPoint(puObject *cb)
}
delete [] WPList[i];
}
if ( globals->get_route()->size() > 0 ) {
WPListsize = globals->get_route()->size();
FGRouteMgr *rm = (FGRouteMgr *)globals->get_subsystem("route-manager");
WPListsize = rm->size();
if ( WPListsize > 0 ) {
WPList = new char* [ WPListsize + 1 ];
for (i = 0; i < globals->get_route()->size(); i++ ) {
sprintf(WPString, "%5s %3.2flon %3.2flat", globals->get_route()->get_waypoint(i).get_id().c_str(), globals->get_route()->get_waypoint(i).get_target_lon(), globals->get_route()->get_waypoint(i).get_target_lat());
for (i = 0; i < WPListsize; i++ ) {
SGWayPoint wp = rm->get_waypoint(i);
sprintf( WPString, "%5s %3.2flon %3.2flat",
wp.get_id().c_str(),
wp.get_target_lon(),
wp.get_target_lat() );
WPList [i] = new char[ strlen(WPString)+1 ];
strcpy ( WPList [i], WPString );
}
@ -777,25 +789,14 @@ void AddWayPoint(puObject *cb)
void PopWayPoint(puObject *cb)
{
globals->get_route()->delete_first();
// see if there are more waypoints on the list
if ( globals->get_route()->size() ) {
// more waypoints
globals->get_autopilot()->set_HeadingMode( FGAutopilot::FG_HEADING_WAYPOINT );
} else {
// end of the line
globals->get_autopilot()->set_HeadingMode( FGAutopilot::FG_TC_HEADING_LOCK );
// use current heading
globals->get_autopilot()
->set_TargetHeading(fgGetDouble("/orientation/heading-deg"));
}
FGRouteMgr *rm = (FGRouteMgr *)globals->get_subsystem("route-manager");
rm->pop_waypoint();
}
void ClearRoute(puObject *cb)
{
globals->get_route()->clear();
FGRouteMgr *rm = (FGRouteMgr *)globals->get_subsystem("route-manager");
rm->init();
}
void NewTgtAirportInit()

View file

@ -25,6 +25,12 @@
#ifndef _AUTO_GUI_HXX
#define _AUTO_GUI_HXX
#include <simgear/compiler.h>
#include STL_STRING
SG_USING_STD( string );
// Defines
#define AP_CURRENT_HEADING -1

View file

@ -22,6 +22,8 @@
//
// $Id$
#error choke me
#ifndef _NEWAUTO_HXX
#define _NEWAUTO_HXX

220
src/Autopilot/route_mgr.cxx Normal file
View file

@ -0,0 +1,220 @@
// route_mgr.cxx - manage a route (i.e. a collection of waypoints)
//
// Written by Curtis Olson, started January 2004.
//
// Copyright (C) 2004 Curtis L. Olson - curt@flightgear.org
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// $Id$
#include <FDM/flight.hxx>
#include <Main/fg_props.hxx>
#include "route_mgr.hxx"
FGRouteMgr::FGRouteMgr() :
route( new SGRoute ),
lon( NULL ),
lat( NULL ),
alt( NULL ),
true_hdg_deg( NULL ),
wp0_id( NULL ),
wp0_dist( NULL ),
wp0_eta( NULL ),
wp1_id( NULL ),
wp1_dist( NULL ),
wp1_eta( NULL ),
wpn_id( NULL ),
wpn_dist( NULL ),
wpn_eta( NULL )
{
cout << "route = " << route << endl;
}
FGRouteMgr::~FGRouteMgr() {
delete route;
}
void FGRouteMgr::init() {
lon = fgGetNode( "/position/longitude-deg", true );
lat = fgGetNode( "/position/latitude-deg", true );
alt = fgGetNode( "/position/altitude-ft", true );
true_hdg_deg = fgGetNode( "/autopilot/settings/true-heading-deg", true );
wp0_id = fgGetNode( "/autopilot/route-manager/wp[0]/id", true );
wp0_dist = fgGetNode( "/autopilot/route-manager/wp[0]/dist", true );
wp0_eta = fgGetNode( "/autopilot/route-manager/wp[0]/eta", true );
wp1_id = fgGetNode( "/autopilot/route-manager/wp[1]/id", true );
wp1_dist = fgGetNode( "/autopilot/route-manager/wp[1]/dist", true );
wp1_eta = fgGetNode( "/autopilot/route-manager/wp[1]/eta", true );
wpn_id = fgGetNode( "/autopilot/route-manager/wp-last/id", true );
wpn_dist = fgGetNode( "/autopilot/route-manager/wp-last/dist", true );
wpn_eta = fgGetNode( "/autopilot/route-manager/wp-last/eta", true );
route->clear();
}
void FGRouteMgr::bind() { }
void FGRouteMgr::unbind() { }
static double get_ground_speed() {
// starts in ft/s so we convert to kts
static const SGPropertyNode * speedup_node = fgGetNode("/sim/speed-up");
double ft_s = cur_fdm_state->get_V_ground_speed()
* speedup_node->getIntValue();
double kts = ft_s * SG_FEET_TO_METER * 3600 * SG_METER_TO_NM;
return kts;
}
void FGRouteMgr::update( double dt ) {
double accum = 0.0;
double wp_course, wp_distance;
char eta_str[128];
// first way point
if ( route->size() > 0 ) {
SGWayPoint wp = route->get_waypoint( 0 );
wp.CourseAndDistance( lon->getDoubleValue(), lat->getDoubleValue(),
alt->getDoubleValue(), &wp_course, &wp_distance );
true_hdg_deg->setDoubleValue( wp_course );
if ( wp_distance < 200.0 ) {
pop_waypoint();
}
}
// next way point
if ( route->size() > 0 ) {
SGWayPoint wp = route->get_waypoint( 0 );
// update the property tree info
wp0_id->setStringValue( wp.get_id().c_str() );
accum += wp_distance;
wp0_dist->setDoubleValue( accum * SG_METER_TO_NM );
double eta = accum * SG_METER_TO_NM / get_ground_speed();
if ( eta >= 100.0 ) { eta = 99.999; }
int major, minor;
if ( eta < (1.0/6.0) ) {
// within 10 minutes, bump up to min/secs
eta *= 60.0;
}
major = (int)eta;
minor = (int)((eta - (int)eta) * 60.0);
snprintf( eta_str, 128, "%d:%02d", major, minor );
wp0_eta->setStringValue( eta_str );
}
// next way point
if ( route->size() > 1 ) {
SGWayPoint wp = route->get_waypoint( 1 );
// update the property tree info
wp1_id->setStringValue( wp.get_id().c_str() );
accum += wp.get_distance();
wp1_dist->setDoubleValue( accum * SG_METER_TO_NM );
double eta = accum * SG_METER_TO_NM / get_ground_speed();
if ( eta >= 100.0 ) { eta = 99.999; }
int major, minor;
if ( eta < (1.0/6.0) ) {
// within 10 minutes, bump up to min/secs
eta *= 60.0;
}
major = (int)eta;
minor = (int)((eta - (int)eta) * 60.0);
snprintf( eta_str, 128, "%d:%02d", major, minor );
wp1_eta->setStringValue( eta_str );
}
// summarize remaining way points
if ( route->size() > 2 ) {
SGWayPoint wp;
for ( int i = 2; i < route->size(); ++i ) {
wp = route->get_waypoint( i );
accum += wp.get_distance();
}
// update the property tree info
wpn_id->setStringValue( wp.get_id().c_str() );
wpn_dist->setDoubleValue( accum * SG_METER_TO_NM );
double eta = accum * SG_METER_TO_NM / get_ground_speed();
if ( eta >= 100.0 ) { eta = 99.999; }
int major, minor;
if ( eta < (1.0/6.0) ) {
// within 10 minutes, bump up to min/secs
eta *= 60.0;
}
major = (int)eta;
minor = (int)((eta - (int)eta) * 60.0);
snprintf( eta_str, 128, "%d:%02d", major, minor );
wpn_eta->setStringValue( eta_str );
}
}
SGWayPoint FGRouteMgr::pop_waypoint() {
SGWayPoint wp;
if ( route->size() > 0 ) {
wp = route->get_first();
route->delete_first();
}
if ( route->size() <= 2 ) {
wpn_id->setStringValue( "" );
wpn_dist->setDoubleValue( 0.0 );
wpn_eta->setStringValue( "" );
}
if ( route->size() <= 1 ) {
wp1_id->setStringValue( "" );
wp1_dist->setDoubleValue( 0.0 );
wp1_eta->setStringValue( "" );
}
if ( route->size() <= 0 ) {
wp0_id->setStringValue( "" );
wp0_dist->setDoubleValue( 0.0 );
wp0_eta->setStringValue( "" );
}
return wp;
}
bool FGRouteMgr::build() {
return true;
}

109
src/Autopilot/route_mgr.hxx Normal file
View file

@ -0,0 +1,109 @@
// route_mgr.hxx - manage a route (i.e. a collection of waypoints)
//
// Written by Curtis Olson, started January 2004.
//
// Copyright (C) 2004 Curtis L. Olson - curt@flightgear.org
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// $Id$
#ifndef _ROUTE_MGR_HXX
#define _ROUTE_MGR_HXX 1
#ifndef __cplusplus
# error This library requires C++
#endif
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <simgear/compiler.h>
#include STL_STRING
#include <vector>
SG_USING_STD(string);
SG_USING_STD(vector);
#include <simgear/props/props.hxx>
#include <simgear/route/route.hxx>
#include <simgear/structure/subsystem_mgr.hxx>
/**
* Top level route manager class
*
*/
class FGRouteMgr : public SGSubsystem
{
private:
SGRoute *route;
// automatic inputs
SGPropertyNode *lon;
SGPropertyNode *lat;
SGPropertyNode *alt;
// automatic outputs
SGPropertyNode *true_hdg_deg;
SGPropertyNode *wp0_id;
SGPropertyNode *wp0_dist;
SGPropertyNode *wp0_eta;
SGPropertyNode *wp1_id;
SGPropertyNode *wp1_dist;
SGPropertyNode *wp1_eta;
SGPropertyNode *wpn_id;
SGPropertyNode *wpn_dist;
SGPropertyNode *wpn_eta;
public:
FGRouteMgr();
~FGRouteMgr();
void init ();
void bind ();
void unbind ();
void update (double dt);
bool build ();
void add_waypoint( SGWayPoint wp ) {
route->add_waypoint( wp );
}
SGWayPoint get_waypoint( int i ) const {
return route->get_waypoint(i);
}
SGWayPoint pop_waypoint();
int size() const {
return route->size();
}
};
#endif // _ROUTE_MGR_HXX

677
src/Autopilot/xmlauto.cxx Normal file
View file

@ -0,0 +1,677 @@
// xmlauto.cxx - a more flexible, generic way to build autopilots
//
// Written by Curtis Olson, started January 2004.
//
// Copyright (C) 2004 Curtis L. Olson - curt@flightgear.org
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// $Id$
#include <simgear/structure/exception.hxx>
#include <simgear/misc/sg_path.hxx>
#include <Main/fg_props.hxx>
#include <Main/globals.hxx>
#include "xmlauto.hxx"
FGPIDController::FGPIDController( SGPropertyNode *node, bool old ):
proportional( false ),
factor( 0.0 ),
offset_prop( NULL ),
offset_value( 0.0 ),
integral( false ),
gain( 0.0 ),
int_sum( 0.0 ),
one_eighty( false ),
clamp( false ),
debug( false ),
y_n( 0.0 ),
r_n( 0.0 ),
Kp( 0.0 ),
alpha( 0.1 ),
beta( 1.0 ),
gamma( 0.0 ),
Ti( 0.0 ),
Td( 0.0 ),
u_min( 0.0 ),
u_max( 0.0 ),
ep_n_1( 0.0 ),
edf_n_1( 0.0 ),
edf_n_2( 0.0 ),
u_n_1( 0.0 )
{
int i;
for ( i = 0; i < node->nChildren(); ++i ) {
SGPropertyNode *child = node->getChild(i);
string cname = child->getName();
string cval = child->getStringValue();
if ( cname == "name" ) {
name = cval;
} else if ( cname == "enable" ) {
cout << "parsing enable" << endl;
SGPropertyNode *prop = child->getChild( "prop" );
if ( prop != NULL ) {
cout << "prop = " << prop->getStringValue() << endl;
enable_prop = fgGetNode( prop->getStringValue(), true );
} else {
cout << "no prop child" << endl;
}
SGPropertyNode *val = child->getChild( "value" );
if ( val != NULL ) {
enable_value = val->getStringValue();
}
} else if ( cname == "debug" ) {
debug = child->getBoolValue();
} else if ( cname == "input" ) {
SGPropertyNode *prop = child->getChild( "prop" );
if ( prop != NULL ) {
input_prop = fgGetNode( prop->getStringValue(), true );
}
} else if ( cname == "reference" ) {
SGPropertyNode *prop = child->getChild( "prop" );
if ( prop != NULL ) {
r_n_prop = fgGetNode( prop->getStringValue(), true );
} else {
prop = child->getChild( "value" );
if ( prop != NULL ) {
r_n_value = prop->getDoubleValue();
}
}
} else if ( cname == "output" ) {
int i = 0;
SGPropertyNode *prop;
while ( (prop = child->getChild("prop", i)) != NULL ) {
SGPropertyNode *tmp = fgGetNode( prop->getStringValue(), true );
output_list.push_back( tmp );
i++;
}
prop = child->getChild( "clamp" );
if ( prop != NULL ) {
clamp = true;
SGPropertyNode *tmp;
tmp = prop->getChild( "min" );
if ( tmp != NULL ) {
u_min = tmp->getDoubleValue();
cout << "min = " << u_min << endl;
}
tmp = prop->getChild( "max" );
if ( tmp != NULL ) {
u_max = tmp->getDoubleValue();
cout << "max = " << u_max << endl;
}
}
} else if ( cname == "proportional" ) {
proportional = true;
SGPropertyNode *prop;
prop = child->getChild( "pre" );
if ( prop != NULL ) {
prop = prop->getChild( "one-eighty" );
if ( prop != NULL && prop->getBoolValue() ) {
one_eighty = true;
}
}
prop = child->getChild( "factor" );
if ( prop != NULL ) {
factor = prop->getDoubleValue();
}
prop = child->getChild( "offset" );
if ( prop != NULL ) {
SGPropertyNode *sub = prop->getChild( "prop" );
if ( sub != NULL ) {
offset_prop = fgGetNode( sub->getStringValue(), true );
cout << "offset prop = " << sub->getStringValue() << endl;
} else {
sub = prop->getChild( "value" );
if ( sub != NULL ) {
offset_value = sub->getDoubleValue();
cout << "offset value = " << offset_value << endl;
}
}
}
} else if ( cname == "integral" ) {
integral = true;
SGPropertyNode *prop;
prop = child->getChild( "gain" );
if ( prop != NULL ) {
gain = prop->getDoubleValue();
}
} else {
SG_LOG( SG_AUTOPILOT, SG_WARN, "Error in autopilot config logic" );
}
}
}
FGPIDController::FGPIDController( SGPropertyNode *node ):
proportional( false ),
factor( 0.0 ),
offset_prop( NULL ),
offset_value( 0.0 ),
integral( false ),
gain( 0.0 ),
int_sum( 0.0 ),
one_eighty( false ),
clamp( false ),
debug( false ),
y_n( 0.0 ),
r_n( 0.0 ),
Kp( 0.0 ),
alpha( 0.1 ),
beta( 1.0 ),
gamma( 0.0 ),
Ti( 0.0 ),
Td( 0.0 ),
u_min( 0.0 ),
u_max( 0.0 ),
ep_n_1( 0.0 ),
edf_n_1( 0.0 ),
edf_n_2( 0.0 ),
u_n_1( 0.0 )
{
int i;
for ( i = 0; i < node->nChildren(); ++i ) {
SGPropertyNode *child = node->getChild(i);
string cname = child->getName();
string cval = child->getStringValue();
if ( cname == "name" ) {
name = cval;
} else if ( cname == "debug" ) {
debug = child->getBoolValue();
} else if ( cname == "enable" ) {
cout << "parsing enable" << endl;
SGPropertyNode *prop = child->getChild( "prop" );
if ( prop != NULL ) {
cout << "prop = " << prop->getStringValue() << endl;
enable_prop = fgGetNode( prop->getStringValue(), true );
} else {
cout << "no prop child" << endl;
}
SGPropertyNode *val = child->getChild( "value" );
if ( val != NULL ) {
enable_value = val->getStringValue();
}
} else if ( cname == "input" ) {
SGPropertyNode *prop = child->getChild( "prop" );
if ( prop != NULL ) {
input_prop = fgGetNode( prop->getStringValue(), true );
}
} else if ( cname == "reference" ) {
SGPropertyNode *prop = child->getChild( "prop" );
if ( prop != NULL ) {
r_n_prop = fgGetNode( prop->getStringValue(), true );
} else {
prop = child->getChild( "value" );
if ( prop != NULL ) {
r_n = prop->getDoubleValue();
}
}
} else if ( cname == "output" ) {
int i = 0;
SGPropertyNode *prop;
while ( (prop = child->getChild("prop", i)) != NULL ) {
SGPropertyNode *tmp = fgGetNode( prop->getStringValue(), true );
output_list.push_back( tmp );
i++;
}
} else if ( cname == "config" ) {
SGPropertyNode *prop;
prop = child->getChild( "Kp" );
if ( prop != NULL ) {
Kp = prop->getDoubleValue();
}
prop = child->getChild( "beta" );
if ( prop != NULL ) {
beta = prop->getDoubleValue();
}
prop = child->getChild( "alpha" );
if ( prop != NULL ) {
alpha = prop->getDoubleValue();
}
prop = child->getChild( "gamma" );
if ( prop != NULL ) {
gamma = prop->getDoubleValue();
}
prop = child->getChild( "Ti" );
if ( prop != NULL ) {
Ti = prop->getDoubleValue();
}
prop = child->getChild( "Td" );
if ( prop != NULL ) {
Td = prop->getDoubleValue();
}
prop = child->getChild( "u_min" );
if ( prop != NULL ) {
u_min = prop->getDoubleValue();
}
prop = child->getChild( "u_max" );
if ( prop != NULL ) {
u_max = prop->getDoubleValue();
}
} else {
SG_LOG( SG_AUTOPILOT, SG_WARN, "Error in autopilot config logic" );
}
}
}
void FGPIDController::update_old( double dt ) {
if (enable_prop != NULL && enable_prop->getStringValue() == enable_value) {
if ( !enabled ) {
// we have just been enabled, zero out int_sum
int_sum = 0.0;
}
enabled = true;
} else {
enabled = false;
}
if ( enabled ) {
if ( debug ) cout << "Updating " << name << endl;
double input = 0.0;
if ( input_prop != NULL ) {
input = input_prop->getDoubleValue();
}
double r_n = 0.0;
if ( r_n_prop != NULL ) {
r_n = r_n_prop->getDoubleValue();
} else {
r_n = r_n_value;
}
double error = r_n - input;
if ( one_eighty ) {
while ( error < -180.0 ) { error += 360.0; }
while ( error > 180.0 ) { error -= 360.0; }
}
if ( debug ) cout << "input = " << input
<< " reference = " << r_n
<< " error = " << error
<< endl;
double prop_comp = 0.0;
double offset = 0.0;
if ( offset_prop != NULL ) {
offset = offset_prop->getDoubleValue();
if ( debug ) cout << "offset = " << offset << endl;
} else {
offset = offset_value;
}
if ( proportional ) {
prop_comp = error * factor + offset;
}
if ( integral ) {
int_sum += error * gain * dt;
} else {
int_sum = 0.0;
}
if ( debug ) cout << "prop_comp = " << prop_comp
<< " int_sum = " << int_sum << endl;
double output = prop_comp + int_sum;
if ( clamp ) {
if ( output < u_min ) {
output = u_min;
}
if ( output > u_max ) {
output = u_max;
}
}
if ( debug ) cout << "output = " << output << endl;
unsigned int i;
for ( i = 0; i < output_list.size(); ++i ) {
output_list[i]->setDoubleValue( output );
}
}
}
/*
* Roy Vegard Ovesen:
*
* Ok! Here is the PID controller algorithm that I would like to see
* implemented:
*
* delta_u_n = Kp * [ (ep_n - ep_n-1) + ((Ts/Ti)*e_n)
* + (Td/Ts)*(edf_n - 2*edf_n-1 + edf_n-2) ]
*
* u_n = u_n-1 + delta_u_n
*
* where:
*
* delta_u : The incremental output
* Kp : Proportional gain
* ep : Proportional error with reference weighing
* ep = beta * r - y
* where:
* beta : Weighing factor
* r : Reference (setpoint)
* y : Process value, measured
* e : Error
* e = r - y
* Ts : Sampling interval
* Ti : Integrator time
* Td : Derivator time
* edf : Derivate error with reference weighing and filtering
* edf_n = edf_n-1 / ((Ts/Tf) + 1) + ed_n * (Ts/Tf) / ((Ts/Tf) + 1)
* where:
* Tf : Filter time
* Tf = alpha * Td , where alpha usually is set to 0.1
* ed : Unfiltered derivate error with reference weighing
* ed = gamma * r - y
* where:
* gamma : Weighing factor
*
* u : absolute output
*
* Index n means the n'th value.
*
*
* Inputs:
* enabled ,
* y_n , r_n , beta=1 , gamma=0 , alpha=0.1 ,
* Kp , Ti , Td , Ts (is the sampling time available?)
* u_min , u_max
*
* Output:
* u_n
*/
void FGPIDController::update( double dt ) {
double ep_n; // proportional error with reference weighing
double e_n; // error
double ed_n; // derivative error
double edf_n; // derivative error filter
double Tf; // filter time
double delta_u_n; // incremental output
double u_n; // absolute output
double Ts = dt; // Sampling interval (sec)
if ( Ts <= 0.0 ) {
// do nothing if time step is not positive (i.e. no time has
// elapsed)
return;
}
if (enable_prop != NULL && enable_prop->getStringValue() == enable_value) {
enabled = true;
} else {
enabled = false;
}
if ( enabled ) {
if ( debug ) cout << "Updating " << name << endl;
double y_n = 0.0;
if ( input_prop != NULL ) {
y_n = input_prop->getDoubleValue();
}
double r_n = 0.0;
if ( r_n_prop != NULL ) {
r_n = r_n_prop->getDoubleValue();
} else {
r_n = r_n_value;
}
if ( debug ) cout << " input = " << y_n << " ref = " << r_n << endl;
// Calculates proportional error:
ep_n = beta * r_n - y_n;
if ( debug ) cout << " ep_n = " << ep_n;
if ( debug ) cout << " ep_n_1 = " << ep_n_1;
// Calculates error:
e_n = r_n - y_n;
if ( debug ) cout << " e_n = " << e_n;
// Calculates derivate error:
ed_n = gamma * r_n - y_n;
if ( debug ) cout << " ed_n = " << ed_n;
// Calculates filter time:
Tf = alpha * Td;
if ( debug ) cout << " Tf = " << Tf;
// Filters the derivate error:
edf_n = edf_n_1 / (Ts/Tf + 1)
+ ed_n * (Ts/Tf) / (Ts/Tf + 1);
if ( debug ) cout << " edf_n = " << edf_n;
// Calculates the incremental output:
delta_u_n = Kp * ( (ep_n - ep_n_1)
+ ((Ts/Ti) * e_n)
+ ((Td/Ts) * (edf_n - 2*edf_n_1 + edf_n_2)) );
if ( debug ) cout << " delta_u_n = " << delta_u_n << endl;
// Integrator anti-windup logic:
if ( delta_u_n > (u_max - u_n_1) ) {
delta_u_n = 0;
} else if ( delta_u_n < (u_min - u_n_1) ) {
delta_u_n = 0;
}
// Calculates absolute output:
u_n = u_n_1 + delta_u_n;
if ( debug ) cout << " output = " << u_n << endl;
// Updates indexed values;
u_n_1 = u_n;
ep_n_1 = ep_n;
edf_n_2 = edf_n_1;
edf_n_1 = edf_n;
unsigned int i;
for ( i = 0; i < output_list.size(); ++i ) {
output_list[i]->setDoubleValue( u_n );
}
} else if ( !enabled ) {
u_n = 0.0;
ep_n = 0.0;
edf_n = 0.0;
// Updates indexed values;
u_n_1 = u_n;
ep_n_1 = ep_n;
edf_n_2 = edf_n_1;
edf_n_1 = edf_n;
}
}
FGXMLAutopilot::FGXMLAutopilot() {
}
FGXMLAutopilot::~FGXMLAutopilot() {
}
void FGXMLAutopilot::init() {
config_props = fgGetNode( "/autopilot/new-config", true );
SGPropertyNode *path_n = fgGetNode("/sim/systems/autopilot/path");
if ( path_n ) {
SGPath config( globals->get_fg_root() );
config.append( path_n->getStringValue() );
SG_LOG( SG_ALL, SG_INFO, "Reading autopilot configuration from "
<< config.str() );
try {
readProperties( config.str(), config_props );
if ( ! build() ) {
SG_LOG( SG_ALL, SG_ALERT,
"Detected an internal inconsistancy in the autopilot");
SG_LOG( SG_ALL, SG_ALERT,
" configuration. See earlier errors for" );
SG_LOG( SG_ALL, SG_ALERT,
" details.");
exit(-1);
}
} catch (const sg_exception& exc) {
SG_LOG( SG_ALL, SG_ALERT, "Failed to load autopilot configuration: "
<< config.str() );
}
} else {
SG_LOG( SG_ALL, SG_WARN,
"No autopilot configuration specified for this model!");
}
}
void FGXMLAutopilot::reinit() {
components.clear();
build();
}
void FGXMLAutopilot::bind() {
}
void FGXMLAutopilot::unbind() {
}
bool FGXMLAutopilot::build() {
SGPropertyNode *node;
int i;
int count = config_props->nChildren();
for ( i = 0; i < count; ++i ) {
node = config_props->getChild(i);
string name = node->getName();
// cout << name << endl;
if ( name == "pid-controller" ) {
FGXMLAutoComponent *c = new FGPIDController( node );
components.push_back( c );
} else {
SG_LOG( SG_ALL, SG_ALERT, "Unknown top level section: "
<< name );
return false;
}
}
return true;
}
/*
* Update helper values
*/
static void update_helper( double dt ) {
// Estimate speed in 5,10 seconds
static SGPropertyNode *vel = fgGetNode( "/velocities/airspeed-kt", true );
static SGPropertyNode *lookahead5
= fgGetNode( "/autopilot/internal/lookahead-5-sec-airspeed-kt", true );
static SGPropertyNode *lookahead10
= fgGetNode( "/autopilot/internal/lookahead-10-sec-airspeed-kt", true );
static double average = 0.0; // average/filtered prediction
static double v_last = 0.0; // last velocity
double v = vel->getDoubleValue();
double a = 0.0;
if ( dt > 0.0 ) {
a = (v - v_last) / dt;
if ( dt < 1.0 ) {
average = (1.0 - dt) * average + dt * a;
} else {
average = a;
}
lookahead5->setDoubleValue( v + average * 5.0 );
lookahead10->setDoubleValue( v + average * 10.0 );
v_last = v;
}
// Calculate heading bug error normalized to +/- 180.0
static SGPropertyNode *bug
= fgGetNode( "/autopilot/settings/heading-bug-deg", true );
static SGPropertyNode *ind_hdg
= fgGetNode( "/instrumentation/heading-indicator/indicated-heading-deg",
true );
static SGPropertyNode *bug_error
= fgGetNode( "/autopilot/internal/heading-bug-error-deg", true );
double diff = bug->getDoubleValue() - ind_hdg->getDoubleValue();
if ( diff < -180.0 ) { diff += 360.0; }
if ( diff > 180.0 ) { diff -= 360.0; }
bug_error->setDoubleValue( diff );
// Calculate true heading error normalized to +/- 180.0
static SGPropertyNode *target_true
= fgGetNode( "/autopilot/settings/true-heading-deg", true );
static SGPropertyNode *true_hdg
= fgGetNode( "/orientation/heading-deg", true );
static SGPropertyNode *true_error
= fgGetNode( "/autopilot/internal/true-heading-error-deg", true );
diff = target_true->getDoubleValue() - true_hdg->getDoubleValue();
if ( diff < -180.0 ) { diff += 360.0; }
if ( diff > 180.0 ) { diff -= 360.0; }
true_error->setDoubleValue( diff );
// Calculate nav1 target heading error normalized to +/- 180.0
static SGPropertyNode *target_nav1
= fgGetNode( "/radios/nav[0]/radials/target-auto-hdg-deg", true );
static SGPropertyNode *true_nav1
= fgGetNode( "/autopilot/internal/nav1-heading-error-deg", true );
diff = target_nav1->getDoubleValue() - true_hdg->getDoubleValue();
if ( diff < -180.0 ) { diff += 360.0; }
if ( diff > 180.0 ) { diff -= 360.0; }
true_nav1->setDoubleValue( diff );
}
/*
* Update the list of autopilot components
*/
void FGXMLAutopilot::update( double dt ) {
update_helper( dt );
unsigned int i;
for ( i = 0; i < components.size(); ++i ) {
components[i]->update( dt );
}
}

186
src/Autopilot/xmlauto.hxx Normal file
View file

@ -0,0 +1,186 @@
// xmlauto.hxx - a more flexible, generic way to build autopilots
//
// Written by Curtis Olson, started January 2004.
//
// Copyright (C) 2004 Curtis L. Olson - curt@flightgear.org
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// $Id$
#ifndef _XMLAUTO_HXX
#define _XMLAUTO_HXX 1
#ifndef __cplusplus
# error This library requires C++
#endif
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <simgear/compiler.h>
#include STL_STRING
#include <vector>
SG_USING_STD(string);
SG_USING_STD(vector);
#include <simgear/props/props.hxx>
#include <simgear/structure/subsystem_mgr.hxx>
/**
* Base class for other autopilot components
*/
class FGXMLAutoComponent {
protected:
string name;
SGPropertyNode *enable_prop;
string enable_value;
bool enabled;
SGPropertyNode *input_prop;
SGPropertyNode *r_n_prop;
double r_n_value;
vector <SGPropertyNode *> output_list;
public:
FGXMLAutoComponent() :
enable_prop( NULL ),
enable_value( "" ),
enabled( false ),
input_prop( NULL ),
r_n_prop( NULL ),
r_n_value( 0.0 )
{ }
virtual ~FGXMLAutoComponent() {}
virtual void update (double dt) {}
inline string get_name() { return name; }
};
/**
* A simple proportional controler
*/
class FGPIDController : public FGXMLAutoComponent {
private:
// proportional component data
bool proportional;
double factor;
SGPropertyNode *offset_prop;
double offset_value;
// integral component data
bool integral;
double gain;
double int_sum;
// prep functions for error term
bool one_eighty;
// post functions for output
bool clamp;
// debug flag
bool debug;
// Input values
double y_n; // measured process value
double r_n; // reference (set point) value
// Configuration values
double Kp; // proportional gain
double alpha; // low pass filter weighing factor (usually 0.1)
double beta; // process value weighing factor for
// calculating proportional error
// (usually 1.0)
double gamma; // process value weighing factor for
// calculating derivative error
// (usually 0.0)
double Ti; // Integrator time (sec)
double Td; // Derivator time (sec)
double u_min; // Minimum output clamp
double u_max; // Maximum output clamp
// Previous state tracking values
double ep_n_1; // ep[n-1] (prop error)
double edf_n_1; // edf[n-1] (derivative error)
double edf_n_2; // edf[n-2] (derivative error)
double u_n_1; // u[n-1] (output)
public:
FGPIDController( SGPropertyNode *node );
FGPIDController( SGPropertyNode *node, bool old );
~FGPIDController() {}
void update_old( double dt );
void update( double dt );
};
/**
* Model an autopilot system.
*
*/
class FGXMLAutopilot : public SGSubsystem
{
public:
FGXMLAutopilot();
~FGXMLAutopilot();
void init();
void reinit();
void bind();
void unbind();
void update( double dt );
bool build();
protected:
typedef vector<FGXMLAutoComponent *> comp_list;
private:
bool serviceable;
SGPropertyNode *config_props;
comp_list components;
};
#endif // _XMLAUTO_HXX

View file

@ -50,7 +50,7 @@
#include <simgear/misc/sg_path.hxx>
#include <Aircraft/aircraft.hxx>
#include <Autopilot/newauto.hxx>
#include <Autopilot/xmlauto.hxx>
#include <GUI/gui.h>
#include <Main/globals.hxx>
#include <Main/fg_props.hxx>
@ -1095,8 +1095,17 @@ void drawHUD()
glDisable(GL_DEPTH_TEST);
glDisable(GL_LIGHTING);
static const SGPropertyNode * antialiased_node
= fgGetNode("/sim/hud/antialiased");
static const SGPropertyNode *antialiased_node
= fgGetNode("/sim/hud/antialiased", true);
static const SGPropertyNode *heading_enabled
= fgGetNode("/autopilot/locks/heading", true);
static const SGPropertyNode *altitude_enabled
= fgGetNode("/autopilot/locks/altitude", true);
static char hud_hdg_text[256];
static char hud_wp0_text[256];
static char hud_wp1_text[256];
static char hud_wp2_text[256];
if( antialiased_node->getBoolValue() ) {
glEnable(GL_LINE_SMOOTH);
@ -1164,35 +1173,50 @@ void drawHUD()
int apY = 480 - 80;
// char scratch[128];
// HUD_TextList.add( fgText( "AUTOPILOT", 20, apY) );
// apY -= 15;
FGAutopilot *AP = globals->get_autopilot();
if( AP->get_HeadingEnabled() ) {
HUD_TextList.add( fgText( 40, apY, AP->get_TargetHeadingStr()) );
if (strcmp( heading_enabled->getStringValue(), "dg-heading-hold") == 0 ) {
snprintf( hud_hdg_text, 256, "hdg = %.1f\n",
fgGetDouble("/autopilot/settings/heading-bug-deg") );
HUD_TextList.add( fgText( 40, apY, hud_hdg_text ) );
apY -= 15;
}
if( AP->get_AltitudeEnabled() ) {
HUD_TextList.add( fgText( 40, apY, AP->get_TargetAltitudeStr()) );
} else if ( strcmp(heading_enabled->getStringValue(), "true-heading-hold") == 0 ) {
snprintf( hud_hdg_text, 256, "hdg = %.1f\n",
fgGetDouble("/autopilot/settings/true-heading-deg") );
HUD_TextList.add( fgText( 40, apY, hud_hdg_text ) );
apY -= 15;
}
if( AP->get_HeadingMode() == FGAutopilot::FG_HEADING_WAYPOINT )
{
if ( strlen( AP->get_TargetWP1Str() ) ) {
HUD_TextList.add( fgText( 40, apY, AP->get_TargetWP1Str() ) );
string wp0_id = fgGetString( "/autopilot/route-manager/wp[0]/id" );
if ( wp0_id.length() > 0 ) {
snprintf( hud_wp0_text, 256, "%5s %6.1fnm %s", wp0_id.c_str(),
fgGetDouble( "/autopilot/route-manager/wp[0]/dist" ),
fgGetString( "/autopilot/route-manager/wp[0]/eta" ) );
HUD_TextList.add( fgText( 40, apY, hud_wp0_text ) );
apY -= 15;
}
if ( strlen( AP->get_TargetWP2Str() ) ) {
HUD_TextList.add( fgText( 40, apY, AP->get_TargetWP2Str() ) );
string wp1_id = fgGetString( "/autopilot/route-manager/wp[1]/id" );
if ( wp1_id.length() > 0 ) {
snprintf( hud_wp1_text, 256, "%5s %6.1fnm %s", wp1_id.c_str(),
fgGetDouble( "/autopilot/route-manager/wp[1]/dist" ),
fgGetString( "/autopilot/route-manager/wp[1]/eta" ) );
HUD_TextList.add( fgText( 40, apY, hud_wp1_text ) );
apY -= 15;
}
if ( strlen( AP->get_TargetWP3Str() ) ) {
HUD_TextList.add( fgText( 40, apY, AP->get_TargetWP3Str() ) );
apY -= 15;
string wp2_id = fgGetString( "/autopilot/route-manager/wp-last/id" );
if ( wp2_id.length() > 0 ) {
snprintf( hud_wp2_text, 256, "%5s %6.1fnm %s", wp2_id.c_str(),
fgGetDouble( "/autopilot/route-manager/wp-last/dist" ),
fgGetString( "/autopilot/route-manager/wp-last/eta" ) );
HUD_TextList.add( fgText( 40, apY, hud_wp2_text ) );
apY -= 15;
}
}
if ( strcmp( altitude_enabled->getStringValue(), "altitude-hold" ) == 0 ) {
HUD_TextList.add( fgText( 40, apY, (char *)fgGetString("/autopilot/settings/altitude-ft") ) );
apY -= 15;
}
HUD_TextList.draw();
HUD_LineList.draw();

View file

@ -28,6 +28,7 @@
#include <stdio.h> // snprintf
#include <simgear/compiler.h>
#include <simgear/sg_inlines.h>
#include <simgear/math/sg_random.h>
#include <simgear/math/vector.hxx>
@ -61,8 +62,12 @@ FGNavCom::FGNavCom() :
nav_heading(0.0),
nav_radial(0.0),
nav_target_radial(0.0),
nav_target_radial_true(0.0),
nav_target_auto_hdg(0.0),
nav_vol_btn(0.0),
nav_ident_btn(true)
nav_ident_btn(true),
horiz_vel(0.0),
last_x(0.0)
{
SGPath path( globals->get_fg_root() );
SGPath term = path;
@ -187,6 +192,13 @@ FGNavCom::bind ()
snprintf(propname, 256, "/radios/nav[%d]/radials/actual-deg", index);
fgTie( propname, this, &FGNavCom::get_nav_radial );
snprintf(propname, 256, "/radios/nav[%d]/radials/target-radial-deg", index);
fgTie( propname, this, &FGNavCom::get_nav_target_radial_true );
snprintf(propname, 256, "/radios/nav[%d]/radials/target-auto-hdg-deg",
index);
fgTie( propname, this, &FGNavCom::get_nav_target_auto_hdg );
snprintf(propname, 256, "/radios/nav[%d]/to-flag", index);
fgTie( propname, this, &FGNavCom::get_nav_to_flag );
@ -205,6 +217,9 @@ FGNavCom::bind ()
snprintf(propname, 256, "/radios/nav[%d]/nav-loc", index);
fgTie( propname, this, &FGNavCom::get_nav_loc );
snprintf(propname, 256, "/radios/nav[%d]/gs-rate-of-climb", index);
fgTie( propname, this, &FGNavCom::get_nav_gs_rate_of_climb );
snprintf(propname, 256, "/radios/nav[%d]/gs-needle-deflection", index);
fgTie( propname, this, &FGNavCom::get_nav_gs_deflection );
@ -425,6 +440,92 @@ FGNavCom::update(double dt)
if ( !nav_loc ) {
nav_target_radial = nav_sel_radial;
}
// Calculate some values for the nav/ils hold autopilot
double cur_radial = get_nav_reciprocal_radial();
if ( nav_loc ) {
// ILS localizers radials are already "true" in our
// database
} else {
cur_radial += nav_twist;
}
if ( get_nav_from_flag() ) {
cur_radial += 180.0;
while ( cur_radial >= 360.0 ) { cur_radial -= 360.0; }
}
// AUTOPILOT HELPERS
// determine the target radial in "true" heading
nav_target_radial_true = nav_target_radial;
if ( nav_loc ) {
// ILS localizers radials are already "true" in our
// database
} else {
// VOR radials need to have that vor's offset added in
nav_target_radial_true += nav_twist;
}
while ( nav_target_radial_true < 0.0 ) {
nav_target_radial_true += 360.0;
}
while ( nav_target_radial_true > 360.0 ) {
nav_target_radial_true -= 360.0;
}
// determine the heading adjustment needed.
double adjustment = get_nav_cdi_deflection()
* (nav_loc_dist * SG_METER_TO_NM);
SG_CLAMP_RANGE( adjustment, -30.0, 30.0 );
#if 0
// CLO - 01/24/2004 - This #ifdef'd out code makes no sense to
// me. Someone please justify it and explain why it should be
// here if they want this reenabled.
// clamp closer when inside cone when beyond 5km...
if ( nav_loc_dist > 5000 ) {
double clamp_angle = fabs(get_nav_cdi_deflection()) * 3;
if (clamp_angle < 30)
SG_CLAMP_RANGE( adjustment, -clamp_angle, clamp_angle);
}
#endif
// determine the target heading to fly to intercept the
// tgt_radial
nav_target_auto_hdg = nav_target_radial_true + adjustment;
while ( nav_target_auto_hdg < 0.0 ) { nav_target_auto_hdg += 360.0; }
while ( nav_target_auto_hdg > 360.0 ) { nav_target_auto_hdg -= 360.0; }
// cross track error
// ????
// Calculate desired rate of climb for intercepting the GS
double x = nav_gs_dist;
double y = (alt_node->getDoubleValue() - nav_elev)
* SG_FEET_TO_METER;
double current_angle = atan2( y, x ) * SGD_RADIANS_TO_DEGREES;
double target_angle = nav_target_gs;
double gs_diff = target_angle - current_angle;
// convert desired vertical path angle into a climb rate
double des_angle = current_angle - 10 * gs_diff;
// estimate horizontal speed towards ILS in meters per minute
double dist = last_x - x;
last_x = x;
double new_vel = ( dist / dt );
horiz_vel = 0.75 * horiz_vel + 0.25 * new_vel;
// double horiz_vel = cur_fdm_state->get_V_ground_speed()
// * SG_FEET_TO_METER * 60.0;
// double horiz_vel = airspeed_node->getFloatValue()
// * SG_FEET_TO_METER * 60.0;
nav_gs_rate_of_climb = -sin( des_angle * SGD_DEGREES_TO_RADIANS )
* horiz_vel * SG_METER_TO_FEET;
} else {
nav_inrange = false;
// cout << "not picking up vor. :-(" << endl;

View file

@ -96,6 +96,8 @@ class FGNavCom : public SGSubsystem
// exactly.)
double nav_sel_radial;
double nav_target_radial;
double nav_target_radial_true;
double nav_target_auto_hdg;
double nav_loclon;
double nav_loclat;
double nav_x;
@ -110,6 +112,7 @@ class FGNavCom : public SGSubsystem
sgdVec3 gs_base_vec;
double nav_gs_dist;
double nav_gs_dist_signed;
double nav_gs_rate_of_climb;
SGTimeStamp prev_time;
SGTimeStamp curr_time;
double nav_elev;
@ -119,6 +122,8 @@ class FGNavCom : public SGSubsystem
double nav_twist;
double nav_vol_btn;
bool nav_ident_btn;
double horiz_vel;
double last_x;
// model standard VOR/DME/TACAN service volumes as per AIM 1-1-8
double adjustNavRange( double stationElev, double aircraftElev,
@ -194,6 +199,12 @@ public:
inline double get_nav_alt_freq () const { return nav_alt_freq; }
inline double get_nav_sel_radial() const { return nav_sel_radial; }
inline double get_nav_target_radial() const { return nav_target_radial; }
inline double get_nav_target_radial_true() const {
return nav_target_radial_true;
}
inline double get_nav_target_auto_hdg() const {
return nav_target_auto_hdg;
}
// Calculated values.
inline bool get_comm_inrange() const { return comm_inrange; }
@ -216,6 +227,9 @@ public:
inline double get_nav_gslat() const { return nav_gslat; }
inline double get_nav_gs_dist() const { return nav_gs_dist; }
inline double get_nav_gs_dist_signed() const { return nav_gs_dist_signed; }
inline double get_nav_gs_rate_of_climb() const {
return nav_gs_rate_of_climb;
}
inline double get_nav_elev() const { return nav_elev; }
double get_nav_heading() const;
double get_nav_radial() const;

View file

@ -69,7 +69,6 @@
#include <Aircraft/aircraft.hxx>
#include <Airports/simple.hxx>
#include <Autopilot/auto_gui.hxx>
#include <Autopilot/newauto.hxx>
#include <Cockpit/panel.hxx>
#include <Controls/controls.hxx>
#include <FDM/flight.hxx>

View file

@ -3,11 +3,11 @@
#include <plib/pu.h>
#include <simgear/debug/logstream.hxx>
#include <Autopilot/auto_gui.hxx>
#include <Input/input.hxx>
#include <Main/globals.hxx>
#include <Main/fg_props.hxx>
#include <Input/input.hxx>
#include "new_gui.hxx"
#include "menubar.hxx"

View file

@ -55,11 +55,9 @@
#include <simgear/screen/screen-dump.hxx>
#include <Include/general.hxx>
//#include <Include/fg_memory.h>
#include <Aircraft/aircraft.hxx>
#include <Airports/simple.hxx>
//#include <Autopilot/auto_gui.hxx>
#include <Autopilot/newauto.hxx>
#include <Autopilot/auto_gui.hxx>
#include <Cockpit/panel.hxx>
#include <Controls/controls.hxx>
#include <FDM/flight.hxx>
@ -231,11 +229,15 @@ static inline float get_elevator() {
}
static inline bool AP_HeadingEnabled() {
return globals->get_autopilot()->get_HeadingEnabled();
static const SGPropertyNode *heading_enabled
= fgGetNode("/autopilot/locks/heading");
return ( strcmp( heading_enabled->getStringValue(), "" ) != 0 );
}
static inline bool AP_AltitudeEnabled() {
return globals->get_autopilot()->get_AltitudeEnabled();
static const SGPropertyNode *altitude_enabled
= fgGetNode("/autopilot/locks/altitude");
return ( strcmp( altitude_enabled->getStringValue(), "" ) != 0 );
}
void TurnCursorOn( void )

View file

@ -48,8 +48,8 @@
#include <simgear/props/props.hxx>
#include <Aircraft/aircraft.hxx>
#include <Autopilot/auto_gui.hxx>
#include <Autopilot/newauto.hxx>
// #include <Autopilot/auto_gui.hxx>
#include <Autopilot/xmlauto.hxx>
#include <Cockpit/hud.hxx>
#include <Cockpit/panel.hxx>
#include <Cockpit/panel_io.hxx>
@ -223,6 +223,9 @@ FGInput::makeDefault (bool status)
void
FGInput::doKey (int k, int modifiers, int x, int y)
{
static SGPropertyNode *heading_enabled
= fgGetNode("/autopilot/locks/heading", true);
// Sanity check.
if (k < 0 || k >= MAX_KEYS) {
SG_LOG(SG_INPUT, SG_WARN, "Key value " << k << " out of range");
@ -297,14 +300,11 @@ FGInput::doKey (int k, int modifiers, int x, int y)
// START SPECIALS
case 256+GLUT_KEY_F6: // F6 toggles Autopilot target location
if ( globals->get_autopilot()->get_HeadingMode() !=
FGAutopilot::FG_HEADING_WAYPOINT ) {
globals->get_autopilot()->set_HeadingMode(
FGAutopilot::FG_HEADING_WAYPOINT );
globals->get_autopilot()->set_HeadingEnabled( true );
if ( strcmp( heading_enabled->getStringValue(),
"true-heading-hold" ) != 0 ) {
heading_enabled->setStringValue( "true-heading-hold" );
} else {
globals->get_autopilot()->set_HeadingMode(
FGAutopilot::FG_TC_HEADING_LOCK );
heading_enabled->setStringValue( "" );
}
return;
}

View file

@ -54,7 +54,6 @@ fgfs_LDADD = \
$(top_builddir)/src/Main/libMain.a \
$(top_builddir)/src/Aircraft/libAircraft.a \
$(top_builddir)/src/ATC/libATC.a \
$(top_builddir)/src/Autopilot/libAutopilot.a \
$(top_builddir)/src/Cockpit/libCockpit.a \
$(top_builddir)/src/Cockpit/built_in/libBuilt_in.a \
$(top_builddir)/src/Controls/libControls.a \
@ -68,6 +67,7 @@ fgfs_LDADD = \
$(top_builddir)/src/FDM/LaRCsim/libLaRCsim.a \
$(top_builddir)/src/FDM/UIUCModel/libUIUCModel.a \
$(top_builddir)/src/GUI/libGUI.a \
$(top_builddir)/src/Autopilot/libAutopilot.a \
$(top_builddir)/src/Input/libInput.a \
$(top_builddir)/src/Instrumentation/libInstrumentation.a \
$(top_builddir)/src/Model/libModel.a \

View file

@ -479,6 +479,43 @@ do_tile_cache_reload (const SGPropertyNode * arg)
}
/**
* Set the sea level outside air temperature and assigning that to all
* boundary and aloft environment layers.
*/
static bool
do_set_sea_level_degc (const SGPropertyNode * arg)
{
double temp_sea_level_degc = arg->getDoubleValue("temp-degc", 15.0);
SGPropertyNode *node, *child;
// boundary layers
node = fgGetNode( "/environment/config/boundary" );
if ( node != NULL ) {
int i = 0;
while ( ( child = node->getNode( "entry", i ) ) != NULL ) {
child->setDoubleValue( "temperature-sea-level-degc",
temp_sea_level_degc );
++i;
}
}
// aloft layers
node = fgGetNode( "/environment/config/aloft" );
if ( node != NULL ) {
int i = 0;
while ( ( child = node->getNode( "entry", i ) ) != NULL ) {
child->setDoubleValue( "temperature-sea-level-degc",
temp_sea_level_degc );
++i;
}
}
return true;
}
/**
* Set the outside air temperature at the "current" altitude by first
* calculating the corresponding sea level temp, and assigning that to
@ -1079,6 +1116,7 @@ static struct {
{ "view-cycle", do_view_cycle },
{ "screen-capture", do_screen_capture },
{ "tile-cache-reload", do_tile_cache_reload },
{ "set-sea-level-air-temp-degc", do_set_sea_level_degc },
{ "set-outside-air-temp-degc", do_set_oat_degc },
{ "timeofday", do_timeofday },
{ "property-toggle", do_property_toggle },

View file

@ -76,7 +76,8 @@
#include <ATC/ATCmgr.hxx>
#include <ATC/AIMgr.hxx>
#include <Autopilot/auto_gui.hxx>
#include <Autopilot/newauto.hxx>
#include <Autopilot/route_mgr.hxx>
#include <Autopilot/xmlauto.hxx>
#include <Cockpit/cockpit.hxx>
#include <Cockpit/radiostack.hxx>
#include <Cockpit/panel.hxx>
@ -1504,13 +1505,19 @@ bool fgInitSubsystems() {
fgAircraftInit(); // In the future this might not be the case.
////////////////////////////////////////////////////////////////////
// Initialize the XML Autopilot subsystem.
////////////////////////////////////////////////////////////////////
globals->add_subsystem( "xml-autopilot", new FGXMLAutopilot );
globals->add_subsystem( "route-manager", new FGRouteMgr );
////////////////////////////////////////////////////////////////////
// Initialize the view manager subsystem.
////////////////////////////////////////////////////////////////////
fgInitView();
////////////////////////////////////////////////////////////////////
// Create and register the logger.
////////////////////////////////////////////////////////////////////
@ -1703,13 +1710,9 @@ bool fgInitSubsystems() {
// Initialize the autopilot subsystem.
////////////////////////////////////////////////////////////////////
globals->set_autopilot(new FGAutopilot);
globals->get_autopilot()->init();
globals->get_autopilot()->bind();
// FIXME: these should go in the
// GUI initialization code, not here.
fgAPAdjustInit();
// fgAPAdjustInit();
NewTgtAirportInit();
NewHeadingInit();
NewAltitudeInit();
@ -1842,7 +1845,6 @@ void fgReInitSubsystems()
fgInitView();
globals->get_controls()->reset_all();
globals->get_autopilot()->reset();
fgUpdateLocalTime();

View file

@ -54,8 +54,7 @@ FGGlobals::FGGlobals() :
time_params( NULL ),
ephem( NULL ),
mag( NULL ),
autopilot( NULL ),
route( NULL ),
route_mgr( NULL ),
current_panel( NULL ),
soundmgr( NULL ),
airports( NULL ),

View file

@ -59,7 +59,6 @@ class SGMagVar;
class SGMaterialLib;
class SGModelLib;
class SGPropertyNode;
class SGRoute;
class SGTime;
class SGSoundMgr;
@ -69,11 +68,11 @@ class FGAIMgr;
class FGATCMgr;
class FGATCDisplay;
class FGAircraftModel;
class FGAutopilot;
class FGControls;
class FGIO;
class FGLight;
class FGModelMgr;
class FGRouteMgr;
class FGScenery;
#ifdef FG_MPLAYER_AS
class FGMultiplayRxMgr;
@ -131,11 +130,8 @@ private:
// Material properties library
SGMaterialLib *matlib;
// Current autopilot
FGAutopilot *autopilot;
// Global autopilot "route"
SGRoute *route;
FGRouteMgr *route_mgr;
// 2D panel
FGPanel *current_panel;
@ -252,12 +248,6 @@ public:
inline SGMaterialLib *get_matlib() const { return matlib; }
inline void set_matlib( SGMaterialLib *m ) { matlib = m; }
inline FGAutopilot *get_autopilot() const { return autopilot; }
inline void set_autopilot( FGAutopilot *ap) { autopilot = ap; }
inline SGRoute *get_route() const { return route; }
inline void set_route( SGRoute *r ) { route = r; }
inline FGAirportList *get_airports() const { return airports; }
inline void set_airports( FGAirportList *a ) {airports = a; }

View file

@ -54,7 +54,6 @@
#include <simgear/ephemeris/ephemeris.hxx>
#include <simgear/scene/model/placement.hxx>
#include <simgear/math/sg_random.h>
#include <simgear/route/route.hxx>
#include <simgear/scene/model/modellib.hxx>
#ifdef FG_USE_CLOUDS_3D
@ -82,7 +81,6 @@
#include <ATC/ATCdisplay.hxx>
#include <ATC/ATCmgr.hxx>
#include <ATC/AIMgr.hxx>
#include <Autopilot/newauto.hxx>
#include <Replay/replay.hxx>
#include <Time/tmp.hxx>
#include <Time/fg_timer.hxx>
@ -885,7 +883,6 @@ void fgUpdateTimeDepCalcs() {
}
if ( ! replay_master->getBoolValue() ) {
globals->get_autopilot()->update( delta_time_sec );
cur_fdm_state->update( delta_time_sec );
} else {
FGReplay *r = (FGReplay *)(globals->get_subsystem( "replay" ));
@ -1501,9 +1498,6 @@ bool fgMainInit( int argc, char **argv ) {
// seed the random number generater
sg_srandom_time();
SGRoute *route = new SGRoute;
globals->set_route( route );
FGControls *controls = new FGControls;
globals->set_controls( controls );

View file

@ -42,8 +42,6 @@
#include <simgear/math/sg_random.h>
#include <simgear/misc/sgstream.hxx>
#include <simgear/misc/sg_path.hxx>
#include <simgear/route/route.hxx>
#include <simgear/route/waypoint.hxx>
// #include <Include/general.hxx>
// #include <Airports/simple.hxx>
@ -51,6 +49,7 @@
// #include <FDM/flight.hxx>
// #include <FDM/UIUCModel/uiuc_aircraftdir.h>
#include <Autopilot/route_mgr.hxx>
#include <GUI/gui.h>
#include "globals.hxx"
@ -618,8 +617,9 @@ parse_wp( const string& arg ) {
FGAirport a;
if ( fgFindAirportID( id, &a ) ) {
FGRouteMgr *rm = (FGRouteMgr *)globals->get_subsystem("route-manager");
SGWayPoint wp( a.longitude, a.latitude, alt, SGWayPoint::WGS84, id );
globals->get_route()->add_waypoint( wp );
rm->add_waypoint( wp );
return true;
} else {

View file

@ -330,6 +330,14 @@ PropsChannel::foundTerminator()
= args.getNode("subsystem", i-2, true);
node->setStringValue( tokens[i].c_str() );
}
} else if ( tokens[1] == "set-sea-level-air-temp-degc" ) {
for ( unsigned int i = 2; i < tokens.size(); ++i ) {
cout << "props: set-sl command = " << tokens[i]
<< endl;
SGPropertyNode *node
= args.getNode("temp-degc", i-2, true);
node->setStringValue( tokens[i].c_str() );
}
} else if ( tokens[1] == "set-outside-air-temp-degc" ) {
for ( unsigned int i = 2; i < tokens.size(); ++i ) {
cout << "props: set-oat command = " << tokens[i]

View file

@ -288,9 +288,10 @@ void FGElectricalSystem::init () {
<< config.str() );
}
} else
} else {
SG_LOG( SG_ALL, SG_WARN,
"No electrical model specified for this model!");
}
delete config_props;
}