3
* Copyright (C) James Goppert 2010 <james.goppert@gmail.com>
5
* FGStateSpace.h is free software: you can redistribute it and/or modify it
6
* under the terms of the GNU Lesser General Public License as published by the
7
* Free Software Foundation, either version 2 of the License, or
8
* (at your option) any later version.
10
* FGStateSpace.h is distributed in the hope that it will be useful, but
11
* WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13
* See the GNU Lesser General Public License for more details.
15
* You should have received a copy of the GNU Lesser General Public License along
16
* with this program. If not, see <http://www.gnu.org/licenses/>.
19
#ifndef JSBSim_FGStateSpace_H
20
#define JSBSim_FGStateSpace_H
22
#include "FGFDMExec.h"
23
#include "models/FGPropulsion.h"
24
#include "models/FGAccelerations.h"
25
#include "models/propulsion/FGEngine.h"
26
#include "models/propulsion/FGThruster.h"
27
#include "models/propulsion/FGTurbine.h"
28
#include "models/propulsion/FGTurboProp.h"
29
#include "models/FGAuxiliary.h"
30
#include "models/FGFCS.h"
46
FGStateSpace * m_stateSpace;
48
std::string m_name, m_unit;
50
Component(const std::string & name, const std::string & unit) :
51
m_stateSpace(), m_fdm(), m_name(name), m_unit(unit) {};
52
virtual ~Component() {};
53
virtual double get() const = 0;
54
virtual void set(double val) = 0;
55
virtual double getDeriv() const
57
// by default should calculate using finite difference approx
58
std::vector<double> x0 = m_stateSpace->x.get();
60
double dt0 = m_fdm->GetDeltaT();
61
double time0 = m_fdm->GetSimTime();
62
m_fdm->Setdt(1./120.);
63
m_fdm->DisableOutput();
66
m_stateSpace->x.set(x0);
67
if (m_fdm->GetDebugLevel() > 1)
69
std::cout << std::scientific
73
<< "\ndt: " << m_fdm->GetDeltaT()
74
<< "\tdf/dt: " << (f1-f0)/m_fdm->GetDeltaT()
75
<< std::fixed << std::endl;
77
double deriv = (f1-f0)/m_fdm->GetDeltaT();
78
m_fdm->Setdt(dt0); // restore original value
79
m_fdm->Setsim_time(time0);
80
m_fdm->EnableOutput();
83
void setStateSpace(FGStateSpace * stateSpace)
85
m_stateSpace = stateSpace;
87
void setFdm(FGFDMExec * fdm)
91
const std::string & getName() const
95
const std::string & getUnit() const
101
// component vector class
102
class ComponentVector
105
ComponentVector(FGFDMExec * fdm, FGStateSpace * stateSpace) :
106
m_stateSpace(stateSpace), m_fdm(fdm), m_components() {}
107
ComponentVector & operator=(ComponentVector & componentVector)
109
m_stateSpace = componentVector.m_stateSpace;
110
m_fdm = componentVector.m_fdm;
111
m_components = componentVector.m_components;
114
ComponentVector(const ComponentVector & componentVector) :
115
m_stateSpace(componentVector.m_stateSpace),
116
m_fdm(componentVector.m_fdm),
117
m_components(componentVector.m_components)
120
void add(Component * comp)
122
comp->setStateSpace(m_stateSpace);
124
m_components.push_back(comp);
128
return m_components.size();
130
Component * getComp(int i) const
132
return m_components[i];
134
Component * getComp(int i)
136
return m_components[i];
138
double get(int i) const
140
return m_components[i]->get();
142
void set(int i, double val)
144
m_components[i]->set(val);
149
return m_components[i]->get();
151
std::vector<double> get() const
153
std::vector<double> val;
154
for (int i=0;i<getSize();i++) val.push_back(m_components[i]->get());
157
void get(double * array) const
159
for (int i=0;i<getSize();i++) array[i] = m_components[i]->get();
161
double getDeriv(int i)
163
return m_components[i]->getDeriv();
165
std::vector<double> getDeriv() const
167
std::vector<double> val;
168
for (int i=0;i<getSize();i++) val.push_back(m_components[i]->getDeriv());
171
void getDeriv(double * array) const
173
for (int i=0;i<getSize();i++) array[i] = m_components[i]->getDeriv();
175
void set(std::vector<double> vals)
177
for (int i=0;i<getSize();i++) m_components[i]->set(vals[i]);
180
void set(double * array)
182
for (int i=0;i<getSize();i++) m_components[i]->set(array[i]);
185
std::string getName(int i) const
187
return m_components[i]->getName();
189
std::vector<std::string> getName() const
191
std::vector<std::string> name;
192
for (int i=0;i<getSize();i++) name.push_back(m_components[i]->getName());
195
std::string getUnit(int i) const
197
return m_components[i]->getUnit();
199
std::vector<std::string> getUnit() const
201
std::vector<std::string> unit;
202
for (int i=0;i<getSize();i++) unit.push_back(m_components[i]->getUnit());
206
m_components.clear();
209
FGStateSpace * m_stateSpace;
211
std::vector<Component *> m_components;
215
ComponentVector x, u, y;
218
FGStateSpace(FGFDMExec * fdm) : x(fdm,this), u(fdm,this), y(fdm,this), m_fdm(fdm) {};
220
void setFdm(FGFDMExec * fdm) { m_fdm = fdm; }
224
m_fdm->Initialize(m_fdm->GetIC());
225
for (unsigned int i=0; i<m_fdm->GetPropulsion()->GetNumEngines(); i++) {
226
m_fdm->GetPropulsion()->GetEngine(i)->InitRunning();
229
// wait for stable state
230
double cost = stateSum();
231
for(int i=0;i<1000;i++) {
232
m_fdm->GetPropulsion()->GetSteadyState();
233
m_fdm->SetTrimStatus(true);
234
m_fdm->DisableOutput();
235
m_fdm->SuspendIntegration();
237
m_fdm->SetTrimStatus(false);
238
m_fdm->EnableOutput();
239
m_fdm->ResumeIntegration();
241
double costNew = stateSum();
242
double dcost = fabs(costNew - cost);
243
if (dcost < std::numeric_limits<double>::epsilon()) {
244
if(m_fdm->GetDebugLevel() > 1) {
245
std::cout << "cost convergd, i: " << i << std::endl;
250
if(m_fdm->GetDebugLevel() > 1) {
251
std::cout << "cost failed to converge, dcost: "
253
<< dcost << std::endl;
263
for (int i=0;i<x.getSize();i++) sum += x.get(i);
274
virtual ~FGStateSpace() {};
276
// linearization function
277
void linearize(std::vector<double> x0, std::vector<double> u0, std::vector<double> y0,
278
std::vector< std::vector<double> > & A,
279
std::vector< std::vector<double> > & B,
280
std::vector< std::vector<double> > & C,
281
std::vector< std::vector<double> > & D);
286
// compute numerical jacobian of a matrix
287
void numericalJacobian(std::vector< std::vector<double> > & J, ComponentVector & y,
288
ComponentVector & x, const std::vector<double> & y0,
289
const std::vector<double> & x0, double h=1e-5, bool computeYDerivative = false);
291
// flight dynamcis model
298
class Vt : public Component
301
Vt() : Component("Vt","ft/s") {};
304
return m_fdm->GetAuxiliary()->GetVt();
308
m_fdm->GetIC()->SetVtrueFpsIC(val);
310
double getDeriv() const
313
return (m_fdm->GetPropagate()->GetUVW(1)*m_fdm->GetAccelerations()->GetUVWdot(1) +
314
m_fdm->GetPropagate()->GetUVW(2)*m_fdm->GetAccelerations()->GetUVWdot(2) +
315
m_fdm->GetPropagate()->GetUVW(3)*m_fdm->GetAccelerations()->GetUVWdot(3))/
316
m_fdm->GetAuxiliary()->GetVt(); // from lewis, vtrue dot
321
class VGround : public Component
324
VGround() : Component("VGround","ft/s") {};
327
return m_fdm->GetAuxiliary()->GetVground();
331
m_fdm->GetIC()->SetVgroundFpsIC(val);
335
class AccelX : public Component
338
AccelX() : Component("AccelX","ft/s^2") {};
341
return m_fdm->GetAuxiliary()->GetPilotAccel(1);
345
// XXX: not possible to implement currently
349
class AccelY : public Component
352
AccelY() : Component("AccelY","ft/s^2") {};
355
return m_fdm->GetAuxiliary()->GetPilotAccel(2);
359
// XXX: not possible to implement currently
363
class AccelZ : public Component
366
AccelZ() : Component("AccelZ","ft/s^2") {};
369
return m_fdm->GetAuxiliary()->GetPilotAccel(3);
373
// XXX: not possible to implement currently
377
class Alpha : public Component
380
Alpha() : Component("Alpha","rad") {};
383
return m_fdm->GetAuxiliary()->Getalpha();
387
double beta = m_fdm->GetIC()->GetBetaDegIC();
388
double psi = m_fdm->GetIC()->GetPsiRadIC();
389
double theta = m_fdm->GetIC()->GetThetaRadIC();
390
m_fdm->GetIC()->SetAlphaRadIC(val);
391
m_fdm->GetIC()->SetBetaRadIC(beta);
392
m_fdm->GetIC()->SetPsiRadIC(psi);
393
m_fdm->GetIC()->SetThetaRadIC(theta);
395
double getDeriv() const
397
return m_fdm->GetAuxiliary()->Getadot();
401
class Theta : public Component
404
Theta() : Component("Theta","rad") {};
407
return m_fdm->GetPropagate()->GetEuler(2);
411
m_fdm->GetIC()->SetFlightPathAngleRadIC(val-m_fdm->GetIC()->GetAlphaRadIC());
412
//m_fdm->GetIC()->SetThetaRadIC(val);
414
double getDeriv() const
416
return m_fdm->GetAuxiliary()->GetEulerRates(2);
420
class Q : public Component
423
Q() : Component("Q","rad/s") {};
426
return m_fdm->GetPropagate()->GetPQR(2);
430
m_fdm->GetIC()->SetQRadpsIC(val);
432
double getDeriv() const
434
return m_fdm->GetAccelerations()->GetPQRdot(2);
438
class Alt : public Component
441
Alt() : Component("Alt","ft") {};
444
return m_fdm->GetPropagate()->GetAltitudeASL();
448
m_fdm->GetIC()->SetAltitudeASLFtIC(val);
450
double getDeriv() const
452
return m_fdm->GetPropagate()->Gethdot();
456
class Beta : public Component
459
Beta() : Component("Beta","rad") {};
462
return m_fdm->GetAuxiliary()->Getbeta();
466
double psi = m_fdm->GetIC()->GetPsiRadIC();
467
m_fdm->GetIC()->SetBetaRadIC(val);
468
m_fdm->GetIC()->SetPsiRadIC(psi);
470
double getDeriv() const
472
return m_fdm->GetAuxiliary()->Getbdot();
476
class Phi : public Component
479
Phi() : Component("Phi","rad") {};
482
return m_fdm->GetPropagate()->GetEuler(1);
486
m_fdm->GetIC()->SetPhiRadIC(val);
488
double getDeriv() const
490
return m_fdm->GetAuxiliary()->GetEulerRates(1);
494
class P : public Component
497
P() : Component("P","rad/s") {};
500
return m_fdm->GetPropagate()->GetPQR(1);
504
m_fdm->GetIC()->SetPRadpsIC(val);
506
double getDeriv() const
508
return m_fdm->GetAccelerations()->GetPQRdot(1);
512
class R : public Component
515
R() : Component("R","rad/s") {};
518
return m_fdm->GetPropagate()->GetPQR(3);
522
m_fdm->GetIC()->SetRRadpsIC(val);
524
double getDeriv() const
526
return m_fdm->GetAccelerations()->GetPQRdot(3);
530
class Psi : public Component
533
Psi() : Component("Psi","rad") {};
536
return m_fdm->GetPropagate()->GetEuler(3);
540
m_fdm->GetIC()->SetPsiRadIC(val);
542
double getDeriv() const
544
return m_fdm->GetAuxiliary()->GetEulerRates(3);
548
class ThrottleCmd : public Component
551
ThrottleCmd() : Component("ThtlCmd","norm") {};
554
return m_fdm->GetFCS()->GetThrottleCmd(0);
558
for (unsigned int i=0;i<m_fdm->GetPropulsion()->GetNumEngines();i++)
559
m_fdm->GetFCS()->SetThrottleCmd(i,val);
560
m_fdm->GetFCS()->Run(true);
564
class ThrottlePos : public Component
567
ThrottlePos() : Component("ThtlPos","norm") {};
570
return m_fdm->GetFCS()->GetThrottlePos(0);
574
for (unsigned int i=0;i<m_fdm->GetPropulsion()->GetNumEngines();i++)
575
m_fdm->GetFCS()->SetThrottlePos(i,val);
579
class DaCmd : public Component
582
DaCmd() : Component("DaCmd","norm") {};
585
return m_fdm->GetFCS()->GetDaCmd();
589
m_fdm->GetFCS()->SetDaCmd(val);
590
m_fdm->GetFCS()->Run(true);
594
class DaPos : public Component
597
DaPos() : Component("DaPos","norm") {};
600
return m_fdm->GetFCS()->GetDaLPos();
604
m_fdm->GetFCS()->SetDaLPos(ofRad,val);
605
m_fdm->GetFCS()->SetDaRPos(ofRad,val); // TODO: check if this is neg.
609
class DeCmd : public Component
612
DeCmd() : Component("DeCmd","norm") {};
615
return m_fdm->GetFCS()->GetDeCmd();
619
m_fdm->GetFCS()->SetDeCmd(val);
620
m_fdm->GetFCS()->Run(true);
624
class DePos : public Component
627
DePos() : Component("DePos","norm") {};
630
return m_fdm->GetFCS()->GetDePos();
634
m_fdm->GetFCS()->SetDePos(ofRad,val);
638
class DrCmd : public Component
641
DrCmd() : Component("DrCmd","norm") {};
644
return m_fdm->GetFCS()->GetDrCmd();
648
m_fdm->GetFCS()->SetDrCmd(val);
649
m_fdm->GetFCS()->Run(true);
653
class DrPos : public Component
656
DrPos() : Component("DrPos","norm") {};
659
return m_fdm->GetFCS()->GetDrPos();
663
m_fdm->GetFCS()->SetDrPos(ofRad,val);
667
class Rpm0 : public Component
670
Rpm0() : Component("Rpm0","rev/min") {};
673
return m_fdm->GetPropulsion()->GetEngine(0)->GetThruster()->GetRPM();
677
m_fdm->GetPropulsion()->GetEngine(0)->GetThruster()->SetRPM(val);
681
class Rpm1 : public Component
684
Rpm1() : Component("Rpm1","rev/min") {};
687
return m_fdm->GetPropulsion()->GetEngine(1)->GetThruster()->GetRPM();
691
m_fdm->GetPropulsion()->GetEngine(1)->GetThruster()->SetRPM(val);
695
class Rpm2 : public Component
698
Rpm2() : Component("Rpm2","rev/min") {};
701
return m_fdm->GetPropulsion()->GetEngine(2)->GetThruster()->GetRPM();
705
m_fdm->GetPropulsion()->GetEngine(2)->GetThruster()->SetRPM(val);
709
class Rpm3 : public Component
712
Rpm3() : Component("Rpm3","rev/min") {};
715
return m_fdm->GetPropulsion()->GetEngine(3)->GetThruster()->GetRPM();
719
m_fdm->GetPropulsion()->GetEngine(3)->GetThruster()->SetRPM(val);
723
class PropPitch : public Component
726
PropPitch() : Component("Prop Pitch","deg") {};
729
return m_fdm->GetPropulsion()->GetEngine(0)->GetThruster()->GetPitch();
733
for (unsigned int i=0;i<m_fdm->GetPropulsion()->GetNumEngines();i++)
734
m_fdm->GetPropulsion()->GetEngine(i)->GetThruster()->SetPitch(val);
738
class Longitude : public Component
741
Longitude() : Component("Longitude","rad") {};
744
return m_fdm->GetPropagate()->GetLongitude();
748
m_fdm->GetIC()->SetLongitudeRadIC(val);
750
double getDeriv() const
752
return m_fdm->GetPropagate()->GetVel(2)/(cos(m_fdm->GetPropagate()->GetLatitude())*m_fdm->GetPropagate()->GetRadius());
756
class Latitude : public Component
759
Latitude() : Component("Latitude","rad") {};
762
return m_fdm->GetPropagate()->GetLatitude();
766
m_fdm->GetIC()->SetLatitudeRadIC(val);
768
double getDeriv() const
770
return m_fdm->GetPropagate()->GetVel(1)/(m_fdm->GetPropagate()->GetRadius());
774
class Pi : public Component
777
Pi() : Component("P inertial","rad/s") {};
780
return m_fdm->GetPropagate()->GetPQRi(1);
785
//VState.vPQR = VState.vPQRi - Ti2b * vOmegaEarth;
786
m_fdm->GetIC()->SetQRadpsIC(val + \
787
(m_fdm->GetPropagate()->GetPQR(1) - m_fdm->GetPropagate()->GetPQRi(1)));
789
double getDeriv() const
791
return m_fdm->GetAccelerations()->GetPQRdot(1);
795
class Qi : public Component
798
Qi() : Component("Q inertial","rad/s") {};
801
return m_fdm->GetPropagate()->GetPQRi(2);
806
//VState.vPQR = VState.vPQRi - Ti2b * vOmegaEarth;
807
m_fdm->GetIC()->SetQRadpsIC(val + \
808
(m_fdm->GetPropagate()->GetPQR(2) - m_fdm->GetPropagate()->GetPQRi(2)));
810
double getDeriv() const
812
return m_fdm->GetAccelerations()->GetPQRdot(2);
816
class Ri : public Component
819
Ri() : Component("R inertial","rad/s") {};
822
return m_fdm->GetPropagate()->GetPQRi(3);
827
//VState.vPQR = VState.vPQRi - Ti2b * vOmegaEarth;
828
m_fdm->GetIC()->SetQRadpsIC(val + \
829
(m_fdm->GetPropagate()->GetPQR(3) - m_fdm->GetPropagate()->GetPQRi(3)));
831
double getDeriv() const
833
return m_fdm->GetAccelerations()->GetPQRdot(3);
837
class Vn : public Component
840
Vn() : Component("Vel north","feet/s") {};
843
return m_fdm->GetPropagate()->GetVel(1);
847
m_fdm->GetIC()->SetVNorthFpsIC(val);
849
double getDeriv() const
851
//get NED accel from body accel
852
return (m_fdm->GetPropagate()->GetTb2l()*m_fdm->GetAccelerations()->GetUVWdot())(1);
856
class Ve : public Component
859
Ve() : Component("Vel east","feet/s") {};
862
return m_fdm->GetPropagate()->GetVel(2);
866
m_fdm->GetIC()->SetVEastFpsIC(val);
868
double getDeriv() const
870
//get NED accel from body accel
871
return (m_fdm->GetPropagate()->GetTb2l()*m_fdm->GetAccelerations()->GetUVWdot())(2);
875
class Vd : public Component
878
Vd() : Component("Vel down","feet/s") {};
881
return m_fdm->GetPropagate()->GetVel(3);
885
m_fdm->GetIC()->SetVDownFpsIC(val);
887
double getDeriv() const
889
//get NED accel from body accel
890
return (m_fdm->GetPropagate()->GetTb2l()*m_fdm->GetAccelerations()->GetUVWdot())(3);
894
class COG : public Component
897
COG() : Component("Course Over Ground","rad") {};
901
return atan2(m_fdm->GetPropagate()->GetVel(2),m_fdm->GetPropagate()->GetVel(1));
905
//set Vn and Ve according to vGround and COG
906
m_fdm->GetIC()->SetVNorthFpsIC(m_fdm->GetAuxiliary()->GetVground()*cos(val));
907
m_fdm->GetIC()->SetVEastFpsIC(m_fdm->GetAuxiliary()->GetVground()*sin(val));
909
double getDeriv() const
911
double Vn = m_fdm->GetPropagate()->GetVel(1);
912
double Vndot = (m_fdm->GetPropagate()->GetTb2l()*m_fdm->GetAccelerations()->GetUVWdot())(1);
913
double Ve = m_fdm->GetPropagate()->GetVel(2);
914
double Vedot = (m_fdm->GetPropagate()->GetTb2l()*m_fdm->GetAccelerations()->GetUVWdot())(2);
916
//dCOG/dt = dCOG/dVe*dVe/dt + dCOG/dVn*dVn/dt
917
return Vn/(Vn*Vn+Ve*Ve)*Vedot - Ve/(Vn*Vn+Ve*Ve)*Vndot;
924
std::ostream &operator<<(std::ostream &out, const FGStateSpace::Component &c );
925
std::ostream &operator<<(std::ostream &out, const FGStateSpace::ComponentVector &v );
926
std::ostream &operator<<(std::ostream &out, const FGStateSpace &ss );
927
std::ostream &operator<<( std::ostream &out, const std::vector< std::vector<double> > &vec2d );
928
std::ostream &operator<<( std::ostream &out, const std::vector<double> &vec );