Skip to content

Commit

Permalink
Merge branch 'opensim-org:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
alexbeattie42 authored Oct 19, 2024
2 parents cc04703 + edbc2e4 commit b8f5a1f
Show file tree
Hide file tree
Showing 18 changed files with 2,550 additions and 49 deletions.
30 changes: 30 additions & 0 deletions Bindings/Java/tests/TestTables.java
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,36 @@ public static void test_DataTable() {
assert tableFlat.getNumRows() == 3;
assert tableFlat.getNumColumns() == 12;
System.out.println(tableFlat);
table = new DataTable();
labels = new StdVectorString();
labels.add("col0.0"); labels.add("col0.1"); labels.add("col0.2");
labels.add("col0.3"); labels.add("col0.4"); labels.add("col0.5");
labels.add("col0.6"); labels.add("col0.7"); labels.add("col0.8");
labels.add("col1.0"); labels.add("col1.1"); labels.add("col1.2");
labels.add("col1.3"); labels.add("col1.4"); labels.add("col1.5");
labels.add("col1.6"); labels.add("col1.7"); labels.add("col1.8");
table.setColumnLabels(labels);
row = new RowVector(18, 1);
table.appendRow(1, row);
row = new RowVector(18, 2);
table.appendRow(2, row);
row = new RowVector(18, 3);
table.appendRow(3, row);
assert table.getColumnLabels().size() == 18;
assert table.getNumRows() == 3;
assert table.getNumColumns() == 18;
DataTableRotation tableRot = table.packRotation();
assert tableRot.getColumnLabel(0).equals("col0");
assert tableRot.getNumRows() == 3;
assert tableRot.getNumColumns() == 2;
System.out.println(tableRot);
tableFlat = tableRot.flatten();
assert tableFlat.getColumnLabels().size() == 18;
assert tableFlat.getColumnLabel( 0).equals("col0_1");
assert tableFlat.getColumnLabel(15).equals("col1_7");
assert tableFlat.getNumRows() == 3;
assert tableFlat.getNumColumns() == 18;
System.out.println(tableFlat);
}

public static void test_DataTableVec3() {
Expand Down
1 change: 1 addition & 0 deletions Bindings/OpenSimHeaders_simulation.h
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@
#include <OpenSim/Simulation/OpenSense/IMU.h>
#include <OpenSim/Simulation/OpenSense/OpenSenseUtilities.h>

#include <OpenSim/Simulation/StatesDocument.h>
#include <OpenSim/Simulation/StatesTrajectory.h>
#include <OpenSim/Simulation/StatesTrajectoryReporter.h>

Expand Down
50 changes: 42 additions & 8 deletions Bindings/Python/tests/test_DataTable.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ def test_DataTable(self):
row[1] == 200 and
row[2] == 300 and
row[3] == 400)
row0 = table.getRowAtIndex(0)
row0 = table.updRowAtIndex(0)
row0[0] = 10
row0[1] = 10
row0[2] = 10
Expand All @@ -140,7 +140,7 @@ def test_DataTable(self):
row0[1] == 10 and
row0[2] == 10 and
row0[3] == 10)
row2 = table.getRow(0.3)
row2 = table.updRow(0.3)
row2[0] = 20
row2[1] = 20
row2[2] = 20
Expand All @@ -152,15 +152,15 @@ def test_DataTable(self):
row2[3] == 20)
print(table)
# Edit columns of the table.
col1 = table.getDependentColumnAtIndex(1)
col1 = table.updDependentColumnAtIndex(1)
col1[0] = 30
col1[1] = 30
col1[2] = 30
col1 = table.getDependentColumnAtIndex(1)
assert (col1[0] == 30 and
col1[1] == 30 and
col1[2] == 30)
col3 = table.getDependentColumn('3')
col3 = table.updDependentColumn('3')
col3[0] = 40
col3[1] = 40
col3[2] = 40
Expand Down Expand Up @@ -299,6 +299,40 @@ def test_DataTable(self):
assert tableFlat.getNumRows() == 3
assert tableFlat.getNumColumns() == 12
print(tableFlat)
table = osim.DataTable()
table.setColumnLabels(('col0_x', 'col0_y', 'col0_z',
'col1_x', 'col1_y', 'col1_z',
'col2_x', 'col2_y', 'col2_z',
'col3_x', 'col3_y', 'col3_z',
'col4_x', 'col4_y', 'col4_z',
'col5_x', 'col5_y', 'col5_z'))
row = osim.RowVector([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1])
table.appendRow(1, row)
row = osim.RowVector([2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2])
table.appendRow(2, row)
row = osim.RowVector([3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3])
table.appendRow(3, row)
assert len(table.getColumnLabels()) == 18
assert table.getNumRows() == 3
assert table.getNumColumns() == 18
table.setColumnLabels(('col0_0', 'col0_1', 'col0_2',
'col0_3', 'col0_4', 'col0_5',
'col0_6', 'col0_7', 'col0_8',
'col1_0', 'col1_1', 'col1_2',
'col1_3', 'col1_4', 'col1_5',
'col1_6', 'col1_7', 'col1_8'))
tableRot = table.packRotation()
tableRot.getColumnLabels() == ('col0', 'col1')
tableRot.getNumRows() == 3
tableRot.getNumColumns() == 2
print(tableRot)
tableFlat = tableRot.flatten()
assert len(tableFlat.getColumnLabels()) == 18
assert tableFlat.getColumnLabel( 0) == 'col0_1'
assert tableFlat.getColumnLabel(15) == 'col1_7'
assert tableFlat.getNumRows() == 3
assert tableFlat.getNumColumns() == 18
print(tableFlat)

def test_TimeSeriesTable(self):
print()
Expand Down Expand Up @@ -475,15 +509,15 @@ def test_DataTableVec3(self):
print(tableDouble)

# Edit rows of the table.
row0 = table.getRowAtIndex(0)
row0 = table.updRowAtIndex(0)
row0[0] = osim.Vec3(10, 10, 10)
row0[1] = osim.Vec3(10, 10, 10)
row0[2] = osim.Vec3(10, 10, 10)
row0 = table.getRowAtIndex(0)
assert (str(row0[0]) == str(osim.Vec3(10, 10, 10)) and
str(row0[1]) == str(osim.Vec3(10, 10, 10)) and
str(row0[2]) == str(osim.Vec3(10, 10, 10)))
row2 = table.getRow(0.3)
row2 = table.updRow(0.3)
row2[0] = osim.Vec3(20, 20, 20)
row2[1] = osim.Vec3(20, 20, 20)
row2[2] = osim.Vec3(20, 20, 20)
Expand All @@ -493,15 +527,15 @@ def test_DataTableVec3(self):
str(row2[2]) == str(osim.Vec3(20, 20, 20)))
print(table)
# Edit columns of the table.
col1 = table.getDependentColumnAtIndex(1)
col1 = table.updDependentColumnAtIndex(1)
col1[0] = osim.Vec3(30, 30, 30)
col1[1] = osim.Vec3(30, 30, 30)
col1[2] = osim.Vec3(30, 30, 30)
col1 = table.getDependentColumnAtIndex(1)
assert (str(col1[0]) == str(osim.Vec3(30, 30, 30)) and
str(col1[1]) == str(osim.Vec3(30, 30, 30)) and
str(col1[2]) == str(osim.Vec3(30, 30, 30)))
col2 = table.getDependentColumn('2')
col2 = table.updDependentColumn('2')
col2[0] = osim.Vec3(40, 40, 40)
col2[1] = osim.Vec3(40, 40, 40)
col2[2] = osim.Vec3(40, 40, 40)
Expand Down
26 changes: 25 additions & 1 deletion Bindings/common.i
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,14 @@ DATATABLE_CLONE(double, SimTK::Rotation_<double>)
packSpatialVec(std::vector<std::string> suffixes) {
return $self->pack<SimTK::SpatialVec>();
}
DataTable_<double, SimTK::Rotation_<double>>
packRotation() {
return $self->pack<SimTK::Rotation_<double>>();
}
DataTable_<double, SimTK::Rotation_<double>>
packRotation(std::vector<std::string> suffixes) {
return $self->pack<SimTK::Rotation_<double>>();
}
}

%ignore OpenSim::TimeSeriesTable_::TimeSeriesTable_(TimeSeriesTable_ &&);
Expand Down Expand Up @@ -294,6 +302,14 @@ DATATABLE_CLONE(double, SimTK::Rotation_<double>)
packSpatialVec(std::vector<std::string> suffixes) {
return $self->pack<SimTK::SpatialVec>();
}
TimeSeriesTable_<SimTK::Rotation_<double>>
packRotation() {
return $self->pack<SimTK::Rotation_<double>>();
}
TimeSeriesTable_<SimTK::Rotation_<double>>
packRotation(std::vector<std::string> suffixes) {
return $self->pack<SimTK::Rotation_<double>>();
}
}
%extend OpenSim::TimeSeriesTable_<SimTK::Vec3> {
TimeSeriesTable_<double> flatten() {
Expand Down Expand Up @@ -335,6 +351,14 @@ DATATABLE_CLONE(double, SimTK::Rotation_<double>)
return $self->flatten(suffixes);
}
}
%extend OpenSim::TimeSeriesTable_<SimTK::Rotation_<double>> {
TimeSeriesTable_<double> flatten() {
return $self->flatten();
}
TimeSeriesTable_<double> flatten(std::vector<std::string> suffixes) {
return $self->flatten(suffixes);
}
}

%include <OpenSim/Common/AbstractDataTable.h>
%include <OpenSim/Common/DataTable.h>
Expand Down Expand Up @@ -371,7 +395,7 @@ DATATABLE_CLONE(double, SimTK::Rotation_<double>)
%shared_ptr(OpenSim::IMUDataReader)
%shared_ptr(OpenSim::XsensDataReader)
%shared_ptr(OpenSim::APDMDataReader)
%shared_ptr(OpenSim::STOFileAdapter_<duoble>)
%shared_ptr(OpenSim::STOFileAdapter_<double>)
%shared_ptr(OpenSim::STOFileAdapter_<SimTK::Vec3>)
%shared_ptr(OpenSim::STOFileAdapter_<SimTK::UnitVec3>)
%shared_ptr(OpenSim::STOFileAdapter_<SimTK::Quaternion>)
Expand Down
5 changes: 5 additions & 0 deletions Bindings/moco.i
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,10 @@ namespace OpenSim {
%include <OpenSim/Moco/MocoTropterSolver.h>
%include <OpenSim/Moco/MocoCasADiSolver/MocoCasADiSolver.h>
%include <OpenSim/Moco/MocoStudy.h>
%template(analyzeVec3) OpenSim::MocoStudy::analyze<SimTK::Vec3>;
%template(analyzeSpatialVec) OpenSim::MocoStudy::analyze<SimTK::SpatialVec>;
%template(analyzeRotation) OpenSim::MocoStudy::analyze<SimTK::Rotation_<double>>;

%include <OpenSim/Moco/MocoStudyFactory.h>

%include <OpenSim/Moco/MocoTool.h>
Expand All @@ -148,5 +152,6 @@ namespace OpenSim {
%template(analyzeMocoTrajectory) OpenSim::analyzeMocoTrajectory<double>;
%template(analyzeMocoTrajectoryVec3) OpenSim::analyzeMocoTrajectory<SimTK::Vec3>;
%template(analyzeMocoTrajectorySpatialVec) OpenSim::analyzeMocoTrajectory<SimTK::SpatialVec>;
%template(analyzeMocoTrajectoryRotation) OpenSim::analyzeMocoTrajectory<SimTK::Rotation_<double>>;

%include <OpenSim/Moco/ModelOperatorsDGF.h>
2 changes: 2 additions & 0 deletions Bindings/simulation.i
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,7 @@ OpenSim::ModelComponentSet<OpenSim::Controller>;

%template(StdVectorIMUs) std::vector< OpenSim::IMU* >;

%include <OpenSim/Simulation/StatesDocument.h>
%include <OpenSim/Simulation/StatesTrajectory.h>
// This enables iterating using the getBetween() method.
%template(IteratorRangeStatesTrajectoryIterator)
Expand All @@ -263,6 +264,7 @@ OpenSim::ModelComponentSet<OpenSim::Controller>;
%template(analyze) OpenSim::analyze<double>;
%template(analyzeVec3) OpenSim::analyze<SimTK::Vec3>;
%template(analyzeSpatialVec) OpenSim::analyze<SimTK::SpatialVec>;
%template(analyzeRotation) OpenSim::analyze<SimTK::Rotation_<double>>;

%include <OpenSim/Simulation/VisualizerUtilities.h>

Expand Down
24 changes: 19 additions & 5 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ v4.6
the case where provided string is just the name of the value, rather than a path to it (#3782)
- Fixed bugs in `MocoStepTimeAsymmetryGoal::printDescriptionImpl()` where there were missing or incorrect values printed. (#3842)
- Added `ModOpPrescribeCoordinateValues` which can prescribe motion of joints in a model given a table of data. (#3862)
- Fixed bugs in `convertToMocoTrajectory()` and `MocoTrajectory::resampleWithFrequency()` by updating `interpolate()` to
allow extrapolation using the `extrapolate` flag. Combined with the `ignoreNaNs` flag, this prevents NaNs from
- Fixed bugs in `convertToMocoTrajectory()` and `MocoTrajectory::resampleWithFrequency()` by updating `interpolate()` to
allow extrapolation using the `extrapolate` flag. Combined with the `ignoreNaNs` flag, this prevents NaNs from
occurring in the output. (#3867)
- Added `Output`s to `ExpressionBasedCoordinateForce`, `ExpressionBasedPointToPointForce`, and `ExpressionBasedBushingForce` for accessing force values. (#3872)
- `PointForceDirection` no longer has a virtual destructor, is `final`, and its `scale` functionality
Expand All @@ -23,12 +23,24 @@ v4.6
components. The `ForceProducer` API was also rolled out to a variety of existing `Force` components, which
means that API users can now now ask many `Force` components what forces they produce (see #3891 for a
comprehensive overview).
- Made improvements to `MocoUtilities::createExternalLoadsTableForGait()`: center of pressure values are now set to zero, rather
than NaN, when vertical force is zero, and the vertical torque is returned in the torque columns (rather than the sum of the
- Made improvements to `MocoUtilities::createExternalLoadsTableForGait()`: center of pressure values are now set to zero, rather
than NaN, when vertical force is zero, and the vertical torque is returned in the torque columns (rather than the sum of the
sphere torques) to be consistent with the center of pressure GRF representation.
- Fixed an issue where a copy of an `OpenSim::Model` containing a `OpenSim::ExternalLoads` could not be
finalized (#3926)
- Updated all code examples to use c++14 (#3929)
- Updated all code examples to use c++14 (#3929)
- Added class `OpenSim::StateDocument` as a systematic means of serializing and deserializing a complete trajectory
(i.e., time history) of all states in the `SimTK::State` to and from a single `.ostates` file. Prior to `StatesDocument`,
only the trajectories of continuous states (e.g., joint angles, joint speeds, muscle forces, and the like) could be systematically
written to file, either in the form of a `Storage` file or as a `TimeSeriesTable` file, leaving discrete states (e.g., muscle
excitations and contact model anchor points) and modeling options (e.g., joint clamps) unserialized. `StatesDocument`, on the
other hand, serializes all continuous states, discrete states, and modeling options registered with `OpenSim::Component`.
Whereas neither `Storage` files nor `TimeSeriesTable` files are currently able to handle mixed variable types, `StatesDocument`
is able to accommodate variables of type `bool`, `int`, `double`, `Vec2`, `Vec3`, `Vec4`, `Vec5`, and `Vec6` all in the same
`.ostates` file. `.ostate` files are written in `XML` format and internally carry the name of the OpenSim model to which the
states belong, a date/time stamp of when the file was written, and a user-specified note. `.ostate` files also support a
configurable output precision. At the highest ouput precsion (~20 significant figures), serialization/deserialization is
a lossless process. (#3902)

v4.5.1
======
Expand Down Expand Up @@ -93,6 +105,8 @@ pointer to avoid crashes in scripting due to invalid pointer ownership (#3781).
- Fixed `MocoOrientationTrackingGoal::initializeOnModelImpl` to check for missing kinematic states, but allow other missing columns. (#3830)
- Improved exception handling for internal errors in `MocoCasADiSolver`. Problems will now abort and print a descriptive error message (rather than fail due to an empty trajectory). (#3834)
- Upgraded the Ipopt dependency Metis to version 5.1.0 on Unix and macOS to enable building on `osx-arm64` (#3874).
- Added Python and Java (Matlab) scripting support for `TimeSeriesTable_<SimTK::Rotation>`. (#3940)
- Added the templatized `MocoStudy::analyze<T>()` and equivalent scripting counterparts: `analyzeVec3`, `analyzeSpatialVec`, `analyzeRotation`. (#3940)

v4.5
====
Expand Down
6 changes: 4 additions & 2 deletions OpenSim/Common/Test/testComponentInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,7 @@ class Bar : public Component {
// and to access a dv that is not type double.
// The following calls put the mo and dv into the maps used to contain
// all mo's and dv's exposed in OpenSim. When Stage::Topology is
// realized, they will allocated in class Bar's override of
// realized, they will be allocated in class Bar's override of
// extendRealizeTopology(). See below.
bool allocate = false;
int maxFlagValue = 1;
Expand All @@ -401,6 +401,8 @@ class Bar : public Component {
// Manually allocate and update the index and subsystem for
// a discrete variable and a modeling option as though they were
// natively allocated in Simbody and brought into OpenSim.
// Note, as of May 2024, this is also what one would need to do in order
// to add a discrete variable that is a type other than double.
void extendRealizeTopology(SimTK::State& state) const override {
Super::extendRealizeTopology(state);

Expand Down Expand Up @@ -2057,7 +2059,7 @@ TEST_CASE("Component Interface State Trajectories")
}

// Create a new state trajectory (as though deserializing)
// newTraj must be must the expected size before any set calls.
// newTraj must be the expected size before any set calls.
SimTK::Array_<SimTK::State> newTraj;
for (int i = 0; i < nsteps; ++i) newTraj.emplace_back(s);
// state variables
Expand Down
Loading

0 comments on commit b8f5a1f

Please sign in to comment.