Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Add FATROP solver support to Moco #3906

Draft
wants to merge 41 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
439eb31
Create time variables across the trajectory
nickbianco Jul 26, 2024
189caa2
Update createTimes()
nickbianco Jul 29, 2024
c761f25
Time constraints now working
nickbianco Jul 29, 2024
9be0783
Removing commented out lines for time changes
nickbianco Jul 29, 2024
d3c56ff
Start adding support for symbolically interpolated controls
nickbianco Aug 2, 2024
f89e50a
Define parameters at all time points
nickbianco Aug 6, 2024
ec111ed
Testing with current control interpolation
nickbianco Aug 6, 2024
0d3946c
Treat time variables as parameters
nickbianco Aug 7, 2024
9a5a29d
First basic problem working (!)
nickbianco Aug 7, 2024
f47d6bf
Remove unneeded code for time and parameter constraints
nickbianco Aug 7, 2024
c5041ab
Provide interface for variable ordering in transcription schemes
nickbianco Aug 9, 2024
e468126
Add time and parameter defects to all transcription schemes
nickbianco Aug 9, 2024
af3dd35
Fix variable ordering for trapezoidal rule
nickbianco Aug 9, 2024
f47938f
Clean up parameter repmatting
nickbianco Aug 9, 2024
b84b58e
Start implementing symbolic control interpolation
nickbianco Aug 12, 2024
d073e49
Problem solving with interpolated controls!
nickbianco Aug 12, 2024
f7650cf
Problem is working with controls (!)
nickbianco Aug 14, 2024
c05a28e
Apply unscaleVariables and calcInterpolatingControls to callback func…
nickbianco Aug 14, 2024
5b6105d
Some cleanup and helpful comments
nickbianco Aug 15, 2024
edb4919
Fix mesh interval calculation
nickbianco Aug 15, 2024
4fd291b
Fixing sparsity for CasOCLegendreGaussRadau
nickbianco Aug 15, 2024
7b4190e
Actually fix sparsity for LegendreGaussRadau
nickbianco Aug 16, 2024
f9d4071
Start adding support for endpoint constraints in FATROP
nickbianco Aug 19, 2024
9a52a22
Merge branch 'main' into moco_fatrop_with_bordalba
nickbianco Aug 26, 2024
a9616f4
Resolve build errors
nickbianco Aug 26, 2024
5329b2d
Still working on support for endpoint constraints in FATROP
nickbianco Aug 29, 2024
b9601a6
Making solving kinematic constraints compatible with FATROP
nickbianco Sep 6, 2024
e02eb3c
Add helper to CasOCTranscription for packing states and state derivat…
nickbianco Sep 9, 2024
9084ddd
Add FATROP support for problems with kinematic constraints; refactor …
nickbianco Sep 11, 2024
232f48a
Merge branch 'main' into moco_fatrop
nickbianco Sep 11, 2024
8f74b2a
Revert exampleSlidingMass
nickbianco Sep 11, 2024
337d2ff
Remove control interpolation and midpoint path constraint options in …
nickbianco Sep 11, 2024
a940c2c
Fixing more tests
nickbianco Sep 12, 2024
b67ee60
Fixes for testMocoGoals, testMocoActuators, and testMocoImplicit
nickbianco Sep 12, 2024
d3d86d4
Use initial and final indices for endpoint function calls in CasOCTra…
nickbianco Sep 12, 2024
66411e1
Fix last set of failing tests
nickbianco Sep 13, 2024
dae3a81
Add CMake build flag for FATROP
nickbianco Sep 13, 2024
151fed0
Silence stdext::checked_array_iterator warnings
nickbianco Sep 13, 2024
d860f87
Remove control interpolation option from MocoCasADiSolver
nickbianco Sep 13, 2024
8526ebb
Add FATROP tests
nickbianco Sep 17, 2024
93d0060
Merge branch 'silence_checked_array_iterator_warning' into moco_fatrop
nickbianco Sep 17, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion OpenSim/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@ add_subdirectory(Moco)
add_subdirectory(Examples)
add_subdirectory(Tests)

#add_subdirectory(Sandbox)
add_subdirectory(Sandbox)

install(FILES OpenSim.h DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/OpenSim")
176 changes: 98 additions & 78 deletions OpenSim/Moco/MocoCasADiSolver/CasOCFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,6 @@ casadi::Sparsity Function::get_jac_sparsity(casadi_int oind, casadi_int iind,
// Split input into separate DMs.
std::vector<casadi::DM> in(this->n_in());
{
int offset = 0;
for (int iin = 0; iin < this->n_in(); ++iin) {
OPENSIM_THROW_IF(this->size2_in(iin) != 1, OpenSim::Exception,
"Internal error.");
Expand All @@ -92,7 +91,6 @@ casadi::Sparsity Function::get_jac_sparsity(casadi_int oind, casadi_int iind,
} else {
in[iin] = casadi::DM::zeros(size, 1);
}
offset += size;
}
}

Expand Down Expand Up @@ -197,7 +195,7 @@ casadi::DM Endpoint::getSubsetPoint(const VariablesDM& fullPoint,
casadi_int i) const {
using casadi::Slice;
if (i == 0) {
return fullPoint.at(initial_time);
return fullPoint.at(initial_time)(0);
} else if (i == 1) {
return fullPoint.at(states)(Slice(), 0);
} else if (i == 2) {
Expand All @@ -207,7 +205,7 @@ casadi::DM Endpoint::getSubsetPoint(const VariablesDM& fullPoint,
} else if (i == 4) {
return fullPoint.at(derivatives)(Slice(), 0);
} else if (i == 5) {
return fullPoint.at(final_time);
return fullPoint.at(final_time)(-1);
} else if (i == 6) {
return fullPoint.at(states)(Slice(), -1);
} else if (i == 7) {
Expand All @@ -217,7 +215,7 @@ casadi::DM Endpoint::getSubsetPoint(const VariablesDM& fullPoint,
} else if (i == 9) {
return fullPoint.at(derivatives)(Slice(), -1);
} else if (i == 10) {
return fullPoint.at(parameters);
return fullPoint.at(parameters)(Slice(), -1);
} else if (i == 11) {
// TODO: We should find a way to actually compute the integral
// from fullPoint. Or, make the integral an optimization variable.
Expand All @@ -243,8 +241,7 @@ VectorDM EndpointConstraint::eval(const VectorDM& args) const {
return out;
}

template <bool calcKCErr>
casadi::Sparsity MultibodySystemExplicit<calcKCErr>::get_sparsity_out(
casadi::Sparsity MultibodySystemExplicit::get_sparsity_out(
casadi_int i) {
if (i == 0) {
return casadi::Sparsity::dense(
Expand All @@ -256,19 +253,13 @@ casadi::Sparsity MultibodySystemExplicit<calcKCErr>::get_sparsity_out(
return casadi::Sparsity::dense(
m_casProblem->getNumAuxiliaryResidualEquations(), 1);
} else if (i == 3) {
if (calcKCErr) {
return casadi::Sparsity::dense(
m_casProblem->getNumKinematicConstraintEquations(), 1);
} else {
return casadi::Sparsity(0, 0);
}
return casadi::Sparsity::dense(m_casProblem->getNumUDotErr(), 1);
} else {
return casadi::Sparsity(0, 0);
}
}

template <bool calcKCErr>
VectorDM MultibodySystemExplicit<calcKCErr>::eval(const VectorDM& args) const {
VectorDM MultibodySystemExplicit::eval(const VectorDM& args) const {
Problem::ContinuousInput input{args.at(0).scalar(), args.at(1), args.at(2),
args.at(3), args.at(4), args.at(5)};
VectorDM out((int)n_out());
Expand All @@ -277,19 +268,90 @@ VectorDM MultibodySystemExplicit<calcKCErr>::eval(const VectorDM& args) const {
}
Problem::MultibodySystemExplicitOutput output{out[0], out[1], out[2],
out[3]};
m_casProblem->calcMultibodySystemExplicit(input, calcKCErr, output);
m_casProblem->calcMultibodySystemExplicit(input, output);
return out;
}

template class CasOC::MultibodySystemExplicit<false>;
template class CasOC::MultibodySystemExplicit<true>;
casadi::Sparsity MultibodySystemImplicit::get_sparsity_out(casadi_int i) {
if (i == 0) {
return casadi::Sparsity::dense(
m_casProblem->getNumMultibodyDynamicsEquations(), 1);
} else if (i == 1) {
return casadi::Sparsity::dense(
m_casProblem->getNumAuxiliaryStates(), 1);
} else if (i == 2) {
return casadi::Sparsity::dense(
m_casProblem->getNumAuxiliaryResidualEquations(), 1);
} else if (i == 3) {
return casadi::Sparsity::dense(m_casProblem->getNumUDotErr(), 1);
} else {
return casadi::Sparsity(0, 0);
}
}

VectorDM MultibodySystemImplicit::eval(const VectorDM& args) const {
Problem::ContinuousInput input{args.at(0).scalar(), args.at(1), args.at(2),
args.at(3), args.at(4), args.at(5)};
VectorDM out((int)n_out());
for (casadi_int i = 0; i < n_out(); ++i) {
out[i] = casadi::DM(sparsity_out(i));
}

Problem::MultibodySystemImplicitOutput output{out[0], out[1], out[2],
out[3]};
m_casProblem->calcMultibodySystemImplicit(input, output);
return out;
}

casadi::Sparsity VelocityCorrection::get_sparsity_in(casadi_int i) {
casadi::Sparsity KinematicConstraints::get_sparsity_in(casadi_int i) {
if (i == 0) {
return casadi::Sparsity::dense(1, 1);
} else if (i == 1) {
return casadi::Sparsity::dense(m_casProblem->getNumMultibodyStates(), 1);
} else if (i == 2) {
return casadi::Sparsity::dense(m_casProblem->getNumParameters(), 1);
} else {
return casadi::Sparsity(0, 0);
}
}

casadi::Sparsity KinematicConstraints::get_sparsity_out(casadi_int i) {
if (i == 0) {
return casadi::Sparsity::dense(
m_casProblem->getNumMultibodyStates(), 1);
m_casProblem->getNumQErr() + m_casProblem->getNumUErr(), 1);
} else {
return casadi::Sparsity(0, 0);
}
}

VectorDM KinematicConstraints::eval(const VectorDM& args) const {
VectorDM out{casadi::DM(sparsity_out(0))};
m_casProblem->calcKinematicConstraintErrors(
args.at(0).scalar(), args.at(1), args.at(2), out[0]);
return out;
}

casadi::DM KinematicConstraints::getSubsetPoint(
const VariablesDM& fullPoint, casadi_int i) const {
int itime = 0;
using casadi::Slice;
const int NMBS = m_casProblem->getNumMultibodyStates();
if (i == 0) {
return fullPoint.at(initial_time)(itime);
} else if (i == 1) {
return fullPoint.at(states)(Slice(0, NMBS), itime);
} else if (i == 3) {
return fullPoint.at(parameters)(Slice(), itime);
} else {
return casadi::DM();
}
}

casadi::Sparsity VelocityCorrection::get_sparsity_in(casadi_int i) {
if (i == 0) {
return casadi::Sparsity::dense(1, 1);
} else if (i == 1) {
return casadi::Sparsity::dense(m_casProblem->getNumMultibodyStates(), 1);
} else if (i == 2) {
return casadi::Sparsity::dense(m_casProblem->getNumSlacks(), 1);
} else if (i == 3) {
Expand All @@ -307,31 +369,31 @@ casadi::Sparsity VelocityCorrection::get_sparsity_out(casadi_int i) {
}
}

VectorDM VelocityCorrection::eval(const VectorDM& args) const {
VectorDM out{casadi::DM(sparsity_out(0))};
m_casProblem->calcVelocityCorrection(
args.at(0).scalar(), args.at(1), args.at(2), args.at(3), out[0]);
return out;
}

casadi::DM VelocityCorrection::getSubsetPoint(
const VariablesDM& fullPoint, casadi_int i) const {
int itime = 0;
using casadi::Slice;
const int NMBS = m_casProblem->getNumMultibodyStates();
if (i == 0) {
return fullPoint.at(initial_time);
return fullPoint.at(initial_time)(itime);
} else if (i == 1) {
return fullPoint.at(states)(Slice(0, NMBS), itime);
} else if (i == 2) {
return fullPoint.at(slacks)(Slice(), itime);
} else if (i == 3) {
return fullPoint.at(parameters);
return fullPoint.at(parameters)(Slice(), itime);
} else {
return casadi::DM();
}
}

VectorDM VelocityCorrection::eval(const VectorDM& args) const {
VectorDM out{casadi::DM(sparsity_out(0))};
m_casProblem->calcVelocityCorrection(
args.at(0).scalar(), args.at(1), args.at(2), args.at(3), out[0]);
return out;
}

casadi::Sparsity StateProjection::get_sparsity_in(casadi_int i) {
if (i == 0) {
return casadi::Sparsity::dense(1, 1);
Expand All @@ -356,6 +418,13 @@ casadi::Sparsity StateProjection::get_sparsity_out(casadi_int i) {
}
}

VectorDM StateProjection::eval(const VectorDM& args) const {
VectorDM out{casadi::DM(sparsity_out(0))};
m_casProblem->calcStateProjection(
args.at(0).scalar(), args.at(1), args.at(2), args.at(3), out[0]);
return out;
}

casadi::DM StateProjection::getSubsetPoint(
const VariablesDM& fullPoint, casadi_int i) const {
int itime = 0;
Expand All @@ -373,52 +442,3 @@ casadi::DM StateProjection::getSubsetPoint(
return casadi::DM();
}
}

VectorDM StateProjection::eval(const VectorDM& args) const {
VectorDM out{casadi::DM(sparsity_out(0))};
m_casProblem->calcStateProjection(
args.at(0).scalar(), args.at(1), args.at(2), args.at(3), out[0]);
return out;
}

template <bool calcKCErr>
casadi::Sparsity MultibodySystemImplicit<calcKCErr>::get_sparsity_out(
casadi_int i) {
if (i == 0) {
return casadi::Sparsity::dense(
m_casProblem->getNumMultibodyDynamicsEquations(), 1);
} else if (i == 1) {
return casadi::Sparsity::dense(
m_casProblem->getNumAuxiliaryStates(), 1);
} else if (i == 2) {
return casadi::Sparsity::dense(
m_casProblem->getNumAuxiliaryResidualEquations(), 1);
} else if (i == 3) {
if (calcKCErr) {
return casadi::Sparsity::dense(
m_casProblem->getNumKinematicConstraintEquations(), 1);
} else {
return casadi::Sparsity(0, 0);
}
} else {
return casadi::Sparsity(0, 0);
}
}

template <bool calcKCErr>
VectorDM MultibodySystemImplicit<calcKCErr>::eval(const VectorDM& args) const {
Problem::ContinuousInput input{args.at(0).scalar(), args.at(1), args.at(2),
args.at(3), args.at(4), args.at(5)};
VectorDM out((int)n_out());
for (casadi_int i = 0; i < n_out(); ++i) {
out[i] = casadi::DM(sparsity_out(i));
}

Problem::MultibodySystemImplicitOutput output{out[0], out[1], out[2],
out[3]};
m_casProblem->calcMultibodySystemImplicit(input, calcKCErr, output);
return out;
}

template class CasOC::MultibodySystemImplicit<false>;
template class CasOC::MultibodySystemImplicit<true>;
Loading
Loading