@@ -58,20 +58,9 @@ InverseKinematicsTool::~InverseKinematicsTool()
58
58
/* *
59
59
* Default constructor.
60
60
*/
61
- InverseKinematicsTool::InverseKinematicsTool () : Tool(),
62
- _modelFileName(_modelFileNameProp.getValueStr()),
63
- _constraintWeight(_constraintWeightProp.getValueDbl()),
64
- _accuracy(_accuracyProp.getValueDbl()),
65
- _ikTaskSetProp(PropertyObj(" " , IKTaskSet())),
66
- _ikTaskSet((IKTaskSet&)_ikTaskSetProp.getValueObj()),
67
- _markerFileName(_markerFileNameProp.getValueStr()),
68
- _coordinateFileName(_coordinateFileNameProp.getValueStr()),
69
- _timeRange(_timeRangeProp.getValueDblArray()),
70
- _reportErrors(_reportErrorsProp.getValueBool()),
71
- _outputMotionFileName(_outputMotionFileNameProp.getValueStr()),
72
- _reportMarkerLocations(_reportMarkerLocationsProp.getValueBool())
61
+ InverseKinematicsTool::InverseKinematicsTool () : Tool()
73
62
{
74
- setNull ();
63
+ constructProperties ();
75
64
}
76
65
// _____________________________________________________________________________
77
66
/* *
@@ -83,176 +72,32 @@ InverseKinematicsTool::InverseKinematicsTool() : Tool(),
83
72
* @param aFileName File name of the document.
84
73
*/
85
74
InverseKinematicsTool::InverseKinematicsTool (const string &aFileName, bool aLoadModel) :
86
- Tool(aFileName, true ),
87
- _modelFileName(_modelFileNameProp.getValueStr()),
88
- _constraintWeight(_constraintWeightProp.getValueDbl()),
89
- _accuracy(_accuracyProp.getValueDbl()),
90
- _ikTaskSetProp(PropertyObj(" " , IKTaskSet())),
91
- _ikTaskSet((IKTaskSet&)_ikTaskSetProp.getValueObj()),
92
- _markerFileName(_markerFileNameProp.getValueStr()),
93
- _coordinateFileName(_coordinateFileNameProp.getValueStr()),
94
- _timeRange(_timeRangeProp.getValueDblArray()),
95
- _reportErrors(_reportErrorsProp.getValueBool()),
96
- _outputMotionFileName(_outputMotionFileNameProp.getValueStr()),
97
- _reportMarkerLocations(_reportMarkerLocationsProp.getValueBool())
75
+ Tool(aFileName, true )
98
76
{
99
- setNull ();
77
+ constructProperties ();
100
78
updateFromXMLDocument ();
101
-
102
- if (aLoadModel) {
103
- // loadModel(aFileName);
104
- }
105
- }
106
- // _____________________________________________________________________________
107
- /* *
108
- * Copy constructor.
109
- *
110
- * @param aTool Object to be copied.
111
-
112
- */
113
- InverseKinematicsTool::InverseKinematicsTool (const InverseKinematicsTool &aTool) :
114
- Tool(aTool),
115
- _modelFileName(_modelFileNameProp.getValueStr()),
116
- _constraintWeight(_constraintWeightProp.getValueDbl()),
117
- _accuracy(_accuracyProp.getValueDbl()),
118
- _ikTaskSetProp(PropertyObj(" " , IKTaskSet())),
119
- _ikTaskSet((IKTaskSet&)_ikTaskSetProp.getValueObj()),
120
- _markerFileName(_markerFileNameProp.getValueStr()),
121
- _coordinateFileName(_coordinateFileNameProp.getValueStr()),
122
- _timeRange(_timeRangeProp.getValueDblArray()),
123
- _reportErrors(_reportErrorsProp.getValueBool()),
124
- _outputMotionFileName(_outputMotionFileNameProp.getValueStr()),
125
- _reportMarkerLocations(_reportMarkerLocationsProp.getValueBool())
126
- {
127
- setNull ();
128
- *this = aTool;
129
- }
130
-
131
- // _____________________________________________________________________________
132
- /* *
133
- * Set all member variables to their null or default values.
134
- */
135
- void InverseKinematicsTool::setNull ()
136
- {
137
- setupProperties ();
138
- _model = NULL ;
139
- }
140
- // _____________________________________________________________________________
141
- /* *
142
- * Connect properties to local pointers.
143
- */
144
- void InverseKinematicsTool::setupProperties ()
145
- {
146
- _modelFileNameProp.setComment (
147
- " Name of the model file (.osim) to use for inverse kinematics." );
148
- _modelFileNameProp.setName (" model_file" );
149
- _propertySet.append ( &_modelFileNameProp );
150
-
151
- _constraintWeightProp.setComment (
152
- " A positive scalar that weights the relative importance of satisfying "
153
- " constraints. A weighting of 'Infinity' (the default) results in the "
154
- " constraints being strictly enforced. Otherwise, the weighted-squared "
155
- " constraint errors are appended to the cost function." );
156
- _constraintWeightProp.setName (" constraint_weight" );
157
- _constraintWeightProp.setValue (std::numeric_limits<SimTK::Real>::infinity ());
158
- _propertySet.append ( &_constraintWeightProp );
159
-
160
- _accuracyProp.setComment (
161
- " The accuracy of the solution in absolute terms. Default is 1e-5. "
162
- " It determines the number of significant digits to which the solution "
163
- " can be trusted." );
164
- _accuracyProp.setName (" accuracy" );
165
- _accuracyProp.setValue (1e-5 );
166
- _propertySet.append ( &_accuracyProp );
167
-
168
- _ikTaskSetProp.setComment (
169
- " Markers and coordinates to be considered (tasks) and their weightings. "
170
- " The sum of weighted-squared task errors composes the cost function." );
171
- _ikTaskSetProp.setName (" IKTaskSet" );
172
- _propertySet.append (&_ikTaskSetProp);
173
-
174
- _markerFileNameProp.setComment (
175
- " TRC file (.trc) containing the time history of observations of marker "
176
- " positions obtained during a motion capture experiment. Markers in this "
177
- " file that have a corresponding task and model marker are included." );
178
- _markerFileNameProp.setName (" marker_file" );
179
- _propertySet.append (&_markerFileNameProp);
180
-
181
- _coordinateFileNameProp.setComment (
182
- " The name of the storage (.sto or .mot) file containing the time history"
183
- " of coordinate observations. Coordinate values from this file are "
184
- " included if there is a corresponding model coordinate and task. " );
185
- _coordinateFileNameProp.setName (" coordinate_file" );
186
- _propertySet.append (&_coordinateFileNameProp);
187
-
188
- const double defaultTimeRange[] =
189
- {-std::numeric_limits<SimTK::Real>::infinity (),
190
- std::numeric_limits<SimTK::Real>::infinity ()};
191
- _timeRangeProp.setComment (
192
- " The desired time range over which inverse kinematics is solved. "
193
- " The closest start and final times from the provided observations "
194
- " are used to specify the actual time range to be processed." );
195
- _timeRangeProp.setName (" time_range" );
196
- _timeRangeProp.setValue (2 , defaultTimeRange);
197
- _timeRangeProp.setAllowableListSize (2 );
198
- _propertySet.append (&_timeRangeProp);
199
-
200
- _reportErrorsProp.setComment (
201
- " Flag (true or false) indicating whether or not to report marker "
202
- " errors from the inverse kinematics solution." );
203
- _reportErrorsProp.setName (" report_errors" );
204
- _reportErrorsProp.setValue (true );
205
- _propertySet.append (&_reportErrorsProp);
206
-
207
- _outputMotionFileNameProp.setComment (
208
- " Name of the resulting inverse kinematics motion (.mot) file." );
209
- _outputMotionFileNameProp.setName (" output_motion_file" );
210
- _propertySet.append (&_outputMotionFileNameProp);
211
-
212
- _reportMarkerLocationsProp.setComment (
213
- " Flag indicating whether or not to report model marker locations. "
214
- " Note, model marker locations are expressed in Ground." );
215
- _reportMarkerLocationsProp.setName (" report_marker_locations" );
216
- _reportMarkerLocationsProp.setValue (false );
217
- _propertySet.append (&_reportMarkerLocationsProp);
218
79
}
219
80
220
81
// _____________________________________________________________________________
221
82
/* *
222
- * Register InverseKinematicsTool and any Object types it may employ internally.
223
- */
224
- void InverseKinematicsTool::registerTypes ()
225
- {
226
- Object::registerType (InverseKinematicsTool ());
227
- }
228
- // =============================================================================
229
- // OPERATORS
230
- // =============================================================================
231
- // _____________________________________________________________________________
232
- /* *
233
- * Assignment operator.
234
- *
235
- * @return Reference to this object.
83
+ * Construct properties
236
84
*/
237
- InverseKinematicsTool& InverseKinematicsTool::
238
- operator =(const InverseKinematicsTool &aTool)
85
+ void InverseKinematicsTool::constructProperties ()
239
86
{
240
- // BASE CLASS
241
- Tool::operator =(aTool);
242
-
243
- // MEMBER VARIABLES
244
- _modelFileName = aTool._modelFileName ;
245
- _constraintWeight = aTool._constraintWeight ;
246
- _accuracy = aTool._accuracy ;
247
- _ikTaskSet = aTool._ikTaskSet ;
248
- _markerFileName = aTool._markerFileName ;
249
- _timeRange = aTool._timeRange ;
250
- _coordinateFileName = aTool._coordinateFileName ;
251
- _reportErrors = aTool._reportErrors ;
252
- _outputMotionFileName = aTool._outputMotionFileName ;
253
- _reportMarkerLocations = aTool._reportMarkerLocations ;
254
-
255
- return (*this );
87
+ constructProperty_model_file (" " );
88
+ constructProperty_constraint_weight (Infinity);
89
+ constructProperty_accuracy (1e-5 );
90
+ constructProperty_IKTaskSet (IKTaskSet ());
91
+ constructProperty_marker_file (" " );
92
+ constructProperty_coordinate_file (" " );
93
+ Array<double > range{Infinity, 2 };
94
+ range[0 ] = -Infinity; // Make range -Infinity to Infinity unless limited by
95
+ // data
96
+ constructProperty_time_range (range);
97
+
98
+ constructProperty_report_errors (true );
99
+ constructProperty_output_motion_file (" " );
100
+ constructProperty_report_marker_locations (false );
256
101
}
257
102
258
103
// =============================================================================
@@ -274,10 +119,10 @@ bool InverseKinematicsTool::run()
274
119
Kinematics* kinematicsReporter = nullptr ;
275
120
try {
276
121
// Load and create the indicated model
277
- if (! _model) {
278
- OPENSIM_THROW_IF_FRMOBJ (_modelFileName .empty (), Exception,
279
- " No model filename was provided." );
280
- _model = new Model (_modelFileName);
122
+ if (_model. empty ()) {
123
+ OPENSIM_THROW_IF_FRMOBJ (get_model_file () .empty (), Exception,
124
+ " No model filename was provided." );
125
+ _model. reset ( new Model (get_model_file ()));
281
126
}
282
127
else
283
128
modelFromFile = false ;
@@ -317,11 +162,11 @@ bool InverseKinematicsTool::run()
317
162
// specified then use time from marker reference.
318
163
// Adjust the time range for the tool if the provided range exceeds
319
164
// that of the marker data.
320
- SimTK::Vec2 markersValidTimRange = markersReference.getValidTimeRange ();
321
- double start_time = (markersValidTimRange [0 ] > _timeRange[ 0 ] ) ?
322
- markersValidTimRange [0 ] : _timeRange[ 0 ] ;
323
- double final_time = (markersValidTimRange [1 ] < _timeRange[ 1 ] ) ?
324
- markersValidTimRange [1 ] : _timeRange[ 1 ] ;
165
+ SimTK::Vec2 markersValidTimeRange = markersReference.getValidTimeRange ();
166
+ double start_time = (markersValidTimeRange [0 ] > get_time_range ( 0 ) ) ?
167
+ markersValidTimeRange [0 ] : get_time_range ( 0 ) ;
168
+ double final_time = (markersValidTimeRange [1 ] < get_time_range ( 1 ) ) ?
169
+ markersValidTimeRange [1 ] : get_time_range ( 1 ) ;
325
170
326
171
SimTK_ASSERT2_ALWAYS (final_time >= start_time,
327
172
" InverseKinematicsTool final time (%f) is before start time (%f)." ,
@@ -337,8 +182,8 @@ bool InverseKinematicsTool::run()
337
182
338
183
// create the solver given the input data
339
184
InverseKinematicsSolver ikSolver (*_model, markersReference,
340
- coordinateReferences, _constraintWeight );
341
- ikSolver.setAccuracy (_accuracy );
185
+ coordinateReferences, get_constraint_weight () );
186
+ ikSolver.setAccuracy (get_accuracy () );
342
187
s.updTime () = times[start_ix];
343
188
ikSolver.assemble (s);
344
189
kinematicsReporter->begin (s);
@@ -352,9 +197,9 @@ bool InverseKinematicsTool::run()
352
197
SimTK::Array_<double > squaredMarkerErrors (nm, 0.0 );
353
198
SimTK::Array_<Vec3> markerLocations (nm, Vec3 (0 ));
354
199
355
- Storage *modelMarkerLocations = _reportMarkerLocations ?
200
+ Storage *modelMarkerLocations = get_report_marker_locations () ?
356
201
new Storage (Nframes, " ModelMarkerLocations" ) : nullptr ;
357
- Storage *modelMarkerErrors = _reportErrors ?
202
+ Storage *modelMarkerErrors = get_report_errors () ?
358
203
new Storage (Nframes, " ModelMarkerErrors" ) : nullptr ;
359
204
360
205
Stopwatch watch;
@@ -365,7 +210,7 @@ bool InverseKinematicsTool::run()
365
210
// show progress line every 1000 frames so users see progress
366
211
if (std::remainder (i - start_ix, 1000 ) == 0 && i != start_ix)
367
212
cout << " Solved " << i - start_ix << " frames..." << std::endl;
368
- if (_reportErrors ){
213
+ if (get_report_errors () ){
369
214
Array<double > markerErrors (0.0 , 3 );
370
215
double totalSquaredMarkerError = 0.0 ;
371
216
double maxSquaredMarkerError = 0.0 ;
@@ -393,7 +238,7 @@ bool InverseKinematicsTool::run()
393
238
<< ikSolver.getMarkerNameForIndex (worst) << " )" << endl;
394
239
}
395
240
396
- if (_reportMarkerLocations ){
241
+ if (get_report_marker_locations () ){
397
242
ikSolver.computeCurrentMarkerLocations (markerLocations);
398
243
Array<double > locations (0.0 , 3 *nm);
399
244
for (int j=0 ; j<nm; ++j){
@@ -411,8 +256,10 @@ bool InverseKinematicsTool::run()
411
256
412
257
// Do the maneuver to change then restore working directory
413
258
// so that output files are saved to same folder as setup file.
414
- if (_outputMotionFileName!= " " && _outputMotionFileName!=" Unassigned" ){
415
- kinematicsReporter->getPositionStorage ()->print (_outputMotionFileName);
259
+ if (get_output_motion_file () != " " &&
260
+ get_output_motion_file () != " Unassigned" ) {
261
+ kinematicsReporter->getPositionStorage ()->print (
262
+ get_output_motion_file ());
416
263
}
417
264
// Remove the analysis we added to the model, this also deletes it
418
265
_model->removeAnalysis (kinematicsReporter);
@@ -472,7 +319,8 @@ bool InverseKinematicsTool::run()
472
319
" please see messages window for details..." ));
473
320
}
474
321
475
- if (modelFromFile) delete _model;
322
+ if (modelFromFile)
323
+ _model.reset ();
476
324
477
325
return success;
478
326
}
@@ -511,9 +359,7 @@ void InverseKinematicsTool::updateFromXMLNode(SimTK::Xml::Element& aNode, int ve
511
359
for (; p!= trialIter->node_end (); ++p) {
512
360
iter->insertNodeAfter ( iter->node_end (), p->clone ());
513
361
}
514
- iter->insertNodeAfter ( iter->node_end (), Xml::Comment (_constraintWeightProp.getComment ()));
515
362
iter->insertNodeAfter ( iter->node_end (), Xml::Element (" constraint_weight" , " 20.0" ));
516
- iter->insertNodeAfter ( iter->node_end (), Xml::Comment (_accuracyProp.getComment ()));
517
363
iter->insertNodeAfter ( iter->node_end (), Xml::Element (" accuracy" , " 1e-4" ));
518
364
// erase node for IKTrialSet
519
365
iter->eraseNode (toolIter);
@@ -545,9 +391,7 @@ void InverseKinematicsTool::updateFromXMLNode(SimTK::Xml::Element& aNode, int ve
545
391
for (; p!= trialIter->node_end (); ++p) {
546
392
root.insertNodeAfter ( root.node_end (), p->clone ());
547
393
}
548
- root.insertNodeAfter ( root.node_end (), Xml::Comment (_constraintWeightProp.getComment ()));
549
394
root.insertNodeAfter ( root.node_end (), Xml::Element (" constraint_weight" , " 20.0" ));
550
- root.insertNodeAfter ( root.node_end (), Xml::Comment (_accuracyProp.getComment ()));
551
395
root.insertNodeAfter ( root.node_end (), Xml::Element (" accuracy" , " 1e-5" ));
552
396
// erase node for IKTrialSet
553
397
root.eraseNode (toolIter);
@@ -577,8 +421,8 @@ void InverseKinematicsTool::populateReferences(MarkersReference& markersReferenc
577
421
FunctionSet *coordFunctions = NULL ;
578
422
// Load the coordinate data
579
423
// bool haveCoordinateFile = false;
580
- if (_coordinateFileName != " " && _coordinateFileName != " Unassigned" ) {
581
- Storage coordinateValues (_coordinateFileName );
424
+ if (get_coordinate_file () != " " && get_coordinate_file () != " Unassigned" ) {
425
+ Storage coordinateValues (get_coordinate_file () );
582
426
// Convert degrees to radian (TODO: this needs to have a check that the storage is, in fact, in degrees!)
583
427
_model->getSimbodyEngine ().convertDegreesToRadians (coordinateValues);
584
428
// haveCoordinateFile = true;
@@ -589,9 +433,9 @@ void InverseKinematicsTool::populateReferences(MarkersReference& markersReferenc
589
433
// Loop through old "IKTaskSet" and assign weights to the coordinate and marker references
590
434
// For coordinates, create the functions for coordinate reference values
591
435
int index = 0 ;
592
- for (int i = 0 ; i < _ikTaskSet .getSize (); i++) {
593
- if (!_ikTaskSet [i].getApply ()) continue ;
594
- if (IKCoordinateTask *coordTask = dynamic_cast <IKCoordinateTask *>(&_ikTaskSet [i])) {
436
+ for (int i = 0 ; i < get_IKTaskSet () .getSize (); i++) {
437
+ if (!get_IKTaskSet () [i].getApply ()) continue ;
438
+ if (IKCoordinateTask *coordTask = dynamic_cast <IKCoordinateTask *>(&get_IKTaskSet () [i])) {
595
439
CoordinateReference *coordRef = NULL ;
596
440
if (coordTask->getValueType () == IKCoordinateTask::FromFile) {
597
441
if (!coordFunctions)
@@ -619,7 +463,7 @@ void InverseKinematicsTool::populateReferences(MarkersReference& markersReferenc
619
463
620
464
coordinateReferences.push_back (*coordRef);
621
465
}
622
- else if (IKMarkerTask *markerTask = dynamic_cast <IKMarkerTask *>(&_ikTaskSet [i])) {
466
+ else if (IKMarkerTask *markerTask = dynamic_cast <IKMarkerTask *>(&get_IKTaskSet () [i])) {
623
467
if (markerTask->getApply ()) {
624
468
// Only track markers that have a task and it is "applied"
625
469
markerWeights.adoptAndAppend (
@@ -631,7 +475,7 @@ void InverseKinematicsTool::populateReferences(MarkersReference& markersReferenc
631
475
// Read in the marker data file and set the weights for associated markers.
632
476
// Markers in the model and the marker file but not in the markerWeights are
633
477
// ignored
634
- markersReference.initializeFromMarkersFile (_markerFileName , markerWeights);
478
+ markersReference.initializeFromMarkersFile (get_marker_file () , markerWeights);
635
479
}
636
480
637
481
0 commit comments