OpenSim Moco  0.2.0
exampleSlidingMassAdvanced.cpp

This example shows setting solver settings, customizing an initial guess, and defining a custom goal (cost term).See Defining a custom goal or cost.

/* -------------------------------------------------------------------------- *
* OpenSim Moco: exampleSlidingMassAdvanced.cpp *
* -------------------------------------------------------------------------- *
* Copyright (c) 2017 Stanford University and the Authors *
* *
* Author(s): Christopher Dembia *
* *
* Licensed under the Apache License, Version 2.0 (the "License"); you may *
* not use this file except in compliance with the License. You may obtain a *
* copy of the License at http://www.apache.org/licenses/LICENSE-2.0 *
* *
* Unless required by applicable law or agreed to in writing, software *
* distributed under the License is distributed on an "AS IS" BASIS, *
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
* See the License for the specific language governing permissions and *
* limitations under the License. *
* -------------------------------------------------------------------------- */
#include <Moco/osimMoco.h>
#include <OpenSim/Actuators/CoordinateActuator.h>
#include <OpenSim/Simulation/SimbodyEngine/SliderJoint.h>
using namespace OpenSim;
std::unique_ptr<Model> createSlidingMassModel() {
auto model = make_unique<Model>();
model->setName("sliding_mass");
model->set_gravity(SimTK::Vec3(0, 0, 0));
auto* body = new Body("body", 2.0, SimTK::Vec3(0), SimTK::Inertia(0));
model->addComponent(body);
// Allows translation along x.
auto* joint = new SliderJoint("slider", model->getGround(), *body);
auto& coord = joint->updCoordinate(SliderJoint::Coord::TranslationX);
coord.setName("position");
model->addComponent(joint);
auto* actu = new CoordinateActuator();
actu->setCoordinate(&coord);
actu->setName("actuator");
actu->setOptimalForce(1);
model->addComponent(actu);
body->attachGeometry(new Sphere(0.05));
model->finalizeConnections();
return model;
}
class MocoCustomEffortGoal : public MocoGoal {
OpenSim_DECLARE_CONCRETE_OBJECT(MocoCustomEffortGoal, MocoGoal);
public:
MocoCustomEffortGoal() {}
MocoCustomEffortGoal(std::string name) : MocoGoal(std::move(name)) {}
MocoCustomEffortGoal(std::string name, double weight)
: MocoGoal(std::move(name), weight) {}
protected:
Mode getDefaultModeImpl() const override { return Mode::Cost; }
bool getSupportsEndpointConstraintImpl() const override { return true; }
void initializeOnModelImpl(const Model&) const override {
setNumIntegralsAndOutputs(1, 1);
}
void calcIntegrandImpl(
const SimTK::State& state, double& integrand) const override {
getModel().realizeVelocity(state);
const auto& controls = getModel().getControls(state);
integrand = controls.normSqr();
}
void calcGoalImpl(
const GoalInput& input, SimTK::Vector& cost) const override {
cost[0] = input.integral;
}
};
int main() {
MocoStudy study;
study.setName("sliding_mass");
// Define the optimal control problem.
// ===================================
MocoProblem& problem = study.updProblem();
// Model (dynamics).
// -----------------
problem.setModel(createSlidingMassModel());
// Bounds.
// -------
// Initial time must be 0, final time can be within [0, 5].
// Initial position must be 0, final position must be 1.
problem.setStateInfo("/slider/position/value", MocoBounds(-5, 5),
// Initial and final speed must be 0. Use compact syntax.
problem.setStateInfo("/slider/position/speed", {-50, 50}, 0, 0);
// Applied force must be between -50 and 50.
problem.setControlInfo("/actuator", MocoBounds(-50, 50));
// Cost.
// -----
problem.addGoal<MocoFinalTimeGoal>("time");
problem.addGoal<MocoCustomEffortGoal>("effort");
// Configure the solver.
// =====================
solver.set_num_mesh_intervals(50);
solver.set_verbosity(2);
solver.set_optim_solver("ipopt");
solver.set_optim_ipopt_print_level(4);
solver.set_optim_max_iterations(50);
solver.set_optim_finite_difference_scheme("forward");
solver.set_optim_sparsity_detection("random");
solver.set_optim_write_sparsity("sliding_mass");
// solver.set_optim_constraint_tolerance(1e-5);
// solver.set_optim_convergence_tolerance(1e-5);
// solver.set_optim_findiff_hessian_step_size(1e-3);
// Specify an initial guess.
// -------------------------
MocoTrajectory guess = solver.createGuess("bounds");
guess.setTime({0, 0.5});
guess.setState("/slider/position/value", {0.0, 1.0});
solver.setGuess(guess);
// Solve the problem.
// ==================
MocoSolution solution = study.solve();
std::cout << "Solution status: " << solution.getStatus() << std::endl;
study.visualize(solution);
return EXIT_SUCCESS;
}
OpenSim::MocoTrajectory::setState
void setState(const std::string &name, const SimTK::Vector &trajectory)
Set the value of a single state variable across time.
OpenSim::MocoStudy::solve
MocoSolution solve() const
Solve the provided MocoProblem using the provided MocoSolver, and obtain the solution to the problem.
OpenSim::MocoProblem::setStateInfo
void setStateInfo(const std::string &name, const MocoBounds &, const MocoInitialBounds &={}, const MocoFinalBounds &={})
Set bounds for a state variable for phase 0.
OpenSim::MocoCasADiSolver
This solver uses the CasADi library (https://casadi.org) to convert the MocoProblem into a generic no...
Definition: MocoCasADiSolver.h:110
OpenSim::MocoInitialBounds
Used for specifying the bounds on a variable at the start of a phase.
Definition: MocoBounds.h:110
OpenSim::MocoProblem::setControlInfo
void setControlInfo(const std::string &name, const MocoBounds &, const MocoInitialBounds &={}, const MocoFinalBounds &={})
Set bounds for a control variable for phase 0.
OpenSim::MocoStudy::updProblem
MocoProblem & updProblem()
If using this method in C++, make sure to include the "&" in the return type; otherwise,...
OpenSim::MocoTrajectory::setTime
void setTime(const SimTK::Vector &time)
Set the time vector.
OpenSim::MocoTrajectory
The values of the variables in an optimal control problem.
Definition: MocoTrajectory.h:98
OpenSim::MocoProblem::setTimeBounds
void setTimeBounds(const MocoInitialBounds &, const MocoFinalBounds &)
Set time bounds for phase 0.
OpenSim::MocoGoal
A goal is term in the cost functional to be minimized, or a set of endpoint constraints that must lie...
Definition: MocoGoal.h:54
OpenSim::MocoBounds
Small struct to handle bounds.
Definition: MocoBounds.h:34
OpenSim::MocoProblem::addGoal
MocoGoalType * addGoal(Args &&... args)
Add a goal for phase 0.
Definition: MocoProblem.h:487
OpenSim::MocoStudy::visualize
void visualize(const MocoTrajectory &it) const
Interactively visualize a trajectory using the simbody-visualizer.
OpenSim::MocoStudy
The top-level class for solving a custom optimal control problem.
Definition: MocoStudy.h:71
OpenSim
The utilities in this file are categorized as follows:
Definition: About.h:24
OpenSim::MocoFinalTimeGoal
Endpoint cost for final time.
Definition: MocoGoal.h:272
OpenSim::MocoTrajectory::resampleWithNumTimes
double resampleWithNumTimes(int numTimes)
Uniformly resample (interpolate) the trajectory so that it retains the same initial and final times b...
OpenSim::MocoSolution
Return type for MocoStudy::solve().
Definition: MocoTrajectory.h:740
OpenSim::MocoProblem
A description of an optimal control problem, backed by OpenSim Models.
Definition: MocoProblem.h:424
CasOC::controls
Algebraic variables.
Definition: CasOCIterate.h:33
OpenSim::MocoFinalBounds
Used for specifying the bounds on a variable at the end of a phase.
Definition: MocoBounds.h:117
OpenSim::MocoSolution::getStatus
const std::string & getStatus() const
Obtain a solver-dependent string describing the return status of the optimization.
Definition: MocoTrajectory.h:756
OpenSim::MocoStudy::initCasADiSolver
MocoCasADiSolver & initCasADiSolver()
Call this method once you have finished setting up your MocoProblem.
OpenSim::MocoProblem::setModel
Model * setModel(std::unique_ptr< Model > model)
Set the model to use for phase 0.