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
13 // =============================================================================
14 
15 #include "chrono/physics/ChLinkMotorLinearSpeed.h"
16 
17 namespace chrono {
18 
19 // Register into the object factory, to enable run-time dynamic creation and persistence
CH_FACTORY_REGISTER(ChLinkMotorLinearSpeed)20 CH_FACTORY_REGISTER(ChLinkMotorLinearSpeed)
21 
22 ChLinkMotorLinearSpeed::ChLinkMotorLinearSpeed() {
23     variable.GetMass()(0, 0) = 1.0;
24     variable.GetInvMass()(0, 0) = 1.0;
25 
26     m_func = chrono_types::make_shared<ChFunction_Const>(1.0);
27 
28     pos_offset = 0;
29 
30     aux_dt = 0;  // used for integrating speed, = pos
31     aux_dtdt = 0;
32 
33     avoid_position_drift = true;
34 }
35 
ChLinkMotorLinearSpeed(const ChLinkMotorLinearSpeed & other)36 ChLinkMotorLinearSpeed::ChLinkMotorLinearSpeed(const ChLinkMotorLinearSpeed& other) : ChLinkMotorLinear(other) {
37     variable = other.variable;
38     pos_offset = other.pos_offset;
39     aux_dt = other.aux_dt;
40     aux_dtdt = other.aux_dtdt;
41     avoid_position_drift = other.avoid_position_drift;
42 }
43 
~ChLinkMotorLinearSpeed()44 ChLinkMotorLinearSpeed::~ChLinkMotorLinearSpeed() {}
45 
Update(double mytime,bool update_assets)46 void ChLinkMotorLinearSpeed::Update(double mytime, bool update_assets) {
47     // Inherit parent class:
48     ChLinkMotorLinear::Update(mytime, update_assets);
49 
50     // Add the time-dependent term in residual C as
51     //   C = d_error - d_setpoint - d_offset
52     // with d_error = x_pos_A- x_pos_B, and d_setpoint = x(t)
53     if (this->avoid_position_drift)
54         C(0) = this->mpos - aux_dt - this->pos_offset;
55     else
56         C(0) = 0.0;
57 }
58 
IntLoadConstraint_Ct(const unsigned int off_L,ChVectorDynamic<> & Qc,const double c)59 void ChLinkMotorLinearSpeed::IntLoadConstraint_Ct(const unsigned int off_L, ChVectorDynamic<>& Qc, const double c) {
60     double mCt = -m_func->Get_y(this->GetChTime());
61     if (mask.Constr_N(0).IsActive()) {
62         Qc(off_L + 0) += c * mCt;
63     }
64 }
65 
ConstraintsBiLoad_Ct(double factor)66 void ChLinkMotorLinearSpeed::ConstraintsBiLoad_Ct(double factor) {
67     if (!this->IsActive())
68         return;
69 
70     double mCt = -m_func->Get_y(this->GetChTime());
71     if (mask.Constr_N(0).IsActive()) {
72         mask.Constr_N(0).Set_b_i(mask.Constr_N(0).Get_b_i() + factor * mCt);
73     }
74 }
75 
76 //// STATE BOOKKEEPING FUNCTIONS
77 
IntStateGather(const unsigned int off_x,ChState & x,const unsigned int off_v,ChStateDelta & v,double & T)78 void ChLinkMotorLinearSpeed::IntStateGather(const unsigned int off_x,  // offset in x state vector
79                                             ChState& x,                // state vector, position part
80                                             const unsigned int off_v,  // offset in v state vector
81                                             ChStateDelta& v,           // state vector, speed part
82                                             double& T                  // time
83 ) {
84     x(off_x) = 0;  // aux;
85     v(off_v) = aux_dt;
86     T = GetChTime();
87 }
88 
IntStateScatter(const unsigned int off_x,const ChState & x,const unsigned int off_v,const ChStateDelta & v,const double T,bool full_update)89 void ChLinkMotorLinearSpeed::IntStateScatter(const unsigned int off_x,  // offset in x state vector
90                                              const ChState& x,          // state vector, position part
91                                              const unsigned int off_v,  // offset in v state vector
92                                              const ChStateDelta& v,     // state vector, speed part
93                                              const double T,            // time
94                                              bool full_update           // perform complete update
95 ) {
96     // aux = x(off_x);
97     aux_dt = v(off_v);
98 
99     Update(T, full_update);
100 }
101 
IntStateGatherAcceleration(const unsigned int off_a,ChStateDelta & a)102 void ChLinkMotorLinearSpeed::IntStateGatherAcceleration(const unsigned int off_a, ChStateDelta& a) {
103     a(off_a) = aux_dtdt;
104 }
105 
IntStateScatterAcceleration(const unsigned int off_a,const ChStateDelta & a)106 void ChLinkMotorLinearSpeed::IntStateScatterAcceleration(const unsigned int off_a, const ChStateDelta& a) {
107     aux_dtdt = a(off_a);
108 }
109 
IntLoadResidual_F(const unsigned int off,ChVectorDynamic<> & R,const double c)110 void ChLinkMotorLinearSpeed::IntLoadResidual_F(const unsigned int off,  // offset in R residual
111                                                ChVectorDynamic<>& R,    // result: the R residual, R += c*F
112                                                const double c           // a scaling factor
113 ) {
114     double imposed_speed = m_func->Get_y(this->GetChTime());
115     R(off) += imposed_speed * c;
116 }
117 
IntLoadResidual_Mv(const unsigned int off,ChVectorDynamic<> & R,const ChVectorDynamic<> & w,const double c)118 void ChLinkMotorLinearSpeed::IntLoadResidual_Mv(const unsigned int off,      // offset in R residual
119                                                 ChVectorDynamic<>& R,        // result: the R residual, R += c*M*v
120                                                 const ChVectorDynamic<>& w,  // the w vector
121                                                 const double c               // a scaling factor
122 ) {
123     R(off) += c * 1.0 * w(off);
124 }
125 
IntToDescriptor(const unsigned int off_v,const ChStateDelta & v,const ChVectorDynamic<> & R,const unsigned int off_L,const ChVectorDynamic<> & L,const ChVectorDynamic<> & Qc)126 void ChLinkMotorLinearSpeed::IntToDescriptor(const unsigned int off_v,  // offset in v, R
127                                              const ChStateDelta& v,
128                                              const ChVectorDynamic<>& R,
129                                              const unsigned int off_L,  // offset in L, Qc
130                                              const ChVectorDynamic<>& L,
131                                              const ChVectorDynamic<>& Qc) {
132     // inherit parent
133     ChLinkMotorLinear::IntToDescriptor(off_v, v, R, off_L, L, Qc);
134 
135     this->variable.Get_qb()(0, 0) = v(off_v);
136     this->variable.Get_fb()(0, 0) = R(off_v);
137 }
138 
IntFromDescriptor(const unsigned int off_v,ChStateDelta & v,const unsigned int off_L,ChVectorDynamic<> & L)139 void ChLinkMotorLinearSpeed::IntFromDescriptor(const unsigned int off_v,  // offset in v
140                                                ChStateDelta& v,
141                                                const unsigned int off_L,  // offset in L
142                                                ChVectorDynamic<>& L) {
143     // inherit parent
144     ChLinkMotorLinear::IntFromDescriptor(off_v, v, off_L, L);
145 
146     v(off_v) = this->variable.Get_qb()(0, 0);
147 }
148 
149 ////
InjectVariables(ChSystemDescriptor & mdescriptor)150 void ChLinkMotorLinearSpeed::InjectVariables(ChSystemDescriptor& mdescriptor) {
151     variable.SetDisabled(!IsActive());
152 
153     mdescriptor.InsertVariables(&variable);
154 }
155 
VariablesFbReset()156 void ChLinkMotorLinearSpeed::VariablesFbReset() {
157     variable.Get_fb().setZero();
158 }
159 
VariablesFbLoadForces(double factor)160 void ChLinkMotorLinearSpeed::VariablesFbLoadForces(double factor) {
161     double imposed_speed = m_func->Get_y(this->GetChTime());
162     variable.Get_fb()(0) += imposed_speed * factor;
163 }
164 
VariablesFbIncrementMq()165 void ChLinkMotorLinearSpeed::VariablesFbIncrementMq() {
166     variable.Compute_inc_Mb_v(variable.Get_fb(), variable.Get_qb());
167 }
168 
VariablesQbLoadSpeed()169 void ChLinkMotorLinearSpeed::VariablesQbLoadSpeed() {
170     // set current speed in 'qb', it can be used by the solver when working in incremental mode
171     variable.Get_qb()(0) = aux_dt;
172 }
173 
VariablesQbSetSpeed(double step)174 void ChLinkMotorLinearSpeed::VariablesQbSetSpeed(double step) {
175     // from 'qb' vector, sets body speed, and updates auxiliary data
176     aux_dt = variable.Get_qb()(0);
177 
178     // Compute accel. by BDF (approximate by differentiation); not needed
179 }
180 
ArchiveOUT(ChArchiveOut & marchive)181 void ChLinkMotorLinearSpeed::ArchiveOUT(ChArchiveOut& marchive) {
182     // version number
183     marchive.VersionWrite<ChLinkMotorLinearSpeed>();
184 
185     // serialize parent class
186     ChLinkMotorLinear::ArchiveOUT(marchive);
187 
188     // serialize all member data:
189     marchive << CHNVP(pos_offset);
190     marchive << CHNVP(avoid_position_drift);
191 }
192 
193 /// Method to allow de serialization of transient data from archives.
ArchiveIN(ChArchiveIn & marchive)194 void ChLinkMotorLinearSpeed::ArchiveIN(ChArchiveIn& marchive) {
195     // version number
196     /*int version =*/ marchive.VersionRead<ChLinkMotorLinearSpeed>();
197 
198     // deserialize parent class
199     ChLinkMotorLinear::ArchiveIN(marchive);
200 
201     // deserialize all member data:
202     marchive >> CHNVP(pos_offset);
203     marchive >> CHNVP(avoid_position_drift);
204 }
205 
206 }  // end namespace chrono
207