Skip to content

Instantly share code, notes, and snippets.

@chrisdembia
Last active August 29, 2015 14:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save chrisdembia/4542ea41b9ed6f3b0967 to your computer and use it in GitHub Desktop.
Save chrisdembia/4542ea41b9ed6f3b0967 to your computer and use it in GitHub Desktop.
opensim-4.0-targets
int main() {
InverseKinematics("c3d");
}
#include <OpenSim/OpenSim.h>
// Load a states traj. from a file and compute the
// average of a column over time.
int main() {
Model model("mymodel.osim");
StatesTrajectory states("states.osimstates");
SimTK::Vector_<SimTK::Vec3> com_hist =
OpenSim::for_each(states.begin(), states.end(), model.getMassCenter);
// Ideal:
//SimTK::Vector_<SimTK::Vec3> com_hist =
// model.getMassCenter(states);
std::cout << "Average COM: " << com_hist.mean() << std::endl;
DataSource jointangles("Kinematics_q.sto");
InverseDynamicsSolver id(model);
id.getInput("kinematics").connect(jointangles);
DataSink moments;
moments.getInput("data").connect(id.getOutput("moments"));)
id.solve();
// Ajay
DataSource dataAngles("myangles.csv");
dataAngles.getOutput("A"); // <- "A" is not known at compile time, need mulitplexer.
Output<Vector> outs = dataAngles.getOutputs();
idSolver.setInput(outs);
idSolver.setInput(dataAngles, "A");
// simulink, signals and slots.
// metadata
// c3d has up dir, corners x,y,z, lab orientation, conversion from voltages
// patient height,
// special inverse dynamics that knows when contact happens.
// idsolver says how metadata must name phases.
// DataSource outputs for metadata.
// metadata is often an event.
// python script...
//
// metadata should have time.
DataSource.getMetadata("left_foot_strikes");
DataSource.getMetadata("get_up_direction");
}
#include <OpenSim/OpenSim.h>
class HeadVelocityGoal : public PSimGoal {
double evaluateGoal() {
return m_integral.getOutput("output") / duration
}
double getHeadVelocity(const State& s) {
return matter.calcSystemMassCenterVelocityInGround(s);
}
void extendConnectToModel() {
m_integral.getInput("input").connect(getOutput("head_velocity"));
addComponent(&m_integral);
}
OpenSim_DECLARE_OUTPUT(head_velocity, double, getHeadVelocity)
Integrate m_integral; // an Operator component.
};
int main() {
}
#include <OpenSim/OpenSim.h>
// Calculate metabolics from a muscle model.
class AndersonMetabolics : public Component {
//OpenSim_DECLARE_INPUT(excitation, double)
//OpenSim_DECLARE_INPUT(activation, double)
//OpenSim_DECLARE_INPUT(force, double)
OpenSim_DECLARE_CONNECTOR(muscle, Muscle)
OpenSim_DECLARE_OUTPUT(metabolic_rate, double, computeMetabolics) // or a std::map?
double computeMetabolics(const State& s) {
return 0.25 * getConnectee<Muscle>("muscle").getActivation(s);
}
};
class AndersonMetabolics : public ModelComponent {
//OpenSim_DECLARE_INPUT(excitation, double)
//OpenSim_DECLARE_INPUT(activation, double)
//OpenSim_DECLARE_INPUT(force, double)
OpenSim_DECLARE_MULTICONNECTOR(muscles, Muscle)
OpenSim_DECLARE_MULTIOUTPUT(metabolic_rate, double, computeMetabolics) // or a std::map?
double computeMetabolics(const State& s) {
return 0.25 * getConnectee<Muscle>("muscle").getActivation(s);
}
};
int main() {
Model model("mymodel.osim");
AndersonMetabolics met;
met.getConnector("muscles").connect(model.getMuscles().get("soleus_r"));)
Reporter.getMultiInput().append("soleus_r/metabolic_rate");
model.addMiscModelComponent(met);
Solver solver = ForwardSolver(model);
solver.solve();
}
#include <OpenSim/OpenSim.h>
int main() {
Vector jointAngles = Vector::linspace(0, 0.25 * Pi, 100);
Vector momentArms(jointAngles.size());
std::transform(jointAngles.begin(), jointAngles.end(), momentArms.begin(), muscle.getMomentArm);
}
#include <OpenSim/OpenSim.h>
// Run a static optimization with a single output.
// Look at the result without writing to a file.
int main() {
Model model("mymodel.osim");
Solver* solver = new StaticOptimization(model);
solver.addResult("soleus_r/activation");
DataTable data = solver.run();
const auto soleus_act = data.getColumn("soleus_r/activation");
std::cout << "Max soleus activity: " << SimTK::max(soleus_act) << std::endl;
}
class InverseDynamicsSolver : public Component {
void constructInputs() {
constructInput("q", SimTK::Vector);
constructInput("u", SimTK::Vector);
constructInput("udot", SimTK::Vector);
}
void constructOutputs() {
constructOutput("residual", SimTK::Vector, &solve);
}
void constructConnectors() {
constructConnector<Model>("model");
}
const SimTK::Vector& solve(const SimTK::State& s) const {
const auto& smss = updConnector<Model>("model").getConnectee().getMatterSubsystem();
smss.calcResidual(getInput(s, "q"), getInput(s, "u"), getInput(s, "udot"), _residual.upd());
return _residual.get();
}
private:
SimTK::ThreadLocal<SimTK::Vector> _residual;
};
class FeedforwardController : public Controller {
OpenSim_DECLARE_PROPERTY(kp, double);
OpenSim_DECLARE_PROPERTY(kv, double);
void constructInputs() {
constructInput("q_des", SimTK::Vector);
constructInput("u_des", SimTK::Vector);
}
void constructOutputs() {
constructOutput("control_law", SimTK::Vector, computeControlLaw());
}
SimTK::Vector computeControlLaw(const SimTK::State& s) {
return kp * (getInput("q_des") - s.getQ()) + kv * (getInput("u_des") - s.getU());
}
void computeControls(const SimTK::State& s, SimTK::Vector& controls) {
controls = _id.getOutputValue(s, "residuals");
// TODO how to deal with only controlling a subset of coordinates?
}
void connectToModel(Model& model) {
_id.upd_model() = model; // I don't think this would work; can't assign to a reference.
// TODO could add noise. Could let the user wire these themselves.
_id.getInput("q").connect(model.getOutput("q"));
_id.getInput("u").connect(model.getOutput("u"));
_id.getInput("udot").connect(getOutput("control_law"));
// _id.getInput("udot").connect(getInput("control_law")) <-- forwarding!
}
private:
InverseDynamics _id;
};
class Study {
};
ForwardStudy
InverseStudy
InverseTool
class Differentiator {
};
class InverseDynamicsStudy {
OpenSim_DECLARE_PROPERTY("kinematics", DataSource);
void run() {
InverseDynamicsSolver idSolver;
idSolver.getInput("q").connect(DataSource.getOutput(???)
}
};
```
<InverseDynamicsStudy>
<DataSource name="kinematics">
<filename>walk0_ik.mot</filename>
</DataSource>
</InverseDynamicsStudy>
```
class InverseStudy {
OpenSim_DECLARE_PROPERTY(state_trajectory, StateTrajectory);
}
class AnalyzeTool {
OpenSim_DECLARE_PROPERTY("model", Model);
OpenSim_DECLARE_PROPERTY("coordinates_file", string);
OpenSim_DECLARE_LIST_PROPERTY("analyses", Analysis);
void run() {
}
};
class ForwardDynamics {
void constructOutputs() {
constructOutput("state", SimTK::State); // WHAT???
}
void constructConnectors() {
constructConnector<Model>("model");
}
};
class InverseKinematics {
OpenSim_DECLARE_LIST_PROPERTY(tasks, IKTask);
void constructInputs() {
constructInput("reference_values", ???)
}
void constructOutputs() {
constructOutput("q", SimTK::Vector);
}
void constructConnectors() {
constructConnector<Model>("model");
}
const SimTK::Vector& solve(const SimTK::State& s) const {
get_model().assemble();
return s
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment