We tracked down the reason for the behavior described in the comment above by Fouad Matari on broken non-uniform scaling.
Restating the issue, in the source file
opensim-core-source\OpenSim\Simulation\SimbodyEngine\Body.cpp, in the function
void Body::scaleInertialProperties(const SimTK::Vec3& scaleFactors, bool scaleMass), one finds that in the code section invoked when the three scale factors are not equal, assignments of the following kinds are used:
Code: Select all
inertia[0][0] = 0.5 * get_mass() * rad_sqr;
inertia[1][1] = get_mass() * ((length * length / 12.0) + 0.25 * rad_sqr);
inertia[2][2] = get_mass() * ((length * length / 12.0) + 0.25 * rad_sqr);
and
Code: Select all
inertia[0][1] *= ((scaleFactors[0] * scaleFactors[1]));
inertia[0][2] *= ((scaleFactors[0] * scaleFactors[2]));
inertia[1][0] *= ((scaleFactors[1] * scaleFactors[0]));
Both of them fail to modify the local object inertia allocated earlier in the statement
Code: Select all
SimTK::SymMat33 inertia = _inertia.asSymMat33();
The reason is as follows. SymMat33 is a typedef for SymMat<3>. In that class, in SymMat.h, one finds
Code: Select all
// These are slow for a symmetric matrix, requiring copying and
// possibly floating point operations for conjugation.
TRow operator[](int i) const {return row(i);}
in which the row() function is defined as
Code: Select all
// Rows and columns have to be copied and Hermitian elements have to
// be conjugated at a floating point cost. This isn't the best way
// to work with a symmetric matrix.
TRow row(int i) const {
...
TRow rowi;
...
return rowi;
}
In this function a local object TRow rowi; is allocated, the row elements of inertia are copied to this local object, and it is then returned by the function. Thus when seeking inertia[j][k], the first [j] operation returns a TRow object whose elements point to newly allocated storage, not to anything in the original object inertia. The second [k] operator then returns a variable whose subsequent modification does not affect the original object inertia.
For this reason changing from SimTK::Mat33 to SimTK::SymMat33 in this function between OpenSim3.3 and OpenSim4.x broke the non-uniform scaling capability of the scaleInertialProperties() routine.