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