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 #ifndef CHSHAFT_H
16 #define CHSHAFT_H
17 
18 #include "chrono/physics/ChPhysicsItem.h"
19 #include "chrono/physics/ChLoadable.h"
20 #include "chrono/solver/ChVariablesShaft.h"
21 
22 
23 namespace chrono {
24 
25 // Forward references (for parent hierarchy pointer)
26 class ChSystem;
27 
28 ///  Class for one-degree-of-freedom mechanical parts with associated
29 ///  inertia (mass, or J moment of inertial for rotating parts).
30 ///  In most cases these represent shafts that can be used to build 1D models
31 ///  of power trains. This is more efficient than simulating power trains
32 ///  modeled with full 3D ChBody objects.
33 
34 class ChApi ChShaft : public ChPhysicsItem, public ChLoadable {
35 
36   private:
37     double torque;  ///< The torque acting on shaft (force, if used as linear DOF)
38 
39     double pos;       //< shaft angle
40     double pos_dt;    //< shaft angular velocity
41     double pos_dtdt;  //< shaft angular acceleration
42 
43     double inertia;  ///< shaft J moment of inertia (or mass, if used as linear DOF)
44 
45     ChVariablesShaft variables;  ///< used as an interface to the solver
46 
47     float max_speed;  ///< limit on linear speed
48 
49     float sleep_time;
50     float sleep_minspeed;
51     float sleep_minwvel;
52     float sleep_starttime;
53 
54     bool fixed;
55     bool limitspeed;
56     bool sleeping;
57     bool use_sleeping;
58 
59     unsigned int id;  ///< shaft id used for internal indexing
60 
61   public:
62     ChShaft();
63     ChShaft(const ChShaft& other);
~ChShaft()64     ~ChShaft() {}
65 
66     /// "Virtual" copy constructor (covariant return type).
Clone()67     virtual ChShaft* Clone() const override { return new ChShaft(*this); }
68 
69     //
70     // FLAGS
71     //
72 
73     /// Sets the 'fixed' state of the shaft. If true, it does not rotate
74     /// despite constraints, forces, etc.
SetShaftFixed(bool mev)75     void SetShaftFixed(bool mev) {
76         fixed = mev;
77         variables.SetDisabled(mev);
78     }
GetShaftFixed()79     bool GetShaftFixed() const { return fixed; }
80     /// Trick. Set the maximum shaft velocity (beyond this limit it will
81     /// be clamped). This is useful in virtual reality and real-time
82     /// simulations.
83     /// The realism is limited, but the simulation is more stable.
SetLimitSpeed(bool mlimit)84     void SetLimitSpeed(bool mlimit) { limitspeed = mlimit; }
GetLimitSpeed()85     bool GetLimitSpeed() const { return limitspeed; }
86 
87     /// Trick. If use sleeping= true, shafts which do not rotate
88     /// for too long time will be deactivated, for optimization.
89     /// The realism is limited, but the simulation is faster.
SetUseSleeping(bool ms)90     void SetUseSleeping(bool ms) { use_sleeping = ms; }
GetUseSleeping()91     bool GetUseSleeping() const { return use_sleeping; }
92 
93     /// Force the shaft in sleeping mode or not (usually this state change is not
94     /// handled by users, anyway, because it is mostly automatic).
SetSleeping(bool ms)95     void SetSleeping(bool ms) { sleeping = ms; }
96     /// Tell if the shaft is actually in sleeping state.
GetSleeping()97     bool GetSleeping() const { return sleeping; }
98 
99     /// Put the shaft in sleeping state if requirements are satisfied.
100     bool TrySleeping();
101 
102     /// Tell if the body is active, i.e. it is neither fixed to ground nor
103     /// it is in sleep mode.
IsActive()104     bool IsActive() const { return !(sleeping || fixed); }
105 
106     //
107     // FUNCTIONS
108     //
109 
110     /// Set the shaft id for indexing (only used internally)
SetId(unsigned int identifier)111     void SetId(unsigned int identifier) { id = identifier; }
112 
113     /// Get the shaft id for indexing (only used internally)
GetId()114     unsigned int GetId() const { return id; }
115 
116     /// Number of coordinates of the shaft
GetDOF()117     virtual int GetDOF() override { return 1; }
118 
119     /// Returns reference to the encapsulated ChVariables,
Variables()120     ChVariablesShaft& Variables() { return variables; }
121 
122     //
123     // STATE FUNCTIONS
124     //
125 
126     // (override/implement interfaces for global state vectors, see ChPhysicsItem for comments.)
127     virtual void IntStateGather(const unsigned int off_x,
128                                 ChState& x,
129                                 const unsigned int off_v,
130                                 ChStateDelta& v,
131                                 double& T) override;
132     virtual void IntStateScatter(const unsigned int off_x,
133                                  const ChState& x,
134                                  const unsigned int off_v,
135                                  const ChStateDelta& v,
136                                  const double T,
137                                  bool full_update) override;
138     virtual void IntStateGatherAcceleration(const unsigned int off_a, ChStateDelta& a) override;
139     virtual void IntStateScatterAcceleration(const unsigned int off_a, const ChStateDelta& a) override;
140     virtual void IntLoadResidual_F(const unsigned int off, ChVectorDynamic<>& R, const double c) override;
141     virtual void IntLoadResidual_Mv(const unsigned int off,
142                                     ChVectorDynamic<>& R,
143                                     const ChVectorDynamic<>& w,
144                                     const double c) override;
145     virtual void IntToDescriptor(const unsigned int off_v,
146                                  const ChStateDelta& v,
147                                  const ChVectorDynamic<>& R,
148                                  const unsigned int off_L,
149                                  const ChVectorDynamic<>& L,
150                                  const ChVectorDynamic<>& Qc) override;
151     virtual void IntFromDescriptor(const unsigned int off_v,
152                                    ChStateDelta& v,
153                                    const unsigned int off_L,
154                                    ChVectorDynamic<>& L) override;
155 
156     //
157     // SOLVER FUNCTIONS
158     //
159 
160     // Override/implement system functions of ChPhysicsItem
161     // (to assemble/manage data for system solver)
162 
163     /// Sets the 'fb' part of the encapsulated ChVariables to zero.
164     virtual void VariablesFbReset() override;
165 
166     /// Adds the current torques in the 'fb' part: qf+=torques*factor
167     virtual void VariablesFbLoadForces(double factor = 1) override;
168 
169     /// Initialize the 'qb' part of the ChVariables with the
170     /// current value of shaft speed. Note: since 'qb' is the unknown , this
171     /// function seems unnecessary, unless used before VariablesFbIncrementMq()
172     virtual void VariablesQbLoadSpeed() override;
173 
174     /// Adds M*q (masses multiplied current 'qb') to Fb, ex. if qb is initialized
175     /// with v_old using VariablesQbLoadSpeed, this method can be used in
176     /// timestepping schemes that do: M*v_new = M*v_old + forces*dt
177     virtual void VariablesFbIncrementMq() override;
178 
179     /// Fetches the shaft speed from the 'qb' part of the ChVariables (does not
180     /// updates the full shaft state) and sets it as the current shaft speed.
181     /// If 'step' is not 0, also computes the approximate acceleration of
182     /// the shaft using backward differences, that is  accel=(new_speed-old_speed)/step.
183     virtual void VariablesQbSetSpeed(double step = 0) override;
184 
185     /// Increment shaft position by the 'qb' part of the ChVariables,
186     /// multiplied by a 'step' factor.
187     ///     pos+=qb*step
188     virtual void VariablesQbIncrementPosition(double step) override;
189 
190     /// Tell to a system descriptor that there are variables of type
191     /// ChVariables in this object (for further passing it to a solver)
192     virtual void InjectVariables(ChSystemDescriptor& mdescriptor) override;
193 
194 	//
195 	// INTERFACE to ChLoadable
196 	//
LoadableGet_ndof_x()197 	virtual int LoadableGet_ndof_x() override { return 1; }
LoadableGet_ndof_w()198     virtual int LoadableGet_ndof_w() override { return 1; }
LoadableGetStateBlock_x(int block_offset,ChState & mD)199     virtual void LoadableGetStateBlock_x(int block_offset, ChState& mD) override { mD(block_offset) = this->GetPos(); }
LoadableGetStateBlock_w(int block_offset,ChStateDelta & mD)200     virtual void LoadableGetStateBlock_w(int block_offset, ChStateDelta& mD) override { mD(block_offset) = this->GetPos_dt(); }
LoadableStateIncrement(const unsigned int off_x,ChState & x_new,const ChState & x,const unsigned int off_v,const ChStateDelta & Dv)201     virtual void LoadableStateIncrement(const unsigned int off_x,
202                                         ChState& x_new,
203                                         const ChState& x,
204                                         const unsigned int off_v,
205                                         const ChStateDelta& Dv) override { x_new(off_x) = x(off_x) + Dv(off_v); }
Get_field_ncoords()206     virtual int Get_field_ncoords() override { return 1; }
GetSubBlocks()207     virtual int GetSubBlocks() override { return 1; }
GetSubBlockOffset(int nblock)208     virtual unsigned int GetSubBlockOffset(int nblock) override { return this->GetOffset_w(); }
GetSubBlockSize(int nblock)209     virtual unsigned int GetSubBlockSize(int nblock) override { return 1; }
IsSubBlockActive(int nblock)210     virtual bool IsSubBlockActive(int nblock) const override { return true; }
LoadableGetVariables(std::vector<ChVariables * > & mvars)211     virtual void LoadableGetVariables(std::vector<ChVariables*>& mvars) override { mvars.push_back(&this->Variables()); };
212 
213 
214     // Other functions
215 
216     /// Set no speed and no accelerations (but does not change the position)
217     void SetNoSpeedNoAcceleration() override;
218 
219     /// Set the torque applied to the shaft
SetAppliedTorque(double mtorque)220     void SetAppliedTorque(double mtorque) { torque = mtorque; }
221     /// Get the torque applied to the shaft
GetAppliedTorque()222     double GetAppliedTorque() const { return torque; }
223 
224     /// Set the angular position
SetPos(double mp)225     void SetPos(double mp) { pos = mp; }
226     /// Get the angular position
GetPos()227     double GetPos() const { return pos; }
228 
229     /// Set the angular velocity
SetPos_dt(double mp)230     void SetPos_dt(double mp) { pos_dt = mp; }
231     /// Get the angular velocity
GetPos_dt()232     double GetPos_dt() const { return pos_dt; }
233 
234     /// Set the angular acceleration
SetPos_dtdt(double mp)235     void SetPos_dtdt(double mp) { pos_dtdt = mp; }
236     /// Get the angular acceleration
GetPos_dtdt()237     double GetPos_dtdt() const { return pos_dtdt; }
238 
239     /// Inertia of the shaft. Must be positive.
240     /// Try not to mix bodies with too high/too low values of mass, for numerical stability.
241     void SetInertia(double newJ);
GetInertia()242     double GetInertia() const { return inertia; }
243 
244     /// Trick. Set the maximum velocity (beyond this limit it will
245     /// be clamped). This is useful in virtual reality and real-time
246     /// simulations, to increase robustness at the cost of realism.
247     /// This limit is active only if you set  SetLimitSpeed(true);
SetMaxSpeed(float m_max_speed)248     void SetMaxSpeed(float m_max_speed) { max_speed = m_max_speed; }
GetMaxSpeed()249     float GetMaxSpeed() const { return max_speed; }
250 
251     /// When this function is called, the speed of the shaft is clamped
252     /// into limits posed by max_speed and max_wvel  - but remember to
253     /// put the shaft in the SetLimitSpeed(true) mode.
254     void ClampSpeed();
255 
256     /// Set the amount of time which must pass before going automatically in
257     /// sleep mode when the shaft has very small movements.
SetSleepTime(float m_t)258     void SetSleepTime(float m_t) { sleep_time = m_t; }
GetSleepTime()259     float GetSleepTime() const { return sleep_time; }
260 
261     /// Set the max linear speed to be kept for 'sleep_time' before freezing.
SetSleepMinSpeed(float m_t)262     void SetSleepMinSpeed(float m_t) { sleep_minspeed = m_t; }
GetSleepMinSpeed()263     float GetSleepMinSpeed() const { return sleep_minspeed; }
264 
265     /// Set the max linear speed to be kept for 'sleep_time' before freezing.
SetSleepMinWvel(float m_t)266     void SetSleepMinWvel(float m_t) { sleep_minwvel = m_t; }
GetSleepMinWvel()267     float GetSleepMinWvel() const { return sleep_minwvel; }
268 
269     //
270     // UPDATE FUNCTIONS
271     //
272 
273     /// Update all auxiliary data of the shaft at given time
274     virtual void Update(double mytime, bool update_assets = true) override;
275 
276     //
277     // SERIALIZATION
278     //
279 
280     /// Method to allow serialization of transient data to archives.
281     virtual void ArchiveOUT(ChArchiveOut& marchive) override;
282 
283     /// Method to allow deserialization of transient data from archives.
284     virtual void ArchiveIN(ChArchiveIn& marchive) override;
285 };
286 
287 CH_CLASS_VERSION(ChShaft,0)
288 
289 
290 }  // end namespace chrono
291 
292 #endif
293