Merge branches 'jmt/xmlauto', 'luff/kln89' and 'curt/radial'
This commit is contained in:
commit
40639d38a8
13 changed files with 474 additions and 497 deletions
|
@ -40,6 +40,20 @@
|
||||||
using std::cout;
|
using std::cout;
|
||||||
using std::endl;
|
using std::endl;
|
||||||
|
|
||||||
|
FGXMLAutoInput::FGXMLAutoInput( SGPropertyNode_ptr node, double value, double offset, double scale) :
|
||||||
|
value(0.0),
|
||||||
|
abs(false),
|
||||||
|
property(NULL),
|
||||||
|
offset(NULL),
|
||||||
|
scale(NULL),
|
||||||
|
min(NULL),
|
||||||
|
max(NULL),
|
||||||
|
_condition(NULL)
|
||||||
|
{
|
||||||
|
parse( node, value, offset, scale );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void FGXMLAutoInput::parse( SGPropertyNode_ptr node, double aValue, double aOffset, double aScale )
|
void FGXMLAutoInput::parse( SGPropertyNode_ptr node, double aValue, double aOffset, double aScale )
|
||||||
{
|
{
|
||||||
value = aValue;
|
value = aValue;
|
||||||
|
@ -151,7 +165,7 @@ double FGXMLAutoInput::get_value()
|
||||||
return abs ? fabs(value) : value;
|
return abs ? fabs(value) : value;
|
||||||
}
|
}
|
||||||
|
|
||||||
FGXMLAutoComponent::FGXMLAutoComponent( SGPropertyNode * node ) :
|
FGXMLAutoComponent::FGXMLAutoComponent() :
|
||||||
_condition( NULL ),
|
_condition( NULL ),
|
||||||
enable_prop( NULL ),
|
enable_prop( NULL ),
|
||||||
enable_value( NULL ),
|
enable_value( NULL ),
|
||||||
|
@ -162,22 +176,28 @@ FGXMLAutoComponent::FGXMLAutoComponent( SGPropertyNode * node ) :
|
||||||
debug(false),
|
debug(false),
|
||||||
enabled( false )
|
enabled( false )
|
||||||
{
|
{
|
||||||
int i;
|
}
|
||||||
|
|
||||||
|
FGXMLAutoComponent::~FGXMLAutoComponent()
|
||||||
|
{
|
||||||
|
delete enable_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FGXMLAutoComponent::parseNode(SGPropertyNode* aNode)
|
||||||
|
{
|
||||||
SGPropertyNode *prop;
|
SGPropertyNode *prop;
|
||||||
|
for (int i = 0; i < aNode->nChildren(); ++i ) {
|
||||||
|
SGPropertyNode *child = aNode->getChild(i);
|
||||||
|
string cname(child->getName());
|
||||||
|
|
||||||
for ( i = 0; i < node->nChildren(); ++i ) {
|
if (parseNodeHook(cname, child)) {
|
||||||
SGPropertyNode *child = node->getChild(i);
|
// derived class handled it, fine
|
||||||
string cname = child->getName();
|
} else if ( cname == "name" ) {
|
||||||
string cval = child->getStringValue();
|
name = child->getStringValue();
|
||||||
if ( cname == "name" ) {
|
|
||||||
name = cval;
|
|
||||||
|
|
||||||
} else if ( cname == "feedback-if-disabled" ) {
|
} else if ( cname == "feedback-if-disabled" ) {
|
||||||
feedback_if_disabled = child->getBoolValue();
|
feedback_if_disabled = child->getBoolValue();
|
||||||
|
|
||||||
} else if ( cname == "debug" ) {
|
} else if ( cname == "debug" ) {
|
||||||
debug = child->getBoolValue();
|
debug = child->getBoolValue();
|
||||||
|
|
||||||
} else if ( cname == "enable" ) {
|
} else if ( cname == "enable" ) {
|
||||||
if( (prop = child->getChild("condition")) != NULL ) {
|
if( (prop = child->getChild("condition")) != NULL ) {
|
||||||
_condition = sgReadCondition(child, prop);
|
_condition = sgReadCondition(child, prop);
|
||||||
|
@ -194,15 +214,10 @@ FGXMLAutoComponent::FGXMLAutoComponent( SGPropertyNode * node ) :
|
||||||
if ( (prop = child->getChild( "honor-passive" )) != NULL ) {
|
if ( (prop = child->getChild( "honor-passive" )) != NULL ) {
|
||||||
honor_passive = prop->getBoolValue();
|
honor_passive = prop->getBoolValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if ( cname == "input" ) {
|
} else if ( cname == "input" ) {
|
||||||
|
|
||||||
valueInput.push_back( new FGXMLAutoInput( child ) );
|
valueInput.push_back( new FGXMLAutoInput( child ) );
|
||||||
|
|
||||||
} else if ( cname == "reference" ) {
|
} else if ( cname == "reference" ) {
|
||||||
|
|
||||||
referenceInput.push_back( new FGXMLAutoInput( child ) );
|
referenceInput.push_back( new FGXMLAutoInput( child ) );
|
||||||
|
|
||||||
} else if ( cname == "output" ) {
|
} else if ( cname == "output" ) {
|
||||||
// grab all <prop> and <property> childs
|
// grab all <prop> and <property> childs
|
||||||
int found = 0;
|
int found = 0;
|
||||||
|
@ -221,20 +236,8 @@ FGXMLAutoComponent::FGXMLAutoComponent( SGPropertyNode * node ) :
|
||||||
// no <prop> elements, text node of <output> is property name
|
// no <prop> elements, text node of <output> is property name
|
||||||
if( found == 0 )
|
if( found == 0 )
|
||||||
output_list.push_back( fgGetNode(child->getStringValue(), true ) );
|
output_list.push_back( fgGetNode(child->getStringValue(), true ) );
|
||||||
|
|
||||||
} else if ( cname == "config" ) {
|
} else if ( cname == "config" ) {
|
||||||
if( (prop = child->getChild("min")) != NULL ) {
|
parseConfig(child);
|
||||||
uminInput.push_back( new FGXMLAutoInput( prop ) );
|
|
||||||
}
|
|
||||||
if( (prop = child->getChild("u_min")) != NULL ) {
|
|
||||||
uminInput.push_back( new FGXMLAutoInput( prop ) );
|
|
||||||
}
|
|
||||||
if( (prop = child->getChild("max")) != NULL ) {
|
|
||||||
umaxInput.push_back( new FGXMLAutoInput( prop ) );
|
|
||||||
}
|
|
||||||
if( (prop = child->getChild("u_max")) != NULL ) {
|
|
||||||
umaxInput.push_back( new FGXMLAutoInput( prop ) );
|
|
||||||
}
|
|
||||||
} else if ( cname == "min" ) {
|
} else if ( cname == "min" ) {
|
||||||
uminInput.push_back( new FGXMLAutoInput( child ) );
|
uminInput.push_back( new FGXMLAutoInput( child ) );
|
||||||
} else if ( cname == "u_min" ) {
|
} else if ( cname == "u_min" ) {
|
||||||
|
@ -243,13 +246,46 @@ FGXMLAutoComponent::FGXMLAutoComponent( SGPropertyNode * node ) :
|
||||||
umaxInput.push_back( new FGXMLAutoInput( child ) );
|
umaxInput.push_back( new FGXMLAutoInput( child ) );
|
||||||
} else if ( cname == "u_max" ) {
|
} else if ( cname == "u_max" ) {
|
||||||
umaxInput.push_back( new FGXMLAutoInput( child ) );
|
umaxInput.push_back( new FGXMLAutoInput( child ) );
|
||||||
|
} else {
|
||||||
|
SG_LOG(SG_AUTOPILOT, SG_ALERT, "malformed autopilot definition - unrecognized node:"
|
||||||
|
<< cname << " in section " << name);
|
||||||
|
throw sg_io_exception("XMLAuto: unrecognized component node:" + cname, "Section=" + name);
|
||||||
}
|
}
|
||||||
}
|
} // of top-level iteration
|
||||||
}
|
}
|
||||||
|
|
||||||
FGXMLAutoComponent::~FGXMLAutoComponent()
|
void FGXMLAutoComponent::parseConfig(SGPropertyNode* aConfig)
|
||||||
{
|
{
|
||||||
delete enable_value;
|
for (int i = 0; i < aConfig->nChildren(); ++i ) {
|
||||||
|
SGPropertyNode *child = aConfig->getChild(i);
|
||||||
|
string cname(child->getName());
|
||||||
|
|
||||||
|
if (parseConfigHook(cname, child)) {
|
||||||
|
// derived class handled it, fine
|
||||||
|
} else if ( cname == "min" ) {
|
||||||
|
uminInput.push_back( new FGXMLAutoInput( child ) );
|
||||||
|
} else if ( cname == "u_min" ) {
|
||||||
|
uminInput.push_back( new FGXMLAutoInput( child ) );
|
||||||
|
} else if ( cname == "max" ) {
|
||||||
|
umaxInput.push_back( new FGXMLAutoInput( child ) );
|
||||||
|
} else if ( cname == "u_max" ) {
|
||||||
|
umaxInput.push_back( new FGXMLAutoInput( child ) );
|
||||||
|
} else {
|
||||||
|
SG_LOG(SG_AUTOPILOT, SG_ALERT, "malformed autopilot definition - unrecognized config node:"
|
||||||
|
<< cname << " in section " << name);
|
||||||
|
throw sg_io_exception("XMLAuto: unrecognized config node:" + cname, "Section=" + name);
|
||||||
|
}
|
||||||
|
} // of config iteration
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FGXMLAutoComponent::parseNodeHook(const string& aName, SGPropertyNode* aNode)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FGXMLAutoComponent::parseConfigHook(const string& aName, SGPropertyNode* aNode)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FGXMLAutoComponent::isPropertyEnabled()
|
bool FGXMLAutoComponent::isPropertyEnabled()
|
||||||
|
@ -289,7 +325,7 @@ double FGXMLAutoComponent::clamp( double value )
|
||||||
}
|
}
|
||||||
|
|
||||||
FGPIDController::FGPIDController( SGPropertyNode *node ):
|
FGPIDController::FGPIDController( SGPropertyNode *node ):
|
||||||
FGXMLAutoComponent( node ),
|
FGXMLAutoComponent(),
|
||||||
alpha( 0.1 ),
|
alpha( 0.1 ),
|
||||||
beta( 1.0 ),
|
beta( 1.0 ),
|
||||||
gamma( 0.0 ),
|
gamma( 0.0 ),
|
||||||
|
@ -300,46 +336,32 @@ FGPIDController::FGPIDController( SGPropertyNode *node ):
|
||||||
desiredTs( 0.0 ),
|
desiredTs( 0.0 ),
|
||||||
elapsedTime( 0.0 )
|
elapsedTime( 0.0 )
|
||||||
{
|
{
|
||||||
int i;
|
parseNode(node);
|
||||||
for ( i = 0; i < node->nChildren(); ++i ) {
|
|
||||||
SGPropertyNode *child = node->getChild(i);
|
|
||||||
string cname = child->getName();
|
|
||||||
string cval = child->getStringValue();
|
|
||||||
if ( cname == "config" ) {
|
|
||||||
SGPropertyNode *config;
|
|
||||||
|
|
||||||
if ( (config = child->getChild( "Ts" )) != NULL ) {
|
|
||||||
desiredTs = config->getDoubleValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
Kp.push_back( new FGXMLAutoInput( child->getChild( "Kp" ) ) );
|
|
||||||
Ti.push_back( new FGXMLAutoInput( child->getChild( "Ti" ) ) );
|
|
||||||
Td.push_back( new FGXMLAutoInput( child->getChild( "Td" ) ) );
|
|
||||||
|
|
||||||
config = child->getChild( "beta" );
|
|
||||||
if ( config != NULL ) {
|
|
||||||
beta = config->getDoubleValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
config = child->getChild( "alpha" );
|
|
||||||
if ( config != NULL ) {
|
|
||||||
alpha = config->getDoubleValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
config = child->getChild( "gamma" );
|
|
||||||
if ( config != NULL ) {
|
|
||||||
gamma = config->getDoubleValue();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool FGPIDController::parseConfigHook(const string& aName, SGPropertyNode* aNode)
|
||||||
|
{
|
||||||
|
if (aName == "Ts") {
|
||||||
|
desiredTs = aNode->getDoubleValue();
|
||||||
|
} else if (aName == "Kp") {
|
||||||
|
Kp.push_back( new FGXMLAutoInput(aNode) );
|
||||||
|
} else if (aName == "Ti") {
|
||||||
|
Ti.push_back( new FGXMLAutoInput(aNode) );
|
||||||
|
} else if (aName == "Td") {
|
||||||
|
Td.push_back( new FGXMLAutoInput(aNode) );
|
||||||
|
} else if (aName == "beta") {
|
||||||
|
beta = aNode->getDoubleValue();
|
||||||
|
} else if (aName == "alpha") {
|
||||||
|
alpha = aNode->getDoubleValue();
|
||||||
|
} else if (aName == "gamma") {
|
||||||
|
gamma = aNode->getDoubleValue();
|
||||||
} else {
|
} else {
|
||||||
SG_LOG( SG_AUTOPILOT, SG_WARN, "Error in autopilot config logic" );
|
// unhandled by us, let the base class try it
|
||||||
if ( get_name().length() ) {
|
return false;
|
||||||
SG_LOG( SG_AUTOPILOT, SG_WARN, "Section = " << get_name() );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Roy Vegard Ovesen:
|
* Roy Vegard Ovesen:
|
||||||
|
@ -512,26 +534,25 @@ void FGPIDController::update( double dt ) {
|
||||||
|
|
||||||
|
|
||||||
FGPISimpleController::FGPISimpleController( SGPropertyNode *node ):
|
FGPISimpleController::FGPISimpleController( SGPropertyNode *node ):
|
||||||
FGXMLAutoComponent( node ),
|
FGXMLAutoComponent(),
|
||||||
int_sum( 0.0 )
|
int_sum( 0.0 )
|
||||||
{
|
{
|
||||||
int i;
|
parseNode(node);
|
||||||
for ( i = 0; i < node->nChildren(); ++i ) {
|
|
||||||
SGPropertyNode *child = node->getChild(i);
|
|
||||||
string cname = child->getName();
|
|
||||||
string cval = child->getStringValue();
|
|
||||||
if ( cname == "config" ) {
|
|
||||||
Kp.push_back( new FGXMLAutoInput( child->getChild( "Kp" ) ) );
|
|
||||||
Ki.push_back( new FGXMLAutoInput( child->getChild( "Ki" ) ) );
|
|
||||||
} else {
|
|
||||||
SG_LOG( SG_AUTOPILOT, SG_WARN, "Error in autopilot config logic" );
|
|
||||||
if ( get_name().length() ) {
|
|
||||||
SG_LOG( SG_AUTOPILOT, SG_WARN, "Section = " << get_name() );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool FGPISimpleController::parseConfigHook(const string& aName, SGPropertyNode* aNode)
|
||||||
|
{
|
||||||
|
if (aName == "Kp") {
|
||||||
|
Kp.push_back( new FGXMLAutoInput(aNode) );
|
||||||
|
} else if (aName == "Ki") {
|
||||||
|
Ki.push_back( new FGXMLAutoInput(aNode) );
|
||||||
|
} else {
|
||||||
|
// unhandled by us, let the base class try it
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void FGPISimpleController::update( double dt ) {
|
void FGPISimpleController::update( double dt ) {
|
||||||
|
|
||||||
|
@ -573,19 +594,23 @@ void FGPISimpleController::update( double dt ) {
|
||||||
|
|
||||||
|
|
||||||
FGPredictor::FGPredictor ( SGPropertyNode *node ):
|
FGPredictor::FGPredictor ( SGPropertyNode *node ):
|
||||||
FGXMLAutoComponent( node ),
|
FGXMLAutoComponent(),
|
||||||
average(0.0)
|
average(0.0)
|
||||||
{
|
{
|
||||||
int i;
|
parseNode(node);
|
||||||
for ( i = 0; i < node->nChildren(); ++i ) {
|
|
||||||
SGPropertyNode *child = node->getChild(i);
|
|
||||||
string cname = child->getName();
|
|
||||||
if ( cname == "seconds" ) {
|
|
||||||
seconds.push_back( new FGXMLAutoInput( child, 0 ) );
|
|
||||||
} else if ( cname == "filter-gain" ) {
|
|
||||||
filter_gain.push_back( new FGXMLAutoInput( child, 0 ) );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool FGPredictor::parseNodeHook(const string& aName, SGPropertyNode* aNode)
|
||||||
|
{
|
||||||
|
if (aName == "seconds") {
|
||||||
|
seconds.push_back( new FGXMLAutoInput( aNode, 0 ) );
|
||||||
|
} else if (aName == "filter-gain") {
|
||||||
|
filter_gain.push_back( new FGXMLAutoInput( aNode, 0 ) );
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FGPredictor::update( double dt ) {
|
void FGPredictor::update( double dt ) {
|
||||||
|
@ -634,47 +659,52 @@ void FGPredictor::update( double dt ) {
|
||||||
|
|
||||||
|
|
||||||
FGDigitalFilter::FGDigitalFilter(SGPropertyNode *node):
|
FGDigitalFilter::FGDigitalFilter(SGPropertyNode *node):
|
||||||
FGXMLAutoComponent( node ),
|
FGXMLAutoComponent(),
|
||||||
filterType(none)
|
filterType(none)
|
||||||
{
|
{
|
||||||
int i;
|
parseNode(node);
|
||||||
for ( i = 0; i < node->nChildren(); ++i ) {
|
|
||||||
SGPropertyNode *child = node->getChild(i);
|
|
||||||
string cname = child->getName();
|
|
||||||
string cval = child->getStringValue();
|
|
||||||
if ( cname == "type" ) {
|
|
||||||
if ( cval == "exponential" ) {
|
|
||||||
filterType = exponential;
|
|
||||||
} else if (cval == "double-exponential") {
|
|
||||||
filterType = doubleExponential;
|
|
||||||
} else if (cval == "moving-average") {
|
|
||||||
filterType = movingAverage;
|
|
||||||
} else if (cval == "noise-spike") {
|
|
||||||
filterType = noiseSpike;
|
|
||||||
} else if (cval == "gain") {
|
|
||||||
filterType = gain;
|
|
||||||
} else if (cval == "reciprocal") {
|
|
||||||
filterType = reciprocal;
|
|
||||||
}
|
|
||||||
} else if ( cname == "filter-time" ) {
|
|
||||||
TfInput.push_back( new FGXMLAutoInput( child, 1.0 ) );
|
|
||||||
if( filterType == none ) filterType = exponential;
|
|
||||||
} else if ( cname == "samples" ) {
|
|
||||||
samplesInput.push_back( new FGXMLAutoInput( child, 1 ) );
|
|
||||||
if( filterType == none ) filterType = movingAverage;
|
|
||||||
} else if ( cname == "max-rate-of-change" ) {
|
|
||||||
rateOfChangeInput.push_back( new FGXMLAutoInput( child, 1 ) );
|
|
||||||
if( filterType == none ) filterType = noiseSpike;
|
|
||||||
} else if ( cname == "gain" ) {
|
|
||||||
gainInput.push_back( new FGXMLAutoInput( child, 1 ) );
|
|
||||||
if( filterType == none ) filterType = gain;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
output.resize(2, 0.0);
|
output.resize(2, 0.0);
|
||||||
input.resize(samplesInput.get_value() + 1, 0.0);
|
input.resize(samplesInput.get_value() + 1, 0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool FGDigitalFilter::parseNodeHook(const string& aName, SGPropertyNode* aNode)
|
||||||
|
{
|
||||||
|
if (aName == "type" ) {
|
||||||
|
string val(aNode->getStringValue());
|
||||||
|
if ( val == "exponential" ) {
|
||||||
|
filterType = exponential;
|
||||||
|
} else if (val == "double-exponential") {
|
||||||
|
filterType = doubleExponential;
|
||||||
|
} else if (val == "moving-average") {
|
||||||
|
filterType = movingAverage;
|
||||||
|
} else if (val == "noise-spike") {
|
||||||
|
filterType = noiseSpike;
|
||||||
|
} else if (val == "gain") {
|
||||||
|
filterType = gain;
|
||||||
|
} else if (val == "reciprocal") {
|
||||||
|
filterType = reciprocal;
|
||||||
|
}
|
||||||
|
} else if (aName == "filter-time" ) {
|
||||||
|
TfInput.push_back( new FGXMLAutoInput( aNode, 1.0 ) );
|
||||||
|
if( filterType == none ) filterType = exponential;
|
||||||
|
} else if (aName == "samples" ) {
|
||||||
|
samplesInput.push_back( new FGXMLAutoInput( aNode, 1 ) );
|
||||||
|
if( filterType == none ) filterType = movingAverage;
|
||||||
|
} else if (aName == "max-rate-of-change" ) {
|
||||||
|
rateOfChangeInput.push_back( new FGXMLAutoInput( aNode, 1 ) );
|
||||||
|
if( filterType == none ) filterType = noiseSpike;
|
||||||
|
} else if (aName == "gain" ) {
|
||||||
|
gainInput.push_back( new FGXMLAutoInput( aNode, 1 ) );
|
||||||
|
if( filterType == none ) filterType = gain;
|
||||||
|
} else {
|
||||||
|
return false; // not handled by us, let the base class try
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void FGDigitalFilter::update(double dt)
|
void FGDigitalFilter::update(double dt)
|
||||||
{
|
{
|
||||||
if ( isPropertyEnabled() ) {
|
if ( isPropertyEnabled() ) {
|
||||||
|
@ -795,9 +825,9 @@ void FGXMLAutopilot::init() {
|
||||||
" details.");
|
" details.");
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
} catch (const sg_exception&) {
|
} catch (const sg_exception& e) {
|
||||||
SG_LOG( SG_ALL, SG_ALERT, "Failed to load autopilot configuration: "
|
SG_LOG( SG_ALL, SG_ALERT, "Failed to load autopilot configuration: "
|
||||||
<< config.str() );
|
<< config.str() << ":" << e.getMessage() );
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -24,30 +24,16 @@
|
||||||
#ifndef _XMLAUTO_HXX
|
#ifndef _XMLAUTO_HXX
|
||||||
#define _XMLAUTO_HXX 1
|
#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 <simgear/compiler.h>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
|
|
||||||
using std::string;
|
|
||||||
using std::vector;
|
|
||||||
using std::deque;
|
|
||||||
|
|
||||||
#include <simgear/props/props.hxx>
|
#include <simgear/props/props.hxx>
|
||||||
#include <simgear/structure/subsystem_mgr.hxx>
|
#include <simgear/structure/subsystem_mgr.hxx>
|
||||||
#include <simgear/props/condition.hxx>
|
#include <simgear/props/condition.hxx>
|
||||||
|
|
||||||
#include <Main/fg_props.hxx>
|
|
||||||
|
|
||||||
|
|
||||||
class FGXMLAutoInput : public SGReferenced {
|
class FGXMLAutoInput : public SGReferenced {
|
||||||
private:
|
private:
|
||||||
|
@ -61,17 +47,7 @@ private:
|
||||||
SGSharedPtr<const SGCondition> _condition;
|
SGSharedPtr<const SGCondition> _condition;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FGXMLAutoInput( SGPropertyNode_ptr node = NULL, double value = 0.0, double offset = 0.0, double scale = 1.0 ) :
|
FGXMLAutoInput( SGPropertyNode_ptr node = NULL, double value = 0.0, double offset = 0.0, double scale = 1.0 );
|
||||||
value(0.0),
|
|
||||||
abs(false),
|
|
||||||
property(NULL),
|
|
||||||
offset(NULL),
|
|
||||||
scale(NULL),
|
|
||||||
min(NULL),
|
|
||||||
max(NULL),
|
|
||||||
_condition(NULL) {
|
|
||||||
parse( node, value, offset, scale );
|
|
||||||
}
|
|
||||||
|
|
||||||
void parse( SGPropertyNode_ptr, double value = 0.0, double offset = 0.0, double scale = 1.0 );
|
void parse( SGPropertyNode_ptr, double value = 0.0, double offset = 0.0, double scale = 1.0 );
|
||||||
|
|
||||||
|
@ -95,7 +71,7 @@ public:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class FGXMLAutoInputList : public vector<SGSharedPtr<FGXMLAutoInput> > {
|
class FGXMLAutoInputList : public std::vector<SGSharedPtr<FGXMLAutoInput> > {
|
||||||
public:
|
public:
|
||||||
FGXMLAutoInput * get_active() {
|
FGXMLAutoInput * get_active() {
|
||||||
for (iterator it = begin(); it != end(); ++it) {
|
for (iterator it = begin(); it != end(); ++it) {
|
||||||
|
@ -119,16 +95,16 @@ class FGXMLAutoInputList : public vector<SGSharedPtr<FGXMLAutoInput> > {
|
||||||
class FGXMLAutoComponent : public SGReferenced {
|
class FGXMLAutoComponent : public SGReferenced {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
vector <SGPropertyNode_ptr> output_list;
|
std::vector <SGPropertyNode_ptr> output_list;
|
||||||
|
|
||||||
SGSharedPtr<const SGCondition> _condition;
|
SGSharedPtr<const SGCondition> _condition;
|
||||||
SGPropertyNode_ptr enable_prop;
|
SGPropertyNode_ptr enable_prop;
|
||||||
string * enable_value;
|
std::string * enable_value;
|
||||||
|
|
||||||
SGPropertyNode_ptr passive_mode;
|
SGPropertyNode_ptr passive_mode;
|
||||||
bool honor_passive;
|
bool honor_passive;
|
||||||
|
|
||||||
string name;
|
std::string name;
|
||||||
|
|
||||||
/* Feed back output property to input property if
|
/* Feed back output property to input property if
|
||||||
this filter is disabled. This is for multi-stage
|
this filter is disabled. This is for multi-stage
|
||||||
|
@ -141,6 +117,31 @@ private:
|
||||||
void do_feedback_if_disabled();
|
void do_feedback_if_disabled();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
FGXMLAutoComponent();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parse a component specification read from a property-list.
|
||||||
|
* Calls the hook methods below to allow derived classes to
|
||||||
|
* specialise parsing bevaiour.
|
||||||
|
*/
|
||||||
|
void parseNode(SGPropertyNode* aNode);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper to parse the config section
|
||||||
|
*/
|
||||||
|
void parseConfig(SGPropertyNode* aConfig);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Over-rideable hook method to allow derived classes to refine top-level
|
||||||
|
* node parsing. Return true if the node was handled, false otherwise.
|
||||||
|
*/
|
||||||
|
virtual bool parseNodeHook(const std::string& aName, SGPropertyNode* aNode);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Over-rideable hook method to allow derived classes to refine config
|
||||||
|
* node parsing. Return true if the node was handled, false otherwise.
|
||||||
|
*/
|
||||||
|
virtual bool parseConfigHook(const std::string& aName, SGPropertyNode* aNode);
|
||||||
|
|
||||||
FGXMLAutoInputList valueInput;
|
FGXMLAutoInputList valueInput;
|
||||||
FGXMLAutoInputList referenceInput;
|
FGXMLAutoInputList referenceInput;
|
||||||
|
@ -157,12 +158,11 @@ protected:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
FGXMLAutoComponent( SGPropertyNode *node);
|
|
||||||
virtual ~FGXMLAutoComponent();
|
virtual ~FGXMLAutoComponent();
|
||||||
|
|
||||||
virtual void update (double dt)=0;
|
virtual void update (double dt)=0;
|
||||||
|
|
||||||
inline const string& get_name() { return name; }
|
inline const std::string& get_name() { return name; }
|
||||||
|
|
||||||
double clamp( double value );
|
double clamp( double value );
|
||||||
|
|
||||||
|
@ -173,7 +173,7 @@ public:
|
||||||
// helpful for things like flight directors which position
|
// helpful for things like flight directors which position
|
||||||
// their vbars from the autopilot computations.
|
// their vbars from the autopilot computations.
|
||||||
if ( honor_passive && passive_mode->getBoolValue() ) return;
|
if ( honor_passive && passive_mode->getBoolValue() ) return;
|
||||||
for( vector <SGPropertyNode_ptr>::iterator it = output_list.begin(); it != output_list.end(); ++it)
|
for( std::vector <SGPropertyNode_ptr>::iterator it = output_list.begin(); it != output_list.end(); ++it)
|
||||||
(*it)->setDoubleValue( clamp( value ) );
|
(*it)->setDoubleValue( clamp( value ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -253,6 +253,8 @@ private:
|
||||||
double elapsedTime; // elapsed time (sec)
|
double elapsedTime; // elapsed time (sec)
|
||||||
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool parseConfigHook(const std::string& aName, SGPropertyNode* aNode);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -279,6 +281,8 @@ private:
|
||||||
FGXMLAutoInputList Ki;
|
FGXMLAutoInputList Ki;
|
||||||
double int_sum;
|
double int_sum;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool parseConfigHook(const std::string& aName, SGPropertyNode* aNode);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -301,6 +305,9 @@ private:
|
||||||
FGXMLAutoInputList seconds;
|
FGXMLAutoInputList seconds;
|
||||||
FGXMLAutoInputList filter_gain;
|
FGXMLAutoInputList filter_gain;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool parseNodeHook(const std::string& aName, SGPropertyNode* aNode);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FGPredictor( SGPropertyNode *node );
|
FGPredictor( SGPropertyNode *node );
|
||||||
~FGPredictor() {}
|
~FGPredictor() {}
|
||||||
|
@ -329,12 +336,15 @@ private:
|
||||||
FGXMLAutoInputList gainInput; //
|
FGXMLAutoInputList gainInput; //
|
||||||
FGXMLAutoInputList TfInput; // Filter time [s]
|
FGXMLAutoInputList TfInput; // Filter time [s]
|
||||||
|
|
||||||
deque <double> output;
|
std::deque <double> output;
|
||||||
deque <double> input;
|
std::deque <double> input;
|
||||||
enum filterTypes { exponential, doubleExponential, movingAverage,
|
enum filterTypes { exponential, doubleExponential, movingAverage,
|
||||||
noiseSpike, gain, reciprocal, none };
|
noiseSpike, gain, reciprocal, none };
|
||||||
filterTypes filterType;
|
filterTypes filterType;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool parseNodeHook(const std::string& aName, SGPropertyNode* aNode);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FGDigitalFilter(SGPropertyNode *node);
|
FGDigitalFilter(SGPropertyNode *node);
|
||||||
~FGDigitalFilter() {}
|
~FGDigitalFilter() {}
|
||||||
|
@ -365,7 +375,7 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
typedef vector<SGSharedPtr<FGXMLAutoComponent> > comp_list;
|
typedef std::vector<SGSharedPtr<FGXMLAutoComponent> > comp_list;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|
|
@ -46,10 +46,90 @@
|
||||||
#include <ATCDCL/ATCProjection.hxx>
|
#include <ATCDCL/ATCProjection.hxx>
|
||||||
#include <Main/fg_props.hxx>
|
#include <Main/fg_props.hxx>
|
||||||
#include <simgear/math/SGMath.hxx>
|
#include <simgear/math/SGMath.hxx>
|
||||||
|
#include <simgear/structure/commands.hxx>
|
||||||
#include <Airports/simple.hxx>
|
#include <Airports/simple.hxx>
|
||||||
|
|
||||||
using std::cout;
|
using std::cout;
|
||||||
|
|
||||||
|
// Command callbacks for FlightGear
|
||||||
|
|
||||||
|
static bool do_kln89_msg_pressed(const SGPropertyNode* arg) {
|
||||||
|
//cout << "do_kln89_msg_pressed called!\n";
|
||||||
|
KLN89* gps = (KLN89*)globals->get_subsystem("kln89");
|
||||||
|
gps->MsgPressed();
|
||||||
|
return(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool do_kln89_obs_pressed(const SGPropertyNode* arg) {
|
||||||
|
//cout << "do_kln89_obs_pressed called!\n";
|
||||||
|
KLN89* gps = (KLN89*)globals->get_subsystem("kln89");
|
||||||
|
gps->OBSPressed();
|
||||||
|
return(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool do_kln89_alt_pressed(const SGPropertyNode* arg) {
|
||||||
|
//cout << "do_kln89_alt_pressed called!\n";
|
||||||
|
KLN89* gps = (KLN89*)globals->get_subsystem("kln89");
|
||||||
|
gps->AltPressed();
|
||||||
|
return(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool do_kln89_nrst_pressed(const SGPropertyNode* arg) {
|
||||||
|
KLN89* gps = (KLN89*)globals->get_subsystem("kln89");
|
||||||
|
gps->NrstPressed();
|
||||||
|
return(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool do_kln89_dto_pressed(const SGPropertyNode* arg) {
|
||||||
|
KLN89* gps = (KLN89*)globals->get_subsystem("kln89");
|
||||||
|
gps->DtoPressed();
|
||||||
|
return(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool do_kln89_clr_pressed(const SGPropertyNode* arg) {
|
||||||
|
KLN89* gps = (KLN89*)globals->get_subsystem("kln89");
|
||||||
|
gps->ClrPressed();
|
||||||
|
return(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool do_kln89_ent_pressed(const SGPropertyNode* arg) {
|
||||||
|
KLN89* gps = (KLN89*)globals->get_subsystem("kln89");
|
||||||
|
gps->EntPressed();
|
||||||
|
return(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool do_kln89_crsr_pressed(const SGPropertyNode* arg) {
|
||||||
|
KLN89* gps = (KLN89*)globals->get_subsystem("kln89");
|
||||||
|
gps->CrsrPressed();
|
||||||
|
return(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool do_kln89_knob1left1(const SGPropertyNode* arg) {
|
||||||
|
KLN89* gps = (KLN89*)globals->get_subsystem("kln89");
|
||||||
|
gps->Knob1Left1();
|
||||||
|
return(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool do_kln89_knob1right1(const SGPropertyNode* arg) {
|
||||||
|
KLN89* gps = (KLN89*)globals->get_subsystem("kln89");
|
||||||
|
gps->Knob1Right1();
|
||||||
|
return(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool do_kln89_knob2left1(const SGPropertyNode* arg) {
|
||||||
|
KLN89* gps = (KLN89*)globals->get_subsystem("kln89");
|
||||||
|
gps->Knob2Left1();
|
||||||
|
return(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool do_kln89_knob2right1(const SGPropertyNode* arg) {
|
||||||
|
KLN89* gps = (KLN89*)globals->get_subsystem("kln89");
|
||||||
|
gps->Knob2Right1();
|
||||||
|
return(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// End command callbacks
|
||||||
|
|
||||||
KLN89::KLN89(RenderArea2D* instrument)
|
KLN89::KLN89(RenderArea2D* instrument)
|
||||||
: DCLGPS(instrument) {
|
: DCLGPS(instrument) {
|
||||||
_mode = KLN89_MODE_DISP;
|
_mode = KLN89_MODE_DISP;
|
||||||
|
@ -77,27 +157,28 @@ KLN89::KLN89(RenderArea2D* instrument)
|
||||||
_pixelated = false;
|
_pixelated = false;
|
||||||
|
|
||||||
// Cyclic pages
|
// Cyclic pages
|
||||||
GPSPage* apt_page = new KLN89AptPage(this);
|
_pages.clear();
|
||||||
|
KLN89Page* apt_page = new KLN89AptPage(this);
|
||||||
_pages.push_back(apt_page);
|
_pages.push_back(apt_page);
|
||||||
GPSPage* vor_page = new KLN89VorPage(this);
|
KLN89Page* vor_page = new KLN89VorPage(this);
|
||||||
_pages.push_back(vor_page);
|
_pages.push_back(vor_page);
|
||||||
GPSPage* ndb_page = new KLN89NDBPage(this);
|
KLN89Page* ndb_page = new KLN89NDBPage(this);
|
||||||
_pages.push_back(ndb_page);
|
_pages.push_back(ndb_page);
|
||||||
GPSPage* int_page = new KLN89IntPage(this);
|
KLN89Page* int_page = new KLN89IntPage(this);
|
||||||
_pages.push_back(int_page);
|
_pages.push_back(int_page);
|
||||||
GPSPage* usr_page = new KLN89UsrPage(this);
|
KLN89Page* usr_page = new KLN89UsrPage(this);
|
||||||
_pages.push_back(usr_page);
|
_pages.push_back(usr_page);
|
||||||
GPSPage* act_page = new KLN89ActPage(this);
|
KLN89Page* act_page = new KLN89ActPage(this);
|
||||||
_pages.push_back(act_page);
|
_pages.push_back(act_page);
|
||||||
GPSPage* nav_page = new KLN89NavPage(this);
|
KLN89Page* nav_page = new KLN89NavPage(this);
|
||||||
_pages.push_back(nav_page);
|
_pages.push_back(nav_page);
|
||||||
GPSPage* fpl_page = new KLN89FplPage(this);
|
KLN89Page* fpl_page = new KLN89FplPage(this);
|
||||||
_pages.push_back(fpl_page);
|
_pages.push_back(fpl_page);
|
||||||
GPSPage* cal_page = new KLN89CalPage(this);
|
KLN89Page* cal_page = new KLN89CalPage(this);
|
||||||
_pages.push_back(cal_page);
|
_pages.push_back(cal_page);
|
||||||
GPSPage* set_page = new KLN89SetPage(this);
|
KLN89Page* set_page = new KLN89SetPage(this);
|
||||||
_pages.push_back(set_page);
|
_pages.push_back(set_page);
|
||||||
GPSPage* oth_page = new KLN89OthPage(this);
|
KLN89Page* oth_page = new KLN89OthPage(this);
|
||||||
_pages.push_back(oth_page);
|
_pages.push_back(oth_page);
|
||||||
_nPages = _pages.size();
|
_nPages = _pages.size();
|
||||||
_curPage = 0;
|
_curPage = 0;
|
||||||
|
@ -196,6 +277,23 @@ void KLN89::unbind() {
|
||||||
DCLGPS::unbind();
|
DCLGPS::unbind();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void KLN89::init() {
|
||||||
|
globals->get_commands()->addCommand("kln89_msg_pressed", do_kln89_msg_pressed);
|
||||||
|
globals->get_commands()->addCommand("kln89_obs_pressed", do_kln89_obs_pressed);
|
||||||
|
globals->get_commands()->addCommand("kln89_alt_pressed", do_kln89_alt_pressed);
|
||||||
|
globals->get_commands()->addCommand("kln89_nrst_pressed", do_kln89_nrst_pressed);
|
||||||
|
globals->get_commands()->addCommand("kln89_dto_pressed", do_kln89_dto_pressed);
|
||||||
|
globals->get_commands()->addCommand("kln89_clr_pressed", do_kln89_clr_pressed);
|
||||||
|
globals->get_commands()->addCommand("kln89_ent_pressed", do_kln89_ent_pressed);
|
||||||
|
globals->get_commands()->addCommand("kln89_crsr_pressed", do_kln89_crsr_pressed);
|
||||||
|
globals->get_commands()->addCommand("kln89_knob1left1", do_kln89_knob1left1);
|
||||||
|
globals->get_commands()->addCommand("kln89_knob1right1", do_kln89_knob1right1);
|
||||||
|
globals->get_commands()->addCommand("kln89_knob2left1", do_kln89_knob2left1);
|
||||||
|
globals->get_commands()->addCommand("kln89_knob2right1", do_kln89_knob2right1);
|
||||||
|
|
||||||
|
DCLGPS::init();
|
||||||
|
}
|
||||||
|
|
||||||
void KLN89::update(double dt) {
|
void KLN89::update(double dt) {
|
||||||
// Run any positional calc's required first
|
// Run any positional calc's required first
|
||||||
DCLGPS::update(dt);
|
DCLGPS::update(dt);
|
||||||
|
@ -476,7 +574,7 @@ void KLN89::NrstPressed() {
|
||||||
void KLN89::AltPressed() {}
|
void KLN89::AltPressed() {}
|
||||||
|
|
||||||
void KLN89::OBSPressed() {
|
void KLN89::OBSPressed() {
|
||||||
DCLGPS::OBSPressed();
|
ToggleOBSMode();
|
||||||
if(_obsMode) {
|
if(_obsMode) {
|
||||||
// if(ORS 02)
|
// if(ORS 02)
|
||||||
_mode = KLN89_MODE_CRSR;
|
_mode = KLN89_MODE_CRSR;
|
||||||
|
@ -494,6 +592,10 @@ void KLN89::MsgPressed() {
|
||||||
_dispMsg = !_dispMsg;
|
_dispMsg = !_dispMsg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void KLN89::ToggleOBSMode() {
|
||||||
|
DCLGPS::ToggleOBSMode();
|
||||||
|
}
|
||||||
|
|
||||||
void KLN89::DrawBar(int page) {
|
void KLN89::DrawBar(int page) {
|
||||||
int px = 1 + (page * 15);
|
int px = 1 + (page * 15);
|
||||||
int py = 1;
|
int py = 1;
|
||||||
|
|
|
@ -31,6 +31,8 @@
|
||||||
#include <Instrumentation/dclgps.hxx>
|
#include <Instrumentation/dclgps.hxx>
|
||||||
#include "kln89_page.hxx"
|
#include "kln89_page.hxx"
|
||||||
|
|
||||||
|
class KLN89Page;
|
||||||
|
|
||||||
const int KLN89MapScales[2][21] = {{1, 2, 3, 5, 7, 10, 12, 15, 17, 20, 25, 30, 40, 60, 80, 100, 120, 160, 240, 320, 500},
|
const int KLN89MapScales[2][21] = {{1, 2, 3, 5, 7, 10, 12, 15, 17, 20, 25, 30, 40, 60, 80, 100, 120, 160, 240, 320, 500},
|
||||||
{2, 4, 6, 9, 13, 18, 22, 28, 32, 37, 46, 55, 75, 110, 150, 185, 220, 300, 440, 600, 925}};
|
{2, 4, 6, 9, 13, 18, 22, 28, 32, 37, 46, 55, 75, 110, 150, 185, 220, 300, 440, 600, 925}};
|
||||||
|
|
||||||
|
@ -48,6 +50,9 @@ const char* KLN89TimeCodes[20] = { "UTC", "GST", "GDT", "ATS", "ATD", "EST", "ED
|
||||||
typedef map<string, string> airport_id_str_map_type;
|
typedef map<string, string> airport_id_str_map_type;
|
||||||
typedef airport_id_str_map_type::iterator airport_id_str_map_iterator;
|
typedef airport_id_str_map_type::iterator airport_id_str_map_iterator;
|
||||||
|
|
||||||
|
typedef vector<KLN89Page*> kln89_page_list_type;
|
||||||
|
typedef kln89_page_list_type::iterator kln89_page_list_itr;
|
||||||
|
|
||||||
class KLN89 : public DCLGPS {
|
class KLN89 : public DCLGPS {
|
||||||
|
|
||||||
friend class KLN89Page;
|
friend class KLN89Page;
|
||||||
|
@ -71,6 +76,7 @@ public:
|
||||||
|
|
||||||
void bind();
|
void bind();
|
||||||
void unbind();
|
void unbind();
|
||||||
|
void init();
|
||||||
void update(double dt);
|
void update(double dt);
|
||||||
|
|
||||||
inline void SetTurnAnticipation(bool b) { _turnAnticipationEnabled = b; }
|
inline void SetTurnAnticipation(bool b) { _turnAnticipationEnabled = b; }
|
||||||
|
@ -100,6 +106,8 @@ public:
|
||||||
void CreateDefaultFlightPlans();
|
void CreateDefaultFlightPlans();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void ToggleOBSMode();
|
||||||
|
|
||||||
//----------------------- Drawing functions which take CHARACTER units -------------------------
|
//----------------------- Drawing functions which take CHARACTER units -------------------------
|
||||||
// Render string s in display field field at position x, y
|
// Render string s in display field field at position x, y
|
||||||
// WHERE POSITION IS IN CHARACTER UNITS!
|
// WHERE POSITION IS IN CHARACTER UNITS!
|
||||||
|
@ -193,15 +201,25 @@ private:
|
||||||
char IncChar(char c, bool gap = false, bool wrap = true);
|
char IncChar(char c, bool gap = false, bool wrap = true);
|
||||||
char DecChar(char c, bool gap = false, bool wrap = true);
|
char DecChar(char c, bool gap = false, bool wrap = true);
|
||||||
|
|
||||||
|
// ==================== Page organisation stuff =============
|
||||||
|
// The list of cyclical pages that the user can cycle through
|
||||||
|
kln89_page_list_type _pages;
|
||||||
|
|
||||||
|
// The currently active page
|
||||||
|
KLN89Page* _activePage;
|
||||||
|
// And a facility to save the immediately preceeding active page
|
||||||
|
KLN89Page* _lastActivePage;
|
||||||
|
|
||||||
// Hackish
|
// Hackish
|
||||||
int _entJump; // The page to jump back to if ent is pressed. -1 indicates no jump
|
int _entJump; // The page to jump back to if ent is pressed. -1 indicates no jump
|
||||||
bool _entRestoreCrsr; // Indicates that pressing ENT at this point should restore cursor mode
|
bool _entRestoreCrsr; // Indicates that pressing ENT at this point should restore cursor mode
|
||||||
|
|
||||||
// Misc pages
|
// Misc pages that aren't in the cyclic list.
|
||||||
// Direct To
|
// Direct To
|
||||||
GPSPage* _dir_page;
|
KLN89Page* _dir_page;
|
||||||
// Nearest
|
// Nearest
|
||||||
GPSPage* _nrst_page;
|
KLN89Page* _nrst_page;
|
||||||
|
// ====================== end of page stuff ===================
|
||||||
|
|
||||||
// Moving-map display stuff
|
// Moving-map display stuff
|
||||||
int _mapOrientation; // 0 => North (true) up, 1 => DTK up, 2 => TK up, 3 => heading up (only when connected to external heading source).
|
int _mapOrientation; // 0 => North (true) up, 1 => DTK up, 2 => TK up, 3 => heading up (only when connected to external heading source).
|
||||||
|
|
|
@ -24,11 +24,11 @@
|
||||||
#include "kln89_page.hxx"
|
#include "kln89_page.hxx"
|
||||||
#include <Main/fg_props.hxx>
|
#include <Main/fg_props.hxx>
|
||||||
|
|
||||||
KLN89Page::KLN89Page(KLN89* parent)
|
KLN89Page::KLN89Page(KLN89* parent) {
|
||||||
: GPSPage(parent) {
|
_kln89 = parent;
|
||||||
_kln89 = (KLN89*)parent;
|
|
||||||
_entInvert = false;
|
_entInvert = false;
|
||||||
_to_flag = true;
|
_to_flag = true;
|
||||||
|
_subPage = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
KLN89Page::~KLN89Page() {
|
KLN89Page::~KLN89Page() {
|
||||||
|
@ -74,14 +74,14 @@ void KLN89Page::Update(double dt) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_kln89->DrawText((_kln89->GetDistVelUnitsSI() ? "km" : "nm"), 1, 4, 3);
|
_kln89->DrawText((_kln89->GetDistVelUnitsSI() ? "km" : "nm"), 1, 4, 3);
|
||||||
GPSWaypoint* awp = _parent->GetActiveWaypoint();
|
GPSWaypoint* awp = _kln89->GetActiveWaypoint();
|
||||||
if(_kln89->_navFlagged) {
|
if(_kln89->_navFlagged) {
|
||||||
_kln89->DrawText("--.-", 1, 0 ,3);
|
_kln89->DrawText("--.-", 1, 0 ,3);
|
||||||
// Only nav1 still gets speed drawn if nav is flagged - not ACT
|
// Only nav1 still gets speed drawn if nav is flagged - not ACT
|
||||||
if(!nav1) _kln89->DrawText("------", 1, 0, 2);
|
if(!nav1) _kln89->DrawText("------", 1, 0, 2);
|
||||||
} else {
|
} else {
|
||||||
char buf[8];
|
char buf[8];
|
||||||
float f = _parent->GetDistToActiveWaypoint() * (_kln89->GetDistVelUnitsSI() ? 0.001 : SG_METER_TO_NM);
|
float f = _kln89->GetDistToActiveWaypoint() * (_kln89->GetDistVelUnitsSI() ? 0.001 : SG_METER_TO_NM);
|
||||||
snprintf(buf, 5, (f >= 100.0 ? "%4.0f" : "%4.1f"), f);
|
snprintf(buf, 5, (f >= 100.0 ? "%4.0f" : "%4.1f"), f);
|
||||||
string s = buf;
|
string s = buf;
|
||||||
_kln89->DrawText(s, 1, 4 - s.size(), 3, true);
|
_kln89->DrawText(s, 1, 4 - s.size(), 3, true);
|
||||||
|
@ -132,7 +132,9 @@ void KLN89Page::Knob1Right1() {
|
||||||
|
|
||||||
void KLN89Page::Knob2Left1() {
|
void KLN89Page::Knob2Left1() {
|
||||||
if(_kln89->_mode != KLN89_MODE_CRSR && !fgGetBool("/instrumentation/kln89/scan-pull")) {
|
if(_kln89->_mode != KLN89_MODE_CRSR && !fgGetBool("/instrumentation/kln89/scan-pull")) {
|
||||||
GPSPage::Knob2Left1();
|
_kln89->_activePage->LooseFocus();
|
||||||
|
_subPage--;
|
||||||
|
if(_subPage < 0) _subPage = _nSubPages - 1;
|
||||||
} else {
|
} else {
|
||||||
if(_uLinePos == 0 && _kln89->_obsMode) {
|
if(_uLinePos == 0 && _kln89->_obsMode) {
|
||||||
_kln89->_obsHeading--;
|
_kln89->_obsHeading--;
|
||||||
|
@ -146,7 +148,9 @@ void KLN89Page::Knob2Left1() {
|
||||||
|
|
||||||
void KLN89Page::Knob2Right1() {
|
void KLN89Page::Knob2Right1() {
|
||||||
if(_kln89->_mode != KLN89_MODE_CRSR && !fgGetBool("/instrumentation/kln89/scan-pull")) {
|
if(_kln89->_mode != KLN89_MODE_CRSR && !fgGetBool("/instrumentation/kln89/scan-pull")) {
|
||||||
GPSPage::Knob2Right1();
|
_kln89->_activePage->LooseFocus();
|
||||||
|
_subPage++;
|
||||||
|
if(_subPage >= _nSubPages) _subPage = 0;
|
||||||
} else {
|
} else {
|
||||||
if(_uLinePos == 0 && _kln89->_obsMode) {
|
if(_uLinePos == 0 && _kln89->_obsMode) {
|
||||||
_kln89->_obsHeading++;
|
_kln89->_obsHeading++;
|
||||||
|
@ -203,3 +207,12 @@ void KLN89Page::SetId(const string& s) {
|
||||||
const string& KLN89Page::GetId() {
|
const string& KLN89Page::GetId() {
|
||||||
return(_id);
|
return(_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO - this function probably shouldn't be here - FG almost certainly has better handling
|
||||||
|
// of this somewhere already.
|
||||||
|
string KLN89Page::GPSitoa(int n) {
|
||||||
|
char buf[6];
|
||||||
|
snprintf(buf, 6, "%i", n);
|
||||||
|
string s = buf;
|
||||||
|
return(s);
|
||||||
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
|
|
||||||
class KLN89;
|
class KLN89;
|
||||||
|
|
||||||
class KLN89Page : public GPSPage {
|
class KLN89Page {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
KLN89Page(KLN89* parent);
|
KLN89Page(KLN89* parent);
|
||||||
|
@ -51,10 +51,15 @@ public:
|
||||||
virtual void OBSPressed();
|
virtual void OBSPressed();
|
||||||
virtual void MsgPressed();
|
virtual void MsgPressed();
|
||||||
|
|
||||||
// See base class comments for this.
|
// Sometimes a page needs to maintain state for some return paths,
|
||||||
|
// but change it for others. The CleanUp function can be used for
|
||||||
|
// changing state for non-ENT return paths in conjunction with
|
||||||
|
// GPS::_cleanUpPage
|
||||||
virtual void CleanUp();
|
virtual void CleanUp();
|
||||||
|
|
||||||
// ditto
|
// The LooseFocus function is called when a page or subpage looses focus
|
||||||
|
// and allows pages to clean up state that is maintained whilst focus is
|
||||||
|
// retained, but lost on return.
|
||||||
virtual void LooseFocus();
|
virtual void LooseFocus();
|
||||||
|
|
||||||
inline void SetEntInvert(bool b) { _entInvert = b; }
|
inline void SetEntInvert(bool b) { _entInvert = b; }
|
||||||
|
@ -63,9 +68,21 @@ public:
|
||||||
virtual void SetId(const string& s);
|
virtual void SetId(const string& s);
|
||||||
virtual const string& GetId();
|
virtual const string& GetId();
|
||||||
|
|
||||||
|
inline int GetSubPage() { return(_subPage); }
|
||||||
|
|
||||||
|
inline int GetNSubPages() { return(_nSubPages); }
|
||||||
|
|
||||||
|
inline const string& GetName() { return(_name); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
KLN89* _kln89;
|
KLN89* _kln89;
|
||||||
|
|
||||||
|
string _name; // eg. "APT", "NAV" etc
|
||||||
|
int _nSubPages;
|
||||||
|
// _subpage is zero based
|
||||||
|
int _subPage; // The subpage gets remembered when other pages are displayed
|
||||||
|
|
||||||
// Underline position in cursor mode is not persistant when subpage is changed - hence we only need one variable per page for it.
|
// Underline position in cursor mode is not persistant when subpage is changed - hence we only need one variable per page for it.
|
||||||
// Note that pos 0 is special - this is the leg pos in field 1, so pos will normally be set to 1 when crsr is pressed.
|
// Note that pos 0 is special - this is the leg pos in field 1, so pos will normally be set to 1 when crsr is pressed.
|
||||||
// Also note that in general it doesn't seem to wrap.
|
// Also note that in general it doesn't seem to wrap.
|
||||||
|
@ -88,6 +105,9 @@ protected:
|
||||||
double _scratchpadTimer; // Used for displaying the scratchpad messages for the right amount of time.
|
double _scratchpadTimer; // Used for displaying the scratchpad messages for the right amount of time.
|
||||||
string _scratchpadLine1;
|
string _scratchpadLine1;
|
||||||
string _scratchpadLine2;
|
string _scratchpadLine2;
|
||||||
|
|
||||||
|
// TODO - remove this function from this class and use a built in method instead.
|
||||||
|
string GPSitoa(int n);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _KLN89_PAGE_HXX
|
#endif // _KLN89_PAGE_HXX
|
||||||
|
|
|
@ -52,13 +52,13 @@ private:
|
||||||
GPSWaypoint* _actWp;
|
GPSWaypoint* _actWp;
|
||||||
|
|
||||||
// The actual ACT page that gets displayed...
|
// The actual ACT page that gets displayed...
|
||||||
GPSPage* _actPage;
|
KLN89Page* _actPage;
|
||||||
// ...which points to one of the below.
|
// ...which points to one of the below.
|
||||||
GPSPage* _aptPage;
|
KLN89Page* _aptPage;
|
||||||
GPSPage* _vorPage;
|
KLN89Page* _vorPage;
|
||||||
GPSPage* _ndbPage;
|
KLN89Page* _ndbPage;
|
||||||
GPSPage* _intPage;
|
KLN89Page* _intPage;
|
||||||
GPSPage* _usrPage;
|
KLN89Page* _usrPage;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _KLN89_PAGE_ACT_HXX
|
#endif // _KLN89_PAGE_ACT_HXX
|
||||||
|
|
|
@ -144,7 +144,7 @@ void KLN89FplPage::Update(double dt) {
|
||||||
//----------------------------------------- end active FP copy ------------------------------------------------
|
//----------------------------------------- end active FP copy ------------------------------------------------
|
||||||
|
|
||||||
// Recalculate which waypoint is displayed at the top of the list if required (generally if this page has lost focus).
|
// Recalculate which waypoint is displayed at the top of the list if required (generally if this page has lost focus).
|
||||||
int idx = _parent->GetActiveWaypointIndex();
|
int idx = _kln89->GetActiveWaypointIndex();
|
||||||
if(_resetFplPos0) {
|
if(_resetFplPos0) {
|
||||||
if(waylist.size() <= 1) {
|
if(waylist.size() <= 1) {
|
||||||
_fplPos = 0;
|
_fplPos = 0;
|
||||||
|
@ -679,7 +679,7 @@ void KLN89FplPage::LooseFocus() {
|
||||||
|
|
||||||
void KLN89FplPage::EntPressed() {
|
void KLN89FplPage::EntPressed() {
|
||||||
if(_delFP) {
|
if(_delFP) {
|
||||||
_parent->ClearFlightPlan(_subPage);
|
_kln89->ClearFlightPlan(_subPage);
|
||||||
CrsrPressed();
|
CrsrPressed();
|
||||||
} else if(_delWp) {
|
} else if(_delWp) {
|
||||||
int pos = _uLinePos - 4 + _fplPos;
|
int pos = _uLinePos - 4 + _fplPos;
|
||||||
|
@ -750,7 +750,7 @@ void KLN89FplPage::EntPressed() {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Use
|
// Use
|
||||||
_parent->ClearFlightPlan(0);
|
_kln89->ClearFlightPlan(0);
|
||||||
for(unsigned int i=0; i<_kln89->_flightPlans[_subPage]->waypoints.size(); ++i) {
|
for(unsigned int i=0; i<_kln89->_flightPlans[_subPage]->waypoints.size(); ++i) {
|
||||||
GPSWaypoint* wp = new GPSWaypoint;
|
GPSWaypoint* wp = new GPSWaypoint;
|
||||||
*wp = *(_kln89->_flightPlans[_subPage]->waypoints[i]);
|
*wp = *(_kln89->_flightPlans[_subPage]->waypoints[i]);
|
||||||
|
@ -759,13 +759,13 @@ void KLN89FplPage::EntPressed() {
|
||||||
_kln89->OrientateToActiveFlightPlan();
|
_kln89->OrientateToActiveFlightPlan();
|
||||||
_subPage = 0;
|
_subPage = 0;
|
||||||
}
|
}
|
||||||
_parent->CrsrPressed();
|
_kln89->CrsrPressed();
|
||||||
} else if(_uLinePos == 2) {
|
} else if(_uLinePos == 2) {
|
||||||
if(_kln89->_flightPlans[_subPage]->IsEmpty()) {
|
if(_kln89->_flightPlans[_subPage]->IsEmpty()) {
|
||||||
// ERROR !!!
|
// ERROR !!!
|
||||||
} else {
|
} else {
|
||||||
// Use Invert
|
// Use Invert
|
||||||
_parent->ClearFlightPlan(0);
|
_kln89->ClearFlightPlan(0);
|
||||||
for(unsigned int i=0; i<_kln89->_flightPlans[_subPage]->waypoints.size(); ++i) {
|
for(unsigned int i=0; i<_kln89->_flightPlans[_subPage]->waypoints.size(); ++i) {
|
||||||
GPSWaypoint* wp = new GPSWaypoint;
|
GPSWaypoint* wp = new GPSWaypoint;
|
||||||
*wp = *(_kln89->_flightPlans[_subPage]->waypoints[i]);
|
*wp = *(_kln89->_flightPlans[_subPage]->waypoints[i]);
|
||||||
|
@ -774,7 +774,7 @@ void KLN89FplPage::EntPressed() {
|
||||||
}
|
}
|
||||||
_kln89->OrientateToActiveFlightPlan();
|
_kln89->OrientateToActiveFlightPlan();
|
||||||
}
|
}
|
||||||
_parent->CrsrPressed();
|
_kln89->CrsrPressed();
|
||||||
_subPage = 0;
|
_subPage = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,8 +48,8 @@ KLN89NavPage::~KLN89NavPage() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void KLN89NavPage::Update(double dt) {
|
void KLN89NavPage::Update(double dt) {
|
||||||
GPSFlightPlan* fp = ((KLN89*)_parent)->_activeFP;
|
GPSFlightPlan* fp = _kln89->_activeFP;
|
||||||
GPSWaypoint* awp = _parent->GetActiveWaypoint();
|
GPSWaypoint* awp = _kln89->GetActiveWaypoint();
|
||||||
// Scan-pull out on nav4 page switches off the cursor
|
// Scan-pull out on nav4 page switches off the cursor
|
||||||
if(3 == _subPage && fgGetBool("/instrumentation/kln89/scan-pull")) { _kln89->_mode = KLN89_MODE_DISP; }
|
if(3 == _subPage && fgGetBool("/instrumentation/kln89/scan-pull")) { _kln89->_mode = KLN89_MODE_DISP; }
|
||||||
bool crsr = (_kln89->_mode == KLN89_MODE_CRSR);
|
bool crsr = (_kln89->_mode == KLN89_MODE_CRSR);
|
||||||
|
|
|
@ -26,7 +26,6 @@
|
||||||
#include "dclgps.hxx"
|
#include "dclgps.hxx"
|
||||||
|
|
||||||
#include <simgear/sg_inlines.h>
|
#include <simgear/sg_inlines.h>
|
||||||
#include <simgear/structure/commands.hxx>
|
|
||||||
#include <simgear/timing/sg_time.hxx>
|
#include <simgear/timing/sg_time.hxx>
|
||||||
#include <simgear/magvar/magvar.hxx>
|
#include <simgear/magvar/magvar.hxx>
|
||||||
|
|
||||||
|
@ -39,85 +38,6 @@
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
// Command callbacks for FlightGear
|
|
||||||
|
|
||||||
static bool do_kln89_msg_pressed(const SGPropertyNode* arg) {
|
|
||||||
//cout << "do_kln89_msg_pressed called!\n";
|
|
||||||
DCLGPS* gps = (DCLGPS*)globals->get_subsystem("kln89");
|
|
||||||
gps->MsgPressed();
|
|
||||||
return(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool do_kln89_obs_pressed(const SGPropertyNode* arg) {
|
|
||||||
//cout << "do_kln89_obs_pressed called!\n";
|
|
||||||
DCLGPS* gps = (DCLGPS*)globals->get_subsystem("kln89");
|
|
||||||
gps->OBSPressed();
|
|
||||||
return(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool do_kln89_alt_pressed(const SGPropertyNode* arg) {
|
|
||||||
//cout << "do_kln89_alt_pressed called!\n";
|
|
||||||
DCLGPS* gps = (DCLGPS*)globals->get_subsystem("kln89");
|
|
||||||
gps->AltPressed();
|
|
||||||
return(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool do_kln89_nrst_pressed(const SGPropertyNode* arg) {
|
|
||||||
DCLGPS* gps = (DCLGPS*)globals->get_subsystem("kln89");
|
|
||||||
gps->NrstPressed();
|
|
||||||
return(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool do_kln89_dto_pressed(const SGPropertyNode* arg) {
|
|
||||||
DCLGPS* gps = (DCLGPS*)globals->get_subsystem("kln89");
|
|
||||||
gps->DtoPressed();
|
|
||||||
return(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool do_kln89_clr_pressed(const SGPropertyNode* arg) {
|
|
||||||
DCLGPS* gps = (DCLGPS*)globals->get_subsystem("kln89");
|
|
||||||
gps->ClrPressed();
|
|
||||||
return(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool do_kln89_ent_pressed(const SGPropertyNode* arg) {
|
|
||||||
DCLGPS* gps = (DCLGPS*)globals->get_subsystem("kln89");
|
|
||||||
gps->EntPressed();
|
|
||||||
return(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool do_kln89_crsr_pressed(const SGPropertyNode* arg) {
|
|
||||||
DCLGPS* gps = (DCLGPS*)globals->get_subsystem("kln89");
|
|
||||||
gps->CrsrPressed();
|
|
||||||
return(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool do_kln89_knob1left1(const SGPropertyNode* arg) {
|
|
||||||
DCLGPS* gps = (DCLGPS*)globals->get_subsystem("kln89");
|
|
||||||
gps->Knob1Left1();
|
|
||||||
return(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool do_kln89_knob1right1(const SGPropertyNode* arg) {
|
|
||||||
DCLGPS* gps = (DCLGPS*)globals->get_subsystem("kln89");
|
|
||||||
gps->Knob1Right1();
|
|
||||||
return(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool do_kln89_knob2left1(const SGPropertyNode* arg) {
|
|
||||||
DCLGPS* gps = (DCLGPS*)globals->get_subsystem("kln89");
|
|
||||||
gps->Knob2Left1();
|
|
||||||
return(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool do_kln89_knob2right1(const SGPropertyNode* arg) {
|
|
||||||
DCLGPS* gps = (DCLGPS*)globals->get_subsystem("kln89");
|
|
||||||
gps->Knob2Right1();
|
|
||||||
return(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// End command callbacks
|
|
||||||
|
|
||||||
GPSWaypoint::GPSWaypoint() {
|
GPSWaypoint::GPSWaypoint() {
|
||||||
appType = GPS_APP_NONE;
|
appType = GPS_APP_NONE;
|
||||||
}
|
}
|
||||||
|
@ -222,58 +142,12 @@ ClockTime::ClockTime(int hr, int min) {
|
||||||
ClockTime::~ClockTime() {
|
ClockTime::~ClockTime() {
|
||||||
}
|
}
|
||||||
|
|
||||||
GPSPage::GPSPage(DCLGPS* parent) {
|
|
||||||
_parent = parent;
|
|
||||||
_subPage = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
GPSPage::~GPSPage() {
|
|
||||||
}
|
|
||||||
|
|
||||||
void GPSPage::Update(double dt) {}
|
|
||||||
|
|
||||||
void GPSPage::Knob1Left1() {}
|
|
||||||
void GPSPage::Knob1Right1() {}
|
|
||||||
|
|
||||||
void GPSPage::Knob2Left1() {
|
|
||||||
_parent->_activePage->LooseFocus();
|
|
||||||
_subPage--;
|
|
||||||
if(_subPage < 0) _subPage = _nSubPages - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GPSPage::Knob2Right1() {
|
|
||||||
_parent->_activePage->LooseFocus();
|
|
||||||
_subPage++;
|
|
||||||
if(_subPage >= _nSubPages) _subPage = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GPSPage::CrsrPressed() {}
|
|
||||||
void GPSPage::EntPressed() {}
|
|
||||||
void GPSPage::ClrPressed() {}
|
|
||||||
void GPSPage::DtoPressed() {}
|
|
||||||
void GPSPage::NrstPressed() {}
|
|
||||||
void GPSPage::AltPressed() {}
|
|
||||||
void GPSPage::OBSPressed() {}
|
|
||||||
void GPSPage::MsgPressed() {}
|
|
||||||
|
|
||||||
string GPSPage::GPSitoa(int n) {
|
|
||||||
char buf[6];
|
|
||||||
snprintf(buf, 6, "%i", n);
|
|
||||||
string s = buf;
|
|
||||||
return(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GPSPage::CleanUp() {}
|
|
||||||
void GPSPage::LooseFocus() {}
|
|
||||||
void GPSPage::SetId(const string& s) {}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------- //
|
// ------------------------------------------------------------------------------------- //
|
||||||
|
|
||||||
DCLGPS::DCLGPS(RenderArea2D* instrument) {
|
DCLGPS::DCLGPS(RenderArea2D* instrument) {
|
||||||
_instrument = instrument;
|
_instrument = instrument;
|
||||||
_nFields = 1;
|
_nFields = 1;
|
||||||
_maxFields = 2;
|
_maxFields = 2;
|
||||||
_pages.clear();
|
|
||||||
|
|
||||||
// Units - lets default to US units - FG can set them to other units from config during startup if desired.
|
// Units - lets default to US units - FG can set them to other units from config during startup if desired.
|
||||||
_altUnits = GPS_ALT_UNITS_FT;
|
_altUnits = GPS_ALT_UNITS_FT;
|
||||||
|
@ -361,18 +235,6 @@ void DCLGPS::draw(osg::State& state) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void DCLGPS::init() {
|
void DCLGPS::init() {
|
||||||
globals->get_commands()->addCommand("kln89_msg_pressed", do_kln89_msg_pressed);
|
|
||||||
globals->get_commands()->addCommand("kln89_obs_pressed", do_kln89_obs_pressed);
|
|
||||||
globals->get_commands()->addCommand("kln89_alt_pressed", do_kln89_alt_pressed);
|
|
||||||
globals->get_commands()->addCommand("kln89_nrst_pressed", do_kln89_nrst_pressed);
|
|
||||||
globals->get_commands()->addCommand("kln89_dto_pressed", do_kln89_dto_pressed);
|
|
||||||
globals->get_commands()->addCommand("kln89_clr_pressed", do_kln89_clr_pressed);
|
|
||||||
globals->get_commands()->addCommand("kln89_ent_pressed", do_kln89_ent_pressed);
|
|
||||||
globals->get_commands()->addCommand("kln89_crsr_pressed", do_kln89_crsr_pressed);
|
|
||||||
globals->get_commands()->addCommand("kln89_knob1left1", do_kln89_knob1left1);
|
|
||||||
globals->get_commands()->addCommand("kln89_knob1right1", do_kln89_knob1right1);
|
|
||||||
globals->get_commands()->addCommand("kln89_knob2left1", do_kln89_knob2left1);
|
|
||||||
globals->get_commands()->addCommand("kln89_knob2right1", do_kln89_knob2right1);
|
|
||||||
|
|
||||||
// Not sure if this should be here, but OK for now.
|
// Not sure if this should be here, but OK for now.
|
||||||
CreateDefaultFlightPlans();
|
CreateDefaultFlightPlans();
|
||||||
|
@ -659,6 +521,15 @@ void DCLGPS::update(double dt) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GPSWaypoint* DCLGPS::GetActiveWaypoint() {
|
||||||
|
return &_activeWaypoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns meters
|
||||||
|
float DCLGPS::GetDistToActiveWaypoint() {
|
||||||
|
return _dist2Act;
|
||||||
|
}
|
||||||
|
|
||||||
// I don't yet fully understand all the gotchas about where to source time from.
|
// I don't yet fully understand all the gotchas about where to source time from.
|
||||||
// This function sets the initial timer before the clock exports properties
|
// This function sets the initial timer before the clock exports properties
|
||||||
// and the one below uses the clock to be consistent with the rest of the code.
|
// and the one below uses the clock to be consistent with the rest of the code.
|
||||||
|
@ -709,18 +580,7 @@ void DCLGPS::DtoCancel() {
|
||||||
_dto = false;
|
_dto = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DCLGPS::Knob1Left1() {}
|
void DCLGPS::ToggleOBSMode() {
|
||||||
void DCLGPS::Knob1Right1() {}
|
|
||||||
void DCLGPS::Knob2Left1() {}
|
|
||||||
void DCLGPS::Knob2Right1() {}
|
|
||||||
void DCLGPS::CrsrPressed() { _activePage->CrsrPressed(); }
|
|
||||||
void DCLGPS::EntPressed() { _activePage->EntPressed(); }
|
|
||||||
void DCLGPS::ClrPressed() { _activePage->ClrPressed(); }
|
|
||||||
void DCLGPS::DtoPressed() {}
|
|
||||||
void DCLGPS::NrstPressed() {}
|
|
||||||
void DCLGPS::AltPressed() {}
|
|
||||||
|
|
||||||
void DCLGPS::OBSPressed() {
|
|
||||||
_obsMode = !_obsMode;
|
_obsMode = !_obsMode;
|
||||||
if(_obsMode) {
|
if(_obsMode) {
|
||||||
if(!_activeWaypoint.id.empty()) {
|
if(!_activeWaypoint.id.empty()) {
|
||||||
|
@ -742,8 +602,6 @@ void DCLGPS::SetOBSFromWaypoint() {
|
||||||
_fromWaypoint.id = "OBSWP";
|
_fromWaypoint.id = "OBSWP";
|
||||||
}
|
}
|
||||||
|
|
||||||
void DCLGPS::MsgPressed() {}
|
|
||||||
|
|
||||||
void DCLGPS::CDIFSDIncrease() {
|
void DCLGPS::CDIFSDIncrease() {
|
||||||
if(_currentCdiScaleIndex == 0) {
|
if(_currentCdiScaleIndex == 0) {
|
||||||
_currentCdiScaleIndex = _cdiScales.size() - 1;
|
_currentCdiScaleIndex = _cdiScales.size() - 1;
|
||||||
|
|
|
@ -186,67 +186,9 @@ private:
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------
|
||||||
|
|
||||||
class DCLGPS;
|
|
||||||
|
|
||||||
class GPSPage {
|
|
||||||
|
|
||||||
public:
|
|
||||||
GPSPage(DCLGPS* parent);
|
|
||||||
virtual ~GPSPage() = 0;
|
|
||||||
virtual void Update(double dt);
|
|
||||||
virtual void Knob1Left1();
|
|
||||||
virtual void Knob1Right1();
|
|
||||||
virtual void Knob2Left1();
|
|
||||||
virtual void Knob2Right1();
|
|
||||||
virtual void CrsrPressed();
|
|
||||||
virtual void EntPressed();
|
|
||||||
virtual void ClrPressed();
|
|
||||||
virtual void DtoPressed();
|
|
||||||
virtual void NrstPressed();
|
|
||||||
virtual void AltPressed();
|
|
||||||
virtual void OBSPressed();
|
|
||||||
virtual void MsgPressed();
|
|
||||||
|
|
||||||
// Sometimes a page needs to maintain state for some return paths,
|
|
||||||
// but change it for others. The CleanUp function can be used for
|
|
||||||
// changing state for non-ENT return paths in conjunction with
|
|
||||||
// GPS::_cleanUpPage
|
|
||||||
virtual void CleanUp();
|
|
||||||
|
|
||||||
// The LooseFocus function is called when a page or subpage looses focus
|
|
||||||
// and allows pages to clean up state that is maintained whilst focus is
|
|
||||||
// retained, but lost on return.
|
|
||||||
virtual void LooseFocus();
|
|
||||||
|
|
||||||
// Allows pages that display info for a given ID to have it set/get if they implement these functions.
|
|
||||||
virtual void SetId(const string& s);
|
|
||||||
virtual const string& GetId()=0;
|
|
||||||
|
|
||||||
inline int GetSubPage() { return(_subPage); }
|
|
||||||
|
|
||||||
inline int GetNSubPages() { return(_nSubPages); }
|
|
||||||
|
|
||||||
inline const string& GetName() { return(_name); }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
DCLGPS* _parent;
|
|
||||||
string _name; // eg. "APT", "NAV" etc
|
|
||||||
int _nSubPages;
|
|
||||||
// _subpage is zero based
|
|
||||||
int _subPage; // The subpage gets remembered when other pages are displayed
|
|
||||||
string GPSitoa(int n);
|
|
||||||
};
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
typedef vector<GPSPage*> gps_page_list_type;
|
|
||||||
typedef gps_page_list_type::iterator gps_page_list_itr;
|
|
||||||
|
|
||||||
// TODO - merge generic GPS functions instead and split out KLN specific stuff.
|
// TODO - merge generic GPS functions instead and split out KLN specific stuff.
|
||||||
class DCLGPS : public SGSubsystem {
|
class DCLGPS : public SGSubsystem {
|
||||||
|
|
||||||
friend class GPSPage;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DCLGPS(RenderArea2D* instrument);
|
DCLGPS(RenderArea2D* instrument);
|
||||||
virtual ~DCLGPS() = 0;
|
virtual ~DCLGPS() = 0;
|
||||||
|
@ -266,18 +208,7 @@ public:
|
||||||
// Render a char at a given position as above
|
// Render a char at a given position as above
|
||||||
virtual void DrawChar(char c, int field, int px, int py, bool bold = false);
|
virtual void DrawChar(char c, int field, int px, int py, bool bold = false);
|
||||||
|
|
||||||
virtual void Knob1Right1();
|
virtual void ToggleOBSMode();
|
||||||
virtual void Knob1Left1();
|
|
||||||
virtual void Knob2Right1();
|
|
||||||
virtual void Knob2Left1();
|
|
||||||
virtual void CrsrPressed();
|
|
||||||
virtual void EntPressed();
|
|
||||||
virtual void ClrPressed();
|
|
||||||
virtual void DtoPressed();
|
|
||||||
virtual void NrstPressed();
|
|
||||||
virtual void AltPressed();
|
|
||||||
virtual void OBSPressed();
|
|
||||||
virtual void MsgPressed();
|
|
||||||
|
|
||||||
// Set the number of fields
|
// Set the number of fields
|
||||||
inline void SetNumFields(int n) { _nFields = (n > _maxFields ? _maxFields : (n < 1 ? 1 : n)); }
|
inline void SetNumFields(int n) { _nFields = (n > _maxFields ? _maxFields : (n < 1 ? 1 : n)); }
|
||||||
|
@ -309,7 +240,7 @@ public:
|
||||||
|
|
||||||
void SetOBSFromWaypoint();
|
void SetOBSFromWaypoint();
|
||||||
|
|
||||||
inline GPSWaypoint* GetActiveWaypoint() { return &_activeWaypoint; }
|
GPSWaypoint* GetActiveWaypoint();
|
||||||
// Get the (zero-based) position of the active waypoint in the active flightplan
|
// Get the (zero-based) position of the active waypoint in the active flightplan
|
||||||
// Returns -1 if no active waypoint.
|
// Returns -1 if no active waypoint.
|
||||||
int GetActiveWaypointIndex();
|
int GetActiveWaypointIndex();
|
||||||
|
@ -317,7 +248,7 @@ public:
|
||||||
int GetWaypointIndex(const string& id);
|
int GetWaypointIndex(const string& id);
|
||||||
|
|
||||||
// Returns meters
|
// Returns meters
|
||||||
inline float GetDistToActiveWaypoint() { return _dist2Act; }
|
float GetDistToActiveWaypoint();
|
||||||
// Returns degrees (magnetic)
|
// Returns degrees (magnetic)
|
||||||
float GetHeadingToActiveWaypoint();
|
float GetHeadingToActiveWaypoint();
|
||||||
// Returns degrees (magnetic)
|
// Returns degrees (magnetic)
|
||||||
|
@ -383,14 +314,6 @@ protected:
|
||||||
// 2D rendering area
|
// 2D rendering area
|
||||||
RenderArea2D* _instrument;
|
RenderArea2D* _instrument;
|
||||||
|
|
||||||
// The actual pages
|
|
||||||
gps_page_list_type _pages;
|
|
||||||
|
|
||||||
// The currently active page
|
|
||||||
GPSPage* _activePage;
|
|
||||||
// And a facility to save the immediately preceeding active page
|
|
||||||
GPSPage* _lastActivePage;
|
|
||||||
|
|
||||||
// Units
|
// Units
|
||||||
GPSSpeedUnits _velUnits;
|
GPSSpeedUnits _velUnits;
|
||||||
GPSDistanceUnits _distUnits;
|
GPSDistanceUnits _distUnits;
|
||||||
|
|
|
@ -150,6 +150,7 @@ FGNavRadio::FGNavRadio(SGPropertyNode *node) :
|
||||||
last_x(0.0),
|
last_x(0.0),
|
||||||
last_loc_dist(0.0),
|
last_loc_dist(0.0),
|
||||||
last_xtrack_error(0.0),
|
last_xtrack_error(0.0),
|
||||||
|
xrate_ms(0.0),
|
||||||
_localizerWidth(5.0),
|
_localizerWidth(5.0),
|
||||||
_name(node->getStringValue("name", "nav")),
|
_name(node->getStringValue("name", "nav")),
|
||||||
_num(node->getIntValue("number", 0)),
|
_num(node->getIntValue("number", 0)),
|
||||||
|
@ -740,7 +741,8 @@ void FGNavRadio::updateCDI(double dt)
|
||||||
//////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////
|
||||||
double t = 0.0;
|
double t = 0.0;
|
||||||
if ( inrange && cdi_serviceable ) {
|
if ( inrange && cdi_serviceable ) {
|
||||||
double xrate_ms = (last_xtrack_error - _cdiCrossTrackErrorM) / dt;
|
double cur_rate = (last_xtrack_error - _cdiCrossTrackErrorM) / dt;
|
||||||
|
xrate_ms = 0.99 * xrate_ms + 0.01 * cur_rate;
|
||||||
if ( fabs(xrate_ms) > 0.00001 ) {
|
if ( fabs(xrate_ms) > 0.00001 ) {
|
||||||
t = _cdiCrossTrackErrorM / xrate_ms;
|
t = _cdiCrossTrackErrorM / xrate_ms;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -136,6 +136,7 @@ class FGNavRadio : public SGSubsystem
|
||||||
double last_x;
|
double last_x;
|
||||||
double last_loc_dist;
|
double last_loc_dist;
|
||||||
double last_xtrack_error;
|
double last_xtrack_error;
|
||||||
|
double xrate_ms;
|
||||||
double _localizerWidth; // cached localizer width in degrees
|
double _localizerWidth; // cached localizer width in degrees
|
||||||
|
|
||||||
string _name;
|
string _name;
|
||||||
|
|
Loading…
Add table
Reference in a new issue