Skip to content

Commit d26be79

Browse files
committed
Add build support for Ubuntu 24.04
Summary of changes, some of which are "drive-by" improvements to the CI workflow: - Upgraded Python version to 3.11 (with NumPy 2.0) on CI - Removed "perf" tests on CI - Added Ubuntu 24.04 CI job - Updated Windows CI job to use windows-2025 runner - Updated the Simbody commit and Mat.h and Vec.h under Bindings/SWIGSimTK based on recent Simbody changes. This change is necessary to avoid a warning that newer compilers (e.g., GCC 13) about potential out-of-bounds errors in SimTK::Mat constructors. - Converted references to copies in testOutputReporter.cpp to avoid dangling reference errors from GCC - Changed how data members in WrapResult and PathWrapPoint are initialized to avoid "possibly uninitialized" errors from GCC
1 parent ff9fbac commit d26be79

File tree

10 files changed

+152
-480
lines changed

10 files changed

+152
-480
lines changed

.github/workflows/continuous_integration.yml

Lines changed: 58 additions & 331 deletions
Large diffs are not rendered by default.

Applications/CMC/test/testCMCGait10dof18musc.cpp

Lines changed: 7 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -29,31 +29,7 @@
2929

3030
using namespace OpenSim;
3131

32-
TEST_CASE("testGait10dof18musc (Windows)", "[win]") {
33-
CMCTool cmc("gait10dof18musc_Setup_CMC.xml");
34-
cmc.run();
35-
36-
const TimeSeriesTable results(
37-
"gait10dof18musc_ResultsCMC/walk_subject_states.sto");
38-
const TimeSeriesTable std(
39-
"gait10dof18musc_std_walk_subject_states_win.sto");
40-
41-
// TODO: Replace with macro from OpenSim/Moco/Test/Testing.h
42-
const auto& actual = results.getMatrix();
43-
const auto& expected = std.getMatrix();
44-
REQUIRE((actual.nrow() == expected.nrow()));
45-
REQUIRE((actual.ncol() == expected.ncol()));
46-
for (int ir = 0; ir < actual.nrow(); ++ir) {
47-
for (int ic = 0; ic < actual.ncol(); ++ic) {
48-
INFO("(" << ir << "," << ic << "): " << actual.getElt(ir, ic) <<
49-
" vs " << expected.getElt(ir, ic));
50-
REQUIRE((Catch::Approx(actual.getElt(ir, ic)).margin(1e-3)
51-
== expected.getElt(ir, ic)));
52-
}
53-
}
54-
}
55-
56-
TEST_CASE("testGait10dof18musc (Mac/Linux)", "[unix]") {
32+
TEST_CASE("testGait10dof18musc") {
5733
CMCTool cmc("gait10dof18musc_Setup_CMC.xml");
5834
cmc.run();
5935

@@ -62,12 +38,12 @@ TEST_CASE("testGait10dof18musc (Mac/Linux)", "[unix]") {
6238
const TimeSeriesTable std(
6339
"gait10dof18musc_std_walk_subject_states_unix.sto");
6440

65-
// Unix systems produce inconsistent results compared to Windows. Somehow,
66-
// CMC produces results with differing number of time points, so we need to
67-
// interpolate the results to the same time points as the standard results.
68-
// The shapes of the muscle activity curves also differ slightly, so we
69-
// allow a larger margin of error for the muscle activity curves. Therefore,
70-
// this is a weaker test compared to the Windows test.
41+
// CMC produces results with differing number of time points on different
42+
// systems, so we need to interpolate the results to the same time points as
43+
// the standard results. The shapes of the muscle activity curves also
44+
// differ slightly, so we allow a larger margin of error for the muscle
45+
// activity curves. Therefore, this is a weaker test compared to other
46+
// CMC tests.
7147
GCVSplineSet resultSplines(results);
7248
GCVSplineSet stdSplines(std);
7349

Bindings/SWIGSimTK/Mat.h

Lines changed: 41 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@
3030

3131
#include "SimTKcommon/internal/common.h"
3232

33+
#include <tuple>
34+
#include <type_traits>
35+
3336
namespace SimTK {
3437

3538
/** This class represents a small matrix whose size is known at compile time,
@@ -336,71 +339,36 @@ template <int M, int N, class ELT, int CS, int RS> class Mat {
336339
explicit Mat(int i)
337340
{ new (this) Mat(ELT(Precision(i))); }
338341

339-
// A bevy of constructors from individual exact-match elements IN ROW ORDER.
340-
Mat(const ELT& e0,const ELT& e1)
341-
{assert(M*N==2);d[rIx(0)]=e0;d[rIx(1)]=e1;}
342-
Mat(const ELT& e0,const ELT& e1,const ELT& e2)
343-
{assert(M*N==3);d[rIx(0)]=e0;d[rIx(1)]=e1;d[rIx(2)]=e2;}
344-
Mat(const ELT& e0,const ELT& e1,const ELT& e2,const ELT& e3)
345-
{assert(M*N==4);d[rIx(0)]=e0;d[rIx(1)]=e1;d[rIx(2)]=e2;d[rIx(3)]=e3;}
346-
Mat(const ELT& e0,const ELT& e1,const ELT& e2,const ELT& e3,const ELT& e4)
347-
{assert(M*N==5);d[rIx(0)]=e0;d[rIx(1)]=e1;d[rIx(2)]=e2;d[rIx(3)]=e3;d[rIx(4)]=e4;}
348-
Mat(const ELT& e0,const ELT& e1,const ELT& e2,const ELT& e3,const ELT& e4,
349-
const ELT& e5)
350-
{assert(M*N==6);d[rIx(0)]=e0;d[rIx(1)]=e1;d[rIx(2)]=e2;d[rIx(3)]=e3;d[rIx(4)]=e4;
351-
d[rIx(5)]=e5;}
352-
Mat(const ELT& e0,const ELT& e1,const ELT& e2,const ELT& e3,const ELT& e4,
353-
const ELT& e5,const ELT& e6)
354-
{assert(M*N==7);d[rIx(0)]=e0;d[rIx(1)]=e1;d[rIx(2)]=e2;d[rIx(3)]=e3;d[rIx(4)]=e4;
355-
d[rIx(5)]=e5;d[rIx(6)]=e6;}
356-
Mat(const ELT& e0,const ELT& e1,const ELT& e2,const ELT& e3,const ELT& e4,
357-
const ELT& e5,const ELT& e6,const ELT& e7)
358-
{assert(M*N==8);d[rIx(0)]=e0;d[rIx(1)]=e1;d[rIx(2)]=e2;d[rIx(3)]=e3;d[rIx(4)]=e4;
359-
d[rIx(5)]=e5;d[rIx(6)]=e6;d[rIx(7)]=e7;}
360-
Mat(const ELT& e0,const ELT& e1,const ELT& e2,const ELT& e3,const ELT& e4,
361-
const ELT& e5,const ELT& e6,const ELT& e7,const ELT& e8)
362-
{assert(M*N==9);d[rIx(0)]=e0;d[rIx(1)]=e1;d[rIx(2)]=e2;d[rIx(3)]=e3;d[rIx(4)]=e4;
363-
d[rIx(5)]=e5;d[rIx(6)]=e6;d[rIx(7)]=e7;d[rIx(8)]=e8;}
364-
Mat(const ELT& e0,const ELT& e1,const ELT& e2,const ELT& e3,const ELT& e4,
365-
const ELT& e5,const ELT& e6,const ELT& e7,const ELT& e8,const ELT& e9)
366-
{assert(M*N==10);d[rIx(0)]=e0;d[rIx(1)]=e1;d[rIx(2)]=e2;d[rIx(3)]=e3;d[rIx(4)]=e4;
367-
d[rIx(5)]=e5;d[rIx(6)]=e6;d[rIx(7)]=e7;d[rIx(8)]=e8;d[rIx(9)]=e9;}
368-
Mat(const ELT& e0,const ELT& e1,const ELT& e2,const ELT& e3,const ELT& e4,
369-
const ELT& e5,const ELT& e6,const ELT& e7,const ELT& e8,const ELT& e9,
370-
const ELT& e10)
371-
{assert(M*N==11);d[rIx(0)]=e0;d[rIx(1)]=e1;d[rIx(2)]=e2;d[rIx(3)]=e3;d[rIx(4)]=e4;
372-
d[rIx(5)]=e5;d[rIx(6)]=e6;d[rIx(7)]=e7;d[rIx(8)]=e8;d[rIx(9)]=e9;d[rIx(10)]=e10;}
373-
Mat(const ELT& e0,const ELT& e1,const ELT& e2,const ELT& e3,const ELT& e4,
374-
const ELT& e5,const ELT& e6,const ELT& e7,const ELT& e8,const ELT& e9,
375-
const ELT& e10, const ELT& e11)
376-
{assert(M*N==12);d[rIx(0)]=e0;d[rIx(1)]=e1;d[rIx(2)]=e2;d[rIx(3)]=e3;d[rIx(4)]=e4;
377-
d[rIx(5)]=e5;d[rIx(6)]=e6;d[rIx(7)]=e7;d[rIx(8)]=e8;d[rIx(9)]=e9;d[rIx(10)]=e10;
378-
d[rIx(11)]=e11;}
379-
Mat(const ELT& e0,const ELT& e1,const ELT& e2,const ELT& e3,const ELT& e4,
380-
const ELT& e5,const ELT& e6,const ELT& e7,const ELT& e8,const ELT& e9,
381-
const ELT& e10, const ELT& e11, const ELT& e12)
382-
{assert(M*N==13);d[rIx(0)]=e0;d[rIx(1)]=e1;d[rIx(2)]=e2;d[rIx(3)]=e3;d[rIx(4)]=e4;
383-
d[rIx(5)]=e5;d[rIx(6)]=e6;d[rIx(7)]=e7;d[rIx(8)]=e8;d[rIx(9)]=e9;d[rIx(10)]=e10;
384-
d[rIx(11)]=e11;d[rIx(12)]=e12;}
385-
Mat(const ELT& e0,const ELT& e1,const ELT& e2,const ELT& e3,const ELT& e4,
386-
const ELT& e5,const ELT& e6,const ELT& e7,const ELT& e8,const ELT& e9,
387-
const ELT& e10, const ELT& e11, const ELT& e12, const ELT& e13)
388-
{assert(M*N==14);d[rIx(0)]=e0;d[rIx(1)]=e1;d[rIx(2)]=e2;d[rIx(3)]=e3;d[rIx(4)]=e4;
389-
d[rIx(5)]=e5;d[rIx(6)]=e6;d[rIx(7)]=e7;d[rIx(8)]=e8;d[rIx(9)]=e9;d[rIx(10)]=e10;
390-
d[rIx(11)]=e11;d[rIx(12)]=e12;d[rIx(13)]=e13;}
391-
Mat(const ELT& e0,const ELT& e1,const ELT& e2,const ELT& e3,const ELT& e4,
392-
const ELT& e5,const ELT& e6,const ELT& e7,const ELT& e8,const ELT& e9,
393-
const ELT& e10, const ELT& e11, const ELT& e12, const ELT& e13, const ELT& e14)
394-
{assert(M*N==15);d[rIx(0)]=e0;d[rIx(1)]=e1;d[rIx(2)]=e2;d[rIx(3)]=e3;d[rIx(4)]=e4;
395-
d[rIx(5)]=e5;d[rIx(6)]=e6;d[rIx(7)]=e7;d[rIx(8)]=e8;d[rIx(9)]=e9;d[rIx(10)]=e10;
396-
d[rIx(11)]=e11;d[rIx(12)]=e12;d[rIx(13)]=e13;d[rIx(14)]=e14;}
397-
Mat(const ELT& e0,const ELT& e1,const ELT& e2,const ELT& e3,const ELT& e4,
398-
const ELT& e5,const ELT& e6,const ELT& e7,const ELT& e8,const ELT& e9,
399-
const ELT& e10, const ELT& e11, const ELT& e12, const ELT& e13, const ELT& e14,
400-
const ELT& e15)
401-
{assert(M*N==16);d[rIx(0)]=e0;d[rIx(1)]=e1;d[rIx(2)]=e2;d[rIx(3)]=e3;d[rIx(4)]=e4;
402-
d[rIx(5)]=e5;d[rIx(6)]=e6;d[rIx(7)]=e7;d[rIx(8)]=e8;d[rIx(9)]=e9;d[rIx(10)]=e10;
403-
d[rIx(11)]=e11;d[rIx(12)]=e12;d[rIx(13)]=e13;d[rIx(14)]=e14;d[rIx(15)]=e15;}
342+
#ifndef SWIG
343+
// Constructs a `Mat` from individual exact-match elements IN ROW ORDER.
344+
template<
345+
typename... Elements,
346+
typename = std::enable_if_t<
347+
(M*N==sizeof...(Elements)) &&
348+
(std::is_convertible_v<Elements&&, const E&> && ...)
349+
>
350+
>
351+
Mat(Elements&&... elementsRowByRow)
352+
{
353+
assignDataRowByRow(
354+
std::forward_as_tuple(elementsRowByRow...),
355+
std::make_integer_sequence<int, sizeof...(Elements)>{}
356+
);
357+
}
358+
#else
359+
template <int MM = M, int NN = N,
360+
typename std::enable_if<(MM==3 && NN==3), int>::type = 0>
361+
Mat(const E& e00, const E& e01, const E& e02,
362+
const E& e10, const E& e11, const E& e12,
363+
const E& e20, const E& e21, const E& e22)
364+
{
365+
const E elems[9] = {e00, e01, e02,
366+
e10, e11, e12,
367+
e20, e21, e22};
368+
for (int idx = 0; idx < 9; ++idx)
369+
d[rIx(idx)] = elems[idx];
370+
}
371+
#endif
404372

405373
#ifndef SWIG
406374
// Construction from 1-6 *exact match* Rows
@@ -1199,6 +1167,14 @@ template <int M, int N, class ELT, int CS, int RS> class Mat {
11991167
const int col = k % N; // that's modulus, not cross product!
12001168
return row*RS + col*CS;
12011169
}
1170+
1171+
#ifndef SWIG
1172+
template<typename ElementsRowByRowTuple, int... Idx>
1173+
void assignDataRowByRow(ElementsRowByRowTuple&& els, std::integer_sequence<int, Idx...>)
1174+
{
1175+
((d[rIx(Idx)] = std::get<Idx>(els)) , ...);
1176+
}
1177+
#endif
12021178
};
12031179

12041180
//////////////////////////////////////////////

Bindings/SWIGSimTK/Vec.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ class Vec {
191191
NRows = M,
192192
NCols = 1,
193193
NPackedElements = M,
194-
NActualElements = M * STRIDE, // includes trailing gap
194+
NActualElements = (M-1)*STRIDE + 1, // no trailing gap
195195
NActualScalars = CNT<E>::NActualScalars * NActualElements,
196196
RowSpacing = STRIDE,
197197
ColSpacing = NActualElements,

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ performance and stability in wrapping solutions.
3636
- Added `Component::removeComponent` and `Component::extractComponent` methods, which enable removing subcomponents that were previously added via `Component::addComponent` or the `<components>` XML element (#4174).
3737
- Updated required language level to C++20. (#3929)
3838
- Breaking: removed the `operator==` and `operator<` overloads in `ControlLinearNode` and replaced usages with the equivalent utility functions `isEqual()` and `isLessThan()`. (#4095)
39+
- Made various changes to support builds on Ubuntu 24.04 with GCC 13. (#4186)
3940

4041

4142
v4.5.2

OpenSim/Analyses/Test/testOutputReporter.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -213,9 +213,9 @@ void simulateMuscle(
213213
TimeSeriesTable_<SimTK::SpatialVec> tableSV("testOutputReporter_OutputsSpatialVec.sto");
214214

215215
double val_t0 = tableD.getIndependentColumn()[0];
216-
const SimTK::Real& val_ke0 = tableD.getRowAtIndex(0)[0];
217-
const Vec3& val_omega0 = tableV3.getRowAtIndex(0)[1];
218-
const SimTK::SpatialVec& val_jrf0 = tableSV.getRowAtIndex(0)[1];
216+
const SimTK::Real val_ke0 = tableD.getRowAtIndex(0)[0];
217+
const Vec3 val_omega0 = tableV3.getRowAtIndex(0)[1];
218+
const SimTK::SpatialVec val_jrf0 = tableSV.getRowAtIndex(0)[1];
219219

220220
CHECK_THAT(t0, Catch::Matchers::WithinAbs(val_t0, SimTK::Eps));
221221
CHECK_THAT(ke0, Catch::Matchers::WithinAbs(val_ke0, SimTK::Eps));
@@ -229,9 +229,9 @@ void simulateMuscle(
229229
}
230230

231231
double val_tf = tableD.getIndependentColumn()[tableD.getNumRows() - 1];
232-
const SimTK::Real& val_ke = tableD.getRowAtIndex(tableD.getNumRows() - 1)[0];
233-
const Vec3& val_omega = tableV3.getRowAtIndex(tableV3.getNumRows() - 1)[1];
234-
const SimTK::SpatialVec& val_jrf =
232+
const SimTK::Real val_ke = tableD.getRowAtIndex(tableD.getNumRows() - 1)[0];
233+
const Vec3 val_omega = tableV3.getRowAtIndex(tableV3.getNumRows() - 1)[1];
234+
const SimTK::SpatialVec val_jrf =
235235
tableSV.getRowAtIndex(tableSV.getNumRows() - 1)[1];
236236

237237
model.realizeReport(state);

OpenSim/Simulation/Wrap/PathWrapPoint.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,11 @@ void OpenSim::PathWrapPoint::extendAddToSystem(SimTK::MultibodySystem& system) c
2727
{
2828
Super::extendAddToSystem(system);
2929

30-
_wrapPath = addCacheVariable("wrap_path", Array<SimTK::Vec3>{}, SimTK::Stage::Position);
30+
_wrapPath = addCacheVariable("wrap_path",
31+
Array<SimTK::Vec3>(SimTK::Vec3(SimTK::NaN), 0, 1),
32+
SimTK::Stage::Position);
3133
_wrapPathLength = addCacheVariable("wrap_path_length", 0.0, SimTK::Stage::Position);
32-
_location = addCacheVariable("wrap_location", SimTK::Vec3{}, SimTK::Stage::Position);
34+
_location = addCacheVariable("wrap_location", SimTK::Vec3(SimTK::NaN), SimTK::Stage::Position);
3335
}
3436

3537
const OpenSim::WrapObject* OpenSim::PathWrapPoint::getWrapObject() const

OpenSim/Simulation/Wrap/WrapResult.cpp

Lines changed: 32 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -32,47 +32,40 @@
3232
using namespace std;
3333
using namespace OpenSim;
3434

35-
WrapResult::WrapResult(const WrapResult& other) {
36-
copyData(other);
37-
}
38-
39-
//_____________________________________________________________________________
40-
/**
41-
* Copy data members from one WrapResult to another.
42-
*
43-
* @param aWrapResult WrapResult to be copied.
44-
*/
45-
void WrapResult::copyData(const WrapResult& aWrapResult) {
46-
wrap_pts = aWrapResult.wrap_pts;
47-
wrap_path_length = aWrapResult.wrap_path_length;
48-
49-
startPoint = aWrapResult.startPoint;
50-
endPoint = aWrapResult.endPoint;
51-
52-
int i;
53-
for (i = 0; i < 3; i++) {
54-
r1[i] = aWrapResult.r1[i];
55-
r2[i] = aWrapResult.r2[i];
56-
c1[i] = aWrapResult.c1[i];
57-
sv[i] = aWrapResult.sv[i];
58-
}
35+
WrapResult::WrapResult()
36+
: startPoint{-1},
37+
endPoint{-1},
38+
wrap_pts{SimTK::Vec3(SimTK::NaN), 0, 1},
39+
wrap_path_length{SimTK::NaN},
40+
r1{SimTK::Vec3(SimTK::NaN)},
41+
r2{SimTK::Vec3(SimTK::NaN)},
42+
c1{SimTK::Vec3(SimTK::NaN)},
43+
sv{SimTK::Vec3(SimTK::NaN)} {}
5944

60-
singleWrap = aWrapResult.singleWrap;
61-
// TODO: Should factor be omitted from the copy?
62-
}
45+
WrapResult::WrapResult(const WrapResult& other)
46+
: startPoint{other.startPoint},
47+
endPoint{other.endPoint},
48+
wrap_pts{other.wrap_pts},
49+
wrap_path_length{other.wrap_path_length},
50+
r1{other.r1},
51+
r2{other.r2},
52+
c1{other.c1},
53+
sv{other.sv},
54+
factor{SimTK::NaN},
55+
singleWrap{other.singleWrap} {}
6356

64-
//=============================================================================
65-
// OPERATORS
66-
//=============================================================================
67-
//_____________________________________________________________________________
68-
/**
69-
* Assignment operator.
70-
*
71-
* @return Reference to this object.
72-
*/
73-
WrapResult& WrapResult::operator=(const WrapResult& aWrapResult) {
74-
if (this != &aWrapResult) {
75-
copyData(aWrapResult);
57+
WrapResult& WrapResult::operator=(const WrapResult& other) {
58+
if (this != &other) {
59+
startPoint = other.startPoint;
60+
endPoint = other.endPoint;
61+
wrap_pts = other.wrap_pts;
62+
wrap_path_length = other.wrap_path_length;
63+
r1 = other.r1;
64+
r2 = other.r2;
65+
c1 = other.c1;
66+
sv = other.sv;
67+
factor = SimTK::NaN;
68+
singleWrap = other.singleWrap;
7669
}
7770

7871
return *this;

OpenSim/Simulation/Wrap/WrapResult.h

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,14 +69,11 @@ class OSIMSIMULATION_API WrapResult
6969
// CONSTRUCTION
7070
//--------------------------------------------------------------------------
7171
public:
72-
WrapResult() = default;
72+
WrapResult();
7373
virtual ~WrapResult() = default;
7474
WrapResult(const WrapResult& other);
7575
WrapResult& operator=(const WrapResult& aWrapResult);
7676

77-
private:
78-
void copyData(const WrapResult& aWrapResult);
79-
8077
//=============================================================================
8178
}; // END of class WrapResult
8279
//=============================================================================

dependencies/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ AddDependency(NAME ezc3d
185185
AddDependency(NAME simbody
186186
DEFAULT ON
187187
GIT_URL https://github.com/simbody/simbody.git
188-
GIT_TAG 77bf63c030e4c30112952602abe120afedbdb1e6
188+
GIT_TAG f9ab12cbad9d0da106473259d34c50577f934f49
189189
CMAKE_ARGS -DBUILD_EXAMPLES:BOOL=OFF
190190
-DBUILD_TESTING:BOOL=OFF
191191
${SIMBODY_EXTRA_CMAKE_ARGS})

0 commit comments

Comments
 (0)