1 // =============================================================================
2 // PROJECT CHRONO - http://projectchrono.org
3 //
4 // Copyright (c) 2014 projectchrono.org
5 // All rights reserved.
6 //
7 // Use of this source code is governed by a BSD-style license that can be found
8 // in the LICENSE file at the top level of the distribution and at
9 // http://projectchrono.org/license-chrono.txt.
10 //
11 // =============================================================================
12 // Authors: Radu Serban
13 //
14 // Linear spring-damper-actuator with force specified through a user-supplied
15 // functor object.
16 // Optionally, a ChLinkSpringCB can have internal dynamics, described by a
17 // system of ODEs. The internal states are integrated simultaneous with the
18 // containing system. They can be accessed and used in the force calculation.
19 // Such objects can be used in active suspension models.
20 // =============================================================================
21 
22 #ifndef CH_LINK_SPRING_CB_H
23 #define CH_LINK_SPRING_CB_H
24 
25 #include "chrono/physics/ChLinkMarkers.h"
26 #include "chrono/solver/ChVariablesGenericDiagonalMass.h"
27 
28 namespace chrono {
29 
30 /// Class for spring-damper systems with the force specified through a functor object.
31 /// Optionally, these objects may have internal dynamics, represented by a system of ODEs.
32 ///
33 /// \deprecated Use ChLinkTSDA instead. This class will be removed in a future Chrono release.
34 class ChApi
35 /// \cond
36 CH_DEPRECATED("deprecated. Use ChLinkTSDA instead.")
37 /// \endcond
38 ChLinkSpringCB : public ChLinkMarkers {
39   public:
40     ChLinkSpringCB();
41     ChLinkSpringCB(const ChLinkSpringCB& other);
42     ~ChLinkSpringCB();
43 
44     /// "Virtual" copy constructor (covariant return type).
45     virtual ChLinkSpringCB* Clone() const override;
46 
47     // Set spring rest (free) length.
48     // Optionally, the free length can be calculated from the initial configuration (see #Initialize).
SetSpringRestLength(double len)49     void SetSpringRestLength(double len) { m_rest_length = len; }
50 
51     // Get current states.
GetStates()52     const ChVectorDynamic<>& GetStates() const { return m_states; }
53 
54     // Get the spring rest (free) length.
GetSpringRestLength()55     double GetSpringRestLength() const { return m_rest_length; }
56 
GetSpringDeform()57     double GetSpringDeform() const { return dist - m_rest_length; }
GetSpringLength()58     double GetSpringLength() const { return dist; }
GetSpringVelocity()59     double GetSpringVelocity() const { return dist_dt; }
GetSpringReact()60     double GetSpringReact() const { return m_force; }
61 
62     /// Class to be used as a callback interface for calculating the general spring-damper force.
63     class ChApi ForceFunctor {
64       public:
~ForceFunctor()65         virtual ~ForceFunctor() {}
66 
67         /// Calculate and return the general spring-damper force at the specified configuration.
68         virtual double operator()(double time,          ///< current time
69                                   double rest_length,   ///< undeformed length
70                                   double length,        ///< current length
71                                   double vel,           ///< current velocity (positive when extending)
72                                   ChLinkSpringCB* link  ///< back-pointer to associated link
73                                   ) = 0;
74     };
75 
76     /// Specify the functor object for calculating the force.
RegisterForceFunctor(ForceFunctor * functor)77     void RegisterForceFunctor(ForceFunctor* functor) { m_force_fun = functor; }
78 
79     /// Class to be used as a callback interface for specifying the ODE, y' = f(t,y); y(0) = y0.
80     class ChApi ODE {
81       public:
~ODE()82         virtual ~ODE() {}
83 
84         /// Specify number of states (dimension of y).
85         virtual int GetNumStates() const = 0;
86 
87         /// Set initial conditions.
88         /// Must load y0 = y(0).
89         virtual void SetInitialConditions(ChVectorDynamic<>& states,  ///< output initial conditions vector
90                                           ChLinkSpringCB* link        ///< back-pointer to associated link
91                                           ) = 0;
92 
93         /// Calculate and return the ODE right-hand side at the provided time and states.
94         /// Must load f(t,y).
95         virtual void CalculateRHS(double time,                      ///< current time
96                                   const ChVectorDynamic<>& states,  ///< current states
97                                   ChVectorDynamic<>& rhs,           ///< output ODE right-hand side vector
98                                   ChLinkSpringCB* link              ///< back-pointer to associated link
99                                   ) = 0;
100     };
101 
102     /// Specify the functor object for calculating the ODE right-hand side.
103     void RegisterODE(ODE* functor);
104 
105     /// Specialized initialization for springs, given the two bodies to be connected, the positions of the two anchor
106     /// endpoints of the spring (each expressed in body or abs. coordinates) and the imposed rest length of the spring.
107     /// Note: Two markers are automatically created and associated with the two connected bodies.
108     void Initialize(
109         std::shared_ptr<ChBody> body1,  ///< first body to link
110         std::shared_ptr<ChBody> body2,  ///< second body to link
111         bool pos_are_relative,          ///< true: following pos. are relative to bodies
112         ChVector<> pos1,                ///< pos. of spring endpoint for 1st body (rel. or abs., see flag above)
113         ChVector<> pos2,                ///< pos. of spring endpoint for 2nd body (rel. or abs., see flag above)
114         bool auto_rest_length = true,   ///< if true, initializes the rest length as the distance between pos1 and pos2
115         double rest_length = 0          ///< rest length (no need to define if auto_rest_length=true.)
116     );
117 
118     /// Get the 1st spring endpoint (expressed in Body1 coordinate system)
GetEndPoint1Rel()119     ChVector<> GetEndPoint1Rel() { return marker1->GetPos(); }
120     /// Set the 1st spring endpoint (expressed in Body1 coordinate system)
SetEndPoint1Rel(const ChVector<> & mset)121     void SetEndPoint1Rel(const ChVector<>& mset) { marker1->Impose_Rel_Coord(ChCoordsys<>(mset, QUNIT)); }
122     /// Get the 1st spring endpoint (expressed in absolute coordinate system)
GetEndPoint1Abs()123     ChVector<> GetEndPoint1Abs() { return marker1->GetAbsCoord().pos; }
124     /// Set the 1st spring endpoint (expressed in absolute coordinate system)
SetEndPoint1Abs(ChVector<> & mset)125     void SetEndPoint1Abs(ChVector<>& mset) { marker1->Impose_Abs_Coord(ChCoordsys<>(mset, QUNIT)); }
126 
127     /// Get the 2nd spring endpoint (expressed in Body2 coordinate system)
GetEndPoint2Rel()128     ChVector<> GetEndPoint2Rel() { return marker2->GetPos(); };
129     /// Set the 2nd spring endpoint (expressed in Body2 coordinate system)
SetEndPoint2Rel(const ChVector<> & mset)130     void SetEndPoint2Rel(const ChVector<>& mset) { marker2->Impose_Rel_Coord(ChCoordsys<>(mset, QUNIT)); }
131     /// Get the 1st spring endpoint (expressed in absolute coordinate system)
GetEndPoint2Abs()132     ChVector<> GetEndPoint2Abs() { return marker2->GetAbsCoord().pos; }
133     /// Set the 1st spring endpoint (expressed in absolute coordinate system)
SetEndPoint2Abs(ChVector<> & mset)134     void SetEndPoint2Abs(ChVector<>& mset) { marker2->Impose_Abs_Coord(ChCoordsys<>(mset, QUNIT)); }
135 
136     /// Inherits, then also adds the spring custom forces to the C_force and C_torque.
137     virtual void UpdateForces(double time) override;
138 
139     /// Method to allow serialization of transient data to archives.
140     virtual void ArchiveOUT(ChArchiveOut& marchive) override;
141 
142     /// Method to allow deserialization of transient data from archives.
143     virtual void ArchiveIN(ChArchiveIn& marchive) override;
144 
145   private:
146     using ChLinkMarkers::Initialize;
147 
148     virtual void Update(double mytime, bool update_assets = true) override;
149 
GetDOF()150     virtual int GetDOF() override { return m_nstates; }
151 
152     // Interface to state operations
153     virtual void IntStateGather(const unsigned int off_x,
154                                 ChState& x,
155                                 const unsigned int off_v,
156                                 ChStateDelta& v,
157                                 double& T) override;
158     virtual void IntStateScatter(const unsigned int off_x,
159                                  const ChState& x,
160                                  const unsigned int off_v,
161                                  const ChStateDelta& v,
162                                  const double T,
163                                  bool full_update) override;
164     virtual void IntStateGatherAcceleration(const unsigned int off_a, ChStateDelta& a) override;
165     virtual void IntStateScatterAcceleration(const unsigned int off_a, const ChStateDelta& a) override;
166     virtual void IntLoadResidual_F(const unsigned int off, ChVectorDynamic<>& R, const double c) override;
167     virtual void IntLoadResidual_Mv(const unsigned int off,
168                                     ChVectorDynamic<>& R,
169                                     const ChVectorDynamic<>& v,
170                                     const double c) override;
171     virtual void IntToDescriptor(const unsigned int off_v,
172                                  const ChStateDelta& v,
173                                  const ChVectorDynamic<>& R,
174                                  const unsigned int off_L,
175                                  const ChVectorDynamic<>& L,
176                                  const ChVectorDynamic<>& Qc) override;
177     virtual void IntFromDescriptor(const unsigned int off_v,
178                                    ChStateDelta& v,
179                                    const unsigned int off_L,
180                                    ChVectorDynamic<>& L) override;
181 
182     // Interface to the solver
Variables()183     ChVariables& Variables() { return *m_variables; }
184     virtual void InjectVariables(ChSystemDescriptor& mdescriptor) override;
185 
186     virtual void VariablesFbReset() override;
187     virtual void VariablesFbLoadForces(double factor = 1) override;
188     virtual void VariablesQbLoadSpeed() override;
189     virtual void VariablesQbSetSpeed(double step = 0) override;
190     virtual void VariablesFbIncrementMq() override;
191     virtual void VariablesQbIncrementPosition(double step) override;
192 
193     ForceFunctor* m_force_fun;  ///< functor for force calculation
194     ODE* m_ode_fun;             ///< functor for ODE specification
195     int m_nstates;              ///< number of internal states
196     double m_rest_length;       ///< undeform length
197     double m_force;             ///< resulting force in distance coord
198 
199     ChVectorDynamic<> m_states;                   ///< vector of internal states
200     ChVectorDynamic<> m_rhs;                      ///< current ODE right-hand side
201     ChVariablesGenericDiagonalMass* m_variables;  ///< carrier for internal dynamics states
202 
203     friend class ChSystemMulticore;
204 };
205 
206 CH_CLASS_VERSION(ChLinkSpringCB, 0)
207 
208 }  // end namespace chrono
209 
210 #endif
211