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