Branch data Line data Source code
1 : : /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2 : :
3 : : Module: FGFCS.cpp
4 : : Author: Jon Berndt
5 : : Date started: 12/12/98
6 : : Purpose: Model the flight controls
7 : : Called by: FDMExec
8 : :
9 : : ------------- Copyright (C) 1999 Jon S. Berndt (jon@jsbsim.org) -------------
10 : :
11 : : This program is free software; you can redistribute it and/or modify it under
12 : : the terms of the GNU Lesser General Public License as published by the Free Software
13 : : Foundation; either version 2 of the License, or (at your option) any later
14 : : version.
15 : :
16 : : This program is distributed in the hope that it will be useful, but WITHOUT
17 : : ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18 : : FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
19 : : details.
20 : :
21 : : You should have received a copy of the GNU Lesser General Public License along with
22 : : this program; if not, write to the Free Software Foundation, Inc., 59 Temple
23 : : Place - Suite 330, Boston, MA 02111-1307, USA.
24 : :
25 : : Further information about the GNU Lesser General Public License can also be found on
26 : : the world wide web at http://www.gnu.org.
27 : :
28 : : FUNCTIONAL DESCRIPTION
29 : : --------------------------------------------------------------------------------
30 : : This class models the flight controls for a specific airplane
31 : :
32 : : HISTORY
33 : : --------------------------------------------------------------------------------
34 : : 12/12/98 JSB Created
35 : :
36 : : %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
37 : : INCLUDES
38 : : %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
39 : :
40 : : #include "FGFCS.h"
41 : : #include "FGFDMExec.h"
42 : : #include "FGGroundReactions.h"
43 : : #include "input_output/FGPropertyManager.h"
44 : : #include <fstream>
45 : : #include <sstream>
46 : : #include <iomanip>
47 : :
48 : : #include "models/flight_control/FGFilter.h"
49 : : #include "models/flight_control/FGDeadBand.h"
50 : : #include "models/flight_control/FGGain.h"
51 : : #include "models/flight_control/FGPID.h"
52 : : #include "models/flight_control/FGSwitch.h"
53 : : #include "models/flight_control/FGSummer.h"
54 : : #include "models/flight_control/FGKinemat.h"
55 : : #include "models/flight_control/FGFCSFunction.h"
56 : : #include "models/flight_control/FGSensor.h"
57 : : #include "models/flight_control/FGActuator.h"
58 : : #include "models/flight_control/FGAccelerometer.h"
59 : : #include "models/flight_control/FGMagnetometer.h"
60 : : #include "models/flight_control/FGGyro.h"
61 : :
62 : : using namespace std;
63 : :
64 : : namespace JSBSim {
65 : :
66 : : static const char *IdSrc = "$Id: FGFCS.cpp,v 1.70 2010/08/21 22:56:11 jberndt Exp $";
67 : : static const char *IdHdr = ID_FCS;
68 : :
69 : : /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
70 : : CLASS IMPLEMENTATION
71 : : %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
72 : :
73 : 1 : FGFCS::FGFCS(FGFDMExec* fdmex) : FGModel(fdmex)
74 : : {
75 : : int i;
76 : 1 : Name = "FGFCS";
77 : :
78 : 1 : DaCmd = DeCmd = DrCmd = DsCmd = DfCmd = DsbCmd = DspCmd = 0;
79 : 1 : PTrimCmd = YTrimCmd = RTrimCmd = 0.0;
80 : 1 : GearCmd = GearPos = 1; // default to gear down
81 : 1 : LeftBrake = RightBrake = CenterBrake = 0.0;
82 : 1 : TailhookPos = WingFoldPos = 0.0;
83 : :
84 : 1 : bind();
85 [ + + ][ # # ]: 5 : for (i=0;i<NForms;i++) {
86 : 4 : DePos[i] = DaLPos[i] = DaRPos[i] = DrPos[i] = 0.0;
87 : 4 : DfPos[i] = DsbPos[i] = DspPos[i] = 0.0;
88 : : }
89 : :
90 : 1 : Debug(0);
91 : 1 : }
92 : :
93 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
94 : :
95 : 1 : FGFCS::~FGFCS()
96 : : {
97 : 1 : ThrottleCmd.clear();
98 : 1 : ThrottlePos.clear();
99 : 1 : MixtureCmd.clear();
100 : 1 : MixturePos.clear();
101 : 1 : PropAdvanceCmd.clear();
102 : 1 : PropAdvance.clear();
103 : 1 : SteerPosDeg.clear();
104 : 1 : PropFeatherCmd.clear();
105 : 1 : PropFeather.clear();
106 : :
107 : : unsigned int i;
108 : :
109 [ # # ][ - + ]: 1 : for (i=0;i<APComponents.size();i++) delete APComponents[i];
[ # # ][ # # ]
110 : 1 : APComponents.clear();
111 [ # # ][ - + ]: 1 : for (i=0;i<FCSComponents.size();i++) delete FCSComponents[i];
[ # # ][ # # ]
112 : 1 : FCSComponents.clear();
113 [ + - ][ + + ]: 44 : for (i=0;i<Systems.size();i++) delete Systems[i];
[ # # ][ # # ]
114 : 1 : Systems.clear();
115 : :
116 : :
117 : 1 : Debug(1);
118 : 2 : }
119 : :
120 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
121 : :
122 : 1 : bool FGFCS::InitModel(void)
123 : : {
124 : : unsigned int i;
125 : :
126 [ - + ]: 1 : if (!FGModel::InitModel()) return false;
127 : :
128 [ - + ]: 1 : for (i=0; i<ThrottlePos.size(); i++) ThrottlePos[i] = 0.0;
129 [ - + ]: 1 : for (i=0; i<MixturePos.size(); i++) MixturePos[i] = 0.0;
130 [ - + ]: 1 : for (i=0; i<ThrottleCmd.size(); i++) ThrottleCmd[i] = 0.0;
131 [ - + ]: 1 : for (i=0; i<MixtureCmd.size(); i++) MixtureCmd[i] = 0.0;
132 [ - + ]: 1 : for (i=0; i<PropAdvance.size(); i++) PropAdvance[i] = 0.0;
133 [ - + ]: 1 : for (i=0; i<PropFeather.size(); i++) PropFeather[i] = 0.0;
134 : :
135 : 1 : DaCmd = DeCmd = DrCmd = DsCmd = DfCmd = DsbCmd = DspCmd = 0;
136 : 1 : PTrimCmd = YTrimCmd = RTrimCmd = 0.0;
137 : 1 : TailhookPos = WingFoldPos = 0.0;
138 : :
139 [ + + ]: 5 : for (i=0;i<NForms;i++) {
140 : 4 : DePos[i] = DaLPos[i] = DaRPos[i] = DrPos[i] = 0.0;
141 : 4 : DfPos[i] = DsbPos[i] = DspPos[i] = 0.0;
142 : : }
143 : :
144 [ - + ]: 1 : for (unsigned int i=0; i<Systems.size(); i++) {
145 [ # # ][ # # ]: 0 : if (Systems[i]->GetType() == "LAG" ||
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
146 : : Systems[i]->GetType() == "LEAD_LAG" ||
147 : : Systems[i]->GetType() == "WASHOUT" ||
148 : : Systems[i]->GetType() == "SECOND_ORDER_FILTER" ||
149 : : Systems[i]->GetType() == "INTEGRATOR")
150 : : {
151 : 0 : ((FGFilter*)Systems[i])->ResetPastStates();
152 [ # # ]: 0 : } else if (Systems[i]->GetType() == "PID" ) {
153 : 0 : ((FGPID*)Systems[i])->ResetPastStates();
154 : : }
155 : : }
156 : :
157 [ - + ]: 1 : for (unsigned int i=0; i<FCSComponents.size(); i++) {
158 [ # # ][ # # ]: 0 : if (FCSComponents[i]->GetType() == "LAG" ||
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
159 : : FCSComponents[i]->GetType() == "LEAD_LAG" ||
160 : : FCSComponents[i]->GetType() == "WASHOUT" ||
161 : : FCSComponents[i]->GetType() == "SECOND_ORDER_FILTER" ||
162 : : FCSComponents[i]->GetType() == "INTEGRATOR")
163 : : {
164 : 0 : ((FGFilter*)FCSComponents[i])->ResetPastStates();
165 [ # # ]: 0 : } else if (FCSComponents[i]->GetType() == "PID" ) {
166 : 0 : ((FGPID*)FCSComponents[i])->ResetPastStates();
167 : : }
168 : : }
169 : :
170 [ - + ]: 1 : for (unsigned int i=0; i<APComponents.size(); i++) {
171 [ # # ][ # # ]: 0 : if (APComponents[i]->GetType() == "LAG" ||
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
172 : : APComponents[i]->GetType() == "LEAD_LAG" ||
173 : : APComponents[i]->GetType() == "WASHOUT" ||
174 : : APComponents[i]->GetType() == "SECOND_ORDER_FILTER" ||
175 : : APComponents[i]->GetType() == "INTEGRATOR")
176 : : {
177 : 0 : ((FGFilter*)APComponents[i])->ResetPastStates();
178 [ # # ]: 0 : } else if (APComponents[i]->GetType() == "PID" ) {
179 : 0 : ((FGPID*)APComponents[i])->ResetPastStates();
180 : : }
181 : : }
182 : :
183 : 1 : return true;
184 : : }
185 : :
186 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
187 : :
188 : 1 : void FGFCS::LateBind(void)
189 : : {
190 : : int i;
191 : :
192 [ + + ]: 44 : for (i=0; i<Systems.size(); i++) Systems[i]->LateBind();
193 [ - + ]: 1 : for (i=0; i<APComponents.size(); i++) APComponents[i]->LateBind();
194 [ - + ]: 1 : for (i=0; i<FCSComponents.size(); i++) FCSComponents[i]->LateBind();
195 : 1 : }
196 : :
197 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
198 : : // Notes: In this logic the default engine commands are set. This is simply a
199 : : // sort of safe-mode method in case the user has not defined control laws for
200 : : // throttle, mixture, and prop-advance. The throttle, mixture, and prop advance
201 : : // positions are set equal to the respective commands. Any control logic that is
202 : : // actually present in the flight_control or autopilot section will override
203 : : // these simple assignments.
204 : :
205 : 54005 : bool FGFCS::Run(void)
206 : : {
207 : : unsigned int i;
208 : :
209 [ - + ]: 54005 : if (FGModel::Run()) return true; // fast exit if nothing to do
210 [ - + ]: 54005 : if (FDMExec->Holding()) return false;
211 : :
212 : 54005 : RunPreFunctions();
213 : :
214 [ + + ]: 702065 : for (i=0; i<ThrottlePos.size(); i++) ThrottlePos[i] = ThrottleCmd[i];
215 [ + + ]: 702065 : for (i=0; i<MixturePos.size(); i++) MixturePos[i] = MixtureCmd[i];
216 [ + + ]: 702065 : for (i=0; i<PropAdvance.size(); i++) PropAdvance[i] = PropAdvanceCmd[i];
217 [ + + ]: 702065 : for (i=0; i<PropFeather.size(); i++) PropFeather[i] = PropFeatherCmd[i];
218 : :
219 : : // Set the default steering angle
220 [ - + ]: 54005 : for (i=0; i<SteerPosDeg.size(); i++) {
221 : 0 : FGLGear* gear = GroundReactions->GetGearUnit(i);
222 : 0 : SteerPosDeg[i] = gear->GetDefaultSteerAngle( GetDsCmd() );
223 : : }
224 : :
225 : : // Execute Systems in order
226 [ + + ]: 2376220 : for (i=0; i<Systems.size(); i++) Systems[i]->Run();
227 : :
228 : : // Execute Autopilot
229 [ - + ]: 54005 : for (i=0; i<APComponents.size(); i++) APComponents[i]->Run();
230 : :
231 : : // Execute Flight Control System
232 [ - + ]: 54005 : for (i=0; i<FCSComponents.size(); i++) FCSComponents[i]->Run();
233 : :
234 : 54005 : RunPostFunctions();
235 : :
236 : 54005 : return false;
237 : : }
238 : :
239 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
240 : :
241 : 0 : void FGFCS::SetDaLPos( int form , double pos )
242 : : {
243 [ # # # # ]: 0 : switch(form) {
244 : : case ofRad:
245 : 0 : DaLPos[ofRad] = pos;
246 : 0 : DaLPos[ofDeg] = pos*radtodeg;
247 : 0 : break;
248 : : case ofDeg:
249 : 0 : DaLPos[ofRad] = pos*degtorad;
250 : 0 : DaLPos[ofDeg] = pos;
251 : 0 : break;
252 : : case ofNorm:
253 : 0 : DaLPos[ofNorm] = pos;
254 : : }
255 : 0 : DaLPos[ofMag] = fabs(DaLPos[ofRad]);
256 : 0 : }
257 : :
258 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
259 : :
260 : 0 : void FGFCS::SetDaRPos( int form , double pos )
261 : : {
262 [ # # # # ]: 0 : switch(form) {
263 : : case ofRad:
264 : 0 : DaRPos[ofRad] = pos;
265 : 0 : DaRPos[ofDeg] = pos*radtodeg;
266 : 0 : break;
267 : : case ofDeg:
268 : 0 : DaRPos[ofRad] = pos*degtorad;
269 : 0 : DaRPos[ofDeg] = pos;
270 : 0 : break;
271 : : case ofNorm:
272 : 0 : DaRPos[ofNorm] = pos;
273 : : }
274 : 0 : DaRPos[ofMag] = fabs(DaRPos[ofRad]);
275 : 0 : }
276 : :
277 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
278 : :
279 : 0 : void FGFCS::SetDePos( int form , double pos )
280 : : {
281 [ # # # # ]: 0 : switch(form) {
282 : : case ofRad:
283 : 0 : DePos[ofRad] = pos;
284 : 0 : DePos[ofDeg] = pos*radtodeg;
285 : 0 : break;
286 : : case ofDeg:
287 : 0 : DePos[ofRad] = pos*degtorad;
288 : 0 : DePos[ofDeg] = pos;
289 : 0 : break;
290 : : case ofNorm:
291 : 0 : DePos[ofNorm] = pos;
292 : : }
293 : 0 : DePos[ofMag] = fabs(DePos[ofRad]);
294 : 0 : }
295 : :
296 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
297 : :
298 : 0 : void FGFCS::SetDrPos( int form , double pos )
299 : : {
300 [ # # # # ]: 0 : switch(form) {
301 : : case ofRad:
302 : 0 : DrPos[ofRad] = pos;
303 : 0 : DrPos[ofDeg] = pos*radtodeg;
304 : 0 : break;
305 : : case ofDeg:
306 : 0 : DrPos[ofRad] = pos*degtorad;
307 : 0 : DrPos[ofDeg] = pos;
308 : 0 : break;
309 : : case ofNorm:
310 : 0 : DrPos[ofNorm] = pos;
311 : : }
312 : 0 : DrPos[ofMag] = fabs(DrPos[ofRad]);
313 : 0 : }
314 : :
315 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
316 : :
317 : 0 : void FGFCS::SetDfPos( int form , double pos )
318 : : {
319 [ # # # # ]: 0 : switch(form) {
320 : : case ofRad:
321 : 0 : DfPos[ofRad] = pos;
322 : 0 : DfPos[ofDeg] = pos*radtodeg;
323 : 0 : break;
324 : : case ofDeg:
325 : 0 : DfPos[ofRad] = pos*degtorad;
326 : 0 : DfPos[ofDeg] = pos;
327 : 0 : break;
328 : : case ofNorm:
329 : 0 : DfPos[ofNorm] = pos;
330 : : }
331 : 0 : DfPos[ofMag] = fabs(DfPos[ofRad]);
332 : 0 : }
333 : :
334 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
335 : :
336 : 0 : void FGFCS::SetDsbPos( int form , double pos )
337 : : {
338 [ # # # # ]: 0 : switch(form) {
339 : : case ofRad:
340 : 0 : DsbPos[ofRad] = pos;
341 : 0 : DsbPos[ofDeg] = pos*radtodeg;
342 : 0 : break;
343 : : case ofDeg:
344 : 0 : DsbPos[ofRad] = pos*degtorad;
345 : 0 : DsbPos[ofDeg] = pos;
346 : 0 : break;
347 : : case ofNorm:
348 : 0 : DsbPos[ofNorm] = pos;
349 : : }
350 : 0 : DsbPos[ofMag] = fabs(DsbPos[ofRad]);
351 : 0 : }
352 : :
353 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
354 : :
355 : 0 : void FGFCS::SetDspPos( int form , double pos )
356 : : {
357 [ # # # # ]: 0 : switch(form) {
358 : : case ofRad:
359 : 0 : DspPos[ofRad] = pos;
360 : 0 : DspPos[ofDeg] = pos*radtodeg;
361 : 0 : break;
362 : : case ofDeg:
363 : 0 : DspPos[ofRad] = pos*degtorad;
364 : 0 : DspPos[ofDeg] = pos;
365 : 0 : break;
366 : : case ofNorm:
367 : 0 : DspPos[ofNorm] = pos;
368 : : }
369 : 0 : DspPos[ofMag] = fabs(DspPos[ofRad]);
370 : 0 : }
371 : :
372 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
373 : :
374 : 213136 : void FGFCS::SetThrottleCmd(int engineNum, double setting)
375 : : {
376 : : unsigned int ctr;
377 : :
378 [ + - ]: 213136 : if (engineNum < (int)ThrottlePos.size()) {
379 [ - + ]: 213136 : if (engineNum < 0) {
380 [ # # ]: 0 : for (ctr=0;ctr<ThrottleCmd.size();ctr++) ThrottleCmd[ctr] = setting;
381 : : } else {
382 : 213136 : ThrottleCmd[engineNum] = setting;
383 : : }
384 : : } else {
385 : : cerr << "Throttle " << engineNum << " does not exist! " << ThrottleCmd.size()
386 : : << " engines exist, but attempted throttle command is for engine "
387 : 0 : << engineNum << endl;
388 : : }
389 : 213136 : }
390 : :
391 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
392 : :
393 : 0 : void FGFCS::SetThrottlePos(int engineNum, double setting)
394 : : {
395 : : unsigned int ctr;
396 : :
397 [ # # ]: 0 : if (engineNum < (int)ThrottlePos.size()) {
398 [ # # ]: 0 : if (engineNum < 0) {
399 [ # # ]: 0 : for (ctr=0;ctr<ThrottlePos.size();ctr++) ThrottlePos[ctr] = setting;
400 : : } else {
401 : 0 : ThrottlePos[engineNum] = setting;
402 : : }
403 : : } else {
404 : : cerr << "Throttle " << engineNum << " does not exist! " << ThrottlePos.size()
405 : : << " engines exist, but attempted throttle position setting is for engine "
406 : 0 : << engineNum << endl;
407 : : }
408 : 0 : }
409 : :
410 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
411 : :
412 : 54074 : double FGFCS::GetThrottleCmd(int engineNum) const
413 : : {
414 [ + - ]: 54074 : if (engineNum < (int)ThrottlePos.size()) {
415 [ - + ]: 54074 : if (engineNum < 0) {
416 : 0 : cerr << "Cannot get throttle value for ALL engines" << endl;
417 : : } else {
418 : 54074 : return ThrottleCmd[engineNum];
419 : : }
420 : : } else {
421 : : cerr << "Throttle " << engineNum << " does not exist! " << ThrottleCmd.size()
422 : : << " engines exist, but throttle setting for engine " << engineNum
423 : 0 : << " is selected" << endl;
424 : : }
425 : 54074 : return 0.0;
426 : : }
427 : :
428 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
429 : :
430 : 648072 : double FGFCS::GetThrottlePos(int engineNum) const
431 : : {
432 [ + - ]: 648072 : if (engineNum < (int)ThrottlePos.size()) {
433 [ - + ]: 648072 : if (engineNum < 0) {
434 : 0 : cerr << "Cannot get throttle value for ALL engines" << endl;
435 : : } else {
436 : 648072 : return ThrottlePos[engineNum];
437 : : }
438 : : } else {
439 : : cerr << "Throttle " << engineNum << " does not exist! " << ThrottlePos.size()
440 : : << " engines exist, but attempted throttle position setting is for engine "
441 : 0 : << engineNum << endl;
442 : : }
443 : 648072 : return 0.0;
444 : : }
445 : :
446 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
447 : :
448 : 0 : void FGFCS::SetMixtureCmd(int engineNum, double setting)
449 : : {
450 : : unsigned int ctr;
451 : :
452 [ # # ]: 0 : if (engineNum < (int)ThrottlePos.size()) {
453 [ # # ]: 0 : if (engineNum < 0) {
454 [ # # ]: 0 : for (ctr=0;ctr<MixtureCmd.size();ctr++) MixtureCmd[ctr] = setting;
455 : : } else {
456 : 0 : MixtureCmd[engineNum] = setting;
457 : : }
458 : : }
459 : 0 : }
460 : :
461 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
462 : :
463 : 0 : void FGFCS::SetMixturePos(int engineNum, double setting)
464 : : {
465 : : unsigned int ctr;
466 : :
467 [ # # ]: 0 : if (engineNum < (int)ThrottlePos.size()) {
468 [ # # ]: 0 : if (engineNum < 0) {
469 [ # # ]: 0 : for (ctr=0;ctr<MixtureCmd.size();ctr++) MixturePos[ctr] = MixtureCmd[ctr];
470 : : } else {
471 : 0 : MixturePos[engineNum] = setting;
472 : : }
473 : : }
474 : 0 : }
475 : :
476 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
477 : :
478 : 0 : void FGFCS::SetPropAdvanceCmd(int engineNum, double setting)
479 : : {
480 : : unsigned int ctr;
481 : :
482 [ # # ]: 0 : if (engineNum < (int)ThrottlePos.size()) {
483 [ # # ]: 0 : if (engineNum < 0) {
484 [ # # ]: 0 : for (ctr=0;ctr<PropAdvanceCmd.size();ctr++) PropAdvanceCmd[ctr] = setting;
485 : : } else {
486 : 0 : PropAdvanceCmd[engineNum] = setting;
487 : : }
488 : : }
489 : 0 : }
490 : :
491 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
492 : :
493 : 0 : void FGFCS::SetPropAdvance(int engineNum, double setting)
494 : : {
495 : : unsigned int ctr;
496 : :
497 [ # # ]: 0 : if (engineNum < (int)ThrottlePos.size()) {
498 [ # # ]: 0 : if (engineNum < 0) {
499 [ # # ]: 0 : for (ctr=0;ctr<PropAdvanceCmd.size();ctr++) PropAdvance[ctr] = PropAdvanceCmd[ctr];
500 : : } else {
501 : 0 : PropAdvance[engineNum] = setting;
502 : : }
503 : : }
504 : 0 : }
505 : :
506 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
507 : :
508 : 0 : void FGFCS::SetFeatherCmd(int engineNum, bool setting)
509 : : {
510 : : unsigned int ctr;
511 : :
512 [ # # ]: 0 : if (engineNum < (int)ThrottlePos.size()) {
513 [ # # ]: 0 : if (engineNum < 0) {
514 [ # # ]: 0 : for (ctr=0;ctr<PropFeatherCmd.size();ctr++) PropFeatherCmd[ctr] = setting;
515 : : } else {
516 : 0 : PropFeatherCmd[engineNum] = setting;
517 : : }
518 : : }
519 : 0 : }
520 : :
521 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
522 : :
523 : 0 : void FGFCS::SetPropFeather(int engineNum, bool setting)
524 : : {
525 : : unsigned int ctr;
526 : :
527 [ # # ]: 0 : if (engineNum < (int)ThrottlePos.size()) {
528 [ # # ]: 0 : if (engineNum < 0) {
529 [ # # ]: 0 : for (ctr=0;ctr<PropFeatherCmd.size();ctr++) PropFeather[ctr] = PropFeatherCmd[ctr];
530 : : } else {
531 : 0 : PropFeather[engineNum] = setting;
532 : : }
533 : : }
534 : 0 : }
535 : :
536 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
537 : :
538 : 4 : bool FGFCS::Load(Element* el, SystemType systype)
539 : : {
540 : 4 : string name, file, fname="", interface_property_string, parent_name;
541 : : vector <FGFCSComponent*> *Components;
542 : : Element *component_element;
543 : : Element *channel_element;
544 : :
545 : 4 : Components=0;
546 : :
547 : : // ToDo: The handling of name and file attributes could be improved, here,
548 : : // considering that a name can be in the external file, as well.
549 : :
550 : 8 : name = el->GetAttributeValue("name");
551 : :
552 [ + - ][ + - ]: 8 : if (name.empty() || !el->GetAttributeValue("file").empty()) {
[ + - ][ # # ]
[ # # ][ + - ]
[ # # ][ + - ]
[ + - ]
553 : 8 : fname = el->GetAttributeValue("file");
554 [ + - ]: 4 : if (systype == stSystem) {
555 : 8 : file = FindSystemFullPathname(fname);
556 : : } else {
557 : 0 : file = FDMExec->GetFullAircraftPath() + "/" + fname + ".xml";
558 : : }
559 [ - + ]: 4 : if (fname.empty()) {
560 : 0 : cerr << "FCS, Autopilot, or system does not appear to be defined inline nor in a file" << endl;
561 : 0 : return false;
562 : : } else {
563 : 8 : document = LoadXMLDocument(file);
564 [ - + ]: 4 : if (!document) {
565 : 0 : cerr << "Error loading file " << file << endl;
566 : 0 : return false;
567 : : }
568 : 8 : name = document->GetAttributeValue("name");
569 : : }
570 : : } else {
571 : 0 : document = el;
572 : : }
573 : :
574 [ - + ]: 4 : if (document->GetName() == "autopilot") {
575 : 0 : Components = &APComponents;
576 : 0 : Name = "Autopilot: " + document->GetAttributeValue("name");
577 [ - + ]: 4 : } else if (document->GetName() == "flight_control") {
578 : 0 : Components = &FCSComponents;
579 : 0 : Name = "FCS: " + document->GetAttributeValue("name");
580 [ + - ]: 4 : } else if (document->GetName() == "system") {
581 : 4 : Components = &Systems;
582 : 8 : Name = "System: " + document->GetAttributeValue("name");
583 : : }
584 : 4 : Debug(2);
585 : :
586 [ - + ]: 4 : if (document->GetName() == "flight_control") bindModel();
587 : :
588 : 4 : FGModel::Load(document); // Load interface properties from document
589 : :
590 : : // After reading interface properties in a file, read properties in the local
591 : : // flight_control, autopilot, or system element. This allows general-purpose
592 : : // systems to be defined in a file, with overrides or initial loaded constants
593 : : // supplied in the relevant element of the aircraft configuration file.
594 : :
595 : 4 : Element* property_element = 0;
596 : :
597 [ + - ]: 4 : if (!fname.empty()) {
598 : 4 : property_element = el->FindElement("property");
599 [ - + ][ # # ]: 4 : if (property_element && debug_lvl > 0) cout << endl << " Overriding properties" << endl << endl;
600 [ - + ]: 4 : while (property_element) {
601 : 0 : double value=0.0;
602 [ # # ]: 0 : if ( ! property_element->GetAttributeValue("value").empty())
603 : 0 : value = property_element->GetAttributeValueAsNumber("value");
604 : :
605 : 0 : interface_property_string = property_element->GetDataLine();
606 [ # # ]: 0 : if (PropertyManager->HasNode(interface_property_string)) {
607 : 0 : FGPropertyManager* node = PropertyManager->GetNode(interface_property_string);
608 [ # # ]: 0 : if (debug_lvl > 0)
609 : : cout << " " << "Overriding value for property " << interface_property_string
610 : 0 : << " (old value: " << node->getDoubleValue() << " new value: " << value << ")" << endl;
611 : 0 : node->setDoubleValue(value);
612 : : } else {
613 : 0 : interface_properties.push_back(new double(value));
614 : 0 : PropertyManager->Tie(interface_property_string, interface_properties.back());
615 [ # # ]: 0 : if (debug_lvl > 0)
616 : 0 : cout << " " << interface_property_string << " (initial value: " << value << ")" << endl;
617 : : }
618 : :
619 : 0 : property_element = el->FindNextElement("property");
620 : : }
621 : : }
622 : :
623 : 4 : channel_element = document->FindElement("channel");
624 [ + + ]: 18 : while (channel_element) {
625 : :
626 [ + - ]: 14 : if (debug_lvl > 0)
627 : : cout << endl << highint << fgblue << " Channel "
628 : 42 : << normint << channel_element->GetAttributeValue("name") << reset << endl;
629 : :
630 : 14 : component_element = channel_element->GetElement();
631 [ + + ]: 57 : while (component_element) {
632 : : try {
633 [ + + ][ + - ]: 246 : if ((component_element->GetName() == string("lag_filter")) ||
[ + - ][ + - ]
[ - + ][ + + ]
[ # # ][ # # ]
[ + + ][ # # ]
[ + + ][ # # ]
[ + + ][ # # ]
[ + + ][ # # ]
[ + + ][ # # ]
[ + + ][ # # ]
[ + + ][ # # ]
[ + - ][ # # ]
[ + - ][ + + ]
634 : : (component_element->GetName() == string("lead_lag_filter")) ||
635 : : (component_element->GetName() == string("washout_filter")) ||
636 : : (component_element->GetName() == string("second_order_filter")) ||
637 : : (component_element->GetName() == string("integrator")) )
638 : : {
639 : 3 : Components->push_back(new FGFilter(this, component_element));
640 [ + + ][ + - ]: 146 : } else if ((component_element->GetName() == string("pure_gain")) ||
[ - + ][ + + ]
[ # # ][ # # ]
[ + + ][ # # ]
[ + + ][ # # ]
[ + + ][ # # ]
[ + - ][ # # ]
[ + - ][ + + ]
641 : : (component_element->GetName() == string("scheduled_gain")) ||
642 : : (component_element->GetName() == string("aerosurface_scale")))
643 : : {
644 : 7 : Components->push_back(new FGGain(this, component_element));
645 [ + + ]: 33 : } else if (component_element->GetName() == string("summer")) {
646 : 4 : Components->push_back(new FGSummer(this, component_element));
647 [ - + ]: 29 : } else if (component_element->GetName() == string("deadband")) {
648 : 0 : Components->push_back(new FGDeadBand(this, component_element));
649 [ + + ]: 29 : } else if (component_element->GetName() == string("switch")) {
650 : 14 : Components->push_back(new FGSwitch(this, component_element));
651 [ - + ]: 15 : } else if (component_element->GetName() == string("kinematic")) {
652 : 0 : Components->push_back(new FGKinemat(this, component_element));
653 [ + + ]: 15 : } else if (component_element->GetName() == string("fcs_function")) {
654 : 4 : Components->push_back(new FGFCSFunction(this, component_element));
655 [ + + ]: 11 : } else if (component_element->GetName() == string("pid")) {
656 : 7 : Components->push_back(new FGPID(this, component_element));
657 [ + - ]: 4 : } else if (component_element->GetName() == string("actuator")) {
658 : 4 : Components->push_back(new FGActuator(this, component_element));
659 [ # # ]: 0 : } else if (component_element->GetName() == string("sensor")) {
660 : 0 : Components->push_back(new FGSensor(this, component_element));
661 [ # # ]: 0 : } else if (component_element->GetName() == string("accelerometer")) {
662 : 0 : Components->push_back(new FGAccelerometer(this, component_element));
663 [ # # ]: 0 : } else if (component_element->GetName() == string("magnetometer")) {
664 : 0 : Components->push_back(new FGMagnetometer(this, component_element));
665 [ # # ]: 0 : } else if (component_element->GetName() == string("gyro")) {
666 : 0 : Components->push_back(new FGGyro(this, component_element));
667 : : } else {
668 : 0 : cerr << "Unknown FCS component: " << component_element->GetName() << endl;
669 : : }
670 : 0 : } catch(string s) {
671 : 0 : cerr << highint << fgred << endl << " " << s << endl;
672 : 0 : cerr << reset << endl;
673 : 0 : return false;
674 : : }
675 : 43 : component_element = channel_element->GetNextElement();
676 : : }
677 : 14 : channel_element = document->FindNextElement("channel");
678 : : }
679 : :
680 : 4 : ResetParser();
681 : :
682 : 4 : return true;
683 : : }
684 : :
685 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
686 : :
687 : 0 : double FGFCS::GetBrake(FGLGear::BrakeGroup bg)
688 : : {
689 [ # # # # ]: 0 : switch (bg) {
690 : : case FGLGear::bgLeft:
691 : 0 : return LeftBrake;
692 : : case FGLGear::bgRight:
693 : 0 : return RightBrake;
694 : : case FGLGear::bgCenter:
695 : 0 : return CenterBrake;
696 : : default:
697 : 0 : cerr << "GetBrake asked to return a bogus brake value" << endl;
698 : : }
699 : 0 : return 0.0;
700 : : }
701 : :
702 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
703 : :
704 : 4 : string FGFCS::FindSystemFullPathname(const string& sysfilename)
705 : : {
706 : 4 : string fullpath, localpath;
707 : 4 : string system_filename = sysfilename;
708 : 4 : string systemPath = FDMExec->GetSystemsPath();
709 : 4 : string aircraftPath = FDMExec->GetFullAircraftPath();
710 : 4 : ifstream system_file;
711 : :
712 : 8 : fullpath = systemPath + "/";
713 : 8 : localpath = aircraftPath + "/Systems/";
714 : :
715 [ + - ][ - + ]: 8 : if (system_filename.length() <=4 || system_filename.substr(system_filename.length()-4, 4) != ".xml") {
[ + - ][ # # ]
[ - + ]
716 : 0 : system_filename.append(".xml");
717 : : }
718 : :
719 : 4 : system_file.open(string(localpath + system_filename).c_str());
720 [ - + ]: 4 : if ( !system_file.is_open()) {
721 : 0 : system_file.open(string(fullpath + system_filename).c_str());
722 [ # # ]: 0 : if ( !system_file.is_open()) {
723 : : cerr << " Could not open system file: " << system_filename << " in path "
724 : 0 : << fullpath << " or " << localpath << endl;
725 : 0 : return string("");
726 : : } else {
727 : 0 : return string(fullpath + system_filename);
728 : : }
729 : : }
730 : 4 : return string(localpath + system_filename);
731 : : }
732 : :
733 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
734 : :
735 : 0 : ifstream* FGFCS::FindSystemFile(const string& sysfilename)
736 : : {
737 : 0 : string fullpath, localpath;
738 : 0 : string system_filename = sysfilename;
739 : 0 : string systemPath = FDMExec->GetSystemsPath();
740 : 0 : string aircraftPath = FDMExec->GetFullAircraftPath();
741 : 0 : ifstream* system_file = new ifstream();
742 : :
743 : 0 : fullpath = systemPath + "/";
744 : 0 : localpath = aircraftPath + "/Systems/";
745 : :
746 [ # # ]: 0 : if (system_filename.substr(system_filename.length()-4, 4) != ".xml") {
747 : 0 : system_filename.append(".xml");
748 : : }
749 : :
750 : 0 : system_file->open(string(localpath + system_filename).c_str());
751 [ # # ]: 0 : if ( !system_file->is_open()) {
752 : 0 : system_file->open(string(fullpath + system_filename).c_str());
753 [ # # ]: 0 : if ( !system_file->is_open()) {
754 : : cerr << " Could not open system file: " << system_filename << " in path "
755 : 0 : << fullpath << " or " << localpath << endl;
756 : : }
757 : : }
758 : 0 : return system_file;
759 : : }
760 : :
761 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
762 : :
763 : 1 : string FGFCS::GetComponentStrings(const string& delimiter)
764 : : {
765 : : unsigned int comp;
766 : 1 : string CompStrings = "";
767 : 1 : bool firstime = true;
768 : 1 : int total_count=0;
769 : :
770 [ + + ]: 44 : for (unsigned int i=0; i<Systems.size(); i++) {
771 [ + + ]: 43 : if (firstime) firstime = false;
772 : 42 : else CompStrings += delimiter;
773 : :
774 : 43 : CompStrings += Systems[i]->GetName();
775 : 43 : total_count++;
776 : : }
777 : :
778 [ - + ]: 1 : for (comp = 0; comp < APComponents.size(); comp++)
779 : : {
780 [ # # ]: 0 : if (firstime) firstime = false;
781 : 0 : else CompStrings += delimiter;
782 : :
783 : 0 : CompStrings += APComponents[comp]->GetName();
784 : 0 : total_count++;
785 : : }
786 : :
787 [ - + ]: 1 : for (comp = 0; comp < FCSComponents.size(); comp++) {
788 [ # # ]: 0 : if (firstime) firstime = false;
789 : 0 : else CompStrings += delimiter;
790 : :
791 : 0 : CompStrings += FCSComponents[comp]->GetName();
792 : 0 : total_count++;
793 : : }
794 : :
795 : 1 : return CompStrings;
796 : : }
797 : :
798 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
799 : :
800 : 4909 : string FGFCS::GetComponentValues(const string& delimiter)
801 : : {
802 : 4909 : std::ostringstream buf;
803 : :
804 : : unsigned int comp;
805 : 4909 : bool firstime = true;
806 : 4909 : int total_count=0;
807 : :
808 [ + + ]: 215996 : for (unsigned int i=0; i<Systems.size(); i++) {
809 [ + + ]: 211087 : if (firstime) firstime = false;
810 : 206178 : else buf << delimiter;
811 : :
812 : 633261 : buf << setprecision(9) << Systems[i]->GetOutput();
813 : 211087 : total_count++;
814 : : }
815 : :
816 [ - + ]: 4909 : for (comp = 0; comp < APComponents.size(); comp++) {
817 [ # # ]: 0 : if (firstime) firstime = false;
818 : 0 : else buf << delimiter;
819 : :
820 : 0 : buf << setprecision(9) << APComponents[comp]->GetOutput();
821 : 0 : total_count++;
822 : : }
823 : :
824 [ - + ]: 4909 : for (comp = 0; comp < FCSComponents.size(); comp++) {
825 [ # # ]: 0 : if (firstime) firstime = false;
826 : 0 : else buf << delimiter;
827 : :
828 : 0 : buf << setprecision(9) << FCSComponents[comp]->GetOutput();
829 : 0 : total_count++;
830 : : }
831 : :
832 : 4909 : return buf.str();
833 : : }
834 : :
835 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
836 : :
837 : 12 : void FGFCS::AddThrottle(void)
838 : : {
839 : 12 : ThrottleCmd.push_back(0.0);
840 : 12 : ThrottlePos.push_back(0.0);
841 : 12 : MixtureCmd.push_back(0.0); // assume throttle and mixture are coupled
842 : 12 : MixturePos.push_back(0.0);
843 : 12 : PropAdvanceCmd.push_back(0.0); // assume throttle and prop pitch are coupled
844 : 12 : PropAdvance.push_back(0.0);
845 : 12 : PropFeatherCmd.push_back(false);
846 : 12 : PropFeather.push_back(false);
847 : :
848 : 24 : unsigned int num = (unsigned int)ThrottleCmd.size()-1;
849 : 12 : bindThrottle(num);
850 : 12 : }
851 : :
852 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
853 : :
854 : 0 : void FGFCS::AddGear(void)
855 : : {
856 : 0 : SteerPosDeg.push_back(0.0);
857 : 0 : }
858 : :
859 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
860 : :
861 : 43 : double FGFCS::GetDt(void)
862 : : {
863 : 43 : return FDMExec->GetDeltaT()*rate;
864 : : }
865 : :
866 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
867 : :
868 : 1 : void FGFCS::bind(void)
869 : : {
870 : 1 : PropertyManager->Tie("fcs/aileron-cmd-norm", this, &FGFCS::GetDaCmd, &FGFCS::SetDaCmd);
871 : 1 : PropertyManager->Tie("fcs/elevator-cmd-norm", this, &FGFCS::GetDeCmd, &FGFCS::SetDeCmd);
872 : 1 : PropertyManager->Tie("fcs/rudder-cmd-norm", this, &FGFCS::GetDrCmd, &FGFCS::SetDrCmd);
873 : 1 : PropertyManager->Tie("fcs/flap-cmd-norm", this, &FGFCS::GetDfCmd, &FGFCS::SetDfCmd);
874 : 1 : PropertyManager->Tie("fcs/speedbrake-cmd-norm", this, &FGFCS::GetDsbCmd, &FGFCS::SetDsbCmd);
875 : 1 : PropertyManager->Tie("fcs/spoiler-cmd-norm", this, &FGFCS::GetDspCmd, &FGFCS::SetDspCmd);
876 : 1 : PropertyManager->Tie("fcs/pitch-trim-cmd-norm", this, &FGFCS::GetPitchTrimCmd, &FGFCS::SetPitchTrimCmd);
877 : 1 : PropertyManager->Tie("fcs/roll-trim-cmd-norm", this, &FGFCS::GetRollTrimCmd, &FGFCS::SetRollTrimCmd);
878 : 1 : PropertyManager->Tie("fcs/yaw-trim-cmd-norm", this, &FGFCS::GetYawTrimCmd, &FGFCS::SetYawTrimCmd);
879 : :
880 : 1 : PropertyManager->Tie("fcs/left-aileron-pos-rad", this, ofRad, &FGFCS::GetDaLPos, &FGFCS::SetDaLPos);
881 : 1 : PropertyManager->Tie("fcs/left-aileron-pos-deg", this, ofDeg, &FGFCS::GetDaLPos, &FGFCS::SetDaLPos);
882 : 1 : PropertyManager->Tie("fcs/left-aileron-pos-norm", this, ofNorm, &FGFCS::GetDaLPos, &FGFCS::SetDaLPos);
883 : 1 : PropertyManager->Tie("fcs/mag-left-aileron-pos-rad", this, ofMag, &FGFCS::GetDaLPos);
884 : :
885 : 1 : PropertyManager->Tie("fcs/right-aileron-pos-rad", this, ofRad, &FGFCS::GetDaRPos, &FGFCS::SetDaRPos);
886 : 1 : PropertyManager->Tie("fcs/right-aileron-pos-deg", this, ofDeg, &FGFCS::GetDaRPos, &FGFCS::SetDaRPos);
887 : 1 : PropertyManager->Tie("fcs/right-aileron-pos-norm", this, ofNorm, &FGFCS::GetDaRPos, &FGFCS::SetDaRPos);
888 : 1 : PropertyManager->Tie("fcs/mag-right-aileron-pos-rad", this, ofMag, &FGFCS::GetDaRPos);
889 : :
890 : 1 : PropertyManager->Tie("fcs/elevator-pos-rad", this, ofRad, &FGFCS::GetDePos, &FGFCS::SetDePos);
891 : 1 : PropertyManager->Tie("fcs/elevator-pos-deg", this, ofDeg, &FGFCS::GetDePos, &FGFCS::SetDePos);
892 : 1 : PropertyManager->Tie("fcs/elevator-pos-norm", this, ofNorm, &FGFCS::GetDePos, &FGFCS::SetDePos);
893 : 1 : PropertyManager->Tie("fcs/mag-elevator-pos-rad", this, ofMag, &FGFCS::GetDePos);
894 : :
895 : 1 : PropertyManager->Tie("fcs/rudder-pos-rad", this,ofRad, &FGFCS::GetDrPos, &FGFCS::SetDrPos);
896 : 1 : PropertyManager->Tie("fcs/rudder-pos-deg", this,ofDeg, &FGFCS::GetDrPos, &FGFCS::SetDrPos);
897 : 1 : PropertyManager->Tie("fcs/rudder-pos-norm", this,ofNorm, &FGFCS::GetDrPos, &FGFCS::SetDrPos);
898 : 1 : PropertyManager->Tie("fcs/mag-rudder-pos-rad", this,ofMag, &FGFCS::GetDrPos);
899 : :
900 : 1 : PropertyManager->Tie("fcs/flap-pos-rad", this,ofRad, &FGFCS::GetDfPos, &FGFCS::SetDfPos);
901 : 1 : PropertyManager->Tie("fcs/flap-pos-deg", this,ofDeg, &FGFCS::GetDfPos, &FGFCS::SetDfPos);
902 : 1 : PropertyManager->Tie("fcs/flap-pos-norm", this,ofNorm, &FGFCS::GetDfPos, &FGFCS::SetDfPos);
903 : :
904 : 1 : PropertyManager->Tie("fcs/speedbrake-pos-rad", this,ofRad, &FGFCS::GetDsbPos, &FGFCS::SetDsbPos);
905 : 1 : PropertyManager->Tie("fcs/speedbrake-pos-deg", this,ofDeg, &FGFCS::GetDsbPos, &FGFCS::SetDsbPos);
906 : 1 : PropertyManager->Tie("fcs/speedbrake-pos-norm", this,ofNorm, &FGFCS::GetDsbPos, &FGFCS::SetDsbPos);
907 : 1 : PropertyManager->Tie("fcs/mag-speedbrake-pos-rad", this,ofMag, &FGFCS::GetDsbPos);
908 : :
909 : 1 : PropertyManager->Tie("fcs/spoiler-pos-rad", this, ofRad, &FGFCS::GetDspPos, &FGFCS::SetDspPos);
910 : 1 : PropertyManager->Tie("fcs/spoiler-pos-deg", this, ofDeg, &FGFCS::GetDspPos, &FGFCS::SetDspPos);
911 : 1 : PropertyManager->Tie("fcs/spoiler-pos-norm", this, ofNorm, &FGFCS::GetDspPos, &FGFCS::SetDspPos);
912 : 1 : PropertyManager->Tie("fcs/mag-spoiler-pos-rad", this, ofMag, &FGFCS::GetDspPos);
913 : :
914 : 1 : PropertyManager->Tie("gear/gear-pos-norm", this, &FGFCS::GetGearPos, &FGFCS::SetGearPos);
915 : 1 : PropertyManager->Tie("gear/gear-cmd-norm", this, &FGFCS::GetGearCmd, &FGFCS::SetGearCmd);
916 : 1 : PropertyManager->Tie("fcs/left-brake-cmd-norm", this, &FGFCS::GetLBrake, &FGFCS::SetLBrake);
917 : 1 : PropertyManager->Tie("fcs/right-brake-cmd-norm", this, &FGFCS::GetRBrake, &FGFCS::SetRBrake);
918 : 1 : PropertyManager->Tie("fcs/center-brake-cmd-norm", this, &FGFCS::GetCBrake, &FGFCS::SetCBrake);
919 : 1 : PropertyManager->Tie("fcs/steer-cmd-norm", this, &FGFCS::GetDsCmd, &FGFCS::SetDsCmd);
920 : :
921 : 1 : PropertyManager->Tie("gear/tailhook-pos-norm", this, &FGFCS::GetTailhookPos, &FGFCS::SetTailhookPos);
922 : 1 : PropertyManager->Tie("fcs/wing-fold-pos-norm", this, &FGFCS::GetWingFoldPos, &FGFCS::SetWingFoldPos);
923 : 1 : }
924 : :
925 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
926 : : // Technically, this function should probably bind propulsion type specific controls
927 : : // rather than mixture and prop-advance.
928 : :
929 : 12 : void FGFCS::bindThrottle(unsigned int num)
930 : : {
931 : 12 : string tmp;
932 : :
933 : 24 : tmp = CreateIndexedPropertyName("fcs/throttle-cmd-norm", num);
934 : : PropertyManager->Tie( tmp.c_str(), this, num, &FGFCS::GetThrottleCmd,
935 : 12 : &FGFCS::SetThrottleCmd);
936 : 24 : tmp = CreateIndexedPropertyName("fcs/throttle-pos-norm", num);
937 : : PropertyManager->Tie( tmp.c_str(), this, num, &FGFCS::GetThrottlePos,
938 : 12 : &FGFCS::SetThrottlePos);
939 : 24 : tmp = CreateIndexedPropertyName("fcs/mixture-cmd-norm", num);
940 : : PropertyManager->Tie( tmp.c_str(), this, num, &FGFCS::GetMixtureCmd,
941 : 12 : &FGFCS::SetMixtureCmd);
942 : 24 : tmp = CreateIndexedPropertyName("fcs/mixture-pos-norm", num);
943 : : PropertyManager->Tie( tmp.c_str(), this, num, &FGFCS::GetMixturePos,
944 : 12 : &FGFCS::SetMixturePos);
945 : 24 : tmp = CreateIndexedPropertyName("fcs/advance-cmd-norm", num);
946 : : PropertyManager->Tie( tmp.c_str(), this, num, &FGFCS::GetPropAdvanceCmd,
947 : 12 : &FGFCS::SetPropAdvanceCmd);
948 : 24 : tmp = CreateIndexedPropertyName("fcs/advance-pos-norm", num);
949 : : PropertyManager->Tie( tmp.c_str(), this, num, &FGFCS::GetPropAdvance,
950 : 12 : &FGFCS::SetPropAdvance);
951 : 24 : tmp = CreateIndexedPropertyName("fcs/feather-cmd-norm", num);
952 : : PropertyManager->Tie( tmp.c_str(), this, num, &FGFCS::GetFeatherCmd,
953 : 12 : &FGFCS::SetFeatherCmd);
954 : 24 : tmp = CreateIndexedPropertyName("fcs/feather-pos-norm", num);
955 : : PropertyManager->Tie( tmp.c_str(), this, num, &FGFCS::GetPropFeather,
956 : 12 : &FGFCS::SetPropFeather);
957 : 12 : }
958 : :
959 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
960 : :
961 : 0 : void FGFCS::bindModel(void)
962 : : {
963 : : unsigned int i;
964 : 0 : string tmp;
965 : :
966 [ # # ]: 0 : for (i=0; i<SteerPosDeg.size(); i++) {
967 [ # # ]: 0 : if (GroundReactions->GetGearUnit(i)->GetSteerable()) {
968 : 0 : tmp = CreateIndexedPropertyName("fcs/steer-pos-deg", i);
969 : 0 : PropertyManager->Tie( tmp.c_str(), this, i, &FGFCS::GetSteerPosDeg, &FGFCS::SetSteerPosDeg);
970 : : }
971 : 0 : }
972 : 0 : }
973 : :
974 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
975 : : // The bitmasked value choices are as follows:
976 : : // unset: In this case (the default) JSBSim would only print
977 : : // out the normally expected messages, essentially echoing
978 : : // the config files as they are read. If the environment
979 : : // variable is not set, debug_lvl is set to 1 internally
980 : : // 0: This requests JSBSim not to output any messages
981 : : // whatsoever.
982 : : // 1: This value explicity requests the normal JSBSim
983 : : // startup messages
984 : : // 2: This value asks for a message to be printed out when
985 : : // a class is instantiated
986 : : // 4: When this value is set, a message is displayed when a
987 : : // FGModel object executes its Run() method
988 : : // 8: When this value is set, various runtime state variables
989 : : // are printed out periodically
990 : : // 16: When set various parameters are sanity checked and
991 : : // a message is printed out when they go out of bounds
992 : :
993 : 6 : void FGFCS::Debug(int from)
994 : : {
995 [ + - ]: 6 : if (debug_lvl <= 0) return;
996 : :
997 [ + - ]: 6 : if (debug_lvl & 1) { // Standard console startup message output
998 [ + + ]: 6 : if (from == 2) { // Loader
999 : 4 : cout << endl << " " << Name << endl;
1000 : : }
1001 : : }
1002 [ - + ]: 6 : if (debug_lvl & 2 ) { // Instantiation/Destruction notification
1003 [ # # ]: 0 : if (from == 0) cout << "Instantiated: FGFCS" << endl;
1004 [ # # ]: 0 : if (from == 1) cout << "Destroyed: FGFCS" << endl;
1005 : : }
1006 : 6 : if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
1007 : : }
1008 : 6 : if (debug_lvl & 8 ) { // Runtime state variables
1009 : : }
1010 : 6 : if (debug_lvl & 16) { // Sanity checking
1011 : : }
1012 [ - + ]: 6 : if (debug_lvl & 64) {
1013 [ # # ]: 0 : if (from == 0) { // Constructor
1014 : 0 : cout << IdSrc << endl;
1015 : 0 : cout << IdHdr << endl;
1016 : : }
1017 : : }
1018 : : }
1019 : :
1020 [ + + ][ + - ]: 12 : }
|