1 // inputvalue.hxx - provide input to autopilot components
3 // Written by Torsten Dreyer
4 // Copyright (C) 2010 Torsten Dreyer - Torsten (at) t3r (dot) de
6 // This program is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU General Public License as
8 // published by the Free Software Foundation; either version 2 of the
9 // License, or (at your option) any later version.
11 // This program is distributed in the hope that it will be useful, but
12 // WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software
18 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23 #include "inputvalue.hxx"
24 #include <Main/fg_props.hxx>
26 using namespace FGXMLAutopilot;
28 //------------------------------------------------------------------------------
29 PeriodicalValue::PeriodicalValue( SGPropertyNode& prop_root,
32 SGPropertyNode_ptr minNode = cfg.getChild( "min" );
33 SGPropertyNode_ptr maxNode = cfg.getChild( "max" );
34 if( !minNode || !maxNode )
40 "periodical defined, but no <min> and/or <max> tag. Period ignored."
45 minPeriod = new InputValue(prop_root, *minNode);
46 maxPeriod = new InputValue(prop_root, *maxNode);
50 //------------------------------------------------------------------------------
51 double PeriodicalValue::normalize( double value ) const
53 return SGMiscd::normalizePeriodic( minPeriod->get_value(),
54 maxPeriod->get_value(),
58 //------------------------------------------------------------------------------
59 double PeriodicalValue::normalizeSymmetric( double value ) const
61 double minValue = minPeriod->get_value();
62 double maxValue = maxPeriod->get_value();
64 value = SGMiscd::normalizePeriodic( minValue, maxValue, value );
65 double width_2 = (maxValue - minValue)/2;
66 return value > width_2 ? width_2 - value : value;
69 //------------------------------------------------------------------------------
70 InputValue::InputValue( SGPropertyNode& prop_root,
78 parse(prop_root, cfg, value, offset, scale);
81 //------------------------------------------------------------------------------
82 void InputValue::parse( SGPropertyNode& prop_root,
98 if( (n = cfg.getChild("condition")) != NULL )
99 _condition = sgReadCondition(&prop_root, n);
101 if( (n = cfg.getChild( "scale" )) != NULL )
102 _scale = new InputValue(prop_root, *n, aScale);
104 if( (n = cfg.getChild( "offset" )) != NULL )
105 _offset = new InputValue(prop_root, *n, aOffset);
107 if( (n = cfg.getChild( "max" )) != NULL )
108 _max = new InputValue(prop_root, *n);
110 if( (n = cfg.getChild( "min" )) != NULL )
111 _min = new InputValue(prop_root, *n);
113 if( (n = cfg.getChild( "abs" )) != NULL )
114 _abs = n->getBoolValue();
116 if( (n = cfg.getChild( "period" )) != NULL )
117 _periodical = new PeriodicalValue(prop_root, *n);
120 SGPropertyNode *valueNode = cfg.getChild("value");
121 if( valueNode != NULL )
122 _value = valueNode->getDoubleValue();
124 if( (n = cfg.getChild("expression")) != NULL )
126 _expression = SGReadDoubleExpression(&prop_root, n->getChild(0));
130 // if no <property> element, check for <prop> element for backwards
132 if( (n = cfg.getChild("property"))
133 || (n = cfg.getChild("prop" )) )
135 _property = prop_root.getNode(n->getStringValue(), true);
138 // initialize property with given value
139 // if both <prop> and <value> exist
140 double s = get_scale();
142 _property->setDoubleValue( (_value - get_offset())/s );
144 _property->setDoubleValue(0); // if scale is zero, value*scale is zero
148 } // of have a <property> or <prop>
153 // no <value>, <prop> or <expression> element, use text node
154 const char * textnode = cfg.getStringValue();
156 // try to convert to a double value. If the textnode does not start with a number
157 // endp will point to the beginning of the string. We assume this should be
159 _value = strtod( textnode, &endp );
160 if( endp == textnode )
161 _property = prop_root.getNode(textnode, true);
165 void InputValue::set_value( double aValue )
170 double s = get_scale();
172 _property->setDoubleValue( (aValue - get_offset())/s );
174 _property->setDoubleValue( 0 ); // if scale is zero, value*scale is zero
177 double InputValue::get_value() const
179 double value = _value;
182 // compute the expression value
183 value = _expression->getValue(NULL);
184 } else if( _property != NULL ) {
185 value = _property->getDoubleValue();
189 value *= _scale->get_value();
192 value += _offset->get_value();
195 double m = _min->get_value();
201 double m = _max->get_value();
207 value = _periodical->normalize( value );
210 return _abs ? fabs(value) : value;