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 ),
70 void FGControls::reset_all()
73 set_aileron_trim( 0.0 );
75 set_elevator_trim( 0.0 );
77 set_rudder_trim( 0.0 );
78 set_throttle( ALL_ENGINES, 0.0 );
79 set_starter( ALL_ENGINES, false );
80 set_magnetos( ALL_ENGINES, 0 );
81 set_fuel_pump( ALL_ENGINES, false );
83 set_fuel_selector( ALL_TANKS, true );
89 FGControls::~FGControls() {
96 for ( int engine = 0; engine < MAX_ENGINES; engine++ ) {
97 throttle[engine] = 0.0;
98 mixture[engine] = 1.0;
99 fuel_pump[engine] = false;
100 prop_advance[engine] = 1.0;
101 magnetos[engine] = 0;
102 starter[engine] = false;
105 for ( int wheel = 0; wheel < MAX_WHEELS; wheel++ ) {
109 auto_coordination = fgGetNode("/sim/auto-coordination", true);
116 fgTie("/controls/aileron", this,
117 &FGControls::get_aileron, &FGControls::set_aileron);
118 fgSetArchivable("/controls/aileron");
119 fgTie("/controls/aileron-trim", this,
120 &FGControls::get_aileron_trim, &FGControls::set_aileron_trim);
121 fgSetArchivable("/controls/aileron-trim");
122 fgTie("/controls/elevator", this,
123 &FGControls::get_elevator, &FGControls::set_elevator);
124 fgSetArchivable("/controls/elevator");
125 fgTie("/controls/elevator-trim", this,
126 &FGControls::get_elevator_trim, &FGControls::set_elevator_trim);
127 fgSetArchivable("/controls/elevator-trim");
128 fgTie("/controls/rudder", this,
129 &FGControls::get_rudder, &FGControls::set_rudder);
130 fgSetArchivable("/controls/rudder");
131 fgTie("/controls/rudder-trim", this,
132 &FGControls::get_rudder_trim, &FGControls::set_rudder_trim);
133 fgSetArchivable("/controls/rudder-trim");
134 fgTie("/controls/flaps", this,
135 &FGControls::get_flaps, &FGControls::set_flaps);
136 fgSetArchivable("/controls/flaps");
138 for (index = 0; index < MAX_ENGINES; index++) {
140 sprintf(name, "/controls/throttle[%d]", index);
141 fgTie(name, this, index,
142 &FGControls::get_throttle, &FGControls::set_throttle);
143 fgSetArchivable(name);
144 sprintf(name, "/controls/mixture[%d]", index);
145 fgTie(name, this, index,
146 &FGControls::get_mixture, &FGControls::set_mixture);
147 fgSetArchivable(name);
148 sprintf(name, "/controls/fuel-pump[%d]", index);
149 fgTie(name, this, index,
150 &FGControls::get_fuel_pump, &FGControls::set_fuel_pump);
151 fgSetArchivable(name);
152 sprintf(name, "/controls/propeller-pitch[%d]", index);
153 fgTie(name, this, index,
154 &FGControls::get_prop_advance, &FGControls::set_prop_advance);
155 fgSetArchivable(name);
156 sprintf(name, "/controls/magnetos[%d]", index);
157 fgTie(name, this, index,
158 &FGControls::get_magnetos, &FGControls::set_magnetos);
159 fgSetArchivable(name);
160 sprintf(name, "/controls/starter[%d]", index);
161 fgTie(name, this, index,
162 &FGControls::get_starter, &FGControls::set_starter);
163 fgSetArchivable(name);
165 fgTie("/controls/parking-brake", this,
166 &FGControls::get_parking_brake, &FGControls::set_parking_brake);
167 fgSetArchivable("/controls/parking-brake");
168 for (index = 0; index < MAX_WHEELS; index++) {
170 sprintf(name, "/controls/brakes[%d]", index);
171 fgTie(name, this, index,
172 &FGControls::get_brake, &FGControls::set_brake);
173 fgSetArchivable(name);
175 for (index = 0; index < MAX_TANKS; index++) {
177 sprintf(name, "/controls/fuel-selector[%d]", index);
178 fgTie(name, this, index,
179 &FGControls::get_fuel_selector, &FGControls::set_fuel_selector);
180 fgSetArchivable(name);
182 fgTie("/controls/gear-down", this,
183 &FGControls::get_gear_down, &FGControls::set_gear_down);
184 fgSetArchivable("/controls/gear-down");
189 FGControls::unbind ()
191 // Tie control properties.
192 fgUntie("/controls/aileron");
193 fgUntie("/controls/aileron-trim");
194 fgUntie("/controls/elevator");
195 fgUntie("/controls/elevator-trim");
196 fgUntie("/controls/rudder");
197 fgUntie("/controls/rudder-trim");
198 fgUntie("/controls/flaps");
200 for (index = 0; index < MAX_ENGINES; index++) {
202 sprintf(name, "/controls/throttle[%d]", index);
204 sprintf(name, "/controls/mixture[%d]", index);
206 sprintf(name, "/controls/fuel-pump[%d]", index);
208 sprintf(name, "/controls/propeller-pitch[%d]", index);
210 sprintf(name, "/controls/magnetos[%d]", index);
212 sprintf(name, "/controls/starter[%d]", index);
215 for (index = 0; index < MAX_WHEELS; index++) {
217 sprintf(name, "/controls/brakes[%d]", index);
220 fgUntie("/controls/fuel-selector");
221 fgUntie("/controls/gear-down");
226 FGControls::update (double dt)
232 ////////////////////////////////////////////////////////////////////////
233 // Setters and adjusters.
234 ////////////////////////////////////////////////////////////////////////
237 FGControls::set_aileron (double pos)
240 CLAMP( &aileron, -1.0, 1.0 );
242 // check for autocoordination
243 if ( auto_coordination->getBoolValue() ) {
244 set_rudder( aileron / 2.0 );
249 FGControls::move_aileron (double amt)
252 CLAMP( &aileron, -1.0, 1.0 );
254 // check for autocoordination
255 if ( auto_coordination->getBoolValue() ) {
256 set_rudder( aileron / 2.0 );
261 FGControls::set_aileron_trim( double pos )
264 CLAMP( &aileron_trim, -1.0, 1.0 );
268 FGControls::move_aileron_trim( double amt )
271 CLAMP( &aileron_trim, -1.0, 1.0 );
275 FGControls::set_elevator( double pos )
278 CLAMP( &elevator, -1.0, 1.0 );
282 FGControls::move_elevator( double amt )
285 CLAMP( &elevator, -1.0, 1.0 );
289 FGControls::set_elevator_trim( double pos )
292 CLAMP( &elevator_trim, -1.0, 1.0 );
296 FGControls::move_elevator_trim( double amt )
298 elevator_trim += amt;
299 CLAMP( &elevator_trim, -1.0, 1.0 );
303 FGControls::set_rudder( double pos )
306 CLAMP( &rudder, -1.0, 1.0 );
310 FGControls::move_rudder( double amt )
313 CLAMP( &rudder, -1.0, 1.0 );
317 FGControls::set_rudder_trim( double pos )
320 CLAMP( &rudder_trim, -1.0, 1.0 );
324 FGControls::move_rudder_trim( double amt )
327 CLAMP( &rudder_trim, -1.0, 1.0 );
331 FGControls::set_flaps( double pos )
334 CLAMP( &flaps, 0.0, 1.0 );
338 FGControls::move_flaps( double amt )
341 CLAMP( &flaps, 0.0, 1.0 );
345 FGControls::set_throttle( int engine, double pos )
347 if ( engine == ALL_ENGINES ) {
348 for ( int i = 0; i < MAX_ENGINES; i++ ) {
350 CLAMP( &throttle[i], 0.0, 1.0 );
353 if ( (engine >= 0) && (engine < MAX_ENGINES) ) {
354 throttle[engine] = pos;
355 CLAMP( &throttle[engine], 0.0, 1.0 );
361 FGControls::move_throttle( int engine, double amt )
363 if ( engine == ALL_ENGINES ) {
364 for ( int i = 0; i < MAX_ENGINES; i++ ) {
366 CLAMP( &throttle[i], 0.0, 1.0 );
369 if ( (engine >= 0) && (engine < MAX_ENGINES) ) {
370 throttle[engine] += amt;
371 CLAMP( &throttle[engine], 0.0, 1.0 );
377 FGControls::set_mixture( int engine, double pos )
379 if ( engine == ALL_ENGINES ) {
380 for ( int i = 0; i < MAX_ENGINES; i++ ) {
382 CLAMP( &mixture[i], 0.0, 1.0 );
385 if ( (engine >= 0) && (engine < MAX_ENGINES) ) {
386 mixture[engine] = pos;
387 CLAMP( &mixture[engine], 0.0, 1.0 );
393 FGControls::move_mixture( int engine, double amt )
395 if ( engine == ALL_ENGINES ) {
396 for ( int i = 0; i < MAX_ENGINES; i++ ) {
398 CLAMP( &mixture[i], 0.0, 1.0 );
401 if ( (engine >= 0) && (engine < MAX_ENGINES) ) {
402 mixture[engine] += amt;
403 CLAMP( &mixture[engine], 0.0, 1.0 );
409 FGControls::set_fuel_pump( int engine, bool val )
411 if ( engine == ALL_ENGINES ) {
412 for ( int i = 0; i < MAX_ENGINES; i++ ) {
416 if ( (engine >= 0) && (engine < MAX_ENGINES) ) {
417 fuel_pump[engine] = val;
423 FGControls::set_prop_advance( int engine, double pos )
425 if ( engine == ALL_ENGINES ) {
426 for ( int i = 0; i < MAX_ENGINES; i++ ) {
427 prop_advance[i] = pos;
428 CLAMP( &prop_advance[i], 0.0, 1.0 );
431 if ( (engine >= 0) && (engine < MAX_ENGINES) ) {
432 prop_advance[engine] = pos;
433 CLAMP( &prop_advance[engine], 0.0, 1.0 );
439 FGControls::move_prop_advance( int engine, double amt )
441 if ( engine == ALL_ENGINES ) {
442 for ( int i = 0; i < MAX_ENGINES; i++ ) {
443 prop_advance[i] += amt;
444 CLAMP( &prop_advance[i], 0.0, 1.0 );
447 if ( (engine >= 0) && (engine < MAX_ENGINES) ) {
448 prop_advance[engine] += amt;
449 CLAMP( &prop_advance[engine], 0.0, 1.0 );
455 FGControls::set_magnetos( int engine, int pos )
457 if ( engine == ALL_ENGINES ) {
458 for ( int i = 0; i < MAX_ENGINES; i++ ) {
460 CLAMP( &magnetos[i], 0, 3 );
463 if ( (engine >= 0) && (engine < MAX_ENGINES) ) {
464 magnetos[engine] = pos;
465 CLAMP( &magnetos[engine], 0, 3 );
471 FGControls::move_magnetos( int engine, int amt )
473 if ( engine == ALL_ENGINES ) {
474 for ( int i = 0; i < MAX_ENGINES; i++ ) {
476 CLAMP( &magnetos[i], 0, 3 );
479 if ( (engine >= 0) && (engine < MAX_ENGINES) ) {
480 magnetos[engine] += amt;
481 CLAMP( &magnetos[engine], 0, 3 );
487 FGControls::set_starter( int engine, bool flag )
489 if ( engine == ALL_ENGINES ) {
490 for ( int i = 0; i < MAX_ENGINES; i++ ) {
494 if ( (engine >= 0) && (engine < MAX_ENGINES) ) {
495 starter[engine] = flag;
501 FGControls::set_fuel_selector( int tank, bool pos )
503 if ( tank == ALL_TANKS ) {
504 for ( int i = 0; i < MAX_TANKS; i++ ) {
505 fuel_selector[i] = pos;
508 if ( (tank >= 0) && (tank < MAX_TANKS) ) {
509 fuel_selector[tank] = pos;
516 FGControls::set_parking_brake( double pos )
519 CLAMP(&parking_brake, 0.0, 1.0);
523 FGControls::set_brake( int wheel, double pos )
525 if ( wheel == ALL_WHEELS ) {
526 for ( int i = 0; i < MAX_WHEELS; i++ ) {
528 CLAMP( &brake[i], 0.0, 1.0 );
531 if ( (wheel >= 0) && (wheel < MAX_WHEELS) ) {
533 CLAMP( &brake[wheel], 0.0, 1.0 );
539 FGControls::move_brake( int wheel, double amt )
541 if ( wheel == ALL_WHEELS ) {
542 for ( int i = 0; i < MAX_WHEELS; i++ ) {
544 CLAMP( &brake[i], 0.0, 1.0 );
547 if ( (wheel >= 0) && (wheel < MAX_WHEELS) ) {
549 CLAMP( &brake[wheel], 0.0, 1.0 );
555 FGControls::set_gear_down( bool gear )