Skip to content

Commit

Permalink
Support Swig 4.0 (#2976)
Browse files Browse the repository at this point in the history
* Fix Doxygen errors, turn on Doxygen translation and up version of swig to 4.0.1

* Restore std_map.i

* Update appveyor.yml

Try swig 4.0.0 if available on chocolatey

* Move inner typedef of C3DFileAdapter::Tables outside class, and fix comments

* Remove template StdMapStringTimeSeriesTableVec3 as unusable for now and swig-out call-site

* Update continuous_integration.yml

use 4.0.2 for ci

* Add function templates to Model class to maintain backwards compatibility and account for changes in swig handling of function templates scoping

* Include doxygen in python module, tests run with python 3.9 but with some failures

* Fix interface entry for shared_ptr of TimeSeriesTableVec3, restore internal typedef

* Update CMakeLists.txt

Use 4.0.0 so as not to force bleeding edge swig

* Update CMakeLists.txt

Remove stale comment referring to swig 3.0.9

* Update continuous_integration.yml

Update SWIG acquisition script

* Update continuous_integration.yml

workaround caching swig

* Update continuous_integration.yml

try get source for swig on linux

* Update continuous_integration.yml

swig location on linux

* Update continuous_integration.yml

SWIG_DIR on linux

* Update continuous_integration.yml

swig4.0 on linux

* Force python 3.7 in ci on windows, osx

* Update continuous_integration.yml

fix syntax
  • Loading branch information
aymanhab authored Apr 12, 2021
1 parent a2d3446 commit d9cf2a7
Show file tree
Hide file tree
Showing 14 changed files with 107 additions and 72 deletions.
29 changes: 22 additions & 7 deletions .github/workflows/continuous_integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,16 @@ jobs:
echo "$env:GITHUB_WORKSPACE\\doxygen" >> $GITHUB_PATH
- name: Install Python packages
# Need numpy to use SWIG numpy typemaps.
uses: actions/setup-python@v2
with:
python-version: '3.7'

- name: Install numpy
#Need numpy to use SWIG numpy typemaps.
run: python -m pip install numpy

- name: Install SWIG
run: choco install swig --version 3.0.12 --yes --limit-output
run: choco install swig --version 4.0.0 --yes --limit-output

- name: Cache dependencies
id: cache-dependencies
Expand Down Expand Up @@ -157,7 +162,7 @@ jobs:
- name: Install Homebrew packages
# Save the gfortran version to a file so we can use it in the cache key.
run: |
brew install cmake pkgconfig autoconf libtool automake wget pcre doxygen
brew install cmake pkgconfig autoconf libtool automake wget pcre doxygen [email protected]
brew reinstall gcc
pip3 install numpy
gfortran -v
Expand All @@ -172,11 +177,11 @@ jobs:
key: ${{ runner.os }}-swig

- name: Install SWIG
if: steps.cache-swig.outputs.cache-hit != 'true'
# if: steps.cache-swig.outputs.cache-hit != 'true'
run: |
mkdir ~/swig-source && cd ~/swig-source
wget https://github.com/swig/swig/archive/rel-3.0.12.tar.gz
tar xzf rel-3.0.12.tar.gz && cd swig-rel-3.0.12
wget https://github.com/swig/swig/archive/refs/tags/rel-4.0.2.tar.gz
tar xzf rel-4.0.2.tar.gz && cd swig-rel-4.0.2
sh autogen.sh && ./configure --prefix=$HOME/swig --disable-ccache
make && make -j4 install
Expand Down Expand Up @@ -300,8 +305,16 @@ jobs:
- uses: actions/checkout@v1

- name: Install packages
run: sudo apt-get update && sudo apt-get install --yes build-essential libtool autoconf pkg-config gfortran libopenblas-dev liblapack-dev freeglut3-dev libxi-dev libxmu-dev doxygen python3 python3-dev python3-numpy python3-setuptools swig
run: sudo apt-get update && sudo apt-get install --yes build-essential libtool autoconf pkg-config gfortran libopenblas-dev liblapack-dev freeglut3-dev libxi-dev libxmu-dev doxygen python3 python3-dev python3-numpy python3-setuptools

- name: Install SWIG
# if: steps.cache-swig.outputs.cache-hit != 'true'
run: |
mkdir ~/swig-source && cd ~/swig-source
wget https://github.com/swig/swig/archive/refs/tags/rel-4.0.2.tar.gz
tar xzf rel-4.0.2.tar.gz && cd swig-rel-4.0.2
sh autogen.sh && ./configure --prefix=$HOME/swig --disable-ccache
make && make -j4 install
- name: Cache dependencies
id: cache-dependencies
uses: actions/cache@v1
Expand Down Expand Up @@ -333,6 +346,8 @@ jobs:
OSIM_CMAKE_ARGS+=(-DOPENSIM_DEPENDENCIES_DIR=~/opensim_dependencies_install)
OSIM_CMAKE_ARGS+=(-DOPENSIM_C3D_PARSER=ezc3d)
OSIM_CMAKE_ARGS+=(-DBUILD_PYTHON_WRAPPING=on -DBUILD_JAVA_WRAPPING=on)
OSIM_CMAKE_ARGS+=(-DSWIG_DIR=~/swig/share/swig)
OSIM_CMAKE_ARGS+=(-DSWIG_EXECUTABLE=~/swig/bin/swig)
OSIM_CMAKE_ARGS+=(-DOPENSIM_INSTALL_UNIX_FHS=OFF)
OSIM_CMAKE_ARGS+=(-DOPENSIM_DOXYGEN_USE_MATHJAX=off)
# TODO: Update to simbody.github.io/latest
Expand Down
8 changes: 1 addition & 7 deletions Bindings/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,11 +1,5 @@
if(BUILD_PYTHON_WRAPPING OR BUILD_JAVA_WRAPPING)
# We require 3.0.8 for the reason mentioned here (for Python 3):
# https://github.com/tensorflow/tensorflow/issues/830
find_package(SWIG 3.0.8 REQUIRED)
if(NOT (SWIG_VERSION VERSION_LESS "4.0.0") AND BUILD_JAVA_WRAPPING)
message(FATAL_ERROR
"SWIG version 4.0.0 and greater not yet supported for Java bindings.")
endif()
find_package(SWIG 4.0.0 REQUIRED)
endif()

# Flags are both Python and Java bindings will use.
Expand Down
2 changes: 1 addition & 1 deletion Bindings/Java/OpenSimJNI/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ set_directory_properties(PROPERTIES COMPILE_OPTIONS "")
function(OpenSimGenerateJavaWrapper
NAME INPUT_INTERFACE_FILE OUTPUT_CXX_FILE OUTPUT_H_FILE)

set(_swig_common_args -c++ -java
set(_swig_common_args -c++ -java -doxygen
-package ${OPENSIM_JAVA_WRAPPING_PACKAGE}
-I${OpenSim_SOURCE_DIR}
-I${OpenSim_SOURCE_DIR}/Bindings
Expand Down
3 changes: 2 additions & 1 deletion Bindings/Python/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ macro(OpenSimAddPythonModule)
# We run swig once to get dependencies and then again to actually generate
# the wrappers. This variable holds the parts of the swig command that
# are shared between both invocations.
set(_swig_common_args -c++ -python
set(_swig_common_args -c++ -python -doxygen
-I${OpenSim_SOURCE_DIR}
-I${OpenSim_SOURCE_DIR}/Bindings/
-I${Simbody_INCLUDE_DIR}
Expand All @@ -95,6 +95,7 @@ macro(OpenSimAddPythonModule)
#-debug-tmused # Which typemaps were used?
-v # verbose
-o ${_output_cxx_file}
-doxygen
-outdir "${CMAKE_CURRENT_BINARY_DIR}"
${_swig_common_args}
DEPENDS ${_${OSIMSWIGPY_MODULE}_dependencies}
Expand Down
24 changes: 12 additions & 12 deletions Bindings/SWIGSimTK/Rotation.h
Original file line number Diff line number Diff line change
Expand Up @@ -518,10 +518,10 @@ class Rotation_ : public Mat<3, 3, P> {
/// Theory: calculate qdot=N_P(q)*w_PB using multiplyByBodyXYZ_N_P().
/// @see multiplyByBodyXYZ_N_P()
static Vec3 convertAngVelInParentToBodyXYZDot
(const Vec2& cosxy, ///< cos(qx), cos(qy)
const Vec2& sinxy, ///< sin(qx), sin(qy)
P oocosy, ///< 1/cos(qy)
const Vec3& w_PB) ///< angular velocity of B in P, exp. in P
(const Vec2& cosxy, //< cos(qx), cos(qy)
const Vec2& sinxy, //< sin(qx), sin(qy)
P oocosy, //< 1/cos(qy)
const Vec3& w_PB) //< angular velocity of B in P, exp. in P
{
return multiplyByBodyXYZ_N_P(cosxy,sinxy,oocosy,w_PB);
}
Expand All @@ -538,11 +538,11 @@ class Rotation_ : public Mat<3, 3, P> {
/// efficiently. The second term is just an acceleration remainder term
/// quadratic in qdot.
static Vec3 convertAngAccInParentToBodyXYZDotDot
(const Vec2& cosxy, ///< cos(qx), cos(qy)
const Vec2& sinxy, ///< sin(qx), sin(qy)
P oocosy, ///< 1/cos(qy)
const Vec3& qdot, ///< previously calculated BodyXYZDot
const Vec3& b_PB) ///< angular acceleration, a.k.a. wdot_PB
(const Vec2& cosxy, //< cos(qx), cos(qy)
const Vec2& sinxy, //< sin(qx), sin(qy)
P oocosy, //< 1/cos(qy)
const Vec3& qdot, //< previously calculated BodyXYZDot
const Vec3& b_PB) //< angular acceleration, a.k.a. wdot_PB
{
const P s1 = sinxy[1], c1 = cosxy[1];
const P q0 = qdot[0], q1 = qdot[1], q2 = qdot[2];
Expand Down Expand Up @@ -1088,14 +1088,14 @@ class InverseRotation_ : public Mat<3,3,P>::TransposeType {
#endif
Rotation_<P>& operator~() { return updInvert(); }
//@}

#ifndef SWIG
/// Access individual rows and columns of this InverseRotation; no cost or
/// copying since suitably-cast references to the actual data are returned.
/// There are no writable versions of these methods since changing a single
/// row or column would violate the contract that these are always legitimate
/// rotation matrices.
//@{
#ifndef SWIG

const RowType& row( int i ) const { return reinterpret_cast<const RowType&>(asMat33()[i]); }
const ColType& col( int j ) const { return reinterpret_cast<const ColType&>(asMat33()(j)); }
const ColType& x() const { return col(0); }
Expand All @@ -1111,8 +1111,8 @@ class InverseRotation_ : public Mat<3,3,P>::TransposeType {
//@{
const BaseMat& asMat33() const { return *static_cast<const BaseMat*>(this); }
BaseMat toMat33() const { return asMat33(); }
#endif
//@}
#endif
};

#ifndef SWIG
Expand Down
31 changes: 17 additions & 14 deletions Bindings/common.i
Original file line number Diff line number Diff line change
Expand Up @@ -133,19 +133,19 @@ namespace OpenSim {
%shared_ptr(OpenSim::DataTable_<double, double>);
%shared_ptr(OpenSim::DataTable_<double, SimTK::Vec3>);
%shared_ptr(OpenSim::DataTable_<double, SimTK::UnitVec3>);
%shared_ptr(OpenSim::DataTable_<double, SimTK::Quaternion_<double>>);
%shared_ptr(OpenSim::DataTable_<double, SimTK::Quaternion_<double> >);
%shared_ptr(OpenSim::DataTable_<double, SimTK::Vec6>);
%shared_ptr(OpenSim::DataTable_<double, SimTK::SpatialVec>);
%shared_ptr(OpenSim::DataTable_<double, SimTK::Mat33>);
%shared_ptr(OpenSim::DataTable_<double, SimTK::Rotation_<double>>);
%shared_ptr(OpenSim::DataTable_<double, SimTK::Rotation_<double> >);
%shared_ptr(OpenSim::TimeSeriesTable_<double>);
%shared_ptr(OpenSim::TimeSeriesTable_<SimTK::Vec3>);
%shared_ptr(OpenSim::TimeSeriesTable_<SimTK::UnitVec3>);
%shared_ptr(OpenSim::TimeSeriesTable_<SimTK::Quaternion_<double>>);
%shared_ptr(OpenSim::TimeSeriesTable_<SimTK::Quaternion_<double> >);
%shared_ptr(OpenSim::TimeSeriesTable_<SimTK::Vec6>);
%shared_ptr(OpenSim::TimeSeriesTable_<SimTK::SpatialVec>);
%shared_ptr(OpenSim::TimeSeriesTable_<SimTK::Mat33>);
%shared_ptr(OpenSim::TimeSeriesTable_<SimTK::Rotation_<double>>);
%shared_ptr(OpenSim::TimeSeriesTable_<SimTK::Rotation_<double> >);
%ignore OpenSim::AbstractDataTable::clone;
%ignore OpenSim::AbstractDataTable::getTableMetaData;
%ignore OpenSim::AbstractDataTable::updTableMetaData;
Expand All @@ -155,7 +155,7 @@ namespace OpenSim {
%ignore OpenSim::AbstractDataTable::setDependentsMetaData;
%ignore OpenSim::AbstractDataTable::setColumnLabels(
const std::initializer_list<std::string>&);
%template(StdVectorMatrix) std::vector<SimTK::Matrix_<double>>;
%template(StdVectorMatrix) std::vector<SimTK::Matrix_<double> >;
%extend OpenSim::AbstractDataTable {
void setColumnLabels(const std::vector<std::string>& columnLabels) {
$self->setColumnLabels(columnLabels);
Expand Down Expand Up @@ -345,28 +345,27 @@ DATATABLE_CLONE(double, SimTK::Rotation_<double>)
%template(DataTable) OpenSim::DataTable_<double, double>;
%template(DataTableVec3) OpenSim::DataTable_<double, SimTK::Vec3>;
%template(DataTableUnitVec3) OpenSim::DataTable_<double, SimTK::UnitVec3>;
%template(DataTableQuaternion) OpenSim::DataTable_<double, SimTK::Quaternion_<double>>;
%template(DataTableQuaternion) OpenSim::DataTable_<double, SimTK::Quaternion_<double> >;
%template(DataTableVec6) OpenSim::DataTable_<double, SimTK::Vec6>;
%template(DataTableSpatialVec) OpenSim::DataTable_<double, SimTK::SpatialVec>;
%template(DataTableMat33) OpenSim::DataTable_<double, SimTK::Mat33>;
%template(DataTableRotation) OpenSim::DataTable_<double, SimTK::Rotation_<double>>;
%template(DataTableRotation) OpenSim::DataTable_<double, SimTK::Rotation_<double> >;

%template(TimeSeriesTable) OpenSim::TimeSeriesTable_<double>;
%template(TimeSeriesTableVec3) OpenSim::TimeSeriesTable_<SimTK::Vec3>;
%template(TimeSeriesTableUnitVec3) OpenSim::TimeSeriesTable_<SimTK::UnitVec3>;
%template(TimeSeriesTableQuaternion)
OpenSim::TimeSeriesTable_<SimTK::Quaternion_<double>>;
OpenSim::TimeSeriesTable_<SimTK::Quaternion_<double> >;
%template(TimeSeriesTableVec6) OpenSim::TimeSeriesTable_<SimTK::Vec6>;
%template(TimeSeriesTableSpatialVec)
OpenSim::TimeSeriesTable_<SimTK::SpatialVec>;
%template(TimeSeriesTableMat33) OpenSim::TimeSeriesTable_<SimTK::Mat33>;
%template(TimeSeriesTableRotation) OpenSim::TimeSeriesTable_<SimTK::Rotation_<double>>;
%template(TimeSeriesTableRotation) OpenSim::TimeSeriesTable_<SimTK::Rotation_<double> >;

%include <OpenSim/Common/Event.h>
%template(StdVectorEvent) std::vector<OpenSim::Event>;
%template(StdMapStringTimeSeriesTableVec3)
std::map<std::string,
std::shared_ptr<OpenSim::TimeSeriesTable_<SimTK::Vec3>>>;
%shared_ptr(OpenSim::TimeSeriesTableVec3)

%shared_ptr(OpenSim::DataAdapter)
%shared_ptr(OpenSim::FileAdapter)
%shared_ptr(OpenSim::DelimFileAdapter)
Expand All @@ -383,9 +382,13 @@ DATATABLE_CLONE(double, SimTK::Rotation_<double>)
%shared_ptr(OpenSim::TRCFileAdapter)
%shared_ptr(OpenSim::C3DFileAdapter)
%template(StdMapStringDataAdapter)
std::map<std::string, std::shared_ptr<OpenSim::DataAdapter>>;
std::map<std::string, std::shared_ptr<OpenSim::DataAdapter> >;
%template(StdMapStringAbstractDataTable)
std::map<std::string, std::shared_ptr<OpenSim::AbstractDataTable>>;
std::map<std::string, std::shared_ptr<OpenSim::AbstractDataTable> >;
//%template(StdMapStringTimeSeriesTableVec3)
// std::map<std::string, std::shared_ptr<OpenSim::TimeSeriesTable_<SimTK::Vec3> > >;


%include <OpenSim/Common/DataAdapter.h>
%include <OpenSim/Common/ExperimentalSensor.h>
%include <OpenSim/Common/IMUDataReader.h>
Expand Down
56 changes: 36 additions & 20 deletions Bindings/simulation.i
Original file line number Diff line number Diff line change
Expand Up @@ -269,12 +269,42 @@ OpenSim::ModelComponentSet<OpenSim::Controller>;
%template(ActuatorList) OpenSim::ComponentList<const OpenSim::Actuator>;
%template(ActuatorIterator) OpenSim::ComponentListIterator<const OpenSim::Actuator>;

%template(getFrameList) OpenSim::Model::getComponentList<OpenSim::Frame>;
%template(getBodyList) OpenSim::Model::getComponentList<OpenSim::Body>;
%template(getMuscleList) OpenSim::Model::getComponentList<OpenSim::Muscle>;
%template(getModelComponentList) OpenSim::Model::getComponentList<OpenSim::ModelComponent>;
%template(getJointList) OpenSim::Model::getComponentList<OpenSim::Joint>;
%template(getActuatorList) OpenSim::Model::getComponentList<OpenSim::Actuator>;
%template(Thelen2003MuscleList)
OpenSim::ComponentList<const OpenSim::Thelen2003Muscle>;
%template(Thelen2003MuscleIterator)
OpenSim::ComponentListIterator<const OpenSim::Thelen2003Muscle>;

%template(Millard2012EquilibriumMuscleList)
OpenSim::ComponentList<const OpenSim::Millard2012EquilibriumMuscle>;
%template(Millard2012EquilibriumMuscleIterator)
OpenSim::ComponentListIterator<const OpenSim::Millard2012EquilibriumMuscle>;

%extend OpenSim::Model {
OpenSim::ComponentList<const OpenSim::Frame> getFrameList(){
return $self->getComponentList<OpenSim::Frame>();
}
OpenSim::ComponentList<const OpenSim::Body> getBodyList(){
return $self->getComponentList<OpenSim::Body>();
}
OpenSim::ComponentList<const OpenSim::Muscle> getMuscleList(){
return $self->getComponentList<OpenSim::Muscle>();
}
OpenSim::ComponentList<const OpenSim::Joint> getJointList(){
return $self->getComponentList<OpenSim::Joint>();
}
OpenSim::ComponentList<const OpenSim::Actuator> getActuatorList(){
return $self->getComponentList<OpenSim::Actuator>();
}
OpenSim::ComponentList<const OpenSim::ModelComponent> getModelComponentList(){
return $self->getComponentList<OpenSim::ModelComponent>();
}
OpenSim::ComponentList<const OpenSim::Thelen2003Muscle> getThelen2003MuscleList(){
return $self->getComponentList<OpenSim::Thelen2003Muscle>();
}
OpenSim::ComponentList<const OpenSim::Millard2012EquilibriumMuscle> getMillard2012EquilibriumMuscleList(){
return $self->getComponentList<OpenSim::Millard2012EquilibriumMuscle>();
}
}

%include <OpenSim/Actuators/osimActuatorsDLL.h>
%include <OpenSim/Actuators/ActiveForceLengthCurve.h>
Expand All @@ -289,20 +319,6 @@ OpenSim::ModelComponentSet<OpenSim::Controller>;
%include <OpenSim/Actuators/Thelen2003Muscle.h>
%include <OpenSim/Actuators/Millard2012EquilibriumMuscle.h>

%template(Thelen2003MuscleList)
OpenSim::ComponentList<const OpenSim::Thelen2003Muscle>;
%template(Thelen2003MuscleIterator)
OpenSim::ComponentListIterator<const OpenSim::Thelen2003Muscle>;

%template(Millard2012EquilibriumMuscleList)
OpenSim::ComponentList<const OpenSim::Millard2012EquilibriumMuscle>;
%template(Millard2012EquilibriumMuscleIterator)
OpenSim::ComponentListIterator<const OpenSim::Millard2012EquilibriumMuscle>;

%template(getThelen2003MuscleList)
OpenSim::Model::getComponentList<OpenSim::Thelen2003Muscle>;
%template(getMillard2012EquilibriumMuscleList)
OpenSim::Model::getComponentList<OpenSim::Millard2012EquilibriumMuscle>;

// Compensate for insufficient C++11 support in SWIG
// =================================================
Expand Down
2 changes: 0 additions & 2 deletions OpenSim/Actuators/ModelFactory.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
* -------------------------------------------------------------------------- */

#include "osimActuatorsDLL.h"

#include <OpenSim/Simulation/Model/Model.h>

namespace OpenSim {
Expand Down Expand Up @@ -91,7 +90,6 @@ class OSIMACTUATORS_API ModelFactory {
double bound = SimTK::NaN,
bool skipCoordinatesWithExistingActuators = true);

/// @}
};

} // namespace OpenSim
Expand Down
4 changes: 2 additions & 2 deletions OpenSim/Common/C3DFileAdapter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,8 @@ C3DFileAdapter::clone() const {
return new C3DFileAdapter{*this};
}

void
C3DFileAdapter::write(const C3DFileAdapter::Tables& tables,
void C3DFileAdapter::write(
const C3DFileAdapter::Tables& tables,
const std::string& fileName) {
OPENSIM_THROW(Exception, "Writing C3D not supported yet.");
}
Expand Down
4 changes: 4 additions & 0 deletions OpenSim/Common/C3DFileAdapter.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,13 +117,17 @@ class OSIMCOMMON_API C3DFileAdapter : public FileAdapter {
return _location;
}

#ifndef SWIG
static
void write(const Tables& markerTable, const std::string& fileName);
#endif

/** Retrieve the TimeSeriesTableVec3 of Markers */
std::shared_ptr<TimeSeriesTableVec3> getMarkersTable(DataAdapter::OutputTables& tables) {
std::shared_ptr<AbstractDataTable>& adt = tables.at("markers");
return std::dynamic_pointer_cast<TimeSeriesTableVec3>(adt);
}

/** Retrieve the TimeSeriesTableVec3 of Forces */
std::shared_ptr<TimeSeriesTableVec3> getForcesTable(DataAdapter::OutputTables& tables) {
std::shared_ptr<AbstractDataTable>& adt = tables.at("forces");
Expand Down
5 changes: 4 additions & 1 deletion OpenSim/Common/Property.h
Original file line number Diff line number Diff line change
Expand Up @@ -577,7 +577,9 @@ class Property : public AbstractProperty {
Property(Property&&) = default;
Property& operator=(const Property&) = default;
Property& operator=(Property&&) = default;
/** @cond **/ // Hide from Doxygen.
#ifndef SWIG
/** @cond **/
// Hide from Doxygen.
// This is the interface that SimpleProperty and ObjectProperty must
// implement.
// Base class verifies that 0 <= index < size(), and for append operations
Expand All @@ -588,6 +590,7 @@ class Property : public AbstractProperty {
virtual int appendValueVirtual(const T& value) = 0;
virtual int adoptAndAppendValueVirtual(T* value) = 0;
/** @endcond **/
#endif
};


Expand Down
4 changes: 2 additions & 2 deletions OpenSim/Moco/MocoStudyFactory.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ class OSIMMOCO_API MocoStudyFactory {
/// LinearTangentFinalSpeed. This function is intended for use in testing.
/// This problem has an analytical solution, and
/// is described in Section 2.4 of Bryson and Ho [1]. Bryson, A. E., Ho,
/// Y.C., Applied Optimal Control, Optimization, Estimation, and Control.
/// New YorkLondonSydneyToronto. John Wiley & Sons. 1975.
/// Y.C., Applied Optimal Control, Optimization, Estimation, and Control.
/// New York London Sydney Toronto. John Wiley & Sons. 1975.
static MocoStudy createLinearTangentSteeringStudy(
double acceleration, double finalTime, double finalHeight);
};
Expand Down
Loading

0 comments on commit d9cf2a7

Please sign in to comment.