1 /* -------------------------------------------------------------------------- *
2 * OpenSim: CMC_Joint.cpp *
3 * -------------------------------------------------------------------------- *
4 * The OpenSim API is a toolkit for musculoskeletal modeling and simulation. *
5 * See http://opensim.stanford.edu and the NOTICE file for more information. *
6 * OpenSim is developed at Stanford University and supported by the US *
7 * National Institutes of Health (U54 GM072970, R24 HD065690) and by DARPA *
8 * through the Warrior Web program. *
9 * *
10 * Copyright (c) 2005-2017 Stanford University and the Authors *
11 * *
12 * Licensed under the Apache License, Version 2.0 (the "License"); you may *
13 * not use this file except in compliance with the License. You may obtain a *
14 * copy of the License at http://www.apache.org/licenses/LICENSE-2.0. *
15 * *
16 * Unless required by applicable law or agreed to in writing, software *
17 * distributed under the License is distributed on an "AS IS" BASIS, *
18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
19 * See the License for the specific language governing permissions and *
20 * limitations under the License. *
21 * -------------------------------------------------------------------------- */
22 //
23 // This software, originally developed by Realistic Dynamics, Inc., was
24 // transferred to Stanford University on November 1, 2006.
25 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
26
27
28 //=============================================================================
29 // INCLUDES
30 //=============================================================================
31 #include <OpenSim/Simulation/Model/Model.h>
32 #include "CMC_Joint.h"
33
34 using namespace std;
35 using namespace OpenSim;
36
37 //=============================================================================
38 // STATICS
39 //=============================================================================
40
41
42 //=============================================================================
43 // CONSTRUCTOR(S) AND DESTRUCTOR
44 //=============================================================================
45 //_____________________________________________________________________________
46 /**
47 * Destructor.
48 */
~CMC_Joint()49 CMC_Joint::~CMC_Joint()
50 {
51 }
52
53 //_____________________________________________________________________________
54 /**
55 * Construct a task for a specified generalized coordinate.
56 *
57 * @param aQID ID of the generalized coordinate to be tracked.
58 * @todo Instead of an integer id, the name of the coordinate
59 * should be used.
60 */
CMC_Joint(const string & aCoordinateName)61 CMC_Joint::CMC_Joint(const string &aCoordinateName) :
62 _coordinateName(_propCoordinateName.getValueStr()),
63 _limit(_propLimit.getValueDbl())
64 {
65 setNull();
66 setCoordinateName(aCoordinateName);
67 }
68
69 //_____________________________________________________________________________
70 /**
71 * Copy constructor.
72 *
73 * @param aTask Joint task to be copied.
74 */
CMC_Joint(const CMC_Joint & aTask)75 CMC_Joint::CMC_Joint(const CMC_Joint &aTask) :
76 CMC_Task(aTask),
77 _coordinateName(_propCoordinateName.getValueStr()),
78 _limit(_propLimit.getValueDbl())
79 {
80 setNull();
81 *this = aTask;
82 }
83
84
85 //=============================================================================
86 // CONSTRUCTION
87 //=============================================================================
88 //_____________________________________________________________________________
89 /**
90 * Set NULL values for all member variables.
91 */
92 void CMC_Joint::
setNull()93 setNull()
94 {
95 setupProperties();
96
97 _nTrk = 1;
98 _q = 0;
99 }
100 //_____________________________________________________________________________
101 /**
102 * Set up serialized member variables.
103 */
104 void CMC_Joint::
setupProperties()105 setupProperties()
106 {
107 _propCoordinateName.setComment("Name of the coordinate to be tracked.");
108 _propCoordinateName.setName("coordinate");
109 _propCoordinateName.setValue("");
110 _propertySet.append(&_propCoordinateName);
111
112 _propLimit.setComment("Error limit on the tracking accuracy for this "
113 "coordinate. If the tracking errors approach this limit, the weighting "
114 "for this coordinate is increased. ");
115 _propLimit.setName("limit");
116 _propLimit.setValue(0);
117 _propertySet.append(&_propLimit);
118 }
119
120
121 //_____________________________________________________________________________
122 /**
123 * Copy only the member data of specified object.
124 */
125 void CMC_Joint::
copyData(const CMC_Joint & aTask)126 copyData(const CMC_Joint &aTask)
127 {
128 setCoordinateName(aTask.getCoordinateName());
129 _limit = aTask._limit;
130 }
131
132
133 //_____________________________________________________________________________
134 /**
135 * Update work variables
136 */
137 void CMC_Joint::
updateWorkVariables()138 updateWorkVariables()
139 {
140 _q = 0;
141 if(_model) {
142 try {
143 _q = &_model->updCoordinateSet().get(_coordinateName);
144 }
145 catch (const Exception&) {
146 throw Exception("CMC_Joint.updateWorkVariables: ERROR- joint task '" + getName()
147 + "' references invalid coordinate '" + _coordinateName + "'",__FILE__,__LINE__);
148 }
149 }
150 }
151
152
153
154 //=============================================================================
155 // OPERATORS
156 //=============================================================================
157 //-----------------------------------------------------------------------------
158 // ASSIGNMENT
159 //-----------------------------------------------------------------------------
160 //_____________________________________________________________________________
161 /**
162 * Assignment operator.
163 *
164 * @param aTask Object to be copied.
165 * @return Reference to the altered object.
166 */
167 CMC_Joint& CMC_Joint::
operator =(const CMC_Joint & aTask)168 operator=(const CMC_Joint &aTask)
169 {
170 // BASE CLASS
171 CMC_Task::operator =(aTask);
172
173 // DATA
174 copyData(aTask);
175
176 return(*this);
177 }
178
179
180 //=============================================================================
181 // GET AND SET
182 //=============================================================================
183 //-----------------------------------------------------------------------------
184 // MODEL
185 //-----------------------------------------------------------------------------
186 //_____________________________________________________________________________
187 /**
188 * Initializes pointers to the Coordinate and Speed in the model given the
189 * coordinate name assigned to this task.
190 *
191 * @param aModel Model.
192 */
193 void CMC_Joint::
setModel(Model & aModel)194 setModel(Model& aModel)
195 {
196 CMC_Task::setModel(aModel);
197 updateWorkVariables();
198 }
199 //-----------------------------------------------------------------------------
200 // Coordinate Name
201 //-----------------------------------------------------------------------------
202 //_____________________________________________________________________________
203 /**
204 * Set the generalized coordinate that is to be tracked.
205 *
206 * @param aName Name of the tracked generalized coordinate.
207 */
208 void CMC_Joint::
setCoordinateName(const string & aName)209 setCoordinateName(const string &aName)
210 {
211 _coordinateName = aName;
212 updateWorkVariables();
213 }
214 //_____________________________________________________________________________
215 /**
216 * Get the generalized coordinate that is to be tracked.
217 *
218 * @return Name of the tracked generalized coordinate.
219 */
220 string CMC_Joint::
getCoordinateName() const221 getCoordinateName() const
222 {
223 return(_coordinateName);
224 }
225 //_____________________________________________________________________________
226 /**
227 * Get the limit.
228 *
229 * @return limit valid of the tracked generalized coordinate.
230 */
231 double CMC_Joint::
getLimit() const232 getLimit() const
233 {
234 return _limit;
235 }
236
237
238 //=============================================================================
239 // COMPUTATIONS
240 //=============================================================================
241 //_____________________________________________________________________________
242 /**
243 * Compute the position and velocity errors.
244 * This method assumes the states have been set for the model.
245 *
246 * @param aT Current time in real time units.
247 * @see Model::set()
248 * @see Model::setStates()
249 */
250 void CMC_Joint::
computeErrors(const SimTK::State & s,double aT)251 computeErrors(const SimTK::State& s, double aT)
252 {
253 // COMPUTE ERRORS
254 //std::cout<<_coordinateName<<std::endl;
255 //std::cout<<"_pTrk[0]->calcValue(aT) = "<< _pTrk[0]->calcValue(SimTK::Vector(1, aT)) <<std::endl;
256 //std::cout<<"_q->getValue(s) = "<<_q->getValue(s)<<std::endl;
257 _pErr[0] = _pTrk[0]->calcValue(SimTK::Vector(1,aT)) - _q->getValue(s);
258 if(_vTrk[0]==NULL) {
259 std::vector<int> derivComponents(1);
260 derivComponents[0]=0;
261 _vErr[0] = _pTrk[0]->calcDerivative(derivComponents,SimTK::Vector(1,aT)) - _q->getSpeedValue(s);
262 } else {
263 _vErr[0] = _vTrk[0]->calcValue(SimTK::Vector(1,aT)) - _q->getSpeedValue(s);
264 }
265 }
266 //_____________________________________________________________________________
267 /**
268 * Compute the desired accelerations.
269 * This method assumes that the states have been set for the model.
270 *
271 * @param aT Time at which the desired accelerations are to be computed in
272 * real time units.
273 * @see Model::set()
274 * @see Model::setStates()
275 */
276 void CMC_Joint::
computeDesiredAccelerations(const SimTK::State & s,double aT)277 computeDesiredAccelerations(const SimTK::State& s, double aT)
278 {
279 _aDes=SimTK::NaN;
280
281 // CHECK
282 if(_model==NULL) return;
283 if(_pTrk[0]==NULL) return;
284
285 // COMPUTE ERRORS
286 computeErrors(s, aT);
287
288 // DESIRED ACCELERATION
289 double p = (_kp)[0]*_pErr[0];
290 double v = (_kv)[0]*_vErr[0];
291 double a;
292 if(_aTrk[0]==NULL) {
293 std::vector<int> derivComponents(2);
294 derivComponents[0]=0;
295 derivComponents[1]=0;
296 a = (_ka)[0]*_pTrk[0]->calcDerivative(derivComponents,SimTK::Vector(1,aT));
297 } else {
298 a = (_ka)[0]*_aTrk[0]->calcValue(SimTK::Vector(1,aT));
299 }
300 _aDes[0] = a + v + p;
301
302 // PRINT
303 //printf("CMC_Joint.computeDesiredAcceleration:\n");
304 //printf("%s: t=%lf aDes=%lf a=%lf vErr=%lf pErr=%lf\n",getName(),t,_aDes[0],
305 // _pTrk[0]->evaluate(2,t),_vErr[0],_pErr[0]);
306 }
307 //_____________________________________________________________________________
308 /**
309 * Compute the desired accelerations.
310 * This method assumes that the states have been set for the model.
311 *
312 * @param aTI Initial time of the controlled interval in real time units.
313 * @param aTF Final time of the controlled interval in real time units.
314 * @see Model::set()
315 * @see Model::setStates()
316 */
317 void CMC_Joint::
computeDesiredAccelerations(const SimTK::State & s,double aTI,double aTF)318 computeDesiredAccelerations(const SimTK::State& s, double aTI,double aTF)
319 {
320 double a;
321 _aDes=SimTK::NaN;
322
323 // CHECK
324 if(_model==NULL) return;
325 if(_pTrk[0]==NULL) return;
326
327 // COMPUTE ERRORS
328 computeErrors(s, aTI);
329
330 // DESIRED ACCELERATION
331 double p = (_kp)[0]*_pErr[0];
332 double v = (_kv)[0]*_vErr[0];
333
334 if(_aTrk[0]==NULL) {
335 std::vector<int> derivComponents(2);
336 derivComponents[0]=0;
337 derivComponents[1]=0;
338 a = (_ka)[0]*_pTrk[0]->calcDerivative(derivComponents,SimTK::Vector(1,aTF));
339 } else {
340 a = (_ka)[0]*_aTrk[0]->calcValue(SimTK::Vector(1,aTF));
341 }
342 _aDes[0] = a + v + p;
343
344 // PRINT
345 //printf("CMC_Joint.computeDesiredAcceleration:\n");
346 //printf("%s: t=%lf aDes=%lf a=%lf vErr=%lf pErr=%lf\n",getName(),t,_aDes[0],
347 // _pTrk[0]->evaluate(2,t),_vErr[0],_pErr[0]);
348 }
349 //_____________________________________________________________________________
350 /**
351 * Compute the acceleration of the appropriate generalized coordinate.
352 * For the computed accelerations to be correct,
353 * Model::computeAccelerations() must have already been called.
354 *
355 * For joints (i.e., generalized coordinates), the acceleration is
356 * not computed. It has already been computed and is simply retrieved
357 * from the model.
358 *
359 * @see Model::computeAccelerations()
360 * @see suTrackObject::getAcceleration()
361 */
362 void CMC_Joint::
computeAccelerations(const SimTK::State & s)363 computeAccelerations(const SimTK::State& s )
364 {
365 _a=SimTK::NaN;
366
367 // CHECK
368 if(_model==NULL) return;
369
370 // ACCELERATION
371 _a[0] = _q->getAccelerationValue(s);
372 }
373
374
375 //=============================================================================
376 // XML
377 //=============================================================================
378 //-----------------------------------------------------------------------------
379 // UPDATE FROM XML NODE
380 //-----------------------------------------------------------------------------
381 //_____________________________________________________________________________
382 /**
383 * Update this object based on its XML node.
384 *
385 * @param aDeep If true, update this object and all its child objects
386 * (that is, member variables that are Object's); if false, update only
387 * the member variables that are not Object's.
388 */
389 void CMC_Joint::
updateFromXMLNode(SimTK::Xml::Element & aNode,int versionNumber)390 updateFromXMLNode(SimTK::Xml::Element& aNode, int versionNumber)
391 {
392 CMC_Task::updateFromXMLNode(aNode, versionNumber);
393 setCoordinateName(_coordinateName);
394 }
395