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"
25 using namespace FGXMLAutopilot;
27 //------------------------------------------------------------------------------
28 PeriodicalValue::PeriodicalValue( SGPropertyNode& prop_root,
31 SGPropertyNode_ptr minNode = cfg.getChild( "min" );
32 SGPropertyNode_ptr maxNode = cfg.getChild( "max" );
33 if( !minNode || !maxNode )
39 "periodical defined, but no <min> and/or <max> tag. Period ignored."
44 minPeriod = new InputValue(prop_root, *minNode);
45 maxPeriod = new InputValue(prop_root, *maxNode);
49 //------------------------------------------------------------------------------
50 double PeriodicalValue::normalize( double value ) const
52 return SGMiscd::normalizePeriodic( minPeriod->get_value(),
53 maxPeriod->get_value(),
57 //------------------------------------------------------------------------------
58 double PeriodicalValue::normalizeSymmetric( double value ) const
60 double minValue = minPeriod->get_value();
61 double maxValue = maxPeriod->get_value();
63 value = SGMiscd::normalizePeriodic( minValue, maxValue, value );
64 double width_2 = (maxValue - minValue)/2;
65 return value > width_2 ? width_2 - value : value;
68 //------------------------------------------------------------------------------
69 InputValue::InputValue( SGPropertyNode& prop_root,
77 parse(prop_root, cfg, value, offset, scale);
80 //------------------------------------------------------------------------------
81 void InputValue::parse( SGPropertyNode& prop_root,
97 if( (n = cfg.getChild("condition")) != NULL )
98 _condition = sgReadCondition(&prop_root, n);
100 if( (n = cfg.getChild( "scale" )) != NULL )
101 _scale = new InputValue(prop_root, *n, aScale);
103 if( (n = cfg.getChild( "offset" )) != NULL )
104 _offset = new InputValue(prop_root, *n, aOffset);
106 if( (n = cfg.getChild( "max" )) != NULL )
107 _max = new InputValue(prop_root, *n);
109 if( (n = cfg.getChild( "min" )) != NULL )
110 _min = new InputValue(prop_root, *n);
112 if( (n = cfg.getChild( "abs" )) != NULL )
113 _abs = n->getBoolValue();
115 if( (n = cfg.getChild( "period" )) != NULL )
116 _periodical = new PeriodicalValue(prop_root, *n);
119 SGPropertyNode *valueNode = cfg.getChild("value");
120 if( valueNode != NULL )
121 _value = valueNode->getDoubleValue();
123 if( (n = cfg.getChild("expression")) != NULL )
125 _expression = SGReadDoubleExpression(&prop_root, n->getChild(0));
129 // if no <property> element, check for <prop> element for backwards
131 if( (n = cfg.getChild("property"))
132 || (n = cfg.getChild("prop" )) )
134 _property = prop_root.getNode(n->getStringValue(), true);
137 // initialize property with given value
138 // if both <prop> and <value> exist
139 double s = get_scale();
141 _property->setDoubleValue( (_value - get_offset())/s );
143 _property->setDoubleValue(0); // if scale is zero, value*scale is zero
147 } // of have a <property> or <prop>
152 // no <value>, <prop> or <expression> element, use text node
153 const char * textnode = cfg.getStringValue();
155 // try to convert to a double value. If the textnode does not start with a number
156 // endp will point to the beginning of the string. We assume this should be
158 _value = strtod( textnode, &endp );
159 if( endp == textnode )
160 _property = prop_root.getNode(textnode, true);
164 void InputValue::set_value( double aValue )
169 double s = get_scale();
171 _property->setDoubleValue( (aValue - get_offset())/s );
173 _property->setDoubleValue( 0 ); // if scale is zero, value*scale is zero
176 double InputValue::get_value() const
178 double value = _value;
181 // compute the expression value
182 value = _expression->getValue(NULL);
183 } else if( _property != NULL ) {
184 value = _property->getDoubleValue();
188 value *= _scale->get_value();
191 value += _offset->get_value();
194 double m = _min->get_value();
200 double m = _max->get_value();
206 value = _periodical->normalize( value );
209 return _abs ? fabs(value) : value;