1
2 #include <OpenSim/OpenSim.h>
3 #include <OpenSim/Common/TableSource.h>
4 #include <OpenSim/Common/STOFileAdapter.h>
5 #include <OpenSim/Simulation/Model/Point.h>
6
7 using namespace OpenSim;
8 using namespace SimTK;
9
10 //==============================================================================
11 // ExperimentalMarker
12 //==============================================================================
13 /**
14 ExperimentalMarker is a concrete Point that represents the experimental value of
15 a Marker and can be used to display that the marker location in the OpenSim
16 Visualizer.
17
18 Unlike its model Marker counterpart, an ExperimentalMarker is a measured value
19 and not physically attached to the musculoskeletal model. It is assumed that its
20 value is its location with respect to the lab (Ground) frame.
21
22 The location in Ground value of an ExperimentalMarker is obtained from its
23 Input<Vec3>("location_in_ground").
24
25 @authors Ajay Seth
26 **/
27 class ExperimentalMarker : public Point {
28 OpenSim_DECLARE_CONCRETE_OBJECT(ExperimentalMarker, Point);
29 public:
ExperimentalMarker()30 ExperimentalMarker() { constructProperties(); }
31
32 OpenSim_DECLARE_PROPERTY(radius, double,
33 "The radius of the sphere used to display the ExperimentalMarker.");
34
35 OpenSim_DECLARE_PROPERTY(color, SimTK::Vec3,
36 "The color of the sphere used to display the ExperimentalMarker.");
37
38 OpenSim_DECLARE_PROPERTY(default_location, SimTK::Vec3,
39 "The default location of the ExperimentalMarker in Ground.");
40
41 OpenSim_DECLARE_INPUT(location_in_ground, SimTK::Vec3, SimTK::Stage::Time,
42 "Provide ExperimentalMarker location_in_ground the Ground.");
43
44 private:
constructProperties()45 void constructProperties() {
46 constructProperty_default_location(SimTK::Vec3(SimTK::NaN));
47 constructProperty_radius(0.005);
48 constructProperty_color(SimTK::Vec3(0.9, 0.9, 0.2));
49 }
50
extendFinalizeFromProperties()51 void extendFinalizeFromProperties() override {
52 _locationInGround = get_default_location();
53 }
54
55 /* Calculate the location with respect to and expressed in Ground */
calcLocationInGround(const SimTK::State & s) const56 SimTK::Vec3 calcLocationInGround(const SimTK::State& s) const override {
57 return getInput<SimTK::Vec3>("location_in_ground").getValue(s);
58 }
59
calcVelocityInGround(const SimTK::State & s) const60 SimTK::Vec3 calcVelocityInGround(const SimTK::State& s) const override {
61 return SimTK::Vec3(NaN);
62 }
63
calcAccelerationInGround(const SimTK::State & s) const64 SimTK::Vec3 calcAccelerationInGround(const SimTK::State& s) const override {
65 return SimTK::Vec3(NaN);
66 }
67
generateDecorations(bool fixed,const ModelDisplayHints & hints,const SimTK::State & state,SimTK::Array_<SimTK::DecorativeGeometry> & appendToThis) const68 void generateDecorations(bool fixed, const ModelDisplayHints& hints,
69 const SimTK::State& state,
70 SimTK::Array_<SimTK::DecorativeGeometry>& appendToThis) const override
71 {
72 Super::generateDecorations(fixed, hints, state, appendToThis);
73 if (!fixed && hints.get_show_markers()) {
74 appendToThis.push_back(
75 SimTK::DecorativeSphere(get_radius()).setBodyId(0)
76 .setColor(get_color()).setOpacity(0.5)
77 .setTransform(getLocationInGround(state)));
78 appendToThis.push_back(SimTK::DecorativeText(getName()).setBodyId(0)
79 .setTransform(getLocationInGround(state))
80 .setScaleFactors(SimTK::Vec3(get_radius()*0.5)));
81 }
82 }
83
84 mutable SimTK::Vec3 _locationInGround{ SimTK::NaN };
85 }; // End of class ExperimentalMarker
86
87
88
previewMarkerData(const std::string & markerDataFile)89 void previewMarkerData(const std::string& markerDataFile)
90 {
91 Model markerWorld;
92 // Load the marker data into a TableSource that has markers
93 // as its output which each markers occupying its own channel
94 TableSourceVec3* markersSource = new TableSourceVec3(markerDataFile);
95 // Add the markersSource Component to the model
96 markerWorld.addComponent(markersSource);
97
98 // Get the underlying Table backing the marker Source so we
99 // know how many markers we have and their names
100 const auto& markerData = markersSource->getTable();
101
102 // Create an ExperimentMarker Component for every column in the markerData
103 for (size_t i = 0; i < markerData.getNumColumns(); ++i) {
104 auto marker = new ExperimentalMarker();
105 marker->setName(markerData.getColumnLabel(i));
106 marker->set_default_location(markerData.getMatrix()(0, i));
107 // markers are owned by the model
108 markerWorld.addComponent(marker);
109 // the time varying location of the marker comes from the markersSource
110 // Component
111 marker->updInput("location_in_ground").connect(
112 markersSource->getOutput("column").getChannel(markerData.getColumnLabel(i)));
113 }
114
115 markerWorld.setUseVisualizer(true);
116 SimTK::State& state = markerWorld.initSystem();
117
118 char c;
119 std::cout << "press any key to visualize '" << markerDataFile <<
120 "' data ..." << std::endl;
121 std::cin >> c;
122
123 auto& times = markerData.getIndependentColumn();
124 for (size_t j = 0; j < times.size(); ++j) {
125 std::cout << "time: " << times[j] << "s" << std::endl;
126 state.setTime(times[j]);
127 markerWorld.realizePosition(state);
128 markerWorld.getVisualizer().show(state);
129 }
130 }
131
main()132 int main() {
133 previewMarkerData("futureMarkerPreviewData.trc");
134
135 return 0;
136 }
137
138
139
140