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