1 // controls.cxx -- defines a standard interface to all flight sim controls
3 // Written by Curtis Olson, started May 1997.
5 // Copyright (C) 1997 Curtis L. Olson - curt@infoplane.com
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License as
9 // published by the Free Software Foundation; either version 2 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 // General Public License for more details.
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include "controls.hxx"
26 #include <simgear/debug/logstream.hxx>
27 #include <Main/fg_props.hxx>
31 ////////////////////////////////////////////////////////////////////////
32 // Inline utility methods.
33 ////////////////////////////////////////////////////////////////////////
36 CLAMP(double *x, double min, double max )
38 if ( *x < min ) { *x = min; }
39 if ( *x > max ) { *x = max; }
43 CLAMP(int *i, int min, int max )
45 if ( *i < min ) { *i = min; }
46 if ( *i > max ) { *i = max; }
50 ////////////////////////////////////////////////////////////////////////
51 // Implementation of FGControls.
52 ////////////////////////////////////////////////////////////////////////
55 FGControls::FGControls() :
64 throttle_idle( true ),
65 fuel_selector( FUEL_BOTH ),
71 void FGControls::reset_all()
74 set_aileron_trim( 0.0 );
76 set_elevator_trim( 0.0 );
78 set_rudder_trim( 0.0 );
79 set_throttle( ALL_ENGINES, 0.0 );
80 set_starter( ALL_ENGINES, false );
81 set_magnetos( ALL_ENGINES, 0 );
83 fuel_selector = FUEL_BOTH;
89 FGControls::~FGControls() {
96 for ( int engine = 0; engine < MAX_ENGINES; engine++ ) {
97 throttle[engine] = 0.0;
98 mixture[engine] = 1.0;
99 prop_advance[engine] = 1.0;
100 magnetos[engine] = 0;
101 starter[engine] = false;
104 for ( int wheel = 0; wheel < MAX_WHEELS; wheel++ ) {
108 auto_coordination = fgGetNode("/sim/auto-coordination", true);
115 fgTie("/controls/aileron", this,
116 &FGControls::get_aileron, &FGControls::set_aileron);
117 fgSetArchivable("/controls/aileron");
118 fgTie("/controls/aileron-trim", this,
119 &FGControls::get_aileron_trim, &FGControls::set_aileron_trim);
120 fgSetArchivable("/controls/aileron-trim");
121 fgTie("/controls/elevator", this,
122 &FGControls::get_elevator, &FGControls::set_elevator);
123 fgSetArchivable("/controls/elevator");
124 fgTie("/controls/elevator-trim", this,
125 &FGControls::get_elevator_trim, &FGControls::set_elevator_trim);
126 fgSetArchivable("/controls/elevator-trim");
127 fgTie("/controls/rudder", this,
128 &FGControls::get_rudder, &FGControls::set_rudder);
129 fgSetArchivable("/controls/rudder");
130 fgTie("/controls/rudder-trim", this,
131 &FGControls::get_rudder_trim, &FGControls::set_rudder_trim);
132 fgSetArchivable("/controls/rudder-trim");
133 fgTie("/controls/flaps", this,
134 &FGControls::get_flaps, &FGControls::set_flaps);
135 fgSetArchivable("/controls/flaps");
137 for (index = 0; index < MAX_ENGINES; index++) {
139 sprintf(name, "/controls/throttle[%d]", index);
140 fgTie(name, this, index,
141 &FGControls::get_throttle, &FGControls::set_throttle);
142 fgSetArchivable(name);
143 sprintf(name, "/controls/mixture[%d]", index);
144 fgTie(name, this, index,
145 &FGControls::get_mixture, &FGControls::set_mixture);
146 fgSetArchivable(name);
147 sprintf(name, "/controls/propeller-pitch[%d]", index);
148 fgTie(name, this, index,
149 &FGControls::get_prop_advance, &FGControls::set_prop_advance);
150 fgSetArchivable(name);
151 sprintf(name, "/controls/magnetos[%d]", index);
152 fgTie(name, this, index,
153 &FGControls::get_magnetos, &FGControls::set_magnetos);
154 fgSetArchivable(name);
155 sprintf(name, "/controls/starter[%d]", index);
156 fgTie(name, this, index,
157 &FGControls::get_starter, &FGControls::set_starter);
158 fgSetArchivable(name);
160 fgTie("/controls/parking-brake", this,
161 &FGControls::get_parking_brake, &FGControls::set_parking_brake);
162 fgSetArchivable("/controls/parking-brake");
163 for (index = 0; index < MAX_WHEELS; index++) {
165 sprintf(name, "/controls/brakes[%d]", index);
166 fgTie(name, this, index,
167 &FGControls::get_brake, &FGControls::set_brake);
168 fgSetArchivable(name);
170 fgTie("/controls/fuel-selector", this,
171 &FGControls::get_fuel_selector, &FGControls::set_fuel_selector);
172 fgSetArchivable("/controls/gear-down");
173 fgTie("/controls/gear-down", this,
174 &FGControls::get_gear_down, &FGControls::set_gear_down);
175 fgSetArchivable("/controls/gear-down");
180 FGControls::unbind ()
182 // Tie control properties.
183 fgUntie("/controls/aileron");
184 fgUntie("/controls/aileron-trim");
185 fgUntie("/controls/elevator");
186 fgUntie("/controls/elevator-trim");
187 fgUntie("/controls/rudder");
188 fgUntie("/controls/rudder-trim");
189 fgUntie("/controls/flaps");
191 for (index = 0; index < MAX_ENGINES; index++) {
193 sprintf(name, "/controls/throttle[%d]", index);
195 sprintf(name, "/controls/mixture[%d]", index);
197 sprintf(name, "/controls/propeller-pitch[%d]", index);
199 sprintf(name, "/controls/magnetos[%d]", index);
201 sprintf(name, "/controls/starter[%d]", index);
204 for (index = 0; index < MAX_WHEELS; index++) {
206 sprintf(name, "/controls/brakes[%d]", index);
209 fgUntie("/controls/fuel-selector");
210 fgUntie("/controls/gear-down");
215 FGControls::update (double dt)
221 ////////////////////////////////////////////////////////////////////////
222 // Setters and adjusters.
223 ////////////////////////////////////////////////////////////////////////
226 FGControls::set_aileron (double pos)
229 CLAMP( &aileron, -1.0, 1.0 );
231 // check for autocoordination
232 if ( auto_coordination->getBoolValue() ) {
233 set_rudder( aileron / 2.0 );
238 FGControls::move_aileron (double amt)
241 CLAMP( &aileron, -1.0, 1.0 );
243 // check for autocoordination
244 if ( auto_coordination->getBoolValue() ) {
245 set_rudder( aileron / 2.0 );
250 FGControls::set_aileron_trim( double pos )
253 CLAMP( &aileron_trim, -1.0, 1.0 );
257 FGControls::move_aileron_trim( double amt )
260 CLAMP( &aileron_trim, -1.0, 1.0 );
264 FGControls::set_elevator( double pos )
267 CLAMP( &elevator, -1.0, 1.0 );
271 FGControls::move_elevator( double amt )
274 CLAMP( &elevator, -1.0, 1.0 );
278 FGControls::set_elevator_trim( double pos )
281 CLAMP( &elevator_trim, -1.0, 1.0 );
285 FGControls::move_elevator_trim( double amt )
287 elevator_trim += amt;
288 CLAMP( &elevator_trim, -1.0, 1.0 );
292 FGControls::set_rudder( double pos )
295 CLAMP( &rudder, -1.0, 1.0 );
299 FGControls::move_rudder( double amt )
302 CLAMP( &rudder, -1.0, 1.0 );
306 FGControls::set_rudder_trim( double pos )
309 CLAMP( &rudder_trim, -1.0, 1.0 );
313 FGControls::move_rudder_trim( double amt )
316 CLAMP( &rudder_trim, -1.0, 1.0 );
320 FGControls::set_flaps( double pos )
323 CLAMP( &flaps, 0.0, 1.0 );
327 FGControls::move_flaps( double amt )
330 CLAMP( &flaps, 0.0, 1.0 );
334 FGControls::set_throttle( int engine, double pos )
336 if ( engine == ALL_ENGINES ) {
337 for ( int i = 0; i < MAX_ENGINES; i++ ) {
339 CLAMP( &throttle[i], 0.0, 1.0 );
342 if ( (engine >= 0) && (engine < MAX_ENGINES) ) {
343 throttle[engine] = pos;
344 CLAMP( &throttle[engine], 0.0, 1.0 );
350 FGControls::move_throttle( int engine, double amt )
352 if ( engine == ALL_ENGINES ) {
353 for ( int i = 0; i < MAX_ENGINES; i++ ) {
355 CLAMP( &throttle[i], 0.0, 1.0 );
358 if ( (engine >= 0) && (engine < MAX_ENGINES) ) {
359 throttle[engine] += amt;
360 CLAMP( &throttle[engine], 0.0, 1.0 );
366 FGControls::set_mixture( int engine, double pos )
368 if ( engine == ALL_ENGINES ) {
369 for ( int i = 0; i < MAX_ENGINES; i++ ) {
371 CLAMP( &mixture[i], 0.0, 1.0 );
374 if ( (engine >= 0) && (engine < MAX_ENGINES) ) {
375 mixture[engine] = pos;
376 CLAMP( &mixture[engine], 0.0, 1.0 );
382 FGControls::move_mixture( int engine, double amt )
384 if ( engine == ALL_ENGINES ) {
385 for ( int i = 0; i < MAX_ENGINES; i++ ) {
387 CLAMP( &mixture[i], 0.0, 1.0 );
390 if ( (engine >= 0) && (engine < MAX_ENGINES) ) {
391 mixture[engine] += amt;
392 CLAMP( &mixture[engine], 0.0, 1.0 );
398 FGControls::set_prop_advance( int engine, double pos )
400 if ( engine == ALL_ENGINES ) {
401 for ( int i = 0; i < MAX_ENGINES; i++ ) {
402 prop_advance[i] = pos;
403 CLAMP( &prop_advance[i], 0.0, 1.0 );
406 if ( (engine >= 0) && (engine < MAX_ENGINES) ) {
407 prop_advance[engine] = pos;
408 CLAMP( &prop_advance[engine], 0.0, 1.0 );
414 FGControls::move_prop_advance( int engine, double amt )
416 if ( engine == ALL_ENGINES ) {
417 for ( int i = 0; i < MAX_ENGINES; i++ ) {
418 prop_advance[i] += amt;
419 CLAMP( &prop_advance[i], 0.0, 1.0 );
422 if ( (engine >= 0) && (engine < MAX_ENGINES) ) {
423 prop_advance[engine] += amt;
424 CLAMP( &prop_advance[engine], 0.0, 1.0 );
430 FGControls::set_magnetos( int engine, int pos )
432 if ( engine == ALL_ENGINES ) {
433 for ( int i = 0; i < MAX_ENGINES; i++ ) {
435 CLAMP( &magnetos[i], 0, 3 );
438 if ( (engine >= 0) && (engine < MAX_ENGINES) ) {
439 magnetos[engine] = pos;
440 CLAMP( &magnetos[engine], 0, 3 );
446 FGControls::move_magnetos( int engine, int amt )
448 if ( engine == ALL_ENGINES ) {
449 for ( int i = 0; i < MAX_ENGINES; i++ ) {
451 CLAMP( &magnetos[i], 0, 3 );
454 if ( (engine >= 0) && (engine < MAX_ENGINES) ) {
455 magnetos[engine] += amt;
456 CLAMP( &magnetos[engine], 0, 3 );
462 FGControls::set_starter( int engine, bool flag )
464 if ( engine == ALL_ENGINES ) {
465 for ( int i = 0; i < MAX_ENGINES; i++ ) {
469 if ( (engine >= 0) && (engine < MAX_ENGINES) ) {
470 starter[engine] = flag;
476 FGControls::set_parking_brake( double pos )
479 CLAMP(&parking_brake, 0.0, 1.0);
483 FGControls::set_brake( int wheel, double pos )
485 if ( wheel == ALL_WHEELS ) {
486 for ( int i = 0; i < MAX_WHEELS; i++ ) {
488 CLAMP( &brake[i], 0.0, 1.0 );
491 if ( (wheel >= 0) && (wheel < MAX_WHEELS) ) {
493 CLAMP( &brake[wheel], 0.0, 1.0 );
499 FGControls::move_brake( int wheel, double amt )
501 if ( wheel == ALL_WHEELS ) {
502 for ( int i = 0; i < MAX_WHEELS; i++ ) {
504 CLAMP( &brake[i], 0.0, 1.0 );
507 if ( (wheel >= 0) && (wheel < MAX_WHEELS) ) {
509 CLAMP( &brake[wheel], 0.0, 1.0 );
515 FGControls::set_gear_down( bool gear )