1 /* Siconos is a program dedicated to modeling, simulation and control
2  * of non smooth dynamical systems.
3  *
4  * Copyright 2021 INRIA.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17 */
18 
19 /*! \file CommonSMC.hpp
20   \brief General interface to define a sliding mode actuator
21   */
22 
23 #ifndef CommonSMC_H
24 #define CommonSMC_H
25 
26 #include "Actuator.hpp"
27 #include "SiconosAlgebraTypeDef.hpp"
28 #include "SiconosFwd.hpp"
29 
30 #include <relay_cst.h>
31 
32 class CommonSMC : public Actuator
33 {
34 private:
35   /** serialization hooks */
36   ACCEPT_SERIALIZATION(CommonSMC);
37 
38 protected:
39   /** default constructor */
CommonSMC()40   CommonSMC() {};
41 
42   /** index for saving data */
43   unsigned int _indx;
44 
45   /** name of the plugin to add a term to the sliding variable; useful when doing trajectory tracking */
46   std::string _plugineName;
47 
48   /** name of the plugin to compute \f$y = h(x, ...)\f$ for the nonlinear case*/
49   std::string _pluginhName;
50 
51   /** name of the plugin to compute \f$\nabla_x h\f$ for the nonlinear case*/
52   std::string _pluginJachxName;
53 
54   /** name of the plugin to compute \f$\nabla_\lambda h\f$ for the nonlinear case*/
55   std::string _pluginJachlambdaName;
56 
57   /** name of the plugin to compute \f$\nabla_\lambda g\f$ for the nonlinear case*/
58   std::string _pluginJacglambdaName;
59 
60   /** the vector defining the linear contribution of the state to the sliding variable  (\f$ \sigma = Cx \f$) */
61   SP::SimpleMatrix _Csurface;
62 
63   /** matrix describing the influence of \f$lambda\f$ on \f$\sigma\f$ */
64   SP::SimpleMatrix _D;
65 
66   /** scalar multiplying Sign; \f$ u^s = - \alpha Sign \f$ */
67   double _alpha;
68 
69   /** the Relation for the Controller */
70   SP::FirstOrderR _relationSMC;
71 
72   /** Interaction for the control */
73   SP::Interaction _interactionSMC;
74 
75   /** easy access to lambda */
76   SP::SiconosVector _lambda;
77 
78   /** Relay solver type */
79   int _numericsSolverId;
80 
81   /** Numerical precision expected for the Relay solver */
82   double _precision;
83 
84   /** the nsds for the controller */
85   SP::NonSmoothDynamicalSystem _nsdsSMC;
86 
87   /** the DynamicalSystem for the controller */
88   SP::FirstOrderNonLinearDS _DS_SMC; // XXX replace this by FirstOrderDS
89 
90   /** the TimeDiscretisation for the controller */
91   SP::TimeDiscretisation _td;
92 
93   /** Simulation for the controller */
94   SP::TimeStepping _simulationSMC;
95 
96   /** Integrator for the controller */
97   SP::OneStepIntegrator _integratorSMC;
98 
99   /** Theta for the controller */
100   double _thetaSMC;
101 
102   /** OneStepNsProblem for the controller */
103   SP::LinearOSNS _OSNSPB_SMC;
104 
105   /** SP::EventsManager of the SMC Simulation */
106   SP::EventsManager _eventsManager;
107 
108   /** SP::NonSmoothLaw for computing the control law */
109   SP::NonSmoothLaw _nsLawSMC;
110 
111   /** inverse of CB */
112   SP::SimpleMatrix _invCB;
113 
114   /** Store \f$u^{eq}\f$ */
115   SP::SiconosVector _ueq;
116 
117   /** Store \f$u^s\f$ */
118   SP::SiconosVector _us;
119 
120   /** Do not use the state-continuous equivaluent control \f$u^{eq}\f$ */
121   bool _noUeq;
122 
123   /** If true perform the computation of the residus in the Newton loop if needed */
124   bool _computeResidus;
125 
126   /** Compute the equivalent part of the control \f$u^{eq}\f$.
127    * The method used here is to discretize the continuous-time
128    * formula using a theta method
129    */
130   void computeUeq();
131 
132 public:
133 
134   /**General constructor
135    * \param type the type of the SMC Actuator
136    * \param sensor the ControlSensor feeding the Actuator
137    */
CommonSMC(unsigned int type,SP::ControlSensor sensor)138   CommonSMC(unsigned int type, SP::ControlSensor sensor): Actuator(type, sensor),
139     _indx(0), _alpha(1.0), _numericsSolverId(SICONOS_RELAY_AVI_CAOFERRIS), _precision(1e-8),
140     _thetaSMC(0.5), _noUeq(false), _computeResidus(true) {}
141 
142   /** Constructor for dynamics affine in control
143    * \param type the type of the SMC Actuator
144    * \param sensor the ControlSensor feeding the Actuator
145    * \param B the matrix multiplying the control input
146    * \param D the saturation matrix (optional)
147    */
CommonSMC(unsigned int type,SP::ControlSensor sensor,SP::SimpleMatrix B,SP::SimpleMatrix D=std::shared_ptr<SimpleMatrix> ())148   CommonSMC(unsigned int type, SP::ControlSensor sensor, SP::SimpleMatrix B, SP::SimpleMatrix D = std::shared_ptr<SimpleMatrix>()):
149     Actuator(type, sensor, B), _indx(0), _D(D), _alpha(1.0), _numericsSolverId(SICONOS_RELAY_AVI_CAOFERRIS),
150     _precision(1e-8), _thetaSMC(0.5), _noUeq(false), _computeResidus(true) {}
151 
152 
153   /** Compute the new control law at each event
154   */
155   virtual void actuate() = 0;
156 
157   /** Initialization
158    * \param nsds current nonsmooth dynamical system
159    * \param s current simulation setup
160    */
161   virtual void initialize(const NonSmoothDynamicalSystem& nsds, const Simulation& s);
162 
163 
164   void sete(const std::string& plugin);
165   void seth(const std::string& plugin);
166   void setJachx(const std::string& plugin);
167   void setJachlambda(const std::string& plugin);
168   void setg(const std::string& plugin);
169   void setJacgx(const std::string& plugin);
170   void setJacglambda(const std::string& plugin);
171 
172   /** Set Csurface
173    * \param Csurface a SP::SimpleMatrix containing the new value for _Csurface
174    */
175   void setCsurface(SP::SimpleMatrix Csurface);
176 
177   /** Set _D to pointer newPtr
178    * \param newSat a SP::SimpleMatrix containing the new value for _D
179    */
180   void setSaturationMatrix(SP::SimpleMatrix newSat);
181 
182   /** Set _alpha
183    * \param alpha the new value for _alpha
184    */
setAlpha(double alpha)185   inline void setAlpha(double alpha) { _alpha = alpha; };
186 
187   /** get _lambda
188    * \return a pointer to _lambda
189    */
lambda() const190   inline SP::SiconosVector lambda() const
191   {
192     return _lambda;
193   };
194 
195   /** Set the solver
196    * \param numericsSolverId the solver for the relay
197    */
setSolver(const int numericsSolverId)198   inline void setSolver(const int numericsSolverId)
199   {
200     _numericsSolverId = numericsSolverId;
201   };
202 
203   /** Set the precision
204    * \param newPrecision a double
205    */
setPrecision(double newPrecision)206   inline void setPrecision(double newPrecision)
207   {
208     _precision = newPrecision;
209   };
210 
211   /** Get the OneStepNSProblem problem associated with the controller. This is useful to
212    * gain access to the data given to the solver in Numerics
213    * \return a reference to the LinearOSNS problem
214    */
relay()215   inline const LinearOSNS& relay()
216   {
217     return * _OSNSPB_SMC;
218   };
219 
220   /** get \f$u^{eq}\f$
221    * \return a reference to _ueq
222    */
ueq()223   inline SiconosVector& ueq()
224   {
225     return *_ueq;
226   };
227 
228   /** get \f$u^{s}\f$
229    * \return a reference to _us
230    */
231 
us()232   inline SiconosVector& us()
233   {
234     return *_us;
235   };
236 
237   /** Set _theta, used in some discretization method for \f$u^{eq}\f$
238    * \param newTheta the new value for _thetaSMC
239    */
240 
setTheta(double newTheta)241   inline void setTheta(double newTheta)
242   {
243     _thetaSMC = newTheta;
244   };
245 
246   /** Disable (or enable) the use of the state-continuous control \f$u^{eq}\f$
247    * \param b disable the use of Ueq if true
248    */
noUeq(bool b)249   inline void noUeq(bool b)
250   {
251     _noUeq = b;
252   };
253 
254   /** Disable (or enable) the computation of the residus on the Newton loop.
255    * This has an incidence only if the Relation is nonlinear
256    * \param b disable the computation of the residus
257    */
setComputeResidus(bool b)258   inline void setComputeResidus(bool b)
259   {
260     _computeResidus = b;
261   };
262 
263   /** This is derived in child classes if they need to copy the TimeDiscretisation
264    * associated with this Sensor
265   *  \param td the TimeDiscretisation for this Sensor
266   */
267   virtual void setTimeDiscretisation(const TimeDiscretisation& td);
268 
269   /** Set the DynamicalSystem used to compute the control law.
270    * This is useful when we have a Nonlinear problem and we need to compute
271    * the control law with an approximate model, or when the dynamics are
272    * quite different.
273    * \param ds the DynamicalSystem to be used in the Controller
274    */
setDS(SP::FirstOrderNonLinearDS ds)275   void setDS(SP::FirstOrderNonLinearDS ds) // XXX replace this by FirstOrderDS
276   {
277     _DS_SMC = ds;
278   };
279 
280   /** get the NSDS used in the SMC
281    * \return the NSDS used in the SMC
282    */
getInternalNSDS() const283   virtual SP::NonSmoothDynamicalSystem getInternalNSDS() const { return _nsdsSMC; };
284 
285   /** get the Integrator used in the SMC
286    * \return the Integrator used in the SMC
287    */
getInternalOSI() const288   OneStepIntegrator& getInternalOSI() const { return *_integratorSMC; };
289 
290 };
291 #endif
292