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: Alessandro Tasora, Radu Serban
13 // =============================================================================
14 //
15 // This file contains a number of ready-to-use loads (ChLoad inherited classes and
16 // their embedded ChLoader classes) that can be applied to objects of ChBody (and
17 // inherited classes) type.
18 // These are 'simplified' tools, that save you from inheriting your custom loads.
19 // Or just look at these classes and learn how to implement some special type of load.
20 //
21 // Example:
22 //    std::shared_ptr<ChBodyEasyBox> body_test(new ChBodyEasyBox(8,4,4,1000));
23 //    mphysicalSystem.Add(body_test);
24 //
25 //    std::shared_ptr<ChLoadContainer> mforcecontainer (new ChLoadContainer);
26 //    mphysicalSystem.Add(mforcecontainer);
27 //
28 //    std::shared_ptr<ChLoadBodyForce> mforce (new ChLoadBodyForce(body_test, ChVector<>(0,80000,0), false,
29 //    ChVector<>(8,0,0),true)); mforcecontainer->Add(mforce);
30 //
31 //    std::shared_ptr<ChLoadBodyTorque> mtorque (new ChLoadBodyTorque(body_test, ChVector<>(0,0,-80000*8), true));
32 //    mforcecontainer->Add(mtorque);
33 //
34 // =============================================================================
35 
36 #ifndef CHLOADSBODY_H
37 #define CHLOADSBODY_H
38 
39 #include "chrono/motion_functions/ChFunction.h"
40 #include "chrono/physics/ChBody.h"
41 #include "chrono/physics/ChLoad.h"
42 
43 namespace chrono {
44 
45 /// Load representing a concentrated force acting on a rigid body.
46 /// The force can rotate together with the body (if in body local coordinates) or not.
47 /// The application point can follow the body (if in body local coordinates) or not.
48 /// The magnitude of the applied force can be optionally modulated by a function of time.
49 /// The default modulation is the constant function with value 1.
50 class ChApi ChLoadBodyForce : public ChLoadCustom {
51   public:
52     ChLoadBodyForce(std::shared_ptr<ChBody> body,  ///< object to apply load to
53                     const ChVector<>& force,       ///< force to apply
54                     bool local_force,              ///< force is in body local coords
55                     const ChVector<>& point,       ///< application point for the force
56                     bool local_point = true        ///< application point is in body local coords
57     );
58 
59     /// "Virtual" copy constructor (covariant return type).
Clone()60     virtual ChLoadBodyForce* Clone() const override { return new ChLoadBodyForce(*this); }
61 
62     /// Set the constant force vector.
63     /// It can be expressed in absolute coordinates or body local coordinates.
64     /// This value is optionally modulated by a function of time.
65     void SetForce(const ChVector<>& force, bool is_local);
66 
67     /// Return the current force vector (scaled by the current modulation value).
68     ChVector<> GetForce() const;
69 
70     /// Set the application point of force, assumed to be constant.
71     /// It can be expressed in absolute coordinates or body local coordinates
72     void SetApplicationPoint(const ChVector<>& point, const bool is_local);
73 
74     /// Return the location of the application point.
GetApplicationPoint()75     ChVector<> GetApplicationPoint() const { return m_point; }
76 
77     /// Set modulation function.
78     /// This is a function of time which (optionally) modulates the specified applied force.
79     /// By default the modulation is a constant function, always returning a value of 1.
SetModulationFunction(std::shared_ptr<ChFunction> modulation)80     void SetModulationFunction(std::shared_ptr<ChFunction> modulation) { m_modulation = modulation; }
81 
82     /// Compute Q, the generalized load.
83     /// Called automatically at each Update().
84     virtual void ComputeQ(ChState* state_x,      ///< state position to evaluate Q
85                           ChStateDelta* state_w  ///< state speed to evaluate Q
86                           ) override;
87 
88   private:
89     ChVector<> m_force;  ///< base force value
90     ChVector<> m_point;  ///< application point
91     bool m_local_force;  ///< is force expressed in local frame?
92     bool m_local_point;  ///< is application expressed in local frame?
93 
94     std::shared_ptr<ChFunction> m_modulation;  ///< modulation function of time
95     double m_scale;                            ///< scaling factor (current modulation value)
96 
IsStiff()97     virtual bool IsStiff() override { return false; }
98 
99     virtual void Update(double time) override;
100 };
101 
102 //------------------------------------------------------------------------------------------------
103 
104 /// Load representing a torque applied to a rigid body.
105 /// Torque direction does not rotate with the body.
106 /// The magnitude of the applied torque can be optionally modulated by a function of time.
107 /// The default modulation is the constant function with value 1.
108 class ChApi ChLoadBodyTorque : public ChLoadCustom {
109   public:
110     ChLoadBodyTorque(std::shared_ptr<ChBody> body,  ///< object to apply load to
111                      const ChVector<>& torque,      ///< torque to apply
112                      bool local_torque              ///< torque is in body local coords
113     );
114 
115     /// "Virtual" copy constructor (covariant return type).
Clone()116     virtual ChLoadBodyTorque* Clone() const override { return new ChLoadBodyTorque(*this); }
117 
118     /// Set the constant torque vector.
119     /// This value is optionally modulated by a function of time.
120     void SetTorque(const ChVector<>& torque, bool is_local);
121 
122     /// Return the current torque vector (scaled by the current modulation value).
123     ChVector<> GetTorque() const;
124 
125     /// Set modulation function.
126     /// This is a function of time which (optionally) modulates the specified applied force.
127     /// By default the modulation is a constant function, always returning a value of 1.
SetModulationFunction(std::shared_ptr<ChFunction> modulation)128     void SetModulationFunction(std::shared_ptr<ChFunction> modulation) { m_modulation = modulation; }
129 
130     /// Compute Q, the generalized load.
131     /// Called automatically at each Update().
132     virtual void ComputeQ(ChState* state_x,      ///< state position to evaluate Q
133                           ChStateDelta* state_w  ///< state speed to evaluate Q
134                           ) override;
135 
136   private:
137     ChVector<> m_torque;  ///< base torque value
138     bool m_local_torque;  ///< is torque expressed in local frame?
139 
140     std::shared_ptr<ChFunction> m_modulation;  ///< modulation function of time
141     double m_scale;                            ///< scaling factor (current modulation value)
142 
IsStiff()143     virtual bool IsStiff() override { return false; }
144 
145     virtual void Update(double time) override;
146 };
147 
148 //------------------------------------------------------------------------------------------------
149 
150 /// Base class for wrench loads (a force + a torque) acting between two bodies.
151 /// See children classes for concrete implementations.
152 class ChApi ChLoadBodyBody : public ChLoadCustomMultiple {
153   public:
154     ChLoadBodyBody(std::shared_ptr<ChBody> bodyA,    ///< body A
155                    std::shared_ptr<ChBody> bodyB,    ///< body B
156                    const ChFrame<>& abs_application  ///< location of load element (in abs. coordinates)
157     );
158 
159     /// Compute the force between the two bodies, in local reference loc_application_B,
160     /// given rel_AB, i.e. the position and speed of loc_application_A respect to loc_application_B.
161     /// Force is assumed applied to loc_application_B of body B, and its opposite reaction to A.
162     /// Inherited classes MUST IMPLEMENT THIS.
163     virtual void ComputeBodyBodyForceTorque(const ChFrameMoving<>& rel_AB,
164                                             ChVector<>& loc_force,
165                                             ChVector<>& loc_torque) = 0;
166 
167     // Optional: inherited classes could implement this to avoid the
168     // default numerical computation of jacobians:
169     //   virtual void ComputeJacobian(...) // see ChLoad
170 
171     /// For diagnosis purposes, this can return the actual last computed value of
172     /// the applied force, expressed in coordinate system of loc_application_B, assumed applied to body B
GetForce()173     ChVector<> GetForce() const { return locB_force; }
174 
175     /// For diagnosis purposes, this can return the actual last computed value of
176     /// the applied torque, expressed in coordinate system of loc_application_B, assumed applied to body B
GetTorque()177     ChVector<> GetTorque() const { return locB_torque; }
178 
179     /// Set the application frame of bushing on bodyA
SetApplicationFrameA(const ChFrame<> & mpA)180     void SetApplicationFrameA(const ChFrame<>& mpA) { loc_application_A = mpA; }
GetApplicationFrameA()181     ChFrame<> GetApplicationFrameA() const { return loc_application_A; }
182 
183     /// Set the application frame of bushing on bodyB
SetApplicationFrameB(const ChFrame<> & mpB)184     void SetApplicationFrameB(const ChFrame<>& mpB) { loc_application_B = mpB; }
GetApplicationFrameB()185     ChFrame<> GetApplicationFrameB() const { return loc_application_B; }
186 
187     /// Get absolute coordinate of frame A (last computed)
GetAbsoluteFrameA()188     ChFrameMoving<> GetAbsoluteFrameA() const { return frame_Aw; }
189 
190     /// Get absolute coordinate of frame B (last computed)
GetAbsoluteFrameB()191     ChFrameMoving<> GetAbsoluteFrameB() const { return frame_Bw; }
192 
193     std::shared_ptr<ChBody> GetBodyA() const;
194     std::shared_ptr<ChBody> GetBodyB() const;
195 
196   protected:
197     ChFrame<> loc_application_A;  ///< application point on body A (local)
198     ChFrame<> loc_application_B;  ///< application point on body B (local)
199     ChVector<> locB_force;        ///< store computed values here
200     ChVector<> locB_torque;       ///< store computed values here
201     ChFrameMoving<> frame_Aw;     ///< for results
202     ChFrameMoving<> frame_Bw;     ///< for results
203 
204     /// Compute Q, the generalized load. It calls ComputeBodyBodyForceTorque, so in
205     /// children classes you do not need to implement it.
206     /// Called automatically at each Update().
207     virtual void ComputeQ(ChState* state_x,      ///< state position to evaluate Q
208                           ChStateDelta* state_w  ///< state speed to evaluate Q
209                           ) override;
210 };
211 
212 //------------------------------------------------------------------------------------------------
213 
214 /// Load representing a torque applied between two bodies.
215 /// The magnitude of the applied torque can be optionally modulated by a function of time.
216 /// The default modulation is the constant function with value 1.
217 class ChApi ChLoadBodyBodyTorque : public ChLoadBodyBody {
218   public:
219     ChLoadBodyBodyTorque(std::shared_ptr<ChBody> bodyA,  ///< first body
220                          std::shared_ptr<ChBody> bodyB,  ///< second body
221                          const ChVector<> torque,        ///< applied torque
222                          bool local_torque               ///< torque is in bodyB local coords
223     );
224 
225     /// "Virtual" copy constructor (covariant return type).
Clone()226     virtual ChLoadBodyBodyTorque* Clone() const override { return new ChLoadBodyBodyTorque(*this); }
227 
228     /// Set modulation function.
229     /// This is a function of time which (optionally) modulates the specified applied torque.
230     /// By default the modulation is a constant function, always returning a value of 1.
SetModulationFunction(std::shared_ptr<ChFunction> modulation)231     void SetModulationFunction(std::shared_ptr<ChFunction> modulation) { m_modulation = modulation; }
232 
233   private:
234     ChVector<> m_torque;  ///< base torque value
235     bool m_local_torque;  ///< is torque expressed in local frame (bodyB)?
236 
237     std::shared_ptr<ChFunction> m_modulation;  ///< modulation function of time
238     double m_scale;                            ///< scaling factor (current modulation value)
239 
IsStiff()240     virtual bool IsStiff() override { return false; }
241 
242     virtual void Update(double time) override;
243 
244     /// Implement the computation of the body-body force, in local
245     /// coordinates of the loc_application_B.
246     /// Force is assumed applied to loc_application_B of body B, and its opposite reaction to A.
247     virtual void ComputeBodyBodyForceTorque(const ChFrameMoving<>& rel_AB,
248                                             ChVector<>& loc_force,
249                                             ChVector<>& loc_torque) override;
250 };
251 
252 //------------------------------------------------------------------------------------------------
253 
254 /// Load for a visco-elastic bushing acting between two bodies.
255 /// It uses three values for stiffness along the X Y Z axes of a coordinate system attached
256 /// to the second body. This is equivalent to having a bushing with 3x3 diagonal local stiffness matrix.
257 class ChApi ChLoadBodyBodyBushingSpherical : public ChLoadBodyBody {
258   public:
259     ChLoadBodyBodyBushingSpherical(
260         std::shared_ptr<ChBody> mbodyA,    ///< body A
261         std::shared_ptr<ChBody> mbodyB,    ///< body B
262         const ChFrame<>& abs_application,  ///< bushing location, in abs. coordinates.
263         const ChVector<>& mstiffness,      ///< stiffness, along x y z axes of the abs_application
264         const ChVector<>& mdamping         ///< damping, along x y z axes of the abs_application
265     );
266 
267     /// "Virtual" copy constructor (covariant return type).
Clone()268     virtual ChLoadBodyBodyBushingSpherical* Clone() const override { return new ChLoadBodyBodyBushingSpherical(*this); }
269 
270     /// Set stiffness, along the x y z axes of loc_application_B, es [N/m]
SetStiffness(const ChVector<> mstiffness)271     void SetStiffness(const ChVector<> mstiffness) { stiffness = mstiffness; }
GetStiffness()272     ChVector<> GetStiffness() const { return stiffness; }
273 
274     /// Set damping, along the x y z axes of loc_application_B, es [Ns/m]
SetDamping(const ChVector<> mdamping)275     void SetDamping(const ChVector<> mdamping) { damping = mdamping; }
GetDamping()276     ChVector<> GetDamping() const { return damping; }
277 
278   protected:
279     ChVector<> stiffness;
280     ChVector<> damping;
281 
IsStiff()282     virtual bool IsStiff() override { return true; }
283 
284     /// Implement the computation of the bushing force, in local
285     /// coordinates of the loc_application_B.
286     /// Force is assumed applied to loc_application_B of body B, and its opposite reaction to A.
287     virtual void ComputeBodyBodyForceTorque(const ChFrameMoving<>& rel_AB,
288                                             ChVector<>& loc_force,
289                                             ChVector<>& loc_torque) override;
290 };
291 
292 //------------------------------------------------------------------------------------------------
293 
294 /// Load for a visco-elasto-plastic bushing acting between two bodies.
295 /// It uses three values for stiffness along the X Y Z axes of a coordinate system attached
296 /// to the second body. This is equivalent to having a bushing with 3x3 diagonal local stiffness matrix.
297 /// Also, it allows a very simple plasticity model, to cap the plastic force on x,y,z given three yelds.
298 class ChApi ChLoadBodyBodyBushingPlastic : public ChLoadBodyBodyBushingSpherical {
299   public:
300     ChLoadBodyBodyBushingPlastic(
301         std::shared_ptr<ChBody> mbodyA,    ///< body A
302         std::shared_ptr<ChBody> mbodyB,    ///< body B
303         const ChFrame<>& abs_application,  ///< create the bushing here, in abs. coordinates.
304         const ChVector<>& mstiffness,      ///< stiffness, along the x y z axes of the abs_application
305         const ChVector<>& mdamping,        ///< damping, along the x y z axes of the abs_application
306         const ChVector<>& myield           ///< plastic yield, along the x y z axes of the abs_application
307     );
308 
309     /// Set plastic yield, forces beyond this limit will be capped.
310     /// Expressed along the x y z axes of loc_application_B.
SetYeld(const ChVector<> myeld)311     void SetYeld(const ChVector<> myeld) { yield = myeld; }
GetYeld()312     ChVector<> GetYeld() const { return yield; }
313 
314     /// Get the current accumulated plastic deformation.
315     /// This could become nonzero if forces went beyond the plastic yield.
GetPlasticDeformation()316     ChVector<> GetPlasticDeformation() const { return plastic_def; }
317 
318   protected:
319     ChVector<> yield;
320     ChVector<> plastic_def;
321 
322     /// Implement the computation of the bushing force, in local
323     /// coordinates of the loc_application_B.
324     /// Force is assumed applied to loc_application_B of body B, and its opposite reaction to A.
325     virtual void ComputeBodyBodyForceTorque(const ChFrameMoving<>& rel_AB,
326                                             ChVector<>& loc_force,
327                                             ChVector<>& loc_torque) override;
328 };
329 
330 //------------------------------------------------------------------------------------------------
331 
332 /// Load for a visco-elastic translational/rotational bushing acting between two bodies.
333 /// It uses three values for stiffness along the X Y Z axes of a coordinate system attached
334 /// to the second body , and three rotational stiffness values for (small) rotations about X Y Z of the
335 /// same coordinate system.
336 /// This is equivalent to having a bushing with 6x6 diagonal local stiffness matrix.
337 class ChApi ChLoadBodyBodyBushingMate : public ChLoadBodyBodyBushingSpherical {
338   public:
339     ChLoadBodyBodyBushingMate(
340         std::shared_ptr<ChBody> mbodyA,    ///< body A
341         std::shared_ptr<ChBody> mbodyB,    ///< body B
342         const ChFrame<>& abs_application,  ///< create the bushing here, in abs. coordinates.
343         const ChVector<>& mstiffness,      ///< stiffness, along x y z axes of the abs_application
344         const ChVector<>& mdamping,        ///< damping, along x y z axes of the abs_application
345         const ChVector<>& mrotstiffness,   ///< rotational stiffness, about x y z axes of the abs_application
346         const ChVector<>& mrotdamping      ///< rotational damping, about x y z axes of the abs_application
347     );
348 
349     /// Set radial stiffness, along the x y z axes of loc_application_B, es [N/m]
SetRotationalStiffness(const ChVector<> mstiffness)350     void SetRotationalStiffness(const ChVector<> mstiffness) { rot_stiffness = mstiffness; }
GetRotationalStiffness()351     ChVector<> GetRotationalStiffness() const { return rot_stiffness; }
352 
353     /// Set radial damping, along the x y z axes of loc_application_B, es [Ns/m]
SetRotationalDamping(const ChVector<> mdamping)354     void SetRotationalDamping(const ChVector<> mdamping) { rot_damping = mdamping; }
GetRotationalDamping()355     ChVector<> GetRotationalDamping() const { return rot_damping; }
356 
357   protected:
358     ChVector<> rot_stiffness;
359     ChVector<> rot_damping;
360 
361     /// Implement the computation of the bushing force, in local
362     /// coordinates of the loc_application_B.
363     /// Force is assumed applied to loc_application_B of body B, and its opposite reaction to A.
364     virtual void ComputeBodyBodyForceTorque(const ChFrameMoving<>& rel_AB,
365                                             ChVector<>& loc_force,
366                                             ChVector<>& loc_torque) override;
367 };
368 
369 //------------------------------------------------------------------------------------------------
370 
371 /// Load for a visco-elastic translational/rotational bushing acting between two bodies.
372 /// It uses a full user-defined 6x6 matrix [K] to express the local stiffness of the
373 /// bushing, assumed expressed in the bushing coordinate system  attached
374 /// to the second body. A user-defined 6x6 matrix [D] can be defined for damping, as well.
375 /// Note that this assumes small rotations.
376 /// Differently from the simpler ChLoadBodyBodyBushingMate and ChLoadBodyBodyBushingSpherical
377 /// this can represent coupled effects, by using extra-diagonal terms in [K] and/or [D].
378 class ChApi ChLoadBodyBodyBushingGeneric : public ChLoadBodyBody {
379   public:
380     ChLoadBodyBodyBushingGeneric(
381         std::shared_ptr<ChBody> mbodyA,    ///< body A
382         std::shared_ptr<ChBody> mbodyB,    ///< body B
383         const ChFrame<>& abs_application,  ///< create the bushing here, in abs. coordinates.
384         ChMatrixConstRef mstiffness,       ///< stiffness as a 6x6 matrix, local in the abs_application frame
385         ChMatrixConstRef mdamping          ///< damping as a 6x6 matrix, local in the abs_application frame
386     );
387 
388     /// "Virtual" copy constructor (covariant return type).
Clone()389     virtual ChLoadBodyBodyBushingGeneric* Clone() const override { return new ChLoadBodyBodyBushingGeneric(*this); }
390 
391     /// Set a generic 6x6 stiffness matrix, expressed in local
392     /// coordinate system of loc_application_B.
SetStiffnessMatrix(ChMatrixConstRef mstiffness)393     void SetStiffnessMatrix(ChMatrixConstRef mstiffness) { stiffness = mstiffness; }
GetStiffnessMatrix()394     const ChMatrixNM<double, 6, 6>& GetStiffnessMatrix() const { return stiffness; }
395 
396     /// Set a generic 6x6 damping matrix, expressed in local
397     /// coordinate system of loc_application_B.
SetDampingMatrix(ChMatrixConstRef mdamping)398     void SetDampingMatrix(ChMatrixConstRef mdamping) { damping = mdamping; }
GetDampingMatrix()399     const ChMatrixNM<double, 6, 6>& GetDampingMatrix() const { return damping; }
400 
401     /// Set the initial pre-load of the bushing, applied to loc_application_A,
402     /// expressed in local coordinate system of loc_application_B.
403     /// By default it is zero.
SetNeutralForce(const ChVector<> mf)404     void SetNeutralForce(const ChVector<> mf) { neutral_force = mf; }
GetNeutralForce()405     ChVector<> GetNeutralForce() const { return neutral_force; }
406 
407     /// Set the initial pre-load torque of the bushing, applied to loc_application_A,
408     /// expressed in local coordinate system of loc_application_B.
409     /// By default it is zero.
SetNeutralTorque(const ChVector<> mt)410     void SetNeutralTorque(const ChVector<> mt) { neutral_torque = mt; }
GetNeutralTorque()411     ChVector<> GetNeutralTorque() const { return neutral_torque; }
412 
413     /// Set/get the initial pre-displacement of the bushing, as the pre-displacement
414     /// of A, expressed in local coordinate system of loc_application_B.
415     /// Default behavior is no initial pre-displacement.
NeutralDisplacement()416     ChFrame<>& NeutralDisplacement() { return neutral_displacement; }
417 
418   protected:
419     ChMatrixNM<double, 6, 6> stiffness;
420     ChMatrixNM<double, 6, 6> damping;
421 
422     ChVector<> neutral_force;
423     ChVector<> neutral_torque;
424     ChFrame<> neutral_displacement;
425 
IsStiff()426     virtual bool IsStiff() override { return true; }
427 
428     /// Implement the computation of the bushing force, in local
429     /// coordinates of the loc_application_B.
430     /// Force is assumed applied to loc_application_B of body B, and its opposite reaction to A.
431     virtual void ComputeBodyBodyForceTorque(const ChFrameMoving<>& rel_AB,
432                                             ChVector<>& loc_force,
433                                             ChVector<>& loc_torque) override;
434 
435   public:
436     EIGEN_MAKE_ALIGNED_OPERATOR_NEW
437 };
438 
439 }  // end namespace chrono
440 
441 #endif
442