From 34daa7a499025796718b54593d5a9759eb944f87 Mon Sep 17 00:00:00 2001 From: Nicholas Bianco Date: Wed, 23 Aug 2023 16:21:51 -0700 Subject: [PATCH 01/24] First pass at implementing AbstractPath --- OpenSim/Simulation/Model/AbstractPath.cpp | 52 +++++ OpenSim/Simulation/Model/AbstractPath.h | 190 ++++++++++++++++++ OpenSim/Simulation/Model/GeometryPath.cpp | 12 +- OpenSim/Simulation/Model/GeometryPath.h | 40 +--- .../RegisterTypes_osimSimulation.cpp | 1 + OpenSim/Simulation/osimSimulation.h | 1 + 6 files changed, 257 insertions(+), 39 deletions(-) create mode 100644 OpenSim/Simulation/Model/AbstractPath.cpp create mode 100644 OpenSim/Simulation/Model/AbstractPath.h diff --git a/OpenSim/Simulation/Model/AbstractPath.cpp b/OpenSim/Simulation/Model/AbstractPath.cpp new file mode 100644 index 0000000000..f0be53bcf1 --- /dev/null +++ b/OpenSim/Simulation/Model/AbstractPath.cpp @@ -0,0 +1,52 @@ +/* -------------------------------------------------------------------------- * + * OpenSim: AbstractPath.cpp * + * -------------------------------------------------------------------------- * + * The OpenSim API is a toolkit for musculoskeletal modeling and simulation. * + * See http://opensim.stanford.edu and the NOTICE file for more information. * + * OpenSim is developed at Stanford University and supported by the US * + * National Institutes of Health (U54 GM072970, R24 HD065690) and by DARPA * + * through the Warrior Web program. * + * * + * Copyright (c) 2005-2023 Stanford University and the Authors * + * Author(s): Nicholas Bianco, Joris Verhagen, Adam Kewley * + * * + * Licensed under the Apache License, Version 2.0 (the "License"); you may * + * not use this file except in compliance with the License. You may obtain a * + * copy of the License at http://www.apache.org/licenses/LICENSE-2.0. * + * * + * Unless required by applicable law or agreed to in writing, software * + * distributed under the License is distributed on an "AS IS" BASIS, * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * + * See the License for the specific language governing permissions and * + * limitations under the License. * + * -------------------------------------------------------------------------- */ + +#include "AbstractPath.h" + +using namespace OpenSim; + +AbstractPath::AbstractPath() : ModelComponent() { + setAuthors("Nicholas Bianco, Joris Verhagen, Adam Kewley"); + + Appearance appearance; + appearance.set_color(SimTK::Gray); + constructProperty_appearance(appearance); +} + +AbstractPath::AbstractPath(AbstractPath const&) = default; + +AbstractPath::~AbstractPath() noexcept = default; + +AbstractPath& AbstractPath::operator=(const AbstractPath&) = default; + +// DEFAULTED METHODS +const SimTK::Vec3& AbstractPath::getDefaultColor() const +{ + return get_appearance().get_color(); +} + +void AbstractPath::setDefaultColor(const SimTK::Vec3& color) +{ + updProperty_appearance().setValueIsDefault(false); + upd_appearance().set_color(color); +} diff --git a/OpenSim/Simulation/Model/AbstractPath.h b/OpenSim/Simulation/Model/AbstractPath.h new file mode 100644 index 0000000000..8638056f57 --- /dev/null +++ b/OpenSim/Simulation/Model/AbstractPath.h @@ -0,0 +1,190 @@ +#ifndef OPENSIM_ABSTRACTPATH_H +#define OPENSIM_ABSTRACTPATH_H +/* -------------------------------------------------------------------------- * + * OpenSim: AbstractPath.h * + * -------------------------------------------------------------------------- * + * The OpenSim API is a toolkit for musculoskeletal modeling and simulation. * + * See http://opensim.stanford.edu and the NOTICE file for more information. * + * OpenSim is developed at Stanford University and supported by the US * + * National Institutes of Health (U54 GM072970, R24 HD065690) and by DARPA * + * through the Warrior Web program. * + * * + * Copyright (c) 2005-2023 Stanford University and the Authors * + * Author(s): Nicholas Bianco, Joris Verhagen, Adam Kewley * + * * + * Licensed under the Apache License, Version 2.0 (the "License"); you may * + * not use this file except in compliance with the License. You may obtain a * + * copy of the License at http://www.apache.org/licenses/LICENSE-2.0. * + * * + * Unless required by applicable law or agreed to in writing, software * + * distributed under the License is distributed on an "AS IS" BASIS, * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * + * See the License for the specific language governing permissions and * + * limitations under the License. * + * -------------------------------------------------------------------------- */ + +#include +#include +#include + +#ifdef SWIG + #ifdef OSIMSIMULATION_API + #undef OSIMSIMULATION_API + #define OSIMSIMULATION_API + #endif +#endif + +namespace OpenSim { + +class Coordinate; + +//============================================================================= +// ABSTRACT PATH +//============================================================================= +/** + * A base class that represents a path that has a computable length and + * lengthening speed. + * + * This class is typically used in places where the model needs to simulate + * the changes in a path over time. For example, in `OpenSim::Muscle`s, + * `OpenSim::Ligament`s, etc. + * + * This class *only* defines a length and lengthening speed. We do not assume + * that an `OpenSim::AbstractPath` is a straight line between two points or + * assume that it is many straight lines between `n` points. The derived + * implementation may define a path using points, or it may define a path using + * a curve fit. It may also define a path based on analytical functions for the + * length and lengthening speed. + */ +class OSIMSIMULATION_API AbstractPath : public ModelComponent { +OpenSim_DECLARE_ABSTRACT_OBJECT(AbstractPath, ModelComponent); + +public: +//============================================================================= +// OUTPUTS +//============================================================================= + OpenSim_DECLARE_OUTPUT(length, double, getLength, SimTK::Stage::Position); + OpenSim_DECLARE_OUTPUT(lengthening_speed, double, getLengtheningSpeed, + SimTK::Stage::Velocity); + +//============================================================================= +// PROPERTIES +//============================================================================= + OpenSim_DECLARE_PROPERTY(appearance, Appearance, + "Default appearance attributes for this AbstractPath."); + +//============================================================================= +// METHODS +//============================================================================= + AbstractPath(); + AbstractPath(const AbstractPath&); + ~AbstractPath() noexcept; + + AbstractPath& operator=(const AbstractPath&); + + // INTERFACE METHODS + // + // Concrete implementations of `GeometryPath` *must* provide these. + + /** + * Get the current color of the path. + * + * This is the runtime, potentially state-dependent, color of the path. It + * is the color used to display the path in that state (e.g., for UI + * rendering). + * + * This color value is typically initialized with the default color (see: + * `getDefaultColor`), but the color can change between simulation states + * because downstream code (e.g. muscles) might call `setColor` to implement + * state-dependent path coloring. + */ + virtual SimTK::Vec3 getColor(const SimTK::State& s) const = 0; + + /** + * Set the current color of the path. + * + * Internally, sets the current color value of the path for the provided + * state (e.g. using cache variables). + * + * The value of this variable is used as the color when the path is drawn, + * which occurs with the state realized to Stage::Dynamics. Therefore, you + * must call this method during realizeDynamics() or earlier in order for it + * to have any effect. + */ + virtual void setColor( + const SimTK::State& s, const SimTK::Vec3& color) const = 0; + + /** + * Get the current length of the path. + * + * Internally, this may use a variety of methods to figure out how long the + * path is, such as using spline-fits, or computing the distance between + * points in space. It is up to concrete implementations (e.g., + * `GeometryPath`) to provide a relevant implementation. + */ + virtual double getLength(const SimTK::State& s) const = 0; + + /** + * Get the lengthening speed of the path. + * + * Internally, this may use a variety of methods to figure out the + * lengthening speed. It might use the finite difference between two + * lengths, or an analytic solution, or always return `0.0`. It is up to + * concrete implementations (e.g., `GeometryPath`) to provide a relevant + * implementation. + */ + virtual double getLengtheningSpeed(const SimTK::State& s) const = 0; + + /** + * Add in the equivalent body and generalized forces to be applied to the + * multibody system resulting from a tension along the AbstractPath. + * + * @param state state used to evaluate forces + * @param[in] tension scalar of the applied (+ve) tensile force + * @param[in,out] bodyForces Vector of forces (SpatialVec's) on bodies + * @param[in,out] mobilityForces Vector of generalized forces + */ + virtual void addInEquivalentForces(const SimTK::State& state, + double tension, + SimTK::Vector_& bodyForces, + SimTK::Vector& mobilityForces) const = 0; + + /** + * Returns the moment arm of the path in the given state with respect to + * the specified coordinate. + */ + virtual double computeMomentArm(const SimTK::State& s, + const Coordinate& aCoord) const = 0; + + // DEFAULTED METHODS + // + // These are non-deprecated methods that for which AbstractPath provides a + // default implementation. + + /** + * Get the default color of the path. + * + * Returns the color that will be used to initialize the color cache + * at the next extendAddToSystem() call. Use `getColor` to retrieve the + * (potentially different) color that will be used to draw the path. + */ + const SimTK::Vec3& getDefaultColor() const; + + /** + * Set the default color of the path. + * + * Sets the internal, default, color value for the path. This is the color + * that's used when the simulation is initialized (specifically, during the + * `extendAddToSystem` call). + * + * This color is not necessarily the *current* color of the path. Other code + * in the system (e.g. muscle implementations) may change the runtime color + * with `setColor`. Use `getColor`, with a particular simulation state, to + * get the color of the path in that state. + */ + void setDefaultColor(const SimTK::Vec3& color); +}; + +} // namespace OpenSim + +#endif // OPENSIM_ABSTRACTPATH_H diff --git a/OpenSim/Simulation/Model/GeometryPath.cpp b/OpenSim/Simulation/Model/GeometryPath.cpp index c9834348e5..cb0e49fa17 100644 --- a/OpenSim/Simulation/Model/GeometryPath.cpp +++ b/OpenSim/Simulation/Model/GeometryPath.cpp @@ -133,9 +133,7 @@ static void PopulatePathElementLookup( /* * Default constructor. */ -GeometryPath::GeometryPath() : - ModelComponent(), - _preScaleLength(0.0) +GeometryPath::GeometryPath() : AbstractPath(), _preScaleLength(0.0) { setAuthors("Peter Loan"); constructProperties(); @@ -193,7 +191,7 @@ void GeometryPath::extendConnectToModel(Model& aModel) // We consider this cache entry valid any time after it has been created // and first marked valid, and we won't ever invalidate it. - this->_colorCV = addCacheVariable("color", get_Appearance().get_color(), SimTK::Stage::Topology); + this->_colorCV = addCacheVariable("color", get_appearance().get_color(), SimTK::Stage::Topology); } void GeometryPath::extendInitStateFromProperties(SimTK::State& s) const @@ -281,10 +279,6 @@ void GeometryPath::constructProperties() constructProperty_PathPointSet(PathPointSet()); constructProperty_PathWrapSet(PathWrapSet()); - - Appearance appearance; - appearance.set_color(SimTK::Gray); - constructProperty_Appearance(appearance); } //_____________________________________________________________________________ @@ -388,7 +382,7 @@ getPointForceDirections(const SimTK::State& s, /* add in the equivalent spatial forces on bodies for an applied tension along the GeometryPath to a set of bodyForces */ void GeometryPath::addInEquivalentForces(const SimTK::State& s, - const double& tension, + double tension, SimTK::Vector_& bodyForces, SimTK::Vector& mobilityForces) const { diff --git a/OpenSim/Simulation/Model/GeometryPath.h b/OpenSim/Simulation/Model/GeometryPath.h index a53b4bc50e..a84253feed 100644 --- a/OpenSim/Simulation/Model/GeometryPath.h +++ b/OpenSim/Simulation/Model/GeometryPath.h @@ -27,6 +27,7 @@ // INCLUDE #include #include "OpenSim/Simulation/Model/ModelComponent.h" +#include "OpenSim/Simulation/Model/AbstractPath.h" #include "PathPointSet.h" #include #include @@ -55,23 +56,12 @@ class WrapObject; * @author Peter Loan * @version 1.0 */ -class OSIMSIMULATION_API GeometryPath : public ModelComponent { -OpenSim_DECLARE_CONCRETE_OBJECT(GeometryPath, ModelComponent); - //============================================================================= - // OUTPUTS - //============================================================================= - OpenSim_DECLARE_OUTPUT(length, double, getLength, SimTK::Stage::Position); - // - OpenSim_DECLARE_OUTPUT(lengthening_speed, double, getLengtheningSpeed, - SimTK::Stage::Velocity); +class OSIMSIMULATION_API GeometryPath : public AbstractPath { +OpenSim_DECLARE_CONCRETE_OBJECT(GeometryPath, AbstractPath); //============================================================================= // DATA //============================================================================= -public: - OpenSim_DECLARE_UNNAMED_PROPERTY(Appearance, - "Default appearance attributes for this GeometryPath"); - private: OpenSim_DECLARE_UNNAMED_PROPERTY(PathPointSet, "The set of points defining the path"); @@ -93,12 +83,13 @@ OpenSim_DECLARE_CONCRETE_OBJECT(GeometryPath, ModelComponent); mutable CacheVariable _lengthCV; mutable CacheVariable _speedCV; + mutable CacheVariable _colorCV; + public: class PathElementLookup; private: mutable CacheVariable> _currentPathCV; - mutable CacheVariable _colorCV; - + //============================================================================= // METHODS //============================================================================= @@ -135,18 +126,6 @@ OpenSim_DECLARE_CONCRETE_OBJECT(GeometryPath, ModelComponent); // GET //-------------------------------------------------------------------------- - /** If you call this prior to extendAddToSystem() it will be used to initialize - the color cache variable. Otherwise %GeometryPath will choose its own - default which varies depending on owner. **/ - void setDefaultColor(const SimTK::Vec3& color) { - updProperty_Appearance().setValueIsDefault(false); - upd_Appearance().set_color(color); - }; - /** Returns the color that will be used to initialize the color cache - at the next extendAddToSystem() call. The actual color used to draw the path - will be taken from the cache variable, so may have changed. **/ - const SimTK::Vec3& getDefaultColor() const { return get_Appearance().get_color(); } - /** %Set the value of the color cache variable owned by this %GeometryPath object, in the cache of the given state. The value of this variable is used as the color when the path is drawn, which occurs with the state realized @@ -184,15 +163,16 @@ OpenSim_DECLARE_CONCRETE_OBJECT(GeometryPath, ModelComponent); @param[in,out] mobilityForces Vector of generalized forces, one per mobility */ void addInEquivalentForces(const SimTK::State& state, - const double& tension, + double tension, SimTK::Vector_& bodyForces, - SimTK::Vector& mobilityForces) const; + SimTK::Vector& mobilityForces) const override; //-------------------------------------------------------------------------- // COMPUTATIONS //-------------------------------------------------------------------------- - virtual double computeMomentArm(const SimTK::State& s, const Coordinate& aCoord) const; + double computeMomentArm(const SimTK::State& s, + const Coordinate& aCoord) const override; //-------------------------------------------------------------------------- // SCALING diff --git a/OpenSim/Simulation/RegisterTypes_osimSimulation.cpp b/OpenSim/Simulation/RegisterTypes_osimSimulation.cpp index 4ac2a3f7d0..ed2fb76075 100644 --- a/OpenSim/Simulation/RegisterTypes_osimSimulation.cpp +++ b/OpenSim/Simulation/RegisterTypes_osimSimulation.cpp @@ -59,6 +59,7 @@ #include "Model/PathPointSet.h" #include "Model/ConditionalPathPoint.h" #include "Model/MovingPathPoint.h" +#include "Model/AbstractPath.h" #include "Model/GeometryPath.h" #include "Model/PrescribedForce.h" #include "Model/ExternalForce.h" diff --git a/OpenSim/Simulation/osimSimulation.h b/OpenSim/Simulation/osimSimulation.h index dc85551b82..44d49f84ef 100644 --- a/OpenSim/Simulation/osimSimulation.h +++ b/OpenSim/Simulation/osimSimulation.h @@ -52,6 +52,7 @@ #include "Model/PathPointSet.h" #include "Model/ConditionalPathPoint.h" #include "Model/MovingPathPoint.h" +#include "Model/AbstractPath.h" #include "Model/GeometryPath.h" #include "Model/PrescribedForce.h" #include "Model/PointToPointSpring.h" From 3d5c2eea5ebb7038a725cab4e412ae708bbf1e6d Mon Sep 17 00:00:00 2001 From: Nicholas Bianco Date: Thu, 24 Aug 2023 16:40:29 -0700 Subject: [PATCH 02/24] Update examples and tests after GeometryPath API changes --- Applications/Scale/test/testScale.cpp | 17 ++++-- .../Actuators/DeGrooteFregly2016Muscle.cpp | 57 +++++++++-------- OpenSim/Actuators/McKibbenActuator.cpp | 2 +- .../Millard2012AccelerationMuscle.cpp | 4 +- .../Millard2012EquilibriumMuscle.cpp | 4 +- OpenSim/Actuators/ModelFactory.cpp | 61 +++++++++++-------- OpenSim/Actuators/RigidTendonMuscle.cpp | 2 +- OpenSim/Actuators/Test/testActuators.cpp | 13 ++-- .../Test/testDeGrooteFregly2016Muscle.cpp | 5 +- OpenSim/Actuators/Test/testModelProcessor.cpp | 6 +- OpenSim/Actuators/Test/testMuscles.cpp | 42 +++++++------ OpenSim/Analyses/MuscleAnalysis.h | 1 + OpenSim/Analyses/Test/testOutputReporter.cpp | 5 +- OpenSim/ExampleComponents/HopperDevice.h | 2 +- .../ExampleHopperDevice/buildDeviceModel.cpp | 3 +- .../buildDeviceModel_answers.cpp | 5 +- .../ExampleHopperDevice/buildHopperModel.cpp | 7 ++- .../defineDeviceAndController.h | 2 +- .../defineDeviceAndController_answers.h | 2 +- .../exampleHopperDevice.cpp | 3 +- .../exampleHopperDevice_answers.cpp | 3 +- .../LuxoMuscle_create_and_simulate.cpp | 32 ++++++---- .../OutputReference/TugOfWar_Complete.cpp | 10 +-- .../exampleHangingMuscle.cpp | 5 +- .../Examples/MuscleExample/mainFatigue.cpp | 10 +-- .../checkEnvironment/checkEnvironment.cpp | 10 +-- OpenSim/Moco/Test/testMocoActuators.cpp | 5 +- OpenSim/Moco/Test/testMocoInterface.cpp | 5 +- OpenSim/Moco/Test/testMocoMetabolics.cpp | 5 +- OpenSim/Simulation/Model/AbstractPath.cpp | 12 ++++ OpenSim/Simulation/Model/AbstractPath.h | 22 +++++++ .../Model/ActivationFiberLengthMuscle.cpp | 4 +- ...ActivationFiberLengthMuscle_Deprecated.cpp | 4 +- .../Model/Blankevoort1991Ligament.cpp | 35 +++-------- .../Model/Blankevoort1991Ligament.h | 16 ++--- OpenSim/Simulation/Model/Force.h | 6 +- OpenSim/Simulation/Model/Ligament.cpp | 34 ++++------- OpenSim/Simulation/Model/Ligament.h | 18 +++--- OpenSim/Simulation/Model/Muscle.cpp | 9 +-- OpenSim/Simulation/Model/Muscle.h | 4 +- OpenSim/Simulation/Model/PathActuator.cpp | 28 +++------ OpenSim/Simulation/Model/PathActuator.h | 25 +++----- OpenSim/Simulation/Model/PathSpring.cpp | 31 ++++------ OpenSim/Simulation/Model/PathSpring.h | 32 +++++----- OpenSim/Simulation/MomentArmSolver.cpp | 1 + OpenSim/Simulation/Test/testForces.cpp | 29 +++++---- OpenSim/Simulation/Test/testMomentArms.cpp | 12 ++-- .../Test/testMuscleMetabolicsProbes.cpp | 15 +++-- OpenSim/Simulation/Test/testProbes.cpp | 5 +- OpenSim/Simulation/Wrap/PathWrap.cpp | 1 + .../Tests/AddComponents/testAddComponents.cpp | 10 +-- OpenSim/Tests/README/testREADME.cpp | 5 +- OpenSim/Tests/Wrapping/testWrapCylinder.cpp | 15 +++-- OpenSim/Tests/Wrapping/testWrapping.cpp | 28 ++++----- .../Tests/Wrapping/testWrappingAlgorithm.cpp | 18 +++--- OpenSim/Tests/testIterators/testIterators.cpp | 1 + 56 files changed, 390 insertions(+), 358 deletions(-) diff --git a/Applications/Scale/test/testScale.cpp b/Applications/Scale/test/testScale.cpp index 0046f7c432..d0e98c0a2c 100644 --- a/Applications/Scale/test/testScale.cpp +++ b/Applications/Scale/test/testScale.cpp @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -561,8 +562,9 @@ void scalePhysicalOffsetFrames() const Vec3 offset1 = Vec3(0.2, 0.4, 0.6); PathActuator* act1 = new PathActuator(); act1->setName("pathActuator1"); - act1->addNewPathPoint("point1a", model->updGround(), Vec3(0)); - act1->addNewPathPoint("point1b", *body, offset1); + auto& path = dynamic_cast(act1->updPath()); + path.appendNewPathPoint("point1a", model->updGround(), Vec3(0)); + path.appendNewPathPoint("point1b", *body, offset1); body->addComponent(act1); // Second PathActuator is attached to the Body via a POF. Both new @@ -575,8 +577,9 @@ void scalePhysicalOffsetFrames() PathActuator* act2 = new PathActuator(); act2->setName("pathActuator2"); - act2->addNewPathPoint("point2a", model->updGround(), Vec3(0)); - act2->addNewPathPoint("point2b", *pof2, offset2); + auto& path2 = dynamic_cast(act2->updPath()); + path2.appendNewPathPoint("point2a", model->updGround(), Vec3(0)); + path2.appendNewPathPoint("point2b", *pof2, offset2); act1->addComponent(act2); State& s = model->initSystem(); @@ -592,9 +595,11 @@ void scalePhysicalOffsetFrames() model->getComponent(pathToAct1); const PathActuator& pa2 = model->getComponent(pathToAct2); + const auto& path1 = dynamic_cast(pa1.getPath()); + const auto& path2 = dynamic_cast(pa2.getPath()); - const PathPointSet& pps1 = pa1.getGeometryPath().getPathPointSet(); - const PathPointSet& pps2 = pa2.getGeometryPath().getPathPointSet(); + const PathPointSet& pps1 = path1.getPathPointSet(); + const PathPointSet& pps2 = path2.getPathPointSet(); for (int i = 0; i < 2; ++i) { diff --git a/OpenSim/Actuators/DeGrooteFregly2016Muscle.cpp b/OpenSim/Actuators/DeGrooteFregly2016Muscle.cpp index 4cf3f431b3..1c9a26f791 100644 --- a/OpenSim/Actuators/DeGrooteFregly2016Muscle.cpp +++ b/OpenSim/Actuators/DeGrooteFregly2016Muscle.cpp @@ -27,6 +27,7 @@ #include #include #include +#include "OpenSim/Simulation/Model/GeometryPath.h" #include "OpenSim/Common/STOFileAdapter.h" using namespace OpenSim; @@ -1021,31 +1022,39 @@ void DeGrooteFregly2016Muscle::replaceMuscles( actu->set_ignore_activation_dynamics( muscBase.get_ignore_activation_dynamics()); - const auto& pathPointSet = muscBase.getGeometryPath().getPathPointSet(); - auto& geomPath = actu->updGeometryPath(); - for (int ipp = 0; ipp < pathPointSet.getSize(); ++ipp) { - auto* pathPoint = pathPointSet.get(ipp).clone(); - const auto& socketNames = pathPoint->getSocketNames(); - for (const auto& socketName : socketNames) { - pathPoint->updSocket(socketName) - .connect(pathPointSet.get(ipp) - .getSocket(socketName) - .getConnecteeAsObject()); + // Copy the muscle's path. + AbstractPath& path = muscBase.updPath(); + actu->updProperty_path().clear(); + if (auto* pGeometryPath = dynamic_cast(&path)) { + actu->updProperty_path().setValue(GeometryPath()); + auto& thisGeometryPath = dynamic_cast( + actu->updPath()); + + const auto& pathPointSet = pGeometryPath->getPathPointSet(); + for (int ipp = 0; ipp < pathPointSet.getSize(); ++ipp) { + auto* pathPoint = pathPointSet.get(ipp).clone(); + const auto& socketNames = pathPoint->getSocketNames(); + for (const auto& socketName : socketNames) { + pathPoint->updSocket(socketName) + .connect(pathPointSet.get(ipp) + .getSocket(socketName) + .getConnecteeAsObject()); + } + thisGeometryPath.updPathPointSet().adoptAndAppend(pathPoint); } - geomPath.updPathPointSet().adoptAndAppend(pathPoint); - } - const auto& pathWrapSet = muscBase.getGeometryPath().getWrapSet(); - for (int ipw = 0; ipw < pathWrapSet.getSize(); ++ipw) { - auto* pathWrap = pathWrapSet.get(ipw).clone(); - const auto& socketNames = pathWrap->getSocketNames(); - for (const auto& socketName : socketNames) { - pathWrap->updSocket(socketName) - .connect(pathWrapSet.get(ipw) - .getSocket(socketName) - .getConnecteeAsObject()); + const auto& pathWrapSet = pGeometryPath->getWrapSet(); + for (int ipw = 0; ipw < pathWrapSet.getSize(); ++ipw) { + auto* pathWrap = pathWrapSet.get(ipw).clone(); + const auto& socketNames = pathWrap->getSocketNames(); + for (const auto& socketName : socketNames) { + pathWrap->updSocket(socketName) + .connect(pathWrapSet.get(ipw) + .getSocket(socketName) + .getConnecteeAsObject()); + } + thisGeometryPath.updWrapSet().adoptAndAppend(pathWrap); } - geomPath.updWrapSet().adoptAndAppend(pathWrap); } std::string actname = actu->getName(); @@ -1074,14 +1083,14 @@ void DeGrooteFregly2016Muscle::extendPostScale( const SimTK::State& s, const ScaleSet& scaleSet) { Super::extendPostScale(s, scaleSet); - GeometryPath& path = upd_GeometryPath(); + AbstractPath& path = upd_path(); if (path.getPreScaleLength(s) > 0.0) { double scaleFactor = path.getLength(s) / path.getPreScaleLength(s); upd_optimal_fiber_length() *= scaleFactor; upd_tendon_slack_length() *= scaleFactor; - // Clear the pre-scale length that was stored in the GeometryPath. + // Clear the pre-scale length that was stored in the path. path.setPreScaleLength(s, 0.0); } } diff --git a/OpenSim/Actuators/McKibbenActuator.cpp b/OpenSim/Actuators/McKibbenActuator.cpp index 65a80bcc37..06719f4c62 100644 --- a/OpenSim/Actuators/McKibbenActuator.cpp +++ b/OpenSim/Actuators/McKibbenActuator.cpp @@ -107,7 +107,7 @@ void McKibbenActuator::computeForce(const SimTK::State& s, double actuation = computeActuation(s); - getGeometryPath().addInEquivalentForces(s, actuation, bodyForces, generalizedForces); + getPath().addInEquivalentForces(s, actuation, bodyForces, generalizedForces); } //_____________________________________________________________________________ /** diff --git a/OpenSim/Actuators/Millard2012AccelerationMuscle.cpp b/OpenSim/Actuators/Millard2012AccelerationMuscle.cpp index 8dfe6bf55e..a2b46cf31e 100644 --- a/OpenSim/Actuators/Millard2012AccelerationMuscle.cpp +++ b/OpenSim/Actuators/Millard2012AccelerationMuscle.cpp @@ -557,14 +557,14 @@ extendPostScale(const SimTK::State& s, const ScaleSet& scaleSet) Super::extendPostScale(s, scaleSet); - GeometryPath& path = upd_GeometryPath(); + AbstractPath& path = upd_path(); if (path.getPreScaleLength(s) > 0.0) { double scaleFactor = path.getLength(s) / path.getPreScaleLength(s); upd_optimal_fiber_length() *= scaleFactor; upd_tendon_slack_length() *= scaleFactor; - // Clear the pre-scale length that was stored in the GeometryPath. + // Clear the pre-scale length that was stored in the path. path.setPreScaleLength(s, 0.0); } } diff --git a/OpenSim/Actuators/Millard2012EquilibriumMuscle.cpp b/OpenSim/Actuators/Millard2012EquilibriumMuscle.cpp index ea5faf233a..c8208c22f1 100644 --- a/OpenSim/Actuators/Millard2012EquilibriumMuscle.cpp +++ b/OpenSim/Actuators/Millard2012EquilibriumMuscle.cpp @@ -598,14 +598,14 @@ extendPostScale(const SimTK::State& s, const ScaleSet& scaleSet) { Super::extendPostScale(s, scaleSet); - GeometryPath& path = upd_GeometryPath(); + AbstractPath& path = upd_path(); if (path.getPreScaleLength(s) > 0.0) { double scaleFactor = path.getLength(s) / path.getPreScaleLength(s); upd_optimal_fiber_length() *= scaleFactor; upd_tendon_slack_length() *= scaleFactor; - // Clear the pre-scale length that was stored in the GeometryPath. + // Clear the pre-scale length that was stored in the path. path.setPreScaleLength(s, 0.0); } } diff --git a/OpenSim/Actuators/ModelFactory.cpp b/OpenSim/Actuators/ModelFactory.cpp index ca5a294d6b..7a4b55aeb3 100644 --- a/OpenSim/Actuators/ModelFactory.cpp +++ b/OpenSim/Actuators/ModelFactory.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include using namespace OpenSim; @@ -171,35 +172,43 @@ void ModelFactory::replaceMusclesWithPathActuators(OpenSim::Model &model) { model.addForce(actu); - // For the connectee names in the PathPoints to be correct, we must add - // the path points after adding the PathActuator to the model. - const auto& pathPointSet = musc.getGeometryPath().getPathPointSet(); - auto& geomPath = actu->updGeometryPath(); - for (int ip = 0; ip < pathPointSet.getSize(); ++ip) { - auto* pathPoint = pathPointSet.get(ip).clone(); - const auto& socketNames = pathPoint->getSocketNames(); - for (const auto& socketName : socketNames) { - pathPoint->updSocket(socketName) - .connect(pathPointSet.get(ip) - .getSocket(socketName) - .getConnecteeAsObject()); + // Copy the muscle's path. + AbstractPath& path = musc.updPath(); + actu->updProperty_path().clear(); + if (auto* pGeometryPath = dynamic_cast(&path)) { + actu->updProperty_path().setValue(GeometryPath()); + auto& thisGeometryPath = dynamic_cast( + actu->updPath()); + + // For the connectee names in the PathPoints to be correct, we must + // add the path points after adding the PathActuator to the model. + const auto& pathPointSet = pGeometryPath->getPathPointSet(); + for (int ip = 0; ip < pathPointSet.getSize(); ++ip) { + auto* pathPoint = pathPointSet.get(ip).clone(); + const auto& socketNames = pathPoint->getSocketNames(); + for (const auto& socketName : socketNames) { + pathPoint->updSocket(socketName) + .connect(pathPointSet.get(ip) + .getSocket(socketName) + .getConnecteeAsObject()); + } + thisGeometryPath.updPathPointSet().adoptAndAppend(pathPoint); } - geomPath.updPathPointSet().adoptAndAppend(pathPoint); - } - // For the connectee names in the PathWraps to be correct, we must add - // the path wraps after adding the PathActuator to the model. - const auto& pathWrapSet = musc.getGeometryPath().getWrapSet(); - for (int ipw = 0; ipw < pathWrapSet.getSize(); ++ipw) { - auto* pathWrap = pathWrapSet.get(ipw).clone(); - const auto& socketNames = pathWrap->getSocketNames(); - for (const auto& socketName : socketNames) { - pathWrap->updSocket(socketName) - .connect(pathWrapSet.get(ipw) - .getSocket(socketName) - .getConnecteeAsObject()); + // For the connectee names in the PathWraps to be correct, we must + // add the path wraps after adding the PathActuator to the model. + const auto& pathWrapSet = pGeometryPath->getWrapSet(); + for (int ipw = 0; ipw < pathWrapSet.getSize(); ++ipw) { + auto* pathWrap = pathWrapSet.get(ipw).clone(); + const auto& socketNames = pathWrap->getSocketNames(); + for (const auto& socketName : socketNames) { + pathWrap->updSocket(socketName) + .connect(pathWrapSet.get(ipw) + .getSocket(socketName) + .getConnecteeAsObject()); + } + thisGeometryPath.updWrapSet().adoptAndAppend(pathWrap); } - geomPath.updWrapSet().adoptAndAppend(pathWrap); } musclesToDelete.push_back(&musc); diff --git a/OpenSim/Actuators/RigidTendonMuscle.cpp b/OpenSim/Actuators/RigidTendonMuscle.cpp index 2663dc13b4..508908df77 100644 --- a/OpenSim/Actuators/RigidTendonMuscle.cpp +++ b/OpenSim/Actuators/RigidTendonMuscle.cpp @@ -161,7 +161,7 @@ void RigidTendonMuscle::calcMusclePotentialEnergyInfo(const SimTK::State& s, void RigidTendonMuscle::calcFiberVelocityInfo(const State& s, FiberVelocityInfo& fvi) const { /*const MuscleLengthInfo &mli = */getMuscleLengthInfo(s); - fvi.fiberVelocity = getGeometryPath().getLengtheningSpeed(s); + fvi.fiberVelocity = getPath().getLengtheningSpeed(s); fvi.normFiberVelocity = fvi.fiberVelocity / (getOptimalFiberLength()*getMaxContractionVelocity()); fvi.fiberForceVelocityMultiplier = diff --git a/OpenSim/Actuators/Test/testActuators.cpp b/OpenSim/Actuators/Test/testActuators.cpp index 3816d32a0e..12cfd35cf9 100644 --- a/OpenSim/Actuators/Test/testActuators.cpp +++ b/OpenSim/Actuators/Test/testActuators.cpp @@ -332,18 +332,18 @@ void testClutchedPathSpring() ClutchedPathSpring* spring = new ClutchedPathSpring("clutch_spring", stiffness, dissipation, 0.01); - - spring->updGeometryPath().appendNewPathPoint("origin", *block, Vec3(-0.1, 0.0 ,0.0)); + auto& path = dynamic_cast(spring->updPath()); + path.appendNewPathPoint("origin", *block, Vec3(-0.1, 0.0 ,0.0)); int N = 10; for(int i=1; iupdGeometryPath().appendNewPathPoint("", *pulleyBody, Vec3(-x, y ,0.0)); + path.appendNewPathPoint("", *pulleyBody, Vec3(-x, y ,0.0)); } - spring->updGeometryPath().appendNewPathPoint("insertion", *block, Vec3(0.1, 0.0 ,0.0)); + path.appendNewPathPoint("insertion", *block, Vec3(0.1, 0.0 ,0.0)); // BUG in defining wrapping API requires that the Force containing the GeometryPath be // connected to the model before the wrap can be added @@ -480,8 +480,9 @@ void testMcKibbenActuator() OpenSim::Body* ball = new OpenSim::Body("ball", mass, Vec3(0), mass*SimTK::Inertia::sphere(0.1)); ball->scale(Vec3(ball_radius), false); - actuator->addNewPathPoint("mck_ground", ground, Vec3(0)); - actuator->addNewPathPoint("mck_ball", *ball, Vec3(ball_radius)); + auto& path = dynamic_cast(actuator->updPath()); + path.appendNewPathPoint("mck_ground", ground, Vec3(0)); + path.appendNewPathPoint("mck_ball", *ball, Vec3(ball_radius)); Vec3 locationInParent(0, ball_radius, 0), orientationInParent(0), locationInBody(0), orientationInBody(0); SliderJoint *ballToGround = new SliderJoint("ballToGround", ground, locationInParent, orientationInParent, *ball, locationInBody, orientationInBody); diff --git a/OpenSim/Actuators/Test/testDeGrooteFregly2016Muscle.cpp b/OpenSim/Actuators/Test/testDeGrooteFregly2016Muscle.cpp index 36b724b248..81627369a6 100644 --- a/OpenSim/Actuators/Test/testDeGrooteFregly2016Muscle.cpp +++ b/OpenSim/Actuators/Test/testDeGrooteFregly2016Muscle.cpp @@ -142,8 +142,9 @@ TEST_CASE("DeGrooteFregly2016Muscle basics") { musclePtr->set_ignore_tendon_compliance(true); musclePtr->set_fiber_damping(0); musclePtr->setName("muscle"); - musclePtr->addNewPathPoint("origin", model.updGround(), SimTK::Vec3(0)); - musclePtr->addNewPathPoint("insertion", *body, SimTK::Vec3(0)); + auto& path = dynamic_cast(musclePtr->updPath()); + path.appendNewPathPoint("origin", model.updGround(), SimTK::Vec3(0)); + path.appendNewPathPoint("insertion", *body, SimTK::Vec3(0)); model.addComponent(musclePtr); auto& muscle = model.updComponent("muscle"); diff --git a/OpenSim/Actuators/Test/testModelProcessor.cpp b/OpenSim/Actuators/Test/testModelProcessor.cpp index 7097cfa089..03ae5c731f 100644 --- a/OpenSim/Actuators/Test/testModelProcessor.cpp +++ b/OpenSim/Actuators/Test/testModelProcessor.cpp @@ -92,8 +92,10 @@ Model createElbowModel() { // Add a muscle that flexes the elbow. auto* biceps = new Millard2012EquilibriumMuscle("biceps", 200, 0.6, 0.55, 0); - biceps->addNewPathPoint("origin", model.getGround(), Vec3(0, 0.8, 0)); - biceps->addNewPathPoint("insertion", *body, Vec3(0, 0.7, 0)); + + auto& path = dynamic_cast(biceps->updPath()); + path.appendNewPathPoint("origin", model.getGround(), Vec3(0, 0.8, 0)); + path.appendNewPathPoint("insertion", *body, Vec3(0, 0.7, 0)); model.addBody(body); model.addJoint(joint); diff --git a/OpenSim/Actuators/Test/testMuscles.cpp b/OpenSim/Actuators/Test/testMuscles.cpp index d4cebd341a..d6c283e2f4 100644 --- a/OpenSim/Actuators/Test/testMuscles.cpp +++ b/OpenSim/Actuators/Test/testMuscles.cpp @@ -255,8 +255,9 @@ void simulateMuscle( //Attach the muscle const string &actuatorType = aMuscle->getConcreteClassName(); aMuscle->setName("muscle"); - aMuscle->addNewPathPoint("muscle-box", ground, Vec3(anchorWidth/2,0,0)); - aMuscle->addNewPathPoint("muscle-ball", *ball, Vec3(-ballRadius,0,0)); + auto& path = dynamic_cast(aMuscle->updPath()); + path.appendNewPathPoint("muscle-box", ground, Vec3(anchorWidth/2,0,0)); + path.appendNewPathPoint("muscle-ball", *ball, Vec3(-ballRadius,0,0)); ActivationFiberLengthMuscle_Deprecated *aflMuscle = dynamic_cast(aMuscle); @@ -607,8 +608,9 @@ void testThelen2003Muscle() false); Model m; - muscle.addNewPathPoint("p1", m.getGround(), SimTK::Vec3(0.0)); - muscle.addNewPathPoint("p2", m.getGround(), SimTK::Vec3(1.0)); + auto& path = dynamic_cast(muscle.updPath()); + path.appendNewPathPoint("p1", m.getGround(), SimTK::Vec3(0.0)); + path.appendNewPathPoint("p2", m.getGround(), SimTK::Vec3(1.0)); // Test property bounds. { Thelen2003Muscle musc = muscle; @@ -697,9 +699,10 @@ void testThelen2003Muscle() Thelen2003Muscle* myMcl = new Thelen2003Muscle("myMuscle", MaxIsometricForce0, OptimalFiberLength0, TendonSlackLength0, PennationAngle0); - - myMcl->addNewPathPoint("p1", myModel.getGround(), SimTK::Vec3(0.0)); - myMcl->addNewPathPoint("p2", myModel.getGround(), SimTK::Vec3(1.0)); + + auto& path = dynamic_cast(myMcl->updPath()); + path.appendNewPathPoint("p1", myModel.getGround(), SimTK::Vec3(0.0)); + path.appendNewPathPoint("p2", myModel.getGround(), SimTK::Vec3(1.0)); myModel.addForce(myMcl); // Set properties of Thelen2003Muscle. @@ -783,8 +786,9 @@ void testThelen2003Muscle() const double tendonSlackLength = 0.001; auto muscle = new Thelen2003Muscle("muscle", 1., optimalFiberLength, tendonSlackLength, 0.); - muscle->addNewPathPoint("p1", model.updGround(), SimTK::Vec3(0)); - muscle->addNewPathPoint("p2", model.updGround(), SimTK::Vec3(0,0,1)); + auto& path = dynamic_cast(muscle->updPath()); + path.appendNewPathPoint("p1", model.updGround(), SimTK::Vec3(0)); + path.appendNewPathPoint("p2", model.updGround(), SimTK::Vec3(0,0,1)); model.addForce(muscle); SimTK::State& state = model.initSystem(); @@ -798,8 +802,9 @@ void testThelen2003Muscle() { Model model; auto muscle = new Thelen2003Muscle("muscle", 1., 0.5, 0.5, 0.); - muscle->addNewPathPoint("p1", model.updGround(), SimTK::Vec3(0)); - muscle->addNewPathPoint("p2", model.updGround(), SimTK::Vec3(0,0,1)); + auto& path = dynamic_cast(muscle->updPath()); + path.appendNewPathPoint("p1", model.updGround(), SimTK::Vec3(0)); + path.appendNewPathPoint("p2", model.updGround(), SimTK::Vec3(0,0,1)); model.addForce(muscle); model.finalizeFromProperties(); @@ -873,8 +878,9 @@ void testMillard2012EquilibriumMuscle() const double tendonSlackLength = 100.0; //long tendon auto muscle = new Millard2012EquilibriumMuscle("muscle", 1., optimalFiberLength, tendonSlackLength, 0.); - muscle->addNewPathPoint("p1", model.updGround(), SimTK::Vec3(0)); - muscle->addNewPathPoint("p2", model.updGround(), SimTK::Vec3(0,0,1)); + auto& path = dynamic_cast(muscle->updPath()); + path.appendNewPathPoint("p1", model.updGround(), SimTK::Vec3(0)); + path.appendNewPathPoint("p2", model.updGround(), SimTK::Vec3(0,0,1)); model.addForce(muscle); SimTK::State& state = model.initSystem(); @@ -891,8 +897,9 @@ void testMillard2012EquilibriumMuscle() const double tendonSlackLength = 0.1; //short tendon auto muscle = new Millard2012EquilibriumMuscle("muscle", 1., optimalFiberLength, tendonSlackLength, 0.); - muscle->addNewPathPoint("p1", model.updGround(), SimTK::Vec3(0)); - muscle->addNewPathPoint("p2", model.updGround(), SimTK::Vec3(0, 0, 1)); + auto& path = dynamic_cast(muscle->updPath()); + path.appendNewPathPoint("p1", model.updGround(), SimTK::Vec3(0)); + path.appendNewPathPoint("p2", model.updGround(), SimTK::Vec3(0, 0, 1)); model.addForce(muscle); SimTK::State& state = model.initSystem(); @@ -907,8 +914,9 @@ void testMillard2012EquilibriumMuscle() { Model model; auto muscle = new Millard2012EquilibriumMuscle("mcl", 1., 0.5, 0.5, 0.); - muscle->addNewPathPoint("p1", model.updGround(), SimTK::Vec3(0)); - muscle->addNewPathPoint("p2", model.updGround(), SimTK::Vec3(0,0,1)); + auto& path = dynamic_cast(muscle->updPath()); + path.appendNewPathPoint("p1", model.updGround(), SimTK::Vec3(0)); + path.appendNewPathPoint("p2", model.updGround(), SimTK::Vec3(0,0,1)); model.addForce(muscle); model.finalizeFromProperties(); diff --git a/OpenSim/Analyses/MuscleAnalysis.h b/OpenSim/Analyses/MuscleAnalysis.h index 28361a2c50..df30dcc4dc 100644 --- a/OpenSim/Analyses/MuscleAnalysis.h +++ b/OpenSim/Analyses/MuscleAnalysis.h @@ -28,6 +28,7 @@ //============================================================================= // INCLUDES //============================================================================= +#include #include #include #include "osimAnalysesDLL.h" diff --git a/OpenSim/Analyses/Test/testOutputReporter.cpp b/OpenSim/Analyses/Test/testOutputReporter.cpp index 822fd0b7b1..4830593d28 100644 --- a/OpenSim/Analyses/Test/testOutputReporter.cpp +++ b/OpenSim/Analyses/Test/testOutputReporter.cpp @@ -161,8 +161,9 @@ void simulateMuscle( //Attach the muscle /*const string &actuatorType = */muscle->getConcreteClassName(); muscle->setName("muscle"); - muscle->addNewPathPoint("muscle-box", ground, Vec3(anchorWidth / 2, 0, 0)); - muscle->addNewPathPoint("muscle-ball", *ball, Vec3(-ballRadius, 0, 0)); + auto& path = dynamic_cast(muscle->updPath()); + path.appendNewPathPoint("muscle-box", ground, Vec3(anchorWidth / 2, 0, 0)); + path.appendNewPathPoint("muscle-ball", *ball, Vec3(-ballRadius, 0, 0)); model.addForce(muscle); diff --git a/OpenSim/ExampleComponents/HopperDevice.h b/OpenSim/ExampleComponents/HopperDevice.h index d63c6f6aa1..af8352a702 100644 --- a/OpenSim/ExampleComponents/HopperDevice.h +++ b/OpenSim/ExampleComponents/HopperDevice.h @@ -101,7 +101,7 @@ class OSIMEXAMPLECOMPONENTS_API HopperDevice : public ModelComponent { void extendRealizeDynamics(const SimTK::State& s) const override { const auto& actuator = getComponent(get_actuator_name()); double level = fmin(1., getTension(s) / actuator.get_optimal_force()); - actuator.getGeometryPath().setColor(s, SimTK::Vec3(level, 0.5, 0)); + actuator.getPath().setColor(s, SimTK::Vec3(level, 0.5, 0)); } }; // end of HopperDevice diff --git a/OpenSim/Examples/ExampleHopperDevice/buildDeviceModel.cpp b/OpenSim/Examples/ExampleHopperDevice/buildDeviceModel.cpp index 901dd35389..718ebe0ed0 100644 --- a/OpenSim/Examples/ExampleHopperDevice/buildDeviceModel.cpp +++ b/OpenSim/Examples/ExampleHopperDevice/buildDeviceModel.cpp @@ -82,7 +82,8 @@ Device* buildDevice() { auto pathActuator = new PathActuator(); pathActuator->setName("cableAtoB"); pathActuator->set_optimal_force(OPTIMAL_FORCE); - pathActuator->addNewPathPoint("pointA", *cuffA, Vec3(0)); + auto& path = dynamic_cast(pathActuator->updPath()); + path.appendNewPathPoint("pointA", *cuffA, Vec3(0)); //pathActuator->addNewPathPoint("pointB", *cuffB, Vec3(0)); device->addComponent(pathActuator); diff --git a/OpenSim/Examples/ExampleHopperDevice/buildDeviceModel_answers.cpp b/OpenSim/Examples/ExampleHopperDevice/buildDeviceModel_answers.cpp index 58c2ec8a37..018bc80606 100644 --- a/OpenSim/Examples/ExampleHopperDevice/buildDeviceModel_answers.cpp +++ b/OpenSim/Examples/ExampleHopperDevice/buildDeviceModel_answers.cpp @@ -111,8 +111,9 @@ Device* buildDevice() { auto pathActuator = new PathActuator(); pathActuator->setName("cableAtoB"); pathActuator->set_optimal_force(OPTIMAL_FORCE); - pathActuator->addNewPathPoint("pointA", *cuffA, Vec3(0)); - pathActuator->addNewPathPoint("pointB", *cuffB, Vec3(0)); + auto& path = dynamic_cast(pathActuator->updPath()); + path.appendNewPathPoint("pointA", *cuffA, Vec3(0)); + path.appendNewPathPoint("pointB", *cuffB, Vec3(0)); device->addComponent(pathActuator); // Create a PropMyoController. diff --git a/OpenSim/Examples/ExampleHopperDevice/buildHopperModel.cpp b/OpenSim/Examples/ExampleHopperDevice/buildHopperModel.cpp index b32f5de02e..e642d3f399 100644 --- a/OpenSim/Examples/ExampleHopperDevice/buildHopperModel.cpp +++ b/OpenSim/Examples/ExampleHopperDevice/buildHopperModel.cpp @@ -144,8 +144,9 @@ Model buildHopper(bool showVisualizer) { mclPennAng = 0.; auto vastus = new Thelen2003Muscle("vastus", mclFmax, mclOptFibLen, mclTendonSlackLen, mclPennAng); - vastus->addNewPathPoint("origin", *thigh, Vec3(linkRadius, 0.1, 0)); - vastus->addNewPathPoint("insertion", *shank, Vec3(linkRadius, 0.15, 0)); + auto& path = dynamic_cast(vastus->updPath()); + path.appendNewPathPoint("origin", *thigh, Vec3(linkRadius, 0.1, 0)); + path.appendNewPathPoint("insertion", *shank, Vec3(linkRadius, 0.15, 0)); hopper.addForce(vastus); // Attach a cylinder (patella) to the distal end of the thigh over which the @@ -162,7 +163,7 @@ Model buildHopper(bool showVisualizer) { thigh->addComponent(patellaFrame); // Configure the vastus muscle to wrap over the patella. - vastus->updGeometryPath().addPathWrap(*patella); + path.addPathWrap(*patella); // Create a controller to excite the vastus muscle. auto brain = new PrescribedController(); diff --git a/OpenSim/Examples/ExampleHopperDevice/defineDeviceAndController.h b/OpenSim/Examples/ExampleHopperDevice/defineDeviceAndController.h index a786d6eab3..cec133cceb 100644 --- a/OpenSim/Examples/ExampleHopperDevice/defineDeviceAndController.h +++ b/OpenSim/Examples/ExampleHopperDevice/defineDeviceAndController.h @@ -105,7 +105,7 @@ class Device : public ModelComponent { void extendRealizeDynamics(const SimTK::State& s) const override { const auto& actuator = getComponent("cableAtoB"); double level = fmin(1., getTension(s) / actuator.get_optimal_force()); - actuator.getGeometryPath().setColor(s, SimTK::Vec3(0.1, level, 0.1)); + actuator.getPath().setColor(s, SimTK::Vec3(0.1, level, 0.1)); } }; // end of Device diff --git a/OpenSim/Examples/ExampleHopperDevice/defineDeviceAndController_answers.h b/OpenSim/Examples/ExampleHopperDevice/defineDeviceAndController_answers.h index 9463b69d1b..9b71d7bfa0 100644 --- a/OpenSim/Examples/ExampleHopperDevice/defineDeviceAndController_answers.h +++ b/OpenSim/Examples/ExampleHopperDevice/defineDeviceAndController_answers.h @@ -154,7 +154,7 @@ class Device : public ModelComponent { void extendRealizeDynamics(const SimTK::State& s) const override { const auto& actuator = getComponent("cableAtoB"); double level = fmin(1., getTension(s) / actuator.get_optimal_force()); - actuator.getGeometryPath().setColor(s, SimTK::Vec3(0.1, level, 0.1)); + actuator.getPath().setColor(s, SimTK::Vec3(0.1, level, 0.1)); } }; // end of Device diff --git a/OpenSim/Examples/ExampleHopperDevice/exampleHopperDevice.cpp b/OpenSim/Examples/ExampleHopperDevice/exampleHopperDevice.cpp index 983b3fb1fa..38605fc3b2 100644 --- a/OpenSim/Examples/ExampleHopperDevice/exampleHopperDevice.cpp +++ b/OpenSim/Examples/ExampleHopperDevice/exampleHopperDevice.cpp @@ -99,7 +99,8 @@ void connectDeviceToModel(OpenSim::Device& device, OpenSim::Model& model, if (model.hasComponent(patellaPath)) { auto& cable = model.updComponent("device/cableAtoB"); auto& wrapObject = model.updComponent(patellaPath); - cable.updGeometryPath().addPathWrap(wrapObject); + auto& path = dynamic_cast(cable.updPath()); + path.addPathWrap(wrapObject); } } diff --git a/OpenSim/Examples/ExampleHopperDevice/exampleHopperDevice_answers.cpp b/OpenSim/Examples/ExampleHopperDevice/exampleHopperDevice_answers.cpp index 429deffb2f..59e9944026 100644 --- a/OpenSim/Examples/ExampleHopperDevice/exampleHopperDevice_answers.cpp +++ b/OpenSim/Examples/ExampleHopperDevice/exampleHopperDevice_answers.cpp @@ -131,7 +131,8 @@ void connectDeviceToModel(OpenSim::Device& device, OpenSim::Model& model, if (model.hasComponent(patellaPath)) { auto& cable = model.updComponent("device/cableAtoB"); auto& wrapObject = model.updComponent(patellaPath); - cable.updGeometryPath().addPathWrap(wrapObject); + auto& path = dynamic_cast(cable.updPath()); + path.addPathWrap(wrapObject); } } diff --git a/OpenSim/Examples/ExampleLuxoMuscle/LuxoMuscle_create_and_simulate.cpp b/OpenSim/Examples/ExampleLuxoMuscle/LuxoMuscle_create_and_simulate.cpp index 81ce50c5df..59064ec6a0 100644 --- a/OpenSim/Examples/ExampleLuxoMuscle/LuxoMuscle_create_and_simulate.cpp +++ b/OpenSim/Examples/ExampleLuxoMuscle/LuxoMuscle_create_and_simulate.cpp @@ -713,9 +713,11 @@ void createLuxoJr(OpenSim::Model& model){ "knee_extensor_right", knee_extensor_F0, knee_extensor_lm0, knee_extensor_lts, pennationAngle); - kneeExtensorRight->addNewPathPoint("knee_extensor_right_origin", *leg_Hlink, + auto& pathKneeRight = dynamic_cast( + kneeExtensorRight->updPath()); + pathKneeRight.appendNewPathPoint("knee_extensor_right_origin", *leg_Hlink, knee_extensor_origin); - kneeExtensorRight->addNewPathPoint("knee_extensor_right_insertion", + pathKneeRight.appendNewPathPoint("knee_extensor_right_insertion", *bottom_bracket, knee_extensor_insertion); kneeExtensorRight->set_ignore_tendon_compliance(true); @@ -727,14 +729,16 @@ void createLuxoJr(OpenSim::Model& model){ knee_extensor_F0, knee_extensor_lm0, knee_extensor_lts, pennationAngle); - kneeExtensorLeft->addNewPathPoint("knee_extensor_left_origin", *leg_Hlink, + auto& pathKneeLeft = dynamic_cast( + kneeExtensorLeft->updPath()); + pathKneeLeft.appendNewPathPoint("knee_extensor_left_origin", *leg_Hlink, knee_extensor_origin); - kneeExtensorLeft->addNewPathPoint("knee_extensor_left_insertion", + pathKneeLeft.appendNewPathPoint("knee_extensor_left_insertion", *bottom_bracket, knee_extensor_insertion); // flip the z coordinates of all path points - PathPointSet& points = kneeExtensorLeft->updGeometryPath().updPathPointSet(); + PathPointSet& points = pathKneeLeft.updPathPointSet(); for (int i=0; i(points[i]).upd_location()[2] *= -1; } @@ -747,10 +751,12 @@ void createLuxoJr(OpenSim::Model& model){ "back_extensor_right", back_extensor_F0, back_extensor_lm0, back_extensor_lts, pennationAngle); - - backExtensorRight->addNewPathPoint("back_extensor_right_origin", *chest, + + auto& pathBackRight = dynamic_cast( + backExtensorRight->updPath()); + pathBackRight.appendNewPathPoint("back_extensor_right_origin", *chest, back_extensor_origin); - backExtensorRight->addNewPathPoint("back_extensor_right_insertion", *back, + pathBackRight.appendNewPathPoint("back_extensor_right_insertion", *back, back_extensor_insertion); backExtensorRight->set_ignore_tendon_compliance(true); model.addForce(backExtensorRight); @@ -760,13 +766,15 @@ void createLuxoJr(OpenSim::Model& model){ new Millard2012EquilibriumMuscle("back_extensor_left", back_extensor_F0, back_extensor_lm0, back_extensor_lts, pennationAngle); - backExtensorLeft->addNewPathPoint("back_extensor_left_origin", *chest, + + auto& pathBackLeft = dynamic_cast( + backExtensorLeft->updPath()); + pathBackLeft.appendNewPathPoint("back_extensor_left_origin", *chest, back_extensor_origin); - backExtensorLeft->addNewPathPoint("back_extensor_left_insertion", *back, + pathBackLeft.appendNewPathPoint("back_extensor_left_insertion", *back, back_extensor_insertion); - PathPointSet& pointsLeft = backExtensorLeft->updGeometryPath() - .updPathPointSet(); + PathPointSet& pointsLeft = pathBackLeft.updPathPointSet(); for (int i=0; i(pointsLeft[i]).upd_location()[2] *= -1; } diff --git a/OpenSim/Examples/ExampleMain/OutputReference/TugOfWar_Complete.cpp b/OpenSim/Examples/ExampleMain/OutputReference/TugOfWar_Complete.cpp index fd9b3009ed..74f5732974 100644 --- a/OpenSim/Examples/ExampleMain/OutputReference/TugOfWar_Complete.cpp +++ b/OpenSim/Examples/ExampleMain/OutputReference/TugOfWar_Complete.cpp @@ -201,11 +201,13 @@ int main() // Specify the paths for the two muscles // Path for muscle 1 - muscle1->addNewPathPoint("muscle1-point1", ground, Vec3(0.0,0.05,-0.35)); - muscle1->addNewPathPoint("muscle1-point2", *block, Vec3(0.0,0.0,-0.05)); + auto& path1 = dynamic_cast(muscle1->updPath()); + path1.appendNewPathPoint("muscle1-point1", ground, Vec3(0.0,0.05,-0.35)); + path1.appendNewPathPoint("muscle1-point2", *block, Vec3(0.0,0.0,-0.05)); // Path for muscle 2 - muscle2->addNewPathPoint("muscle2-point1", ground, Vec3(0.0,0.05,0.35)); - muscle2->addNewPathPoint("muscle2-point2", *block, Vec3(0.0,0.0,0.05)); + auto& path2 = dynamic_cast(muscle2->updPath()); + path2.appendNewPathPoint("muscle2-point1", ground, Vec3(0.0,0.05,0.35)); + path2.appendNewPathPoint("muscle2-point2", *block, Vec3(0.0,0.0,0.05)); // Add the two muscles (as forces) to the model osimModel.addForce(muscle1); diff --git a/OpenSim/Examples/Moco/exampleHangingMuscle/exampleHangingMuscle.cpp b/OpenSim/Examples/Moco/exampleHangingMuscle/exampleHangingMuscle.cpp index 68f3c364b5..05de78f562 100644 --- a/OpenSim/Examples/Moco/exampleHangingMuscle/exampleHangingMuscle.cpp +++ b/OpenSim/Examples/Moco/exampleHangingMuscle/exampleHangingMuscle.cpp @@ -63,8 +63,9 @@ Model createHangingMuscleModel(bool ignoreActivationDynamics, actu->set_tendon_compliance_dynamics_mode("implicit"); actu->set_max_contraction_velocity(10); actu->set_pennation_angle_at_optimal(0.10); - actu->addNewPathPoint("origin", model.updGround(), SimTK::Vec3(0)); - actu->addNewPathPoint("insertion", *body, SimTK::Vec3(0)); + auto& path = dynamic_cast(actu->updPath()); + path.appendNewPathPoint("origin", model.updGround(), SimTK::Vec3(0)); + path.appendNewPathPoint("insertion", *body, SimTK::Vec3(0)); model.addForce(actu); // Add metabolics probes: one for the total metabolic rate, diff --git a/OpenSim/Examples/MuscleExample/mainFatigue.cpp b/OpenSim/Examples/MuscleExample/mainFatigue.cpp index 7b64fda44b..1b5cedfbbf 100644 --- a/OpenSim/Examples/MuscleExample/mainFatigue.cpp +++ b/OpenSim/Examples/MuscleExample/mainFatigue.cpp @@ -133,14 +133,16 @@ int main() pennationAngle); // Define the path of the muscles - fatigable->addNewPathPoint("fatigable-point1", ground, + auto& fatigablePath = dynamic_cast(fatigable->updPath()); + fatigablePath.appendNewPathPoint("fatigable-point1", ground, Vec3(0.0, halfLength, -0.35)); - fatigable->addNewPathPoint("fatigable-point2", *block, + fatigablePath.appendNewPathPoint("fatigable-point2", *block, Vec3(0.0, halfLength, -halfLength)); - original->addNewPathPoint("original-point1", ground, + auto& originalPath = dynamic_cast(original->updPath()); + originalPath.appendNewPathPoint("original-point1", ground, Vec3(0.0, halfLength, 0.35)); - original->addNewPathPoint("original-point2", *block, + originalPath.appendNewPathPoint("original-point2", *block, Vec3(0.0, halfLength, halfLength)); // Define the default states for the two muscles diff --git a/OpenSim/Examples/checkEnvironment/checkEnvironment.cpp b/OpenSim/Examples/checkEnvironment/checkEnvironment.cpp index 48feb8dae2..e456bcc2d2 100644 --- a/OpenSim/Examples/checkEnvironment/checkEnvironment.cpp +++ b/OpenSim/Examples/checkEnvironment/checkEnvironment.cpp @@ -133,11 +133,13 @@ int main() // Specify the paths for the two muscles // Path for muscle 1 - muscle1->addNewPathPoint("muscle1-point1", ground, Vec3(0.0,0.05,-0.35)); - muscle1->addNewPathPoint("muscle1-point2", *block, Vec3(0.0,0.0,-0.05)); + auto& path1 = dynamic_cast(muscle1->updPath()); + path1.appendNewPathPoint("muscle1-point1", ground, Vec3(0.0,0.05,-0.35)); + path1.appendNewPathPoint("muscle1-point2", *block, Vec3(0.0,0.0,-0.05)); // Path for muscle 2 - muscle2->addNewPathPoint("muscle2-point1", ground, Vec3(0.0,0.05,0.35)); - muscle2->addNewPathPoint("muscle2-point2", *block, Vec3(0.0,0.0,0.05)); + auto& path2 = dynamic_cast(muscle2->updPath()); + path2.appendNewPathPoint("muscle2-point1", ground, Vec3(0.0,0.05,0.35)); + path2.appendNewPathPoint("muscle2-point2", *block, Vec3(0.0,0.0,0.05)); // Add the two muscles (as forces) to the model osimModel.addForce(muscle1); diff --git a/OpenSim/Moco/Test/testMocoActuators.cpp b/OpenSim/Moco/Test/testMocoActuators.cpp index 4a2839e181..dfc3ce0adc 100644 --- a/OpenSim/Moco/Test/testMocoActuators.cpp +++ b/OpenSim/Moco/Test/testMocoActuators.cpp @@ -58,8 +58,9 @@ Model createHangingMuscleModel(double optimalFiberLength, } actu->set_max_contraction_velocity(10); actu->set_pennation_angle_at_optimal(0); - actu->addNewPathPoint("origin", model.updGround(), SimTK::Vec3(0)); - actu->addNewPathPoint("insertion", *body, SimTK::Vec3(0)); + auto& path = dynamic_cast(actu->updPath()); + path.appendNewPathPoint("origin", model.updGround(), SimTK::Vec3(0)); + path.appendNewPathPoint("insertion", *body, SimTK::Vec3(0)); model.addForce(actu); body->attachGeometry(new Sphere(0.05)); diff --git a/OpenSim/Moco/Test/testMocoInterface.cpp b/OpenSim/Moco/Test/testMocoInterface.cpp index e0a045560e..54b441bf8f 100644 --- a/OpenSim/Moco/Test/testMocoInterface.cpp +++ b/OpenSim/Moco/Test/testMocoInterface.cpp @@ -1965,8 +1965,9 @@ TEST_CASE("MocoPhase::bound_activation_from_excitation") { musclePtr->set_ignore_tendon_compliance(true); musclePtr->set_fiber_damping(0); musclePtr->setName("muscle"); - musclePtr->addNewPathPoint("origin", model.updGround(), SimTK::Vec3(0)); - musclePtr->addNewPathPoint("insertion", *body, SimTK::Vec3(0)); + auto& path = dynamic_cast(musclePtr->updPath()); + path.appendNewPathPoint("origin", model.updGround(), SimTK::Vec3(0)); + path.appendNewPathPoint("insertion", *body, SimTK::Vec3(0)); model.addComponent(musclePtr); model.finalizeConnections(); SECTION("bound_activation_from_excitation is false") { diff --git a/OpenSim/Moco/Test/testMocoMetabolics.cpp b/OpenSim/Moco/Test/testMocoMetabolics.cpp index e31c1b557c..b9136e52a6 100644 --- a/OpenSim/Moco/Test/testMocoMetabolics.cpp +++ b/OpenSim/Moco/Test/testMocoMetabolics.cpp @@ -37,8 +37,9 @@ TEST_CASE("Bhargava2004SmoothedMuscleMetabolics basics") { musclePtr->set_ignore_tendon_compliance(false); musclePtr->set_fiber_damping(0.01); musclePtr->setName("muscle"); - musclePtr->addNewPathPoint("origin", model.updGround(), SimTK::Vec3(0)); - musclePtr->addNewPathPoint("insertion", *body, SimTK::Vec3(0)); + auto& path = dynamic_cast(musclePtr->updPath()); + path.appendNewPathPoint("origin", model.updGround(), SimTK::Vec3(0)); + path.appendNewPathPoint("insertion", *body, SimTK::Vec3(0)); model.addComponent(musclePtr); auto& muscle = model.getComponent("muscle"); diff --git a/OpenSim/Simulation/Model/AbstractPath.cpp b/OpenSim/Simulation/Model/AbstractPath.cpp index f0be53bcf1..9071c1aa2a 100644 --- a/OpenSim/Simulation/Model/AbstractPath.cpp +++ b/OpenSim/Simulation/Model/AbstractPath.cpp @@ -22,6 +22,7 @@ * -------------------------------------------------------------------------- */ #include "AbstractPath.h" +#include "Appearance.h" using namespace OpenSim; @@ -50,3 +51,14 @@ void AbstractPath::setDefaultColor(const SimTK::Vec3& color) updProperty_appearance().setValueIsDefault(false); upd_appearance().set_color(color); } + +double OpenSim::AbstractPath::getPreScaleLength(const SimTK::State&) const +{ + return _preScaleLength; +} + +void OpenSim::AbstractPath::setPreScaleLength(const SimTK::State&, + double preScaleLength) +{ + _preScaleLength = preScaleLength; +} \ No newline at end of file diff --git a/OpenSim/Simulation/Model/AbstractPath.h b/OpenSim/Simulation/Model/AbstractPath.h index 8638056f57..a682cf3554 100644 --- a/OpenSim/Simulation/Model/AbstractPath.h +++ b/OpenSim/Simulation/Model/AbstractPath.h @@ -183,6 +183,28 @@ OpenSim_DECLARE_ABSTRACT_OBJECT(AbstractPath, ModelComponent); * get the color of the path in that state. */ void setDefaultColor(const SimTK::Vec3& color); + + /** + * Get the current length of the path, *before* the last set of scaling + * operations were applied to it. + * + * Internally, the path stores the original length in a `double` during + * `extendPreScale`. Therefore, be *very* careful with this method, because + * the recorded length is dependent on the length as computed during + * `extendPreScale`, which may have been called with a different state. + */ + double getPreScaleLength(const SimTK::State& s) const; + void setPreScaleLength(const SimTK::State& s, double preScaleLength); + +private: + // Used by `(get|set)PreLengthScale`. Used during `extend(Pre|Post)Scale` by + // downstream users of AbstractPath to cache the length of the path before + // scaling. + // + // Ideally, downstream classes would perform the caching themselves, because + // the AbstractPath API isn't an ideal place to store this information. This + // field is mostly here for backwards-compatability with the API. + double _preScaleLength = 0.0; }; } // namespace OpenSim diff --git a/OpenSim/Simulation/Model/ActivationFiberLengthMuscle.cpp b/OpenSim/Simulation/Model/ActivationFiberLengthMuscle.cpp index aa686fc7e6..87947705cb 100644 --- a/OpenSim/Simulation/Model/ActivationFiberLengthMuscle.cpp +++ b/OpenSim/Simulation/Model/ActivationFiberLengthMuscle.cpp @@ -182,14 +182,14 @@ extendPostScale(const SimTK::State& s, const ScaleSet& scaleSet) { Super::extendPostScale(s, scaleSet); - GeometryPath& path = upd_GeometryPath(); + AbstractPath& path = upd_path(); if (path.getPreScaleLength(s) > 0.0) { double scaleFactor = path.getLength(s) / path.getPreScaleLength(s); upd_optimal_fiber_length() *= scaleFactor; upd_tendon_slack_length() *= scaleFactor; - // Clear the pre-scale length that was stored in the GeometryPath. + // Clear the pre-scale length that was stored in the path. path.setPreScaleLength(s, 0.0); } } diff --git a/OpenSim/Simulation/Model/ActivationFiberLengthMuscle_Deprecated.cpp b/OpenSim/Simulation/Model/ActivationFiberLengthMuscle_Deprecated.cpp index 95aee886fd..d9a90ecfd6 100644 --- a/OpenSim/Simulation/Model/ActivationFiberLengthMuscle_Deprecated.cpp +++ b/OpenSim/Simulation/Model/ActivationFiberLengthMuscle_Deprecated.cpp @@ -346,14 +346,14 @@ extendPostScale(const SimTK::State& s, const ScaleSet& scaleSet) { Super::extendPostScale(s, scaleSet); - GeometryPath& path = upd_GeometryPath(); + AbstractPath& path = upd_path(); if (path.getPreScaleLength(s) > 0.0) { double scaleFactor = path.getLength(s) / path.getPreScaleLength(s); upd_optimal_fiber_length() *= scaleFactor; upd_tendon_slack_length() *= scaleFactor; - // Clear the pre-scale length that was stored in the GeometryPath. + // Clear the pre-scale length that was stored in the path. path.setPreScaleLength(s, 0.0); } } diff --git a/OpenSim/Simulation/Model/Blankevoort1991Ligament.cpp b/OpenSim/Simulation/Model/Blankevoort1991Ligament.cpp index 5d68506aad..4600117e55 100644 --- a/OpenSim/Simulation/Model/Blankevoort1991Ligament.cpp +++ b/OpenSim/Simulation/Model/Blankevoort1991Ligament.cpp @@ -24,6 +24,7 @@ #include #include #include "Blankevoort1991Ligament.h" +#include "GeometryPath.h" using namespace OpenSim; @@ -36,24 +37,6 @@ Blankevoort1991Ligament::Blankevoort1991Ligament() : Force() { setNull(); } -Blankevoort1991Ligament::Blankevoort1991Ligament(std::string name, - const PhysicalFrame& frame1, SimTK::Vec3 point1, - const PhysicalFrame& frame2, SimTK::Vec3 point2) - : Blankevoort1991Ligament() { - setName(name); - upd_GeometryPath().appendNewPathPoint("p1", frame1, point1); - upd_GeometryPath().appendNewPathPoint("p2", frame2, point2); -} - -Blankevoort1991Ligament::Blankevoort1991Ligament(std::string name, - const PhysicalFrame& frame1, SimTK::Vec3 point1, - const PhysicalFrame& frame2, SimTK::Vec3 point2, - double linear_stiffness, double slack_length) - : Blankevoort1991Ligament(name, frame1, point1, frame2, point2) { - set_linear_stiffness(linear_stiffness); - set_slack_length(slack_length); -} - Blankevoort1991Ligament::Blankevoort1991Ligament( std::string name, double linear_stiffness, double slack_length) : Blankevoort1991Ligament() { @@ -81,7 +64,7 @@ void Blankevoort1991Ligament::setNull() } void Blankevoort1991Ligament::constructProperties() { - constructProperty_GeometryPath(GeometryPath()); + constructProperty_path(GeometryPath()); constructProperty_linear_stiffness(1.0); constructProperty_transition_strain(0.06); constructProperty_damping_coefficient(0.003); @@ -109,7 +92,7 @@ void Blankevoort1991Ligament::extendFinalizeFromProperties() { "Transistion Strain cannot be less than 0"); // Set Default Ligament Color - GeometryPath& path = upd_GeometryPath(); + AbstractPath& path = upd_path(); path.setDefaultColor(SimTK::Vec3(0.1202, 0.7054, 0.1318)); } @@ -132,14 +115,14 @@ void Blankevoort1991Ligament::extendPostScale( const SimTK::State& s, const ScaleSet& scaleSet) { Super::extendPostScale(s, scaleSet); - GeometryPath& path = upd_GeometryPath(); + AbstractPath& path = upd_path(); double slack_length = get_slack_length(); if (path.getPreScaleLength(s) > 0.0) { double scaleFactor = path.getLength(s) / path.getPreScaleLength(s); set_slack_length(scaleFactor * slack_length); - // Clear the pre-scale length that was stored in the GeometryPath. + // Clear the pre-scale length that was stored in the path. path.setPreScaleLength(s, 0.0); } } @@ -149,12 +132,12 @@ void Blankevoort1991Ligament::extendPostScale( //============================================================================= double Blankevoort1991Ligament::getLength(const SimTK::State& state) const { - return get_GeometryPath().getLength(state); + return get_path().getLength(state); } double Blankevoort1991Ligament::getLengtheningSpeed( const SimTK::State& state) const { - return get_GeometryPath().getLengtheningSpeed(state); + return get_path().getLengtheningSpeed(state); } double Blankevoort1991Ligament::getStrain(const SimTK::State& state) const { @@ -340,7 +323,7 @@ void Blankevoort1991Ligament::computeForce(const SimTK::State& s, // total force double force_total = getTotalForce(s); - const GeometryPath &path = get_GeometryPath(); + const AbstractPath &path = get_path(); path.addInEquivalentForces( s, force_total, bodyForces, generalizedForces); @@ -372,7 +355,7 @@ double Blankevoort1991Ligament::computePotentialEnergy( double Blankevoort1991Ligament::computeMomentArm( const SimTK::State& s, Coordinate& aCoord) const { - return get_GeometryPath().computeMomentArm(s, aCoord); + return get_path().computeMomentArm(s, aCoord); } //============================================================================= diff --git a/OpenSim/Simulation/Model/Blankevoort1991Ligament.h b/OpenSim/Simulation/Model/Blankevoort1991Ligament.h index 4177aa704c..5c28d0cb24 100644 --- a/OpenSim/Simulation/Model/Blankevoort1991Ligament.h +++ b/OpenSim/Simulation/Model/Blankevoort1991Ligament.h @@ -24,7 +24,6 @@ * -------------------------------------------------------------------------- */ #include -#include namespace OpenSim { @@ -169,6 +168,8 @@ affected by scaling the model. */ +class AbstractPath; + class OSIMSIMULATION_API Blankevoort1991Ligament : public Force { OpenSim_DECLARE_CONCRETE_OBJECT(Blankevoort1991Ligament, Force) @@ -177,8 +178,8 @@ OpenSim_DECLARE_CONCRETE_OBJECT(Blankevoort1991Ligament, Force) // PROPERTIES //============================================================================= - OpenSim_DECLARE_UNNAMED_PROPERTY(GeometryPath, - "The set of points defining the path of the ligament") + OpenSim_DECLARE_PROPERTY(path, AbstractPath, + "The path defines the length and lengthening speed of the ligament.") OpenSim_DECLARE_PROPERTY(linear_stiffness, double, "The slope of the linear region of the force-strain curve. " "Units of force/strain (N).") @@ -223,15 +224,6 @@ OpenSim_DECLARE_CONCRETE_OBJECT(Blankevoort1991Ligament, Force) public: //Constructors Blankevoort1991Ligament(); - - Blankevoort1991Ligament(std::string name, - const PhysicalFrame& frame1, SimTK::Vec3 point1, - const PhysicalFrame& frame2, SimTK::Vec3 point2); - - Blankevoort1991Ligament(std::string name, - const PhysicalFrame& frame1, SimTK::Vec3 point1, - const PhysicalFrame& frame2, SimTK::Vec3 point2, - double linear_stiffness, double slack_length); Blankevoort1991Ligament(std::string name, double linear_stiffness, double slack_length); diff --git a/OpenSim/Simulation/Model/Force.h b/OpenSim/Simulation/Model/Force.h index 1a7466c57f..fcb72a33be 100644 --- a/OpenSim/Simulation/Model/Force.h +++ b/OpenSim/Simulation/Model/Force.h @@ -103,9 +103,9 @@ OpenSim_DECLARE_ABSTRACT_OBJECT(Force, ModelComponent); /** Return a flag indicating whether the Force is applied along a Path. If you override this method to return true for a specific subclass, it must - also implement the getGeometryPath() method. **/ - virtual bool hasGeometryPath() const { - return getPropertyIndex("GeometryPath").isValid(); + also implement the getPath() method. **/ + virtual bool hasPath() const { + return getPropertyIndex("path").isValid(); }; protected: diff --git a/OpenSim/Simulation/Model/Ligament.cpp b/OpenSim/Simulation/Model/Ligament.cpp index 942a90e426..db9298e3e7 100644 --- a/OpenSim/Simulation/Model/Ligament.cpp +++ b/OpenSim/Simulation/Model/Ligament.cpp @@ -63,7 +63,7 @@ Ligament::Ligament() void Ligament::constructProperties() { setAuthors("Peter Loan"); - constructProperty_GeometryPath(GeometryPath()); + constructProperty_path(GeometryPath()); constructProperty_resting_length(0.0); constructProperty_pcsa_force(0.0); @@ -84,7 +84,7 @@ void Ligament::extendFinalizeFromProperties() // Resting length must be greater than 0.0. assert(get_resting_length() > 0.0); - GeometryPath& path = upd_GeometryPath(); + AbstractPath& path = upd_path(); path.setDefaultColor(DefaultLigamentColor); } @@ -99,7 +99,7 @@ void Ligament::extendRealizeDynamics(const SimTK::State& state) const { if(appliesForce(state)){ const SimTK::Vec3 color = computePathColor(state); if (!color.isNaN()) - getGeometryPath().setColor(state, color); + getPath().setColor(state, color); } } @@ -145,7 +145,7 @@ SimTK::Vec3 Ligament::computePathColor(const SimTK::State& state) const { */ double Ligament::getLength(const SimTK::State& s) const { - return getGeometryPath().getLength(s); + return getPath().getLength(s); } //_____________________________________________________________________________ @@ -193,13 +193,13 @@ void Ligament::extendPostScale(const SimTK::State& s, const ScaleSet& scaleSet) { Super::extendPostScale(s, scaleSet); - GeometryPath& path = upd_GeometryPath(); + AbstractPath& path = upd_path(); if (path.getPreScaleLength(s) > 0.0) { double scaleFactor = path.getLength(s) / path.getPreScaleLength(s); upd_resting_length() *= scaleFactor; - // Clear the pre-scale length that was stored in the GeometryPath. + // Clear the pre-scale length that was stored in the path. path.setPreScaleLength(s, 0.0); } } @@ -218,7 +218,7 @@ const double& Ligament::getTension(const SimTK::State& s) const */ double Ligament::computeMomentArm(const SimTK::State& s, Coordinate& aCoord) const { - return getGeometryPath().computeMomentArm(s, aCoord); + return getPath().computeMomentArm(s, aCoord); } @@ -227,30 +227,22 @@ void Ligament::computeForce(const SimTK::State& s, SimTK::Vector_& bodyForces, SimTK::Vector& generalizedForces) const { - const GeometryPath& path = getGeometryPath(); + const auto& path = getPath(); const double& restingLength = get_resting_length(); const double& pcsaForce = get_pcsa_force(); - double force = 0; + double tension = 0; if (path.getLength(s) <= restingLength){ - setCacheVariableValue(s, _tensionCV, force); + setCacheVariableValue(s, _tensionCV, tension); return; } // evaluate normalized tendon force length curve - force = getForceLengthCurve().calcValue( + tension = getForceLengthCurve().calcValue( SimTK::Vector(1, path.getLength(s)/restingLength))* pcsaForce; - setCacheVariableValue(s, _tensionCV, force); + setCacheVariableValue(s, _tensionCV, tension); - OpenSim::Array PFDs; - path.getPointForceDirections(s, &PFDs); - - for (int i=0; i < PFDs.getSize(); i++) { - applyForceToPoint(s, PFDs[i]->frame(), PFDs[i]->point(), - force*PFDs[i]->direction(), bodyForces); - } - for(int i=0; i < PFDs.getSize(); i++) - delete PFDs[i]; + path.addInEquivalentForces(s, tension, bodyForces, generalizedForces); } diff --git a/OpenSim/Simulation/Model/Ligament.h b/OpenSim/Simulation/Model/Ligament.h index 9e5770332e..1314c1b4e4 100644 --- a/OpenSim/Simulation/Model/Ligament.h +++ b/OpenSim/Simulation/Model/Ligament.h @@ -39,14 +39,14 @@ namespace OpenSim { class Function; -class GeometryPath; +class AbstractPath; class ScaleSet; //============================================================================= //============================================================================= /** * A class implementing a ligament. The path of the ligament is - * stored in a GeometryPath object. + * stored in an object derived from AbstractPath. */ class OSIMSIMULATION_API Ligament : public Force { OpenSim_DECLARE_CONCRETE_OBJECT(Ligament, Force); @@ -54,8 +54,8 @@ OpenSim_DECLARE_CONCRETE_OBJECT(Ligament, Force); //============================================================================= // PROPERTIES //============================================================================= - OpenSim_DECLARE_UNNAMED_PROPERTY(GeometryPath, - "the set of points defining the path of the ligament"); + OpenSim_DECLARE_PROPERTY(path, AbstractPath, + "The path defines the length and lengthening speed of the PathSpring"); OpenSim_DECLARE_PROPERTY(resting_length, double, "resting length of the ligament"); OpenSim_DECLARE_PROPERTY(pcsa_force, double, @@ -76,11 +76,11 @@ OpenSim_DECLARE_CONCRETE_OBJECT(Ligament, Force); // GET //-------------------------------------------------------------------------- // Properties - const GeometryPath& getGeometryPath() const - { return get_GeometryPath(); } - GeometryPath& updGeometryPath() - { return upd_GeometryPath(); } - bool hasGeometryPath() const override { return true;}; + const AbstractPath& getPath() const + { return get_path(); } + AbstractPath& updPath() + { return upd_path(); } + bool hasPath() const override { return true;}; virtual double getLength(const SimTK::State& s) const; virtual double getRestingLength() const { return get_resting_length(); } diff --git a/OpenSim/Simulation/Model/Muscle.cpp b/OpenSim/Simulation/Model/Muscle.cpp index 3d1544109d..04ef81eb7f 100644 --- a/OpenSim/Simulation/Model/Muscle.cpp +++ b/OpenSim/Simulation/Model/Muscle.cpp @@ -26,7 +26,6 @@ //============================================================================= #include "Muscle.h" -#include "GeometryPath.h" #include "Model.h" #include @@ -156,7 +155,7 @@ void Muscle::constructProperties() // By default the min and max controls on muscle are 0.0 and 1.0 setMinControl(0.0); setMaxControl(1.0); - upd_GeometryPath().setDefaultColor(DefaultMuscleColor); + upd_path().setDefaultColor(DefaultMuscleColor); } @@ -680,12 +679,6 @@ SimTK::Vec3 Muscle::computePathColor(const SimTK::State& state) const { } -void Muscle::updateGeometry(const SimTK::State& s) -{ - updGeometryPath().updateGeometry(s); -} - - //_____________________________________________________________________________ /** * Utility function to calculate the current pennation angle in a diff --git a/OpenSim/Simulation/Model/Muscle.h b/OpenSim/Simulation/Model/Muscle.h index bbcec228dc..3dbfa6e389 100644 --- a/OpenSim/Simulation/Model/Muscle.h +++ b/OpenSim/Simulation/Model/Muscle.h @@ -440,9 +440,7 @@ OpenSim_DECLARE_ABSTRACT_OBJECT(Muscle, PathActuator); void extendAddToSystem(SimTK::MultibodySystem& system) const override; void extendSetPropertiesFromState(const SimTK::State &s) override; void extendInitStateFromProperties(SimTK::State& state) const override; - - // Update the display geometry attached to the muscle - virtual void updateGeometry(const SimTK::State& s); + // End of Interfaces imposed by parent classes. //@} diff --git a/OpenSim/Simulation/Model/PathActuator.cpp b/OpenSim/Simulation/Model/PathActuator.cpp index 130965241c..460c2a01fa 100644 --- a/OpenSim/Simulation/Model/PathActuator.cpp +++ b/OpenSim/Simulation/Model/PathActuator.cpp @@ -25,6 +25,7 @@ // INCLUDES //============================================================================= #include "PathActuator.h" +#include "GeometryPath.h" using namespace OpenSim; using namespace std; @@ -62,7 +63,7 @@ void PathActuator::setNull() */ void PathActuator::constructProperties() { - constructProperty_GeometryPath(GeometryPath()); + constructProperty_path(GeometryPath()); // TODO is this the best default? constructProperty_optimal_force(1.0); } @@ -107,7 +108,7 @@ double PathActuator::getOptimalForce() const */ double PathActuator::getLength(const SimTK::State& s) const { - return getGeometryPath().getLength(s); + return getPath().getLength(s); } //_____________________________________________________________________________ /** @@ -117,7 +118,7 @@ double PathActuator::getLength(const SimTK::State& s) const */ double PathActuator::getLengtheningSpeed(const SimTK::State& s) const { - return getGeometryPath().getLengtheningSpeed(s); + return getPath().getLengtheningSpeed(s); } //_____________________________________________________________________________ /** @@ -130,21 +131,6 @@ double PathActuator::getStress( const SimTK::State& s) const return fabs(getActuation(s)/get_optimal_force()); } - -//_____________________________________________________________________________ -/** - * Add a Path point to the _path of the actuator. The new point is appended - * to the end of the current path - * - */ -void PathActuator::addNewPathPoint( - const std::string& proposedName, - const PhysicalFrame& aBody, - const SimTK::Vec3& aPositionOnBody) { - // Create new PathPoint already appended to the PathPointSet for the path - updGeometryPath().appendNewPathPoint(proposedName, aBody, aPositionOnBody); -} - //============================================================================= // COMPUTATIONS //============================================================================= @@ -173,7 +159,7 @@ void PathActuator::computeForce( const SimTK::State& s, { if(!_model) return; - const GeometryPath &path = getGeometryPath(); + const auto &path = getPath(); // compute path's lengthening speed if necessary double speed = path.getLengtheningSpeed(s); @@ -200,7 +186,7 @@ void PathActuator::computeForce( const SimTK::State& s, */ double PathActuator::computeMomentArm(const SimTK::State& s, Coordinate& aCoord) const { - return getGeometryPath().computeMomentArm(s, aCoord); + return getPath().computeMomentArm(s, aCoord); } //------------------------------------------------------------------------------ @@ -216,7 +202,7 @@ void PathActuator::extendRealizeDynamics(const SimTK::State& state) const if (appliesForce(state) && !isActuationOverridden(state)){ const SimTK::Vec3 color = computePathColor(state); if (!color.isNaN()) - getGeometryPath().setColor(state, color); + getPath().setColor(state, color); } } diff --git a/OpenSim/Simulation/Model/PathActuator.h b/OpenSim/Simulation/Model/PathActuator.h index 49e1f5b2ec..5c874cd732 100644 --- a/OpenSim/Simulation/Model/PathActuator.h +++ b/OpenSim/Simulation/Model/PathActuator.h @@ -24,7 +24,7 @@ * -------------------------------------------------------------------------- */ #include "Actuator.h" -#include "GeometryPath.h" +#include "AbstractPath.h" //============================================================================= //============================================================================= @@ -37,8 +37,8 @@ class Model; /** * This is the base class for actuators that apply controllable tension along - * a geometry path. %PathActuator has no states; the control is simply the - * tension to be applied along a geometry path (i.e. tensionable rope). + * a path. %PathActuator has no states; the control is simply the tension to be + * applied along a path (i.e. tensionable rope). * * @author Ajay Seth */ @@ -48,8 +48,8 @@ class OSIMSIMULATION_API PathActuator : public ScalarActuator { //============================================================================= // PROPERTIES //============================================================================= - OpenSim_DECLARE_UNNAMED_PROPERTY(GeometryPath, - "The set of points defining the path of the actuator."); + OpenSim_DECLARE_PROPERTY(path, AbstractPath, + "The path of the actuator which defines length and lengthening speed."); OpenSim_DECLARE_PROPERTY(optimal_force, double, "The maximum force this actuator can produce."); @@ -67,10 +67,10 @@ class OSIMSIMULATION_API PathActuator : public ScalarActuator { // GET AND SET //-------------------------------------------------------------------------- // Path - GeometryPath& updGeometryPath() { return upd_GeometryPath(); } - const GeometryPath& getGeometryPath() const - { return get_GeometryPath(); } - bool hasGeometryPath() const override { return true;}; + AbstractPath& updPath() { return upd_path(); } + const AbstractPath& getPath() const + { return get_path(); } + bool hasPath() const override { return true;}; // OPTIMAL FORCE void setOptimalForce(double aOptimalForce); @@ -89,13 +89,6 @@ class OSIMSIMULATION_API PathActuator : public ScalarActuator { // STRESS double getStress( const SimTK::State& s ) const override; - // Convenience method to add PathPoints - /** Note that this function does not maintain the State and so should be used only - before a valid State is created */ - void addNewPathPoint(const std::string& proposedName, - const PhysicalFrame& aBody, - const SimTK::Vec3& aPositionOnBody); - //-------------------------------------------------------------------------- // APPLICATION //-------------------------------------------------------------------------- diff --git a/OpenSim/Simulation/Model/PathSpring.cpp b/OpenSim/Simulation/Model/PathSpring.cpp index 695380e4e3..9c1aa8465e 100644 --- a/OpenSim/Simulation/Model/PathSpring.cpp +++ b/OpenSim/Simulation/Model/PathSpring.cpp @@ -64,7 +64,7 @@ PathSpring::PathSpring(const string& name, double restLength, void PathSpring::constructProperties() { setAuthors("Ajay Seth"); - constructProperty_GeometryPath(GeometryPath()); + constructProperty_path(GeometryPath()); constructProperty_resting_length(SimTK::NaN); constructProperty_stiffness(SimTK::NaN); constructProperty_dissipation(SimTK::NaN); @@ -106,7 +106,7 @@ void PathSpring::extendFinalizeFromProperties() { Super::extendFinalizeFromProperties(); - GeometryPath& path = upd_GeometryPath(); + AbstractPath& path = upd_path(); path.setDefaultColor(DefaultPathSpringColor); OPENSIM_THROW_IF_FRMOBJ( @@ -139,7 +139,7 @@ void PathSpring::extendFinalizeFromProperties() */ double PathSpring::getLength(const SimTK::State& s) const { - return getGeometryPath().getLength(s); + return getPath().getLength(s); } double PathSpring::getStretch(const SimTK::State& s) const @@ -152,7 +152,7 @@ double PathSpring::getStretch(const SimTK::State& s) const double PathSpring::getLengtheningSpeed(const SimTK::State& s) const { - return getGeometryPath().getLengtheningSpeed(s); + return getPath().getLengtheningSpeed(s); } double PathSpring::getTension(const SimTK::State& s) const @@ -174,13 +174,13 @@ extendPostScale(const SimTK::State& s, const ScaleSet& scaleSet) { Super::extendPostScale(s, scaleSet); - GeometryPath& path = upd_GeometryPath(); + AbstractPath& path = upd_path(); if (path.getPreScaleLength(s) > 0.0) { double scaleFactor = path.getLength(s) / path.getPreScaleLength(s); upd_resting_length() *= scaleFactor; - // Clear the pre-scale length that was stored in the GeometryPath. + // Clear the pre-scale length that was stored in the AbstractPath. path.setPreScaleLength(s, 0.0); } } @@ -191,9 +191,10 @@ extendPostScale(const SimTK::State& s, const ScaleSet& scaleSet) /** * Compute the moment-arm of this muscle about a coordinate. */ -double PathSpring::computeMomentArm(const SimTK::State& s, const Coordinate& aCoord) const +double PathSpring::computeMomentArm(const SimTK::State& s, + const Coordinate& aCoord) const { - return getGeometryPath().computeMomentArm(s, aCoord); + return getPath().computeMomentArm(s, aCoord); } @@ -202,17 +203,7 @@ void PathSpring::computeForce(const SimTK::State& s, SimTK::Vector_& bodyForces, SimTK::Vector& generalizedForces) const { - const GeometryPath& path = getGeometryPath(); + const AbstractPath& path = getPath(); const double& tension = getTension(s); - - OpenSim::Array PFDs; - path.getPointForceDirections(s, &PFDs); - - for (int i=0; i < PFDs.getSize(); i++) { - applyForceToPoint(s, PFDs[i]->frame(), PFDs[i]->point(), - tension*PFDs[i]->direction(), bodyForces); - } - - for(int i=0; i < PFDs.getSize(); i++) - delete PFDs[i]; + path.addInEquivalentForces(s, tension, bodyForces, generalizedForces); } diff --git a/OpenSim/Simulation/Model/PathSpring.h b/OpenSim/Simulation/Model/PathSpring.h index 4d9f2fe332..b4ddabf6e9 100644 --- a/OpenSim/Simulation/Model/PathSpring.h +++ b/OpenSim/Simulation/Model/PathSpring.h @@ -31,20 +31,20 @@ namespace OpenSim { -class GeometryPath; +class AbstractPath; class ScaleSet; //============================================================================= //============================================================================= /** * A class implementing a PathSpring. The path of the PathSpring is - * determined by a GeometryPath object. A PathSpring is a massless Force - * element which applies tension along a path connected to bodies and can wrap - * over surfaces. The tension is proportional to its stretch beyond its - * resting length and the amount of dissipation scales with amount of stretch, - * such that tension = (K*s)*(1+D*ldot) where stretch, s = l-lo for l > lo, and - * 0 otherwise. l is the path length of the spring and lo is its rest length. - * K is the linear stiffness and D is the dissipation factor. + * determined by an object derived from AbstractPath. A PathSpring is a + * massless Force element which applies tension along a path connected to bodies + * and can wrap over surfaces. The tension is proportional to its stretch + * beyond its resting length and the amount of dissipation scales with amount of + * stretch, such that tension = (K*s)*(1+D*ldot) where stretch, s = l-lo for + * l > lo, and 0 otherwise. l is the path length of the spring and lo is its + * rest length. K is the linear stiffness and D is the dissipation factor. * When l < lo the spring applies no tension to the bodies and considered * to be slack. * @@ -62,9 +62,8 @@ OpenSim_DECLARE_CONCRETE_OBJECT(PathSpring, Force); "The linear stiffness (N/m) of the PathSpring"); OpenSim_DECLARE_PROPERTY(dissipation, double, "The dissipation factor (s/m) of the PathSpring"); - OpenSim_DECLARE_UNNAMED_PROPERTY(GeometryPath, - "The GeometryPath defines the set of points and wrapping surface" - "interactions that form the path of action of the PathSpring"); + OpenSim_DECLARE_PROPERTY(path, AbstractPath, + "The path defines the length and lengthening speed of the PathSpring"); //============================================================================= // OUTPUTS @@ -118,12 +117,11 @@ OpenSim_DECLARE_CONCRETE_OBJECT(PathSpring, Force); { return get_dissipation(); } void setDissipation(double dissipation); - /** Access the GeometryPath to update connection points and - specify wrap objects the path can interact with. */ - const GeometryPath& getGeometryPath() const - { return get_GeometryPath(); } - GeometryPath& updGeometryPath() - { return upd_GeometryPath(); } + /** Accessors for the AbstractPath object */ + const AbstractPath& getPath() const + { return get_path(); } + AbstractPath& updPath() + { return upd_path(); } //-------------------------------------------------------------------------- // State dependent values diff --git a/OpenSim/Simulation/MomentArmSolver.cpp b/OpenSim/Simulation/MomentArmSolver.cpp index 807b796475..c65fa9622d 100644 --- a/OpenSim/Simulation/MomentArmSolver.cpp +++ b/OpenSim/Simulation/MomentArmSolver.cpp @@ -24,6 +24,7 @@ #include "MomentArmSolver.h" #include "Model/PointForceDirection.h" #include "Model/Model.h" +#include "Model/GeometryPath.h" using namespace std; using namespace SimTK; diff --git a/OpenSim/Simulation/Test/testForces.cpp b/OpenSim/Simulation/Test/testForces.cpp index cdfb53dc0e..0b46ecec94 100644 --- a/OpenSim/Simulation/Test/testForces.cpp +++ b/OpenSim/Simulation/Test/testForces.cpp @@ -431,20 +431,18 @@ void testPathSpring() { osimModel.setGravity(gravity_vec); PathSpring spring("spring", restlength, stiffness, dissipation); - spring.updGeometryPath().appendNewPathPoint( - "origin", block, Vec3(-0.1, 0.0, 0.0)); + auto& path = dynamic_cast(spring.updPath()); + path.appendNewPathPoint("origin", block, Vec3(-0.1, 0.0, 0.0)); int N = 10; for (int i = 1; i < N; ++i) { double angle = i * Pi / N; double x = 0.1 * cos(angle); double y = 0.1 * sin(angle); - spring.updGeometryPath().appendNewPathPoint( - "", pulleyBody, Vec3(-x, y, 0.0)); + path.appendNewPathPoint("", pulleyBody, Vec3(-x, y, 0.0)); } - spring.updGeometryPath().appendNewPathPoint( - "insertion", block, Vec3(0.1, 0.0, 0.0)); + path.appendNewPathPoint("insertion", block, Vec3(0.1, 0.0, 0.0)); // BUG in defining wrapping API requires that the Force containing the // GeometryPath be connected to the model before the wrap can be added @@ -2093,14 +2091,12 @@ void testBlankevoort1991Ligament() { new Blankevoort1991Ligament("ligament", stiffness, restlength); ligament->set_damping_coefficient(0.0); - ligament->upd_GeometryPath().appendNewPathPoint( - "origin", ground, Vec3(0.0, 0.0, 0.0)); - ligament->upd_GeometryPath().addPathWrap(*pulley1); - ligament->upd_GeometryPath().appendNewPathPoint( - "midpoint", ground, Vec3(0.1, 0.6, 0.0)); - ligament->upd_GeometryPath().addPathWrap(*pulley2); - ligament->upd_GeometryPath().appendNewPathPoint( - "insertion", *block, Vec3(0.0, 0.0, 0.0)); + auto& path = dynamic_cast(ligament->upd_path()); + path.appendNewPathPoint("origin", ground, Vec3(0.0, 0.0, 0.0)); + path.addPathWrap(*pulley1); + path.appendNewPathPoint("midpoint", ground, Vec3(0.1, 0.6, 0.0)); + path.addPathWrap(*pulley2); + path.appendNewPathPoint("insertion", *block, Vec3(0.0, 0.0, 0.0)); osimModel.addForce(ligament); @@ -2210,8 +2206,11 @@ void testBlankevoort1991Ligament() { double lig_slack_length = 1.0; Blankevoort1991Ligament* lig = new Blankevoort1991Ligament("ligament", - model.updGround(), SimTK::Vec3(0), *brick, SimTK::Vec3(0), lig_stiffness, lig_slack_length); + // TODO assumes that GeometryPath is the default path type + auto& path2 = dynamic_cast(lig->upd_path()); + path2.appendNewPathPoint("origin", model.updGround(), SimTK::Vec3(0)); + path2.appendNewPathPoint("insertion", *brick, SimTK::Vec3(0)); model.addForce(lig); SimTK::State state = model.initSystem(); diff --git a/OpenSim/Simulation/Test/testMomentArms.cpp b/OpenSim/Simulation/Test/testMomentArms.cpp index 30365fb399..9d4c8b8949 100644 --- a/OpenSim/Simulation/Test/testMomentArms.cpp +++ b/OpenSim/Simulation/Test/testMomentArms.cpp @@ -152,8 +152,9 @@ void testMomentArmsAcrossCompoundJoint() model.addComponent(hip); Thelen2003Muscle* musc = new Thelen2003Muscle("muscle", 10., 0.1, 0.2, 0.); - musc->addNewPathPoint("p1", model.updGround(), SimTK::Vec3(0.05, 0, 0)); - musc->addNewPathPoint("p2", *leg, SimTK::Vec3(0.05, 0.25, 0.01)); + auto& path = dynamic_cast(musc->updPath()); + path.appendNewPathPoint("p1", model.updGround(), SimTK::Vec3(0.05, 0, 0)); + path.appendNewPathPoint("p2", *leg, SimTK::Vec3(0.05, 0.25, 0.01)); model.addForce(musc); SimTK::State& s = model.initSystem(); @@ -252,7 +253,7 @@ SimTK::Vector computeGenForceScaling(const Model &osimModel, const SimTK::State && (ac.getJoint().getName() != "tib_pat_r") ){ MobilizedBodyIndex modbodIndex = ac.getBodyIndex(); const MobilizedBody& mobod = osimModel.getMatterSubsystem().getMobilizedBody(modbodIndex); - SpatialVec Hcol = mobod.getHCol(s, SimTK::MobilizerUIndex(0)); //ac.getMobilizerQIndex())); // get n’th column of H + SpatialVec Hcol = mobod.getHCol(s, SimTK::MobilizerUIndex(0)); //ac.getMobilizerQIndex())); // get n�th column of H /*double thetaScale = */Hcol[0].norm(); // magnitude of the rotational part of this column of H @@ -349,8 +350,9 @@ void testMomentArmDefinitionForModel(const string &filename, const string &coord //cout << "muscle force: " << muscle.getForce(s) << endl; //double ma = muscle.computeMomentArm(s, coord); - double ma = maSolver.solve(s, coord, muscle.getGeometryPath()); - double ma_dldtheta = computeMomentArmFromDefinition(s, muscle.getGeometryPath(), coord); + const auto& path = dynamic_cast(muscle.updPath()); + double ma = maSolver.solve(s, coord, path); + double ma_dldtheta = computeMomentArmFromDefinition(s, path, coord); cout << "r's = " << ma << "::" << ma_dldtheta <<" at q = " << coord.getValue(s)*180/Pi; diff --git a/OpenSim/Simulation/Test/testMuscleMetabolicsProbes.cpp b/OpenSim/Simulation/Test/testMuscleMetabolicsProbes.cpp index 1017d32f38..068c59a100 100644 --- a/OpenSim/Simulation/Test/testMuscleMetabolicsProbes.cpp +++ b/OpenSim/Simulation/Test/testMuscleMetabolicsProbes.cpp @@ -385,8 +385,9 @@ void generateUmbergerMuscleData(const std::string& muscleName, // Create muscle attached to ground and block. UmbergerMuscle *muscle = new UmbergerMuscle(muscleName, maxIsometricForce, optimalFiberLength, width, Arel, Brel, FmaxEccentric); - muscle->addNewPathPoint("muscle-ground", ground, Vec3(0)); - muscle->addNewPathPoint("muscle-block", *block, Vec3(0)); + auto& path = dynamic_cast(muscle->updPath()); + path.appendNewPathPoint("muscle-ground", ground, Vec3(0)); + path.appendNewPathPoint("muscle-block", *block, Vec3(0)); model.addForce(muscle); // Attach muscle controller. @@ -696,15 +697,17 @@ void testProbesUsingMillardMuscleSimulation() Millard2012EquilibriumMuscle *muscle1 = new Millard2012EquilibriumMuscle( "muscle1", 100, optimalFiberLength, tendonSlackLength, 0); - muscle1->addNewPathPoint("m1_ground", ground, Vec3(-anchorDistance,0,0)); - muscle1->addNewPathPoint("m1_block", *block, Vec3(-blockSideLength/2,0,0)); + auto& path1 = dynamic_cast(muscle1->updPath()); + path1.appendNewPathPoint("m1_ground", ground, Vec3(-anchorDistance,0,0)); + path1.appendNewPathPoint("m1_block", *block, Vec3(-blockSideLength/2,0,0)); muscle1->setDefaultActivation(desiredActivation); model.addForce(muscle1); Millard2012EquilibriumMuscle *muscle2 = new Millard2012EquilibriumMuscle( "muscle2", 100, optimalFiberLength, tendonSlackLength, 0); - muscle2->addNewPathPoint("m2_ground", ground, Vec3(anchorDistance,0,0)); - muscle2->addNewPathPoint("m2_block", *block, Vec3(blockSideLength/2,0,0)); + auto& path2 = dynamic_cast(muscle2->updPath()); + path2.appendNewPathPoint("m2_ground", ground, Vec3(anchorDistance,0,0)); + path2.appendNewPathPoint("m2_block", *block, Vec3(blockSideLength/2,0,0)); muscle2->setDefaultActivation(desiredActivation); model.addForce(muscle2); diff --git a/OpenSim/Simulation/Test/testProbes.cpp b/OpenSim/Simulation/Test/testProbes.cpp index 232de3b022..34e7a5708c 100644 --- a/OpenSim/Simulation/Test/testProbes.cpp +++ b/OpenSim/Simulation/Test/testProbes.cpp @@ -247,8 +247,9 @@ void simulateMuscle( //Attach the muscle /*const string &actuatorType = */aMuscle->getConcreteClassName(); aMuscle->setName("muscle"); - aMuscle->addNewPathPoint("muscle-box", ground, Vec3(anchorWidth / 2, 0, 0)); - aMuscle->addNewPathPoint("muscle-ball", *ball, Vec3(-ballRadius, 0, 0)); + auto& path = dynamic_cast(aMuscle->updPath()); + path.appendNewPathPoint("muscle-box", ground, Vec3(anchorWidth / 2, 0, 0)); + path.appendNewPathPoint("muscle-ball", *ball, Vec3(-ballRadius, 0, 0)); ActivationFiberLengthMuscle_Deprecated *aflMuscle = dynamic_cast(aMuscle); diff --git a/OpenSim/Simulation/Wrap/PathWrap.cpp b/OpenSim/Simulation/Wrap/PathWrap.cpp index 9d2d81b36e..223d24e88f 100644 --- a/OpenSim/Simulation/Wrap/PathWrap.cpp +++ b/OpenSim/Simulation/Wrap/PathWrap.cpp @@ -26,6 +26,7 @@ //============================================================================= #include "PathWrap.h" #include +#include //============================================================================= // STATICS diff --git a/OpenSim/Tests/AddComponents/testAddComponents.cpp b/OpenSim/Tests/AddComponents/testAddComponents.cpp index 5f43a8bcb2..0b7f504280 100644 --- a/OpenSim/Tests/AddComponents/testAddComponents.cpp +++ b/OpenSim/Tests/AddComponents/testAddComponents.cpp @@ -199,11 +199,13 @@ void addComponentsToModel(Model& osimModel) // Specify the paths for the two muscles // Path for muscle 1 - muscle1->addNewPathPoint("muscle1-point1", ground, Vec3(0.0, 0.05, -0.35)); - muscle1->addNewPathPoint("muscle1-point2", *block, Vec3(0.0, 0.0, -0.05)); + auto& path1 = dynamic_cast(muscle1->updPath()); + path1.appendNewPathPoint("muscle1-point1", ground, Vec3(0.0,0.05,-0.35)); + path1.appendNewPathPoint("muscle1-point2", *block, Vec3(0.0,0.0,-0.05)); // Path for muscle 2 - muscle2->addNewPathPoint("muscle2-point1", ground, Vec3(0.0, 0.05, 0.35)); - muscle2->addNewPathPoint("muscle2-point2", *block, Vec3(0.0, 0.0, 0.05)); + auto& path2 = dynamic_cast(muscle2->updPath()); + path2.appendNewPathPoint("muscle2-point1", ground, Vec3(0.0,0.05,0.35)); + path2.appendNewPathPoint("muscle2-point2", *block, Vec3(0.0,0.0,0.05)); // Add the two muscles (as forces) to the model osimModel.addComponent(muscle1); diff --git a/OpenSim/Tests/README/testREADME.cpp b/OpenSim/Tests/README/testREADME.cpp index dfded913dc..83e2263692 100644 --- a/OpenSim/Tests/README/testREADME.cpp +++ b/OpenSim/Tests/README/testREADME.cpp @@ -76,8 +76,9 @@ int main() { // Add a muscle that flexes the elbow. Millard2012EquilibriumMuscle* biceps = new Millard2012EquilibriumMuscle("biceps", 100, 0.6, 0.55, 0); - biceps->addNewPathPoint("origin", *humerus, Vec3(0, 0.3, 0)); - biceps->addNewPathPoint("insertion", *radius, Vec3(0, 0.2, 0)); + auto& path = dynamic_cast(biceps->updPath()); + path.appendNewPathPoint("origin", *humerus, Vec3(0, 0.3, 0)); + path.appendNewPathPoint("insertion", *radius, Vec3(0, 0.2, 0)); // Add a controller that specifies the excitation of the muscle. PrescribedController* brain = new PrescribedController(); diff --git a/OpenSim/Tests/Wrapping/testWrapCylinder.cpp b/OpenSim/Tests/Wrapping/testWrapCylinder.cpp index 5d01272b8c..ab00db2765 100644 --- a/OpenSim/Tests/Wrapping/testWrapCylinder.cpp +++ b/OpenSim/Tests/Wrapping/testWrapCylinder.cpp @@ -413,11 +413,12 @@ namespace { { std::unique_ptr spring( new PathSpring("spring", 1., 1., 1.)); - spring->updGeometryPath().appendNewPathPoint( + auto& path = dynamic_cast(spring->updPath()); + path.appendNewPathPoint( "startPoint", model.get_ground(), input.path.start); - spring->updGeometryPath().appendNewPathPoint( + path.appendNewPathPoint( "endPoint", model.get_ground(), input.path.end); @@ -435,8 +436,9 @@ namespace { cylinder->set_xyz_body_rotation(input.eulerRotations); cylinder->setFrame(model.getGround()); - model.updComponent("spring") - .updGeometryPath().addPathWrap(*cylinder.get()); + auto& path = dynamic_cast( + model.updComponent("spring").updPath()); + path.addPathWrap(*cylinder.get()); model.updGround().addWrapObject(cylinder.release()); } @@ -451,8 +453,9 @@ namespace { // Trigger computing the wrapping path (realizing the state will not). model.getComponent("spring").getLength(state); - const WrapResult wrapResult = model.getComponent("spring") - .getGeometryPath() + const auto& path = dynamic_cast( + model.getComponent("spring").getPath()); + const WrapResult wrapResult = path .getWrapSet() .get("pathwrap") .getPreviousWrap(); diff --git a/OpenSim/Tests/Wrapping/testWrapping.cpp b/OpenSim/Tests/Wrapping/testWrapping.cpp index cf4e0dc6dc..6c78208fde 100644 --- a/OpenSim/Tests/Wrapping/testWrapping.cpp +++ b/OpenSim/Tests/Wrapping/testWrapping.cpp @@ -356,11 +356,10 @@ void testWrapCylinder() // One spring has wrap cylinder with respect to ground origin PathSpring* spring1 = new PathSpring("spring1", 1.0, 0.1, 0.01); - spring1->updGeometryPath(). - appendNewPathPoint("origin", ground, Vec3(-off, 0, 0)); - spring1->updGeometryPath(). - appendNewPathPoint("insert", *body, Vec3(0)); - spring1->updGeometryPath().addPathWrap(*pulley1); + auto& path1 = dynamic_cast(spring1->updPath()); + path1.appendNewPathPoint("origin", ground, Vec3(-off, 0, 0)); + path1.appendNewPathPoint("insert", *body, Vec3(0)); + path1.addPathWrap(*pulley1); model.addComponent(spring1); @@ -375,12 +374,11 @@ void testWrapCylinder() // Second spring has wrap cylinder with respect to bodyOffse origin PathSpring* spring2 = new PathSpring("spring2", 1.0, 0.1, 0.01); - spring2->updGeometryPath(). - appendNewPathPoint("origin", ground, Vec3(-off, 0, 0)); - spring2->updGeometryPath(). - appendNewPathPoint("insert", *body, Vec3(0)); - spring2->updGeometryPath().addPathWrap(*pulley2); - spring2->updGeometryPath().setDefaultColor(Vec3(0, 0.8, 0)); + auto& path2 = dynamic_cast(spring2->updPath()); + path2.appendNewPathPoint("origin", ground, Vec3(-off, 0, 0)); + path2.appendNewPathPoint("insert", *body, Vec3(0)); + path2.addPathWrap(*pulley2); + path2.setDefaultColor(Vec3(0, 0.8, 0)); model.addComponent(spring2); @@ -536,7 +534,8 @@ void simulateModelWithCables(const string &modelFile, double finalTime) Ligament* lig = dynamic_cast(&osimModel.getForceSet()[i]); if (lig != 0) { numLigaments++; - paths.append(&lig->updGeometryPath()); + auto& ligPath = dynamic_cast(lig->updPath()); + paths.append(&ligPath); pathNames.append(lig->getName()); continue; } @@ -544,9 +543,10 @@ void simulateModelWithCables(const string &modelFile, double finalTime) Muscle* mus = dynamic_cast(&osimModel.getForceSet()[i]); if (mus != 0) { numMuscles++; - paths.append(&mus->updGeometryPath()); + auto& musPath = dynamic_cast(mus->updPath()); + paths.append(&musPath); pathNames.append(mus->getName()); - cout << mus->getName() << ": " << mus->getGeometryPath().getWrapSet().getSize() << endl; + cout << mus->getName() << ": " << musPath.getWrapSet().getSize() << endl; continue; } } diff --git a/OpenSim/Tests/Wrapping/testWrappingAlgorithm.cpp b/OpenSim/Tests/Wrapping/testWrappingAlgorithm.cpp index 040e793753..b49457e4c8 100644 --- a/OpenSim/Tests/Wrapping/testWrappingAlgorithm.cpp +++ b/OpenSim/Tests/Wrapping/testWrappingAlgorithm.cpp @@ -151,11 +151,10 @@ void testSingleWrapObjectPerpendicular(WrapObject* wrapObject, Vec3 axisRotation PathSpring* spring1 = new PathSpring("spring1", 1.0, 0.1, 0.01); //offset in X direction to avoid ambiguous scenario where path passes through center - spring1->updGeometryPath(). - appendNewPathPoint("origin", ground, Vec3(r-.1, r, 0)); - spring1->updGeometryPath(). - appendNewPathPoint("insert", *body, Vec3(-r, r, 0)); - spring1->updGeometryPath().addPathWrap(*wObj); + auto& path1 = dynamic_cast(spring1->updPath()); + path1.appendNewPathPoint("origin", ground, Vec3(r-.1, r, 0)); + path1.appendNewPathPoint("insert", *body, Vec3(-r, r, 0)); + path1.addPathWrap(*wObj); model.addComponent(spring1); @@ -210,12 +209,11 @@ void testEllipsoidWrapLength(OpenSim::WrapEllipsoid* wrapObject) PathSpring* spring1 = new PathSpring("spring1", 1.0, 0.1, 0.01); //offset in X direction to avoid ambiguous scenario where path passes through center - spring1->updGeometryPath(). - appendNewPathPoint("origin", ground, Vec3(r - .1, r, 0)); + auto& path1 = dynamic_cast(spring1->updPath()); + path1.appendNewPathPoint("origin", ground, Vec3(r - .1, r, 0)); // insertion point is -r down from the tip of the long axis of the ellipsoid - spring1->updGeometryPath(). - appendNewPathPoint("insert", *body, Vec3(-wrapObject->get_dimensions()[0], -r, 0)); - spring1->updGeometryPath().addPathWrap(*wObj); + path1.appendNewPathPoint("insert", *body, Vec3(-wrapObject->get_dimensions()[0], -r, 0)); + path1.addPathWrap(*wObj); model.addComponent(spring1); diff --git a/OpenSim/Tests/testIterators/testIterators.cpp b/OpenSim/Tests/testIterators/testIterators.cpp index a3b837b9b8..0f7f51ee1a 100644 --- a/OpenSim/Tests/testIterators/testIterators.cpp +++ b/OpenSim/Tests/testIterators/testIterators.cpp @@ -23,6 +23,7 @@ * -------------------------------------------------------------------------- */ #include #include +#include #include "OpenSim/Simulation/SimbodyEngine/PinJoint.h" #include #include From 81d1aeeabb9cae06290a9a698532d406a142bad3 Mon Sep 17 00:00:00 2001 From: Nicholas Bianco Date: Fri, 25 Aug 2023 16:51:01 -0700 Subject: [PATCH 03/24] Safely initialize GeometryPath for path-based objects --- Applications/Scale/test/testScale.cpp | 4 +-- .../Actuators/DeGrooteFregly2016Muscle.cpp | 5 +-- OpenSim/Actuators/ModelFactory.cpp | 5 +-- OpenSim/Actuators/Test/testActuators.cpp | 4 +-- .../Test/testDeGrooteFregly2016Muscle.cpp | 2 +- OpenSim/Actuators/Test/testModelProcessor.cpp | 2 +- OpenSim/Actuators/Test/testMuscles.cpp | 16 ++++----- OpenSim/Analyses/Test/testOutputReporter.cpp | 2 +- .../ExampleHopperDevice/buildDeviceModel.cpp | 2 +- .../buildDeviceModel_answers.cpp | 2 +- .../ExampleHopperDevice/buildHopperModel.cpp | 2 +- .../exampleHopperDevice.cpp | 2 +- .../exampleHopperDevice_answers.cpp | 2 +- .../LuxoMuscle_create_and_simulate.cpp | 12 +++---- .../OutputReference/TugOfWar_Complete.cpp | 4 +-- .../exampleHangingMuscle.cpp | 2 +- .../Examples/MuscleExample/mainFatigue.cpp | 4 +-- .../checkEnvironment/checkEnvironment.cpp | 4 +-- OpenSim/Moco/Test/testMocoActuators.cpp | 2 +- OpenSim/Moco/Test/testMocoInterface.cpp | 2 +- OpenSim/Moco/Test/testMocoMetabolics.cpp | 2 +- OpenSim/Simulation/Model/AbstractPath.h | 2 +- .../Model/Blankevoort1991Ligament.cpp | 19 +++++----- .../Model/Blankevoort1991Ligament.h | 30 +++++++++++++--- OpenSim/Simulation/Model/Ligament.cpp | 7 ++++ OpenSim/Simulation/Model/Ligament.h | 35 ++++++++++++++----- OpenSim/Simulation/Model/PathActuator.cpp | 11 +++++- OpenSim/Simulation/Model/PathActuator.h | 24 ++++++++++--- OpenSim/Simulation/Model/PathSpring.cpp | 10 +++++- OpenSim/Simulation/Model/PathSpring.h | 32 ++++++++++++----- OpenSim/Simulation/Test/testForces.cpp | 7 ++-- OpenSim/Simulation/Test/testMomentArms.cpp | 2 +- .../Test/testMuscleMetabolicsProbes.cpp | 6 ++-- OpenSim/Simulation/Test/testProbes.cpp | 2 +- .../Tests/AddComponents/testAddComponents.cpp | 4 +-- OpenSim/Tests/README/testREADME.cpp | 2 +- .../Wrapping/testMuscleLengthRegression.cpp | 4 +-- OpenSim/Tests/Wrapping/testWrapCylinder.cpp | 6 ++-- OpenSim/Tests/Wrapping/testWrapping.cpp | 8 ++--- .../Tests/Wrapping/testWrappingAlgorithm.cpp | 4 +-- 40 files changed, 191 insertions(+), 106 deletions(-) diff --git a/Applications/Scale/test/testScale.cpp b/Applications/Scale/test/testScale.cpp index d0e98c0a2c..042711cacf 100644 --- a/Applications/Scale/test/testScale.cpp +++ b/Applications/Scale/test/testScale.cpp @@ -562,7 +562,7 @@ void scalePhysicalOffsetFrames() const Vec3 offset1 = Vec3(0.2, 0.4, 0.6); PathActuator* act1 = new PathActuator(); act1->setName("pathActuator1"); - auto& path = dynamic_cast(act1->updPath()); + auto& path = act1->updPath(); path.appendNewPathPoint("point1a", model->updGround(), Vec3(0)); path.appendNewPathPoint("point1b", *body, offset1); body->addComponent(act1); @@ -577,7 +577,7 @@ void scalePhysicalOffsetFrames() PathActuator* act2 = new PathActuator(); act2->setName("pathActuator2"); - auto& path2 = dynamic_cast(act2->updPath()); + auto& path2 = act2->updPath(); path2.appendNewPathPoint("point2a", model->updGround(), Vec3(0)); path2.appendNewPathPoint("point2b", *pof2, offset2); act1->addComponent(act2); diff --git a/OpenSim/Actuators/DeGrooteFregly2016Muscle.cpp b/OpenSim/Actuators/DeGrooteFregly2016Muscle.cpp index 1c9a26f791..60ca99c053 100644 --- a/OpenSim/Actuators/DeGrooteFregly2016Muscle.cpp +++ b/OpenSim/Actuators/DeGrooteFregly2016Muscle.cpp @@ -1024,11 +1024,8 @@ void DeGrooteFregly2016Muscle::replaceMuscles( // Copy the muscle's path. AbstractPath& path = muscBase.updPath(); - actu->updProperty_path().clear(); if (auto* pGeometryPath = dynamic_cast(&path)) { - actu->updProperty_path().setValue(GeometryPath()); - auto& thisGeometryPath = dynamic_cast( - actu->updPath()); + auto& thisGeometryPath = actu->initGeometryPath(); const auto& pathPointSet = pGeometryPath->getPathPointSet(); for (int ipp = 0; ipp < pathPointSet.getSize(); ++ipp) { diff --git a/OpenSim/Actuators/ModelFactory.cpp b/OpenSim/Actuators/ModelFactory.cpp index 7a4b55aeb3..a3a94c9d03 100644 --- a/OpenSim/Actuators/ModelFactory.cpp +++ b/OpenSim/Actuators/ModelFactory.cpp @@ -174,11 +174,8 @@ void ModelFactory::replaceMusclesWithPathActuators(OpenSim::Model &model) { // Copy the muscle's path. AbstractPath& path = musc.updPath(); - actu->updProperty_path().clear(); if (auto* pGeometryPath = dynamic_cast(&path)) { - actu->updProperty_path().setValue(GeometryPath()); - auto& thisGeometryPath = dynamic_cast( - actu->updPath()); + GeometryPath& thisGeometryPath = actu->initGeometryPath(); // For the connectee names in the PathPoints to be correct, we must // add the path points after adding the PathActuator to the model. diff --git a/OpenSim/Actuators/Test/testActuators.cpp b/OpenSim/Actuators/Test/testActuators.cpp index 12cfd35cf9..f0fc23cace 100644 --- a/OpenSim/Actuators/Test/testActuators.cpp +++ b/OpenSim/Actuators/Test/testActuators.cpp @@ -332,7 +332,7 @@ void testClutchedPathSpring() ClutchedPathSpring* spring = new ClutchedPathSpring("clutch_spring", stiffness, dissipation, 0.01); - auto& path = dynamic_cast(spring->updPath()); + auto& path = spring->updPath(); path.appendNewPathPoint("origin", *block, Vec3(-0.1, 0.0 ,0.0)); int N = 10; @@ -480,7 +480,7 @@ void testMcKibbenActuator() OpenSim::Body* ball = new OpenSim::Body("ball", mass, Vec3(0), mass*SimTK::Inertia::sphere(0.1)); ball->scale(Vec3(ball_radius), false); - auto& path = dynamic_cast(actuator->updPath()); + auto& path = actuator->updPath(); path.appendNewPathPoint("mck_ground", ground, Vec3(0)); path.appendNewPathPoint("mck_ball", *ball, Vec3(ball_radius)); diff --git a/OpenSim/Actuators/Test/testDeGrooteFregly2016Muscle.cpp b/OpenSim/Actuators/Test/testDeGrooteFregly2016Muscle.cpp index 81627369a6..1342d6f5a3 100644 --- a/OpenSim/Actuators/Test/testDeGrooteFregly2016Muscle.cpp +++ b/OpenSim/Actuators/Test/testDeGrooteFregly2016Muscle.cpp @@ -142,7 +142,7 @@ TEST_CASE("DeGrooteFregly2016Muscle basics") { musclePtr->set_ignore_tendon_compliance(true); musclePtr->set_fiber_damping(0); musclePtr->setName("muscle"); - auto& path = dynamic_cast(musclePtr->updPath()); + auto& path = musclePtr->updPath(); path.appendNewPathPoint("origin", model.updGround(), SimTK::Vec3(0)); path.appendNewPathPoint("insertion", *body, SimTK::Vec3(0)); model.addComponent(musclePtr); diff --git a/OpenSim/Actuators/Test/testModelProcessor.cpp b/OpenSim/Actuators/Test/testModelProcessor.cpp index 03ae5c731f..8129e9a989 100644 --- a/OpenSim/Actuators/Test/testModelProcessor.cpp +++ b/OpenSim/Actuators/Test/testModelProcessor.cpp @@ -93,7 +93,7 @@ Model createElbowModel() { auto* biceps = new Millard2012EquilibriumMuscle("biceps", 200, 0.6, 0.55, 0); - auto& path = dynamic_cast(biceps->updPath()); + auto& path = biceps->updPath(); path.appendNewPathPoint("origin", model.getGround(), Vec3(0, 0.8, 0)); path.appendNewPathPoint("insertion", *body, Vec3(0, 0.7, 0)); diff --git a/OpenSim/Actuators/Test/testMuscles.cpp b/OpenSim/Actuators/Test/testMuscles.cpp index d6c283e2f4..3eeeb44536 100644 --- a/OpenSim/Actuators/Test/testMuscles.cpp +++ b/OpenSim/Actuators/Test/testMuscles.cpp @@ -255,7 +255,7 @@ void simulateMuscle( //Attach the muscle const string &actuatorType = aMuscle->getConcreteClassName(); aMuscle->setName("muscle"); - auto& path = dynamic_cast(aMuscle->updPath()); + auto& path = aMuscle->updPath(); path.appendNewPathPoint("muscle-box", ground, Vec3(anchorWidth/2,0,0)); path.appendNewPathPoint("muscle-ball", *ball, Vec3(-ballRadius,0,0)); @@ -608,7 +608,7 @@ void testThelen2003Muscle() false); Model m; - auto& path = dynamic_cast(muscle.updPath()); + auto& path = muscle.updPath(); path.appendNewPathPoint("p1", m.getGround(), SimTK::Vec3(0.0)); path.appendNewPathPoint("p2", m.getGround(), SimTK::Vec3(1.0)); // Test property bounds. @@ -700,7 +700,7 @@ void testThelen2003Muscle() MaxIsometricForce0, OptimalFiberLength0, TendonSlackLength0, PennationAngle0); - auto& path = dynamic_cast(myMcl->updPath()); + auto& path = myMcl->updPath(); path.appendNewPathPoint("p1", myModel.getGround(), SimTK::Vec3(0.0)); path.appendNewPathPoint("p2", myModel.getGround(), SimTK::Vec3(1.0)); myModel.addForce(myMcl); @@ -786,7 +786,7 @@ void testThelen2003Muscle() const double tendonSlackLength = 0.001; auto muscle = new Thelen2003Muscle("muscle", 1., optimalFiberLength, tendonSlackLength, 0.); - auto& path = dynamic_cast(muscle->updPath()); + auto& path = muscle->updPath(); path.appendNewPathPoint("p1", model.updGround(), SimTK::Vec3(0)); path.appendNewPathPoint("p2", model.updGround(), SimTK::Vec3(0,0,1)); model.addForce(muscle); @@ -802,7 +802,7 @@ void testThelen2003Muscle() { Model model; auto muscle = new Thelen2003Muscle("muscle", 1., 0.5, 0.5, 0.); - auto& path = dynamic_cast(muscle->updPath()); + auto& path = muscle->updPath(); path.appendNewPathPoint("p1", model.updGround(), SimTK::Vec3(0)); path.appendNewPathPoint("p2", model.updGround(), SimTK::Vec3(0,0,1)); model.addForce(muscle); @@ -878,7 +878,7 @@ void testMillard2012EquilibriumMuscle() const double tendonSlackLength = 100.0; //long tendon auto muscle = new Millard2012EquilibriumMuscle("muscle", 1., optimalFiberLength, tendonSlackLength, 0.); - auto& path = dynamic_cast(muscle->updPath()); + auto& path = muscle->updPath(); path.appendNewPathPoint("p1", model.updGround(), SimTK::Vec3(0)); path.appendNewPathPoint("p2", model.updGround(), SimTK::Vec3(0,0,1)); model.addForce(muscle); @@ -897,7 +897,7 @@ void testMillard2012EquilibriumMuscle() const double tendonSlackLength = 0.1; //short tendon auto muscle = new Millard2012EquilibriumMuscle("muscle", 1., optimalFiberLength, tendonSlackLength, 0.); - auto& path = dynamic_cast(muscle->updPath()); + auto& path = muscle->updPath(); path.appendNewPathPoint("p1", model.updGround(), SimTK::Vec3(0)); path.appendNewPathPoint("p2", model.updGround(), SimTK::Vec3(0, 0, 1)); model.addForce(muscle); @@ -914,7 +914,7 @@ void testMillard2012EquilibriumMuscle() { Model model; auto muscle = new Millard2012EquilibriumMuscle("mcl", 1., 0.5, 0.5, 0.); - auto& path = dynamic_cast(muscle->updPath()); + auto& path = muscle->updPath(); path.appendNewPathPoint("p1", model.updGround(), SimTK::Vec3(0)); path.appendNewPathPoint("p2", model.updGround(), SimTK::Vec3(0,0,1)); model.addForce(muscle); diff --git a/OpenSim/Analyses/Test/testOutputReporter.cpp b/OpenSim/Analyses/Test/testOutputReporter.cpp index 4830593d28..a54832dd51 100644 --- a/OpenSim/Analyses/Test/testOutputReporter.cpp +++ b/OpenSim/Analyses/Test/testOutputReporter.cpp @@ -161,7 +161,7 @@ void simulateMuscle( //Attach the muscle /*const string &actuatorType = */muscle->getConcreteClassName(); muscle->setName("muscle"); - auto& path = dynamic_cast(muscle->updPath()); + auto& path = muscle->updPath(); path.appendNewPathPoint("muscle-box", ground, Vec3(anchorWidth / 2, 0, 0)); path.appendNewPathPoint("muscle-ball", *ball, Vec3(-ballRadius, 0, 0)); diff --git a/OpenSim/Examples/ExampleHopperDevice/buildDeviceModel.cpp b/OpenSim/Examples/ExampleHopperDevice/buildDeviceModel.cpp index 718ebe0ed0..8cbb7f2751 100644 --- a/OpenSim/Examples/ExampleHopperDevice/buildDeviceModel.cpp +++ b/OpenSim/Examples/ExampleHopperDevice/buildDeviceModel.cpp @@ -82,7 +82,7 @@ Device* buildDevice() { auto pathActuator = new PathActuator(); pathActuator->setName("cableAtoB"); pathActuator->set_optimal_force(OPTIMAL_FORCE); - auto& path = dynamic_cast(pathActuator->updPath()); + auto& path = pathActuator->updPath(); path.appendNewPathPoint("pointA", *cuffA, Vec3(0)); //pathActuator->addNewPathPoint("pointB", *cuffB, Vec3(0)); device->addComponent(pathActuator); diff --git a/OpenSim/Examples/ExampleHopperDevice/buildDeviceModel_answers.cpp b/OpenSim/Examples/ExampleHopperDevice/buildDeviceModel_answers.cpp index 018bc80606..7ac3053f7e 100644 --- a/OpenSim/Examples/ExampleHopperDevice/buildDeviceModel_answers.cpp +++ b/OpenSim/Examples/ExampleHopperDevice/buildDeviceModel_answers.cpp @@ -111,7 +111,7 @@ Device* buildDevice() { auto pathActuator = new PathActuator(); pathActuator->setName("cableAtoB"); pathActuator->set_optimal_force(OPTIMAL_FORCE); - auto& path = dynamic_cast(pathActuator->updPath()); + auto& path = pathActuator->updPath(); path.appendNewPathPoint("pointA", *cuffA, Vec3(0)); path.appendNewPathPoint("pointB", *cuffB, Vec3(0)); device->addComponent(pathActuator); diff --git a/OpenSim/Examples/ExampleHopperDevice/buildHopperModel.cpp b/OpenSim/Examples/ExampleHopperDevice/buildHopperModel.cpp index e642d3f399..49dc116244 100644 --- a/OpenSim/Examples/ExampleHopperDevice/buildHopperModel.cpp +++ b/OpenSim/Examples/ExampleHopperDevice/buildHopperModel.cpp @@ -144,7 +144,7 @@ Model buildHopper(bool showVisualizer) { mclPennAng = 0.; auto vastus = new Thelen2003Muscle("vastus", mclFmax, mclOptFibLen, mclTendonSlackLen, mclPennAng); - auto& path = dynamic_cast(vastus->updPath()); + auto& path = vastus->updPath(); path.appendNewPathPoint("origin", *thigh, Vec3(linkRadius, 0.1, 0)); path.appendNewPathPoint("insertion", *shank, Vec3(linkRadius, 0.15, 0)); hopper.addForce(vastus); diff --git a/OpenSim/Examples/ExampleHopperDevice/exampleHopperDevice.cpp b/OpenSim/Examples/ExampleHopperDevice/exampleHopperDevice.cpp index 38605fc3b2..bbc23bff52 100644 --- a/OpenSim/Examples/ExampleHopperDevice/exampleHopperDevice.cpp +++ b/OpenSim/Examples/ExampleHopperDevice/exampleHopperDevice.cpp @@ -99,7 +99,7 @@ void connectDeviceToModel(OpenSim::Device& device, OpenSim::Model& model, if (model.hasComponent(patellaPath)) { auto& cable = model.updComponent("device/cableAtoB"); auto& wrapObject = model.updComponent(patellaPath); - auto& path = dynamic_cast(cable.updPath()); + auto& path = cable.updPath(); path.addPathWrap(wrapObject); } } diff --git a/OpenSim/Examples/ExampleHopperDevice/exampleHopperDevice_answers.cpp b/OpenSim/Examples/ExampleHopperDevice/exampleHopperDevice_answers.cpp index 59e9944026..6a6384f324 100644 --- a/OpenSim/Examples/ExampleHopperDevice/exampleHopperDevice_answers.cpp +++ b/OpenSim/Examples/ExampleHopperDevice/exampleHopperDevice_answers.cpp @@ -131,7 +131,7 @@ void connectDeviceToModel(OpenSim::Device& device, OpenSim::Model& model, if (model.hasComponent(patellaPath)) { auto& cable = model.updComponent("device/cableAtoB"); auto& wrapObject = model.updComponent(patellaPath); - auto& path = dynamic_cast(cable.updPath()); + auto& path = cable.updPath(); path.addPathWrap(wrapObject); } } diff --git a/OpenSim/Examples/ExampleLuxoMuscle/LuxoMuscle_create_and_simulate.cpp b/OpenSim/Examples/ExampleLuxoMuscle/LuxoMuscle_create_and_simulate.cpp index 59064ec6a0..86a318b62a 100644 --- a/OpenSim/Examples/ExampleLuxoMuscle/LuxoMuscle_create_and_simulate.cpp +++ b/OpenSim/Examples/ExampleLuxoMuscle/LuxoMuscle_create_and_simulate.cpp @@ -713,8 +713,7 @@ void createLuxoJr(OpenSim::Model& model){ "knee_extensor_right", knee_extensor_F0, knee_extensor_lm0, knee_extensor_lts, pennationAngle); - auto& pathKneeRight = dynamic_cast( - kneeExtensorRight->updPath()); + auto& pathKneeRight = kneeExtensorRight->updPath(); pathKneeRight.appendNewPathPoint("knee_extensor_right_origin", *leg_Hlink, knee_extensor_origin); pathKneeRight.appendNewPathPoint("knee_extensor_right_insertion", @@ -729,8 +728,7 @@ void createLuxoJr(OpenSim::Model& model){ knee_extensor_F0, knee_extensor_lm0, knee_extensor_lts, pennationAngle); - auto& pathKneeLeft = dynamic_cast( - kneeExtensorLeft->updPath()); + auto& pathKneeLeft = kneeExtensorLeft->updPath(); pathKneeLeft.appendNewPathPoint("knee_extensor_left_origin", *leg_Hlink, knee_extensor_origin); pathKneeLeft.appendNewPathPoint("knee_extensor_left_insertion", @@ -752,8 +750,7 @@ void createLuxoJr(OpenSim::Model& model){ back_extensor_F0, back_extensor_lm0, back_extensor_lts, pennationAngle); - auto& pathBackRight = dynamic_cast( - backExtensorRight->updPath()); + auto& pathBackRight = backExtensorRight->updPath(); pathBackRight.appendNewPathPoint("back_extensor_right_origin", *chest, back_extensor_origin); pathBackRight.appendNewPathPoint("back_extensor_right_insertion", *back, @@ -767,8 +764,7 @@ void createLuxoJr(OpenSim::Model& model){ back_extensor_F0, back_extensor_lm0, back_extensor_lts, pennationAngle); - auto& pathBackLeft = dynamic_cast( - backExtensorLeft->updPath()); + auto& pathBackLeft = backExtensorLeft->updPath(); pathBackLeft.appendNewPathPoint("back_extensor_left_origin", *chest, back_extensor_origin); pathBackLeft.appendNewPathPoint("back_extensor_left_insertion", *back, diff --git a/OpenSim/Examples/ExampleMain/OutputReference/TugOfWar_Complete.cpp b/OpenSim/Examples/ExampleMain/OutputReference/TugOfWar_Complete.cpp index 74f5732974..09837028a1 100644 --- a/OpenSim/Examples/ExampleMain/OutputReference/TugOfWar_Complete.cpp +++ b/OpenSim/Examples/ExampleMain/OutputReference/TugOfWar_Complete.cpp @@ -201,11 +201,11 @@ int main() // Specify the paths for the two muscles // Path for muscle 1 - auto& path1 = dynamic_cast(muscle1->updPath()); + auto& path1 = muscle1->updPath(); path1.appendNewPathPoint("muscle1-point1", ground, Vec3(0.0,0.05,-0.35)); path1.appendNewPathPoint("muscle1-point2", *block, Vec3(0.0,0.0,-0.05)); // Path for muscle 2 - auto& path2 = dynamic_cast(muscle2->updPath()); + auto& path2 = muscle2->updPath(); path2.appendNewPathPoint("muscle2-point1", ground, Vec3(0.0,0.05,0.35)); path2.appendNewPathPoint("muscle2-point2", *block, Vec3(0.0,0.0,0.05)); diff --git a/OpenSim/Examples/Moco/exampleHangingMuscle/exampleHangingMuscle.cpp b/OpenSim/Examples/Moco/exampleHangingMuscle/exampleHangingMuscle.cpp index 05de78f562..ec7d102053 100644 --- a/OpenSim/Examples/Moco/exampleHangingMuscle/exampleHangingMuscle.cpp +++ b/OpenSim/Examples/Moco/exampleHangingMuscle/exampleHangingMuscle.cpp @@ -63,7 +63,7 @@ Model createHangingMuscleModel(bool ignoreActivationDynamics, actu->set_tendon_compliance_dynamics_mode("implicit"); actu->set_max_contraction_velocity(10); actu->set_pennation_angle_at_optimal(0.10); - auto& path = dynamic_cast(actu->updPath()); + auto& path = actu->updPath(); path.appendNewPathPoint("origin", model.updGround(), SimTK::Vec3(0)); path.appendNewPathPoint("insertion", *body, SimTK::Vec3(0)); model.addForce(actu); diff --git a/OpenSim/Examples/MuscleExample/mainFatigue.cpp b/OpenSim/Examples/MuscleExample/mainFatigue.cpp index 1b5cedfbbf..28ef25ab38 100644 --- a/OpenSim/Examples/MuscleExample/mainFatigue.cpp +++ b/OpenSim/Examples/MuscleExample/mainFatigue.cpp @@ -133,13 +133,13 @@ int main() pennationAngle); // Define the path of the muscles - auto& fatigablePath = dynamic_cast(fatigable->updPath()); + auto& fatigablePath = fatigable->updPath(); fatigablePath.appendNewPathPoint("fatigable-point1", ground, Vec3(0.0, halfLength, -0.35)); fatigablePath.appendNewPathPoint("fatigable-point2", *block, Vec3(0.0, halfLength, -halfLength)); - auto& originalPath = dynamic_cast(original->updPath()); + auto& originalPath = original->updPath(); originalPath.appendNewPathPoint("original-point1", ground, Vec3(0.0, halfLength, 0.35)); originalPath.appendNewPathPoint("original-point2", *block, diff --git a/OpenSim/Examples/checkEnvironment/checkEnvironment.cpp b/OpenSim/Examples/checkEnvironment/checkEnvironment.cpp index e456bcc2d2..2d8976ab62 100644 --- a/OpenSim/Examples/checkEnvironment/checkEnvironment.cpp +++ b/OpenSim/Examples/checkEnvironment/checkEnvironment.cpp @@ -133,11 +133,11 @@ int main() // Specify the paths for the two muscles // Path for muscle 1 - auto& path1 = dynamic_cast(muscle1->updPath()); + auto& path1 = muscle1->updPath(); path1.appendNewPathPoint("muscle1-point1", ground, Vec3(0.0,0.05,-0.35)); path1.appendNewPathPoint("muscle1-point2", *block, Vec3(0.0,0.0,-0.05)); // Path for muscle 2 - auto& path2 = dynamic_cast(muscle2->updPath()); + auto& path2 = muscle2->updPath(); path2.appendNewPathPoint("muscle2-point1", ground, Vec3(0.0,0.05,0.35)); path2.appendNewPathPoint("muscle2-point2", *block, Vec3(0.0,0.0,0.05)); diff --git a/OpenSim/Moco/Test/testMocoActuators.cpp b/OpenSim/Moco/Test/testMocoActuators.cpp index dfc3ce0adc..b4a4ad9765 100644 --- a/OpenSim/Moco/Test/testMocoActuators.cpp +++ b/OpenSim/Moco/Test/testMocoActuators.cpp @@ -58,7 +58,7 @@ Model createHangingMuscleModel(double optimalFiberLength, } actu->set_max_contraction_velocity(10); actu->set_pennation_angle_at_optimal(0); - auto& path = dynamic_cast(actu->updPath()); + auto& path = actu->updPath(); path.appendNewPathPoint("origin", model.updGround(), SimTK::Vec3(0)); path.appendNewPathPoint("insertion", *body, SimTK::Vec3(0)); model.addForce(actu); diff --git a/OpenSim/Moco/Test/testMocoInterface.cpp b/OpenSim/Moco/Test/testMocoInterface.cpp index 54b441bf8f..382d59db1f 100644 --- a/OpenSim/Moco/Test/testMocoInterface.cpp +++ b/OpenSim/Moco/Test/testMocoInterface.cpp @@ -1965,7 +1965,7 @@ TEST_CASE("MocoPhase::bound_activation_from_excitation") { musclePtr->set_ignore_tendon_compliance(true); musclePtr->set_fiber_damping(0); musclePtr->setName("muscle"); - auto& path = dynamic_cast(musclePtr->updPath()); + auto& path = musclePtr->updPath(); path.appendNewPathPoint("origin", model.updGround(), SimTK::Vec3(0)); path.appendNewPathPoint("insertion", *body, SimTK::Vec3(0)); model.addComponent(musclePtr); diff --git a/OpenSim/Moco/Test/testMocoMetabolics.cpp b/OpenSim/Moco/Test/testMocoMetabolics.cpp index b9136e52a6..d962a8e3af 100644 --- a/OpenSim/Moco/Test/testMocoMetabolics.cpp +++ b/OpenSim/Moco/Test/testMocoMetabolics.cpp @@ -37,7 +37,7 @@ TEST_CASE("Bhargava2004SmoothedMuscleMetabolics basics") { musclePtr->set_ignore_tendon_compliance(false); musclePtr->set_fiber_damping(0.01); musclePtr->setName("muscle"); - auto& path = dynamic_cast(musclePtr->updPath()); + auto& path = musclePtr->updPath(); path.appendNewPathPoint("origin", model.updGround(), SimTK::Vec3(0)); path.appendNewPathPoint("insertion", *body, SimTK::Vec3(0)); model.addComponent(musclePtr); diff --git a/OpenSim/Simulation/Model/AbstractPath.h b/OpenSim/Simulation/Model/AbstractPath.h index a682cf3554..c4abef4eca 100644 --- a/OpenSim/Simulation/Model/AbstractPath.h +++ b/OpenSim/Simulation/Model/AbstractPath.h @@ -84,7 +84,7 @@ OpenSim_DECLARE_ABSTRACT_OBJECT(AbstractPath, ModelComponent); // INTERFACE METHODS // - // Concrete implementations of `GeometryPath` *must* provide these. + // Concrete implementations of `AbstractPath` *must* provide these. /** * Get the current color of the path. diff --git a/OpenSim/Simulation/Model/Blankevoort1991Ligament.cpp b/OpenSim/Simulation/Model/Blankevoort1991Ligament.cpp index 4600117e55..1545fbdecc 100644 --- a/OpenSim/Simulation/Model/Blankevoort1991Ligament.cpp +++ b/OpenSim/Simulation/Model/Blankevoort1991Ligament.cpp @@ -22,7 +22,6 @@ * -------------------------------------------------------------------------- */ #include -#include #include "Blankevoort1991Ligament.h" #include "GeometryPath.h" @@ -45,6 +44,11 @@ Blankevoort1991Ligament::Blankevoort1991Ligament( set_slack_length(slack_length); } +GeometryPath& Blankevoort1991Ligament::initGeometryPath() { + set_path(GeometryPath()); + return updPath(); +} + void Blankevoort1991Ligament::setNull() { setAuthors("Colin Smith"); @@ -92,8 +96,7 @@ void Blankevoort1991Ligament::extendFinalizeFromProperties() { "Transistion Strain cannot be less than 0"); // Set Default Ligament Color - AbstractPath& path = upd_path(); - path.setDefaultColor(SimTK::Vec3(0.1202, 0.7054, 0.1318)); + updPath().setDefaultColor(SimTK::Vec3(0.1202, 0.7054, 0.1318)); } void Blankevoort1991Ligament::extendAddToSystem( @@ -115,7 +118,7 @@ void Blankevoort1991Ligament::extendPostScale( const SimTK::State& s, const ScaleSet& scaleSet) { Super::extendPostScale(s, scaleSet); - AbstractPath& path = upd_path(); + AbstractPath& path = updPath(); double slack_length = get_slack_length(); if (path.getPreScaleLength(s) > 0.0) { @@ -132,12 +135,12 @@ void Blankevoort1991Ligament::extendPostScale( //============================================================================= double Blankevoort1991Ligament::getLength(const SimTK::State& state) const { - return get_path().getLength(state); + return getPath().getLength(state); } double Blankevoort1991Ligament::getLengtheningSpeed( const SimTK::State& state) const { - return get_path().getLengtheningSpeed(state); + return getPath().getLengtheningSpeed(state); } double Blankevoort1991Ligament::getStrain(const SimTK::State& state) const { @@ -323,7 +326,7 @@ void Blankevoort1991Ligament::computeForce(const SimTK::State& s, // total force double force_total = getTotalForce(s); - const AbstractPath &path = get_path(); + const AbstractPath &path = getPath(); path.addInEquivalentForces( s, force_total, bodyForces, generalizedForces); @@ -355,7 +358,7 @@ double Blankevoort1991Ligament::computePotentialEnergy( double Blankevoort1991Ligament::computeMomentArm( const SimTK::State& s, Coordinate& aCoord) const { - return get_path().computeMomentArm(s, aCoord); + return getPath().computeMomentArm(s, aCoord); } //============================================================================= diff --git a/OpenSim/Simulation/Model/Blankevoort1991Ligament.h b/OpenSim/Simulation/Model/Blankevoort1991Ligament.h index 5c28d0cb24..7bc0625c2f 100644 --- a/OpenSim/Simulation/Model/Blankevoort1991Ligament.h +++ b/OpenSim/Simulation/Model/Blankevoort1991Ligament.h @@ -24,6 +24,7 @@ * -------------------------------------------------------------------------- */ #include +#include namespace OpenSim { @@ -106,7 +107,7 @@ setLinearStiffnessForcePerLength() and getLinearStiffnessForcePerLength(). When scaling a model (using the ScaleTool) that contains a Blankevoort1991Ligament, the slack_length property is scaled by the ratio of -the entire GeometryPath length in the default model pose before and after +the entire path length in the default model pose before and after scaling the bone geometries. This ensures that the strain in the ligament in the default pose is equivilent before and after scaling. Thus, it is important to consider the order of scaling the model and setting the slack_length @@ -168,7 +169,7 @@ affected by scaling the model. */ -class AbstractPath; +class GeometryPath; class OSIMSIMULATION_API Blankevoort1991Ligament : public Force { OpenSim_DECLARE_CONCRETE_OBJECT(Blankevoort1991Ligament, Force) @@ -178,8 +179,6 @@ OpenSim_DECLARE_CONCRETE_OBJECT(Blankevoort1991Ligament, Force) // PROPERTIES //============================================================================= - OpenSim_DECLARE_PROPERTY(path, AbstractPath, - "The path defines the length and lengthening speed of the ligament.") OpenSim_DECLARE_PROPERTY(linear_stiffness, double, "The slope of the linear region of the force-strain curve. " "Units of force/strain (N).") @@ -222,12 +221,30 @@ OpenSim_DECLARE_CONCRETE_OBJECT(Blankevoort1991Ligament, Force) // METHODS //============================================================================= public: - //Constructors + // Constructors Blankevoort1991Ligament(); Blankevoort1991Ligament(std::string name, double linear_stiffness, double slack_length); + // Path + AbstractPath& updPath() { return upd_path(); } + const AbstractPath& getPath() const { return get_path(); } + template + PathType& updPath() { + return dynamic_cast(upd_path()); + } + template + const PathType& getPath() const { + return dynamic_cast(get_path()); + } + bool hasPath() const override { return true;}; + + /// Initialize the path of the PathActuator with a GeometryPath. This + /// returns a reference to the newly created GeometryPath, which you can + /// then edit. This deletes the previous path if one exists. + GeometryPath& initGeometryPath(); + //------------------------------------------------------------------------- // SET //------------------------------------------------------------------------- @@ -310,6 +327,9 @@ OpenSim_DECLARE_CONCRETE_OBJECT(Blankevoort1991Ligament, Force) const SimTK::State& state) const override; protected: + OpenSim_DECLARE_PROPERTY(path, AbstractPath, + "The path defines the length and lengthening speed of the " + "ligament.") void extendFinalizeFromProperties() override; void extendAddToSystem(SimTK::MultibodySystem& system) const override; diff --git a/OpenSim/Simulation/Model/Ligament.cpp b/OpenSim/Simulation/Model/Ligament.cpp index db9298e3e7..95ee593b0c 100644 --- a/OpenSim/Simulation/Model/Ligament.cpp +++ b/OpenSim/Simulation/Model/Ligament.cpp @@ -48,6 +48,13 @@ Ligament::Ligament() constructProperties(); } +//_____________________________________________________________________________ +// Initialize a GeometryPath. +GeometryPath& Ligament::initGeometryPath() { + set_path(GeometryPath()); + return updPath(); +} + //_____________________________________________________________________________ /* * Construct and initialize the properties for the ligament. diff --git a/OpenSim/Simulation/Model/Ligament.h b/OpenSim/Simulation/Model/Ligament.h index 1314c1b4e4..c5a89b6616 100644 --- a/OpenSim/Simulation/Model/Ligament.h +++ b/OpenSim/Simulation/Model/Ligament.h @@ -28,6 +28,7 @@ // INCLUDES //============================================================================= #include "Force.h" +#include "AbstractPath.h" #ifdef SWIG #ifdef OSIMACTUATORS_API @@ -39,8 +40,8 @@ namespace OpenSim { class Function; -class AbstractPath; class ScaleSet; +class GeometryPath; //============================================================================= //============================================================================= @@ -54,8 +55,6 @@ OpenSim_DECLARE_CONCRETE_OBJECT(Ligament, Force); //============================================================================= // PROPERTIES //============================================================================= - OpenSim_DECLARE_PROPERTY(path, AbstractPath, - "The path defines the length and lengthening speed of the PathSpring"); OpenSim_DECLARE_PROPERTY(resting_length, double, "resting length of the ligament"); OpenSim_DECLARE_PROPERTY(pcsa_force, double, @@ -73,14 +72,28 @@ OpenSim_DECLARE_CONCRETE_OBJECT(Ligament, Force); // assignment operator. //-------------------------------------------------------------------------- - // GET + // PATH //-------------------------------------------------------------------------- - // Properties - const AbstractPath& getPath() const - { return get_path(); } - AbstractPath& updPath() - { return upd_path(); } + AbstractPath& updPath() { return upd_path(); } + const AbstractPath& getPath() const { return get_path(); } + template + PathType& updPath() { + return dynamic_cast(upd_path()); + } + template + const PathType& getPath() const { + return dynamic_cast(get_path()); + } bool hasPath() const override { return true;}; + + /// Initialize the path of the PathActuator with a GeometryPath. This + /// returns a reference to the newly created GeometryPath, which you can + /// then edit. This deletes the previous path if one exists. + GeometryPath& initGeometryPath(); + + //-------------------------------------------------------------------------- + // GET + //-------------------------------------------------------------------------- virtual double getLength(const SimTK::State& s) const; virtual double getRestingLength() const { return get_resting_length(); } @@ -162,6 +175,10 @@ OpenSim_DECLARE_CONCRETE_OBJECT(Ligament, Force); return values; } + OpenSim_DECLARE_PROPERTY(path, AbstractPath, + "The path defines the length and lengthening speed of the " + "PathSpring"); + private: void constructProperties(); diff --git a/OpenSim/Simulation/Model/PathActuator.cpp b/OpenSim/Simulation/Model/PathActuator.cpp index 460c2a01fa..398529a1e8 100644 --- a/OpenSim/Simulation/Model/PathActuator.cpp +++ b/OpenSim/Simulation/Model/PathActuator.cpp @@ -63,7 +63,7 @@ void PathActuator::setNull() */ void PathActuator::constructProperties() { - constructProperty_path(GeometryPath()); // TODO is this the best default? + constructProperty_path(GeometryPath()); constructProperty_optimal_force(1.0); } @@ -71,6 +71,15 @@ void PathActuator::constructProperties() //============================================================================= // GET AND SET //============================================================================= +//----------------------------------------------------------------------------- +// PATH +//----------------------------------------------------------------------------- +//_____________________________________________________________________________ +GeometryPath& PathActuator::initGeometryPath() { + set_path(GeometryPath()); + return updPath(); +} + //----------------------------------------------------------------------------- // OPTIMAL FORCE //----------------------------------------------------------------------------- diff --git a/OpenSim/Simulation/Model/PathActuator.h b/OpenSim/Simulation/Model/PathActuator.h index 5c874cd732..f8900d739b 100644 --- a/OpenSim/Simulation/Model/PathActuator.h +++ b/OpenSim/Simulation/Model/PathActuator.h @@ -34,6 +34,7 @@ namespace OpenSim { class Coordinate; class ForceSet; class Model; +class GeometryPath; /** * This is the base class for actuators that apply controllable tension along @@ -48,8 +49,6 @@ class OSIMSIMULATION_API PathActuator : public ScalarActuator { //============================================================================= // PROPERTIES //============================================================================= - OpenSim_DECLARE_PROPERTY(path, AbstractPath, - "The path of the actuator which defines length and lengthening speed."); OpenSim_DECLARE_PROPERTY(optimal_force, double, "The maximum force this actuator can produce."); @@ -68,10 +67,22 @@ class OSIMSIMULATION_API PathActuator : public ScalarActuator { //-------------------------------------------------------------------------- // Path AbstractPath& updPath() { return upd_path(); } - const AbstractPath& getPath() const - { return get_path(); } + const AbstractPath& getPath() const { return get_path(); } + template + PathType& updPath() { + return dynamic_cast(upd_path()); + } + template + const PathType& getPath() const { + return dynamic_cast(get_path()); + } bool hasPath() const override { return true;}; + /// Initialize the path of the PathActuator with a GeometryPath. This + /// returns a reference to the newly created GeometryPath, which you can + /// then edit. This deletes the previous path if one exists. + GeometryPath& initGeometryPath(); + // OPTIMAL FORCE void setOptimalForce(double aOptimalForce); double getOptimalForce() const override; @@ -125,6 +136,11 @@ class OSIMSIMULATION_API PathActuator : public ScalarActuator { /** Extension of parent class method; derived classes may extend further. **/ void extendRealizeDynamics(const SimTK::State& state) const override; +protected: + OpenSim_DECLARE_PROPERTY(path, AbstractPath, + "The path of the actuator which defines length and lengthening " + "speed."); + private: void setNull(); void constructProperties(); diff --git a/OpenSim/Simulation/Model/PathSpring.cpp b/OpenSim/Simulation/Model/PathSpring.cpp index 9c1aa8465e..3865d59ab8 100644 --- a/OpenSim/Simulation/Model/PathSpring.cpp +++ b/OpenSim/Simulation/Model/PathSpring.cpp @@ -26,7 +26,6 @@ //============================================================================= #include "PathSpring.h" #include "GeometryPath.h" -#include "PointForceDirection.h" //============================================================================= // STATICS @@ -95,6 +94,15 @@ void PathSpring::setDissipation(double dissipation) set_dissipation(dissipation); } +//_____________________________________________________________________________ +/* + * Initialize a GeometryPath. + */ +GeometryPath& PathSpring::initGeometryPath() { + set_path(GeometryPath()); + return updPath(); +} + //_____________________________________________________________________________ /** * Perform some setup functions that happen after the diff --git a/OpenSim/Simulation/Model/PathSpring.h b/OpenSim/Simulation/Model/PathSpring.h index b4ddabf6e9..4e3ca94e13 100644 --- a/OpenSim/Simulation/Model/PathSpring.h +++ b/OpenSim/Simulation/Model/PathSpring.h @@ -28,10 +28,11 @@ // INCLUDES //============================================================================= #include "Force.h" +#include "AbstractPath.h" namespace OpenSim { -class AbstractPath; +class GeometryPath; class ScaleSet; //============================================================================= @@ -62,8 +63,6 @@ OpenSim_DECLARE_CONCRETE_OBJECT(PathSpring, Force); "The linear stiffness (N/m) of the PathSpring"); OpenSim_DECLARE_PROPERTY(dissipation, double, "The dissipation factor (s/m) of the PathSpring"); - OpenSim_DECLARE_PROPERTY(path, AbstractPath, - "The path defines the length and lengthening speed of the PathSpring"); //============================================================================= // OUTPUTS @@ -117,11 +116,23 @@ OpenSim_DECLARE_CONCRETE_OBJECT(PathSpring, Force); { return get_dissipation(); } void setDissipation(double dissipation); - /** Accessors for the AbstractPath object */ - const AbstractPath& getPath() const - { return get_path(); } - AbstractPath& updPath() - { return upd_path(); } + /** get/set the path object */ + AbstractPath& updPath() { return upd_path(); } + const AbstractPath& getPath() const { return get_path(); } + template + PathType& updPath() { + return dynamic_cast(upd_path()); + } + template + const PathType& getPath() const { + return dynamic_cast(get_path()); + } + bool hasPath() const override { return true;}; + + /// Initialize the path of the PathActuator with a GeometryPath. This + /// returns a reference to the newly created GeometryPath, which you can + /// then edit. This deletes the previous path if one exists. + GeometryPath& initGeometryPath(); //-------------------------------------------------------------------------- // State dependent values @@ -183,6 +194,11 @@ OpenSim_DECLARE_CONCRETE_OBJECT(PathSpring, Force); return values; } +protected: + OpenSim_DECLARE_PROPERTY(path, AbstractPath, + "The path defines the length and lengthening speed of the " + "PathSpring"); + private: void constructProperties(); diff --git a/OpenSim/Simulation/Test/testForces.cpp b/OpenSim/Simulation/Test/testForces.cpp index 0b46ecec94..519c0ebc23 100644 --- a/OpenSim/Simulation/Test/testForces.cpp +++ b/OpenSim/Simulation/Test/testForces.cpp @@ -431,7 +431,7 @@ void testPathSpring() { osimModel.setGravity(gravity_vec); PathSpring spring("spring", restlength, stiffness, dissipation); - auto& path = dynamic_cast(spring.updPath()); + auto& path = spring.updPath(); path.appendNewPathPoint("origin", block, Vec3(-0.1, 0.0, 0.0)); int N = 10; @@ -2091,7 +2091,7 @@ void testBlankevoort1991Ligament() { new Blankevoort1991Ligament("ligament", stiffness, restlength); ligament->set_damping_coefficient(0.0); - auto& path = dynamic_cast(ligament->upd_path()); + auto& path = ligament->updPath(); path.appendNewPathPoint("origin", ground, Vec3(0.0, 0.0, 0.0)); path.addPathWrap(*pulley1); path.appendNewPathPoint("midpoint", ground, Vec3(0.1, 0.6, 0.0)); @@ -2207,8 +2207,7 @@ void testBlankevoort1991Ligament() { Blankevoort1991Ligament* lig = new Blankevoort1991Ligament("ligament", lig_stiffness, lig_slack_length); - // TODO assumes that GeometryPath is the default path type - auto& path2 = dynamic_cast(lig->upd_path()); + auto& path2 = lig->updPath(); path2.appendNewPathPoint("origin", model.updGround(), SimTK::Vec3(0)); path2.appendNewPathPoint("insertion", *brick, SimTK::Vec3(0)); model.addForce(lig); diff --git a/OpenSim/Simulation/Test/testMomentArms.cpp b/OpenSim/Simulation/Test/testMomentArms.cpp index 9d4c8b8949..6273ee5381 100644 --- a/OpenSim/Simulation/Test/testMomentArms.cpp +++ b/OpenSim/Simulation/Test/testMomentArms.cpp @@ -152,7 +152,7 @@ void testMomentArmsAcrossCompoundJoint() model.addComponent(hip); Thelen2003Muscle* musc = new Thelen2003Muscle("muscle", 10., 0.1, 0.2, 0.); - auto& path = dynamic_cast(musc->updPath()); + auto& path = musc->updPath(); path.appendNewPathPoint("p1", model.updGround(), SimTK::Vec3(0.05, 0, 0)); path.appendNewPathPoint("p2", *leg, SimTK::Vec3(0.05, 0.25, 0.01)); model.addForce(musc); diff --git a/OpenSim/Simulation/Test/testMuscleMetabolicsProbes.cpp b/OpenSim/Simulation/Test/testMuscleMetabolicsProbes.cpp index 068c59a100..e12cc420fa 100644 --- a/OpenSim/Simulation/Test/testMuscleMetabolicsProbes.cpp +++ b/OpenSim/Simulation/Test/testMuscleMetabolicsProbes.cpp @@ -385,7 +385,7 @@ void generateUmbergerMuscleData(const std::string& muscleName, // Create muscle attached to ground and block. UmbergerMuscle *muscle = new UmbergerMuscle(muscleName, maxIsometricForce, optimalFiberLength, width, Arel, Brel, FmaxEccentric); - auto& path = dynamic_cast(muscle->updPath()); + auto& path = muscle->updPath(); path.appendNewPathPoint("muscle-ground", ground, Vec3(0)); path.appendNewPathPoint("muscle-block", *block, Vec3(0)); model.addForce(muscle); @@ -697,7 +697,7 @@ void testProbesUsingMillardMuscleSimulation() Millard2012EquilibriumMuscle *muscle1 = new Millard2012EquilibriumMuscle( "muscle1", 100, optimalFiberLength, tendonSlackLength, 0); - auto& path1 = dynamic_cast(muscle1->updPath()); + auto& path1 = muscle1->updPath(); path1.appendNewPathPoint("m1_ground", ground, Vec3(-anchorDistance,0,0)); path1.appendNewPathPoint("m1_block", *block, Vec3(-blockSideLength/2,0,0)); muscle1->setDefaultActivation(desiredActivation); @@ -705,7 +705,7 @@ void testProbesUsingMillardMuscleSimulation() Millard2012EquilibriumMuscle *muscle2 = new Millard2012EquilibriumMuscle( "muscle2", 100, optimalFiberLength, tendonSlackLength, 0); - auto& path2 = dynamic_cast(muscle2->updPath()); + auto& path2 = muscle2->updPath(); path2.appendNewPathPoint("m2_ground", ground, Vec3(anchorDistance,0,0)); path2.appendNewPathPoint("m2_block", *block, Vec3(blockSideLength/2,0,0)); muscle2->setDefaultActivation(desiredActivation); diff --git a/OpenSim/Simulation/Test/testProbes.cpp b/OpenSim/Simulation/Test/testProbes.cpp index 34e7a5708c..12e73e962d 100644 --- a/OpenSim/Simulation/Test/testProbes.cpp +++ b/OpenSim/Simulation/Test/testProbes.cpp @@ -247,7 +247,7 @@ void simulateMuscle( //Attach the muscle /*const string &actuatorType = */aMuscle->getConcreteClassName(); aMuscle->setName("muscle"); - auto& path = dynamic_cast(aMuscle->updPath()); + auto& path = aMuscle->updPath(); path.appendNewPathPoint("muscle-box", ground, Vec3(anchorWidth / 2, 0, 0)); path.appendNewPathPoint("muscle-ball", *ball, Vec3(-ballRadius, 0, 0)); diff --git a/OpenSim/Tests/AddComponents/testAddComponents.cpp b/OpenSim/Tests/AddComponents/testAddComponents.cpp index 0b7f504280..dba917d4cc 100644 --- a/OpenSim/Tests/AddComponents/testAddComponents.cpp +++ b/OpenSim/Tests/AddComponents/testAddComponents.cpp @@ -199,11 +199,11 @@ void addComponentsToModel(Model& osimModel) // Specify the paths for the two muscles // Path for muscle 1 - auto& path1 = dynamic_cast(muscle1->updPath()); + auto& path1 = muscle1->updPath(); path1.appendNewPathPoint("muscle1-point1", ground, Vec3(0.0,0.05,-0.35)); path1.appendNewPathPoint("muscle1-point2", *block, Vec3(0.0,0.0,-0.05)); // Path for muscle 2 - auto& path2 = dynamic_cast(muscle2->updPath()); + auto& path2 = muscle2->updPath(); path2.appendNewPathPoint("muscle2-point1", ground, Vec3(0.0,0.05,0.35)); path2.appendNewPathPoint("muscle2-point2", *block, Vec3(0.0,0.0,0.05)); diff --git a/OpenSim/Tests/README/testREADME.cpp b/OpenSim/Tests/README/testREADME.cpp index 83e2263692..cfa74eac13 100644 --- a/OpenSim/Tests/README/testREADME.cpp +++ b/OpenSim/Tests/README/testREADME.cpp @@ -76,7 +76,7 @@ int main() { // Add a muscle that flexes the elbow. Millard2012EquilibriumMuscle* biceps = new Millard2012EquilibriumMuscle("biceps", 100, 0.6, 0.55, 0); - auto& path = dynamic_cast(biceps->updPath()); + auto& path = biceps->updPath(); path.appendNewPathPoint("origin", *humerus, Vec3(0, 0.3, 0)); path.appendNewPathPoint("insertion", *radius, Vec3(0, 0.2, 0)); diff --git a/OpenSim/Tests/Wrapping/testMuscleLengthRegression.cpp b/OpenSim/Tests/Wrapping/testMuscleLengthRegression.cpp index 4f3a17221a..bf9799ae80 100644 --- a/OpenSim/Tests/Wrapping/testMuscleLengthRegression.cpp +++ b/OpenSim/Tests/Wrapping/testMuscleLengthRegression.cpp @@ -40,8 +40,8 @@ namespace { SimTK::RowVector lengthsRow(muscleSet.getSize()); for (int imuscle = 0; imuscle < muscleSet.getSize(); ++imuscle) { const auto& muscle = muscleSet.get(imuscle); - const auto& geometryPath = muscle.getGeometryPath(); - lengthsRow[imuscle] = geometryPath.getLength(state); + const auto& path = muscle.getPath(); + lengthsRow[imuscle] = path.getLength(state); } lengths.appendRow(state.getTime(), lengthsRow); } diff --git a/OpenSim/Tests/Wrapping/testWrapCylinder.cpp b/OpenSim/Tests/Wrapping/testWrapCylinder.cpp index ab00db2765..8a548c4c1b 100644 --- a/OpenSim/Tests/Wrapping/testWrapCylinder.cpp +++ b/OpenSim/Tests/Wrapping/testWrapCylinder.cpp @@ -413,7 +413,7 @@ namespace { { std::unique_ptr spring( new PathSpring("spring", 1., 1., 1.)); - auto& path = dynamic_cast(spring->updPath()); + auto& path = spring->updPath(); path.appendNewPathPoint( "startPoint", model.get_ground(), @@ -436,8 +436,8 @@ namespace { cylinder->set_xyz_body_rotation(input.eulerRotations); cylinder->setFrame(model.getGround()); - auto& path = dynamic_cast( - model.updComponent("spring").updPath()); + auto& path = model.updComponent("spring") + .updPath(); path.addPathWrap(*cylinder.get()); model.updGround().addWrapObject(cylinder.release()); } diff --git a/OpenSim/Tests/Wrapping/testWrapping.cpp b/OpenSim/Tests/Wrapping/testWrapping.cpp index 6c78208fde..7b37730f73 100644 --- a/OpenSim/Tests/Wrapping/testWrapping.cpp +++ b/OpenSim/Tests/Wrapping/testWrapping.cpp @@ -356,7 +356,7 @@ void testWrapCylinder() // One spring has wrap cylinder with respect to ground origin PathSpring* spring1 = new PathSpring("spring1", 1.0, 0.1, 0.01); - auto& path1 = dynamic_cast(spring1->updPath()); + auto& path1 = spring1->updPath(); path1.appendNewPathPoint("origin", ground, Vec3(-off, 0, 0)); path1.appendNewPathPoint("insert", *body, Vec3(0)); path1.addPathWrap(*pulley1); @@ -374,7 +374,7 @@ void testWrapCylinder() // Second spring has wrap cylinder with respect to bodyOffse origin PathSpring* spring2 = new PathSpring("spring2", 1.0, 0.1, 0.01); - auto& path2 = dynamic_cast(spring2->updPath()); + auto& path2 = spring2->updPath(); path2.appendNewPathPoint("origin", ground, Vec3(-off, 0, 0)); path2.appendNewPathPoint("insert", *body, Vec3(0)); path2.addPathWrap(*pulley2); @@ -534,7 +534,7 @@ void simulateModelWithCables(const string &modelFile, double finalTime) Ligament* lig = dynamic_cast(&osimModel.getForceSet()[i]); if (lig != 0) { numLigaments++; - auto& ligPath = dynamic_cast(lig->updPath()); + auto& ligPath = lig->updPath(); paths.append(&ligPath); pathNames.append(lig->getName()); continue; @@ -543,7 +543,7 @@ void simulateModelWithCables(const string &modelFile, double finalTime) Muscle* mus = dynamic_cast(&osimModel.getForceSet()[i]); if (mus != 0) { numMuscles++; - auto& musPath = dynamic_cast(mus->updPath()); + auto& musPath = mus->updPath(); paths.append(&musPath); pathNames.append(mus->getName()); cout << mus->getName() << ": " << musPath.getWrapSet().getSize() << endl; diff --git a/OpenSim/Tests/Wrapping/testWrappingAlgorithm.cpp b/OpenSim/Tests/Wrapping/testWrappingAlgorithm.cpp index b49457e4c8..3163c92b11 100644 --- a/OpenSim/Tests/Wrapping/testWrappingAlgorithm.cpp +++ b/OpenSim/Tests/Wrapping/testWrappingAlgorithm.cpp @@ -151,7 +151,7 @@ void testSingleWrapObjectPerpendicular(WrapObject* wrapObject, Vec3 axisRotation PathSpring* spring1 = new PathSpring("spring1", 1.0, 0.1, 0.01); //offset in X direction to avoid ambiguous scenario where path passes through center - auto& path1 = dynamic_cast(spring1->updPath()); + auto& path1 = spring1->updPath(); path1.appendNewPathPoint("origin", ground, Vec3(r-.1, r, 0)); path1.appendNewPathPoint("insert", *body, Vec3(-r, r, 0)); path1.addPathWrap(*wObj); @@ -209,7 +209,7 @@ void testEllipsoidWrapLength(OpenSim::WrapEllipsoid* wrapObject) PathSpring* spring1 = new PathSpring("spring1", 1.0, 0.1, 0.01); //offset in X direction to avoid ambiguous scenario where path passes through center - auto& path1 = dynamic_cast(spring1->updPath()); + auto& path1 = spring1->updPath(); path1.appendNewPathPoint("origin", ground, Vec3(r - .1, r, 0)); // insertion point is -r down from the tip of the long axis of the ellipsoid path1.appendNewPathPoint("insert", *body, Vec3(-wrapObject->get_dimensions()[0], -r, 0)); From b4f11fd31fefdf14bcc91ced36f1c11d3693a505 Mon Sep 17 00:00:00 2001 From: Nicholas Bianco Date: Fri, 25 Aug 2023 17:15:29 -0700 Subject: [PATCH 04/24] Update changelog // use updPath instead of upd_path --- CHANGELOG.md | 4 ++++ OpenSim/Actuators/DeGrooteFregly2016Muscle.cpp | 2 +- OpenSim/Actuators/Millard2012AccelerationMuscle.cpp | 2 +- OpenSim/Actuators/Millard2012EquilibriumMuscle.cpp | 2 +- OpenSim/Simulation/Model/ActivationFiberLengthMuscle.cpp | 2 +- .../Model/ActivationFiberLengthMuscle_Deprecated.cpp | 2 +- OpenSim/Simulation/Model/Ligament.cpp | 5 ++--- OpenSim/Simulation/Model/PathSpring.cpp | 5 ++--- 8 files changed, 13 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6e252392c7..ba5726f138 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ request related to the change, then we may provide the commit. This is not a comprehensive list of changes but rather a hand-curated collection of the more notable ones. For a comprehensive history, see the [OpenSim Core GitHub repo](https://github.com/opensim-org/opensim-core). +v4.5 +==== +- Added `AbstractPath` which is a base class for `GeometryPath` and other path types (#3388). TODO: add API changes. + v4.4.1 ====== - IMU::calcGyroscopeSignal() now reports angular velocities in the IMU frame. diff --git a/OpenSim/Actuators/DeGrooteFregly2016Muscle.cpp b/OpenSim/Actuators/DeGrooteFregly2016Muscle.cpp index 60ca99c053..72bb79db3f 100644 --- a/OpenSim/Actuators/DeGrooteFregly2016Muscle.cpp +++ b/OpenSim/Actuators/DeGrooteFregly2016Muscle.cpp @@ -1080,7 +1080,7 @@ void DeGrooteFregly2016Muscle::extendPostScale( const SimTK::State& s, const ScaleSet& scaleSet) { Super::extendPostScale(s, scaleSet); - AbstractPath& path = upd_path(); + AbstractPath& path = updPath(); if (path.getPreScaleLength(s) > 0.0) { double scaleFactor = path.getLength(s) / path.getPreScaleLength(s); diff --git a/OpenSim/Actuators/Millard2012AccelerationMuscle.cpp b/OpenSim/Actuators/Millard2012AccelerationMuscle.cpp index a2b46cf31e..8da5b485f6 100644 --- a/OpenSim/Actuators/Millard2012AccelerationMuscle.cpp +++ b/OpenSim/Actuators/Millard2012AccelerationMuscle.cpp @@ -557,7 +557,7 @@ extendPostScale(const SimTK::State& s, const ScaleSet& scaleSet) Super::extendPostScale(s, scaleSet); - AbstractPath& path = upd_path(); + AbstractPath& path = updPath(); if (path.getPreScaleLength(s) > 0.0) { double scaleFactor = path.getLength(s) / path.getPreScaleLength(s); diff --git a/OpenSim/Actuators/Millard2012EquilibriumMuscle.cpp b/OpenSim/Actuators/Millard2012EquilibriumMuscle.cpp index c8208c22f1..25ce5e5bc0 100644 --- a/OpenSim/Actuators/Millard2012EquilibriumMuscle.cpp +++ b/OpenSim/Actuators/Millard2012EquilibriumMuscle.cpp @@ -598,7 +598,7 @@ extendPostScale(const SimTK::State& s, const ScaleSet& scaleSet) { Super::extendPostScale(s, scaleSet); - AbstractPath& path = upd_path(); + AbstractPath& path = updPath(); if (path.getPreScaleLength(s) > 0.0) { double scaleFactor = path.getLength(s) / path.getPreScaleLength(s); diff --git a/OpenSim/Simulation/Model/ActivationFiberLengthMuscle.cpp b/OpenSim/Simulation/Model/ActivationFiberLengthMuscle.cpp index 87947705cb..a37983c358 100644 --- a/OpenSim/Simulation/Model/ActivationFiberLengthMuscle.cpp +++ b/OpenSim/Simulation/Model/ActivationFiberLengthMuscle.cpp @@ -182,7 +182,7 @@ extendPostScale(const SimTK::State& s, const ScaleSet& scaleSet) { Super::extendPostScale(s, scaleSet); - AbstractPath& path = upd_path(); + AbstractPath& path = updPath(); if (path.getPreScaleLength(s) > 0.0) { double scaleFactor = path.getLength(s) / path.getPreScaleLength(s); diff --git a/OpenSim/Simulation/Model/ActivationFiberLengthMuscle_Deprecated.cpp b/OpenSim/Simulation/Model/ActivationFiberLengthMuscle_Deprecated.cpp index d9a90ecfd6..27dd9c6908 100644 --- a/OpenSim/Simulation/Model/ActivationFiberLengthMuscle_Deprecated.cpp +++ b/OpenSim/Simulation/Model/ActivationFiberLengthMuscle_Deprecated.cpp @@ -346,7 +346,7 @@ extendPostScale(const SimTK::State& s, const ScaleSet& scaleSet) { Super::extendPostScale(s, scaleSet); - AbstractPath& path = upd_path(); + AbstractPath& path = updPath(); if (path.getPreScaleLength(s) > 0.0) { double scaleFactor = path.getLength(s) / path.getPreScaleLength(s); diff --git a/OpenSim/Simulation/Model/Ligament.cpp b/OpenSim/Simulation/Model/Ligament.cpp index 95ee593b0c..875a86f52c 100644 --- a/OpenSim/Simulation/Model/Ligament.cpp +++ b/OpenSim/Simulation/Model/Ligament.cpp @@ -91,8 +91,7 @@ void Ligament::extendFinalizeFromProperties() // Resting length must be greater than 0.0. assert(get_resting_length() > 0.0); - AbstractPath& path = upd_path(); - path.setDefaultColor(DefaultLigamentColor); + updPath().setDefaultColor(DefaultLigamentColor); } @@ -200,7 +199,7 @@ void Ligament::extendPostScale(const SimTK::State& s, const ScaleSet& scaleSet) { Super::extendPostScale(s, scaleSet); - AbstractPath& path = upd_path(); + AbstractPath& path = updPath(); if (path.getPreScaleLength(s) > 0.0) { double scaleFactor = path.getLength(s) / path.getPreScaleLength(s); diff --git a/OpenSim/Simulation/Model/PathSpring.cpp b/OpenSim/Simulation/Model/PathSpring.cpp index 3865d59ab8..6861f79691 100644 --- a/OpenSim/Simulation/Model/PathSpring.cpp +++ b/OpenSim/Simulation/Model/PathSpring.cpp @@ -114,8 +114,7 @@ void PathSpring::extendFinalizeFromProperties() { Super::extendFinalizeFromProperties(); - AbstractPath& path = upd_path(); - path.setDefaultColor(DefaultPathSpringColor); + updPath().setDefaultColor(DefaultPathSpringColor); OPENSIM_THROW_IF_FRMOBJ( (SimTK::isNaN(get_resting_length()) || get_resting_length() < 0), @@ -182,7 +181,7 @@ extendPostScale(const SimTK::State& s, const ScaleSet& scaleSet) { Super::extendPostScale(s, scaleSet); - AbstractPath& path = upd_path(); + AbstractPath& path = updPath(); if (path.getPreScaleLength(s) > 0.0) { double scaleFactor = path.getLength(s) / path.getPreScaleLength(s); From b70b2faef73a34df7b46ddcaeebda2edd966ec6e Mon Sep 17 00:00:00 2001 From: Nicholas Bianco Date: Mon, 28 Aug 2023 12:02:34 -0700 Subject: [PATCH 05/24] Update the Java bindings with path changes --- Bindings/Java/OpenSimJNI/OpenSimContext.cpp | 17 +++++++++++---- Bindings/Java/OpenSimJNI/OpenSimContext.h | 1 + Bindings/Java/OpenSimJNI/Test/testContext.cpp | 21 ++++++++++--------- Bindings/Java/tests/TestBasics.java | 10 +++++---- Bindings/Java/tests/TestModelBuilding.java | 5 +++-- 5 files changed, 34 insertions(+), 20 deletions(-) diff --git a/Bindings/Java/OpenSimJNI/OpenSimContext.cpp b/Bindings/Java/OpenSimJNI/OpenSimContext.cpp index 9f64c6ac53..360478b686 100644 --- a/Bindings/Java/OpenSimJNI/OpenSimContext.cpp +++ b/Bindings/Java/OpenSimJNI/OpenSimContext.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -124,13 +125,21 @@ double OpenSimContext::getMuscleLength(Muscle& m) { } const Array& OpenSimContext::getCurrentPath(Muscle& m) { - return m.getGeometryPath().getCurrentPath(*_configState); + if (auto* p = dynamic_cast(&m.getPath())) { + return p->getCurrentPath(*_configState); + } else { + OPENSIM_THROW(Exception, "Muscle path is not a GeometryPath.") + } } void OpenSimContext::copyMuscle(Muscle& from, Muscle& to) { - to = from; - recreateSystemKeepStage(); - to.updGeometryPath().updateGeometry(*_configState); + if (auto* p = dynamic_cast(&from.getPath())) { + to = from; + recreateSystemKeepStage(); + to.updPath().updateGeometry(*_configState); + } else { + OPENSIM_THROW(Exception, "Muscle path is not a GeometryPath.") + } } // Muscle Points diff --git a/Bindings/Java/OpenSimJNI/OpenSimContext.h b/Bindings/Java/OpenSimJNI/OpenSimContext.h index 7eded75a6d..60694317dc 100644 --- a/Bindings/Java/OpenSimJNI/OpenSimContext.h +++ b/Bindings/Java/OpenSimJNI/OpenSimContext.h @@ -48,6 +48,7 @@ class GeometryPath; class AbstractPathPoint; class PathWrap; class ConditionalPathPoint; +class PathPoint; class WrapObject; class Analysis; class AnalyzeTool; diff --git a/Bindings/Java/OpenSimJNI/Test/testContext.cpp b/Bindings/Java/OpenSimJNI/Test/testContext.cpp index 54bed517b2..0d914687cd 100644 --- a/Bindings/Java/OpenSimJNI/Test/testContext.cpp +++ b/Bindings/Java/OpenSimJNI/Test/testContext.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -121,7 +122,7 @@ int main() cout << "Prop after create system is " << dProp2.toString() << endl; bool after = PropertyHelper::getValueBool(dProp); SimTK_ASSERT_ALWAYS(!after, "Property has wrong value!!"); - dTRIlong->updGeometryPath().updateGeometry(context->getCurrentStateRef()); + dTRIlong->updPath().updateGeometry(context->getCurrentStateRef()); const OpenSim::Array& path = context->getCurrentPath(*dTRIlong); cout << "Muscle Path" << endl; cout << path.getSize() << endl; @@ -156,7 +157,7 @@ int main() cout << "After setting coordinate to 100 deg." << endl; cout << xform << endl; // Compare to known xform - dTRIlong->updGeometryPath().updateGeometry(context->getCurrentStateRef()); + dTRIlong->updPath().updateGeometry(context->getCurrentStateRef()); const OpenSim::Array& newPath = context->getCurrentPath(*dTRIlong); context->realizePosition(); // Compare to known path @@ -190,8 +191,8 @@ int main() context->restoreStateFromCachedModel(); // Exercise PathPoint operations used to edit Path in GUI - PathPointSet& pathPoints = dTRIlong->updGeometryPath().updPathPointSet(); - std::string pathBeforeInXML = dTRIlong->updGeometryPath().dump(); + PathPointSet& pathPoints = dTRIlong->updPath().updPathPointSet(); + std::string pathBeforeInXML = dTRIlong->updPath().dump(); std::cout << pathBeforeInXML << endl; int origSize = pathPoints.getSize(); AbstractPathPoint& savePoint = pathPoints.get("TRIlong-P2"); @@ -199,17 +200,17 @@ int main() AbstractPathPoint* clonedPoint = savePoint.clone(); // Test delete second PathPoint from TRIlong muscle - context->deletePathPoint(dTRIlong->updGeometryPath(), 2); + context->deletePathPoint(dTRIlong->updPath(), 2); assert(pathPoints.getSize() == origSize - 1); - std::string pathAfterDeletionInXML = dTRIlong->updGeometryPath().dump(); + std::string pathAfterDeletionInXML = dTRIlong->updPath().dump(); std::cout << pathAfterDeletionInXML << endl; // Test adding PathPoint to TRIlong muscle (Stationary) Component& frame = model->updBodySet().updComponent(saveFrameName); PhysicalFrame* physFrame = PhysicalFrame::safeDownCast(&frame); - context->addPathPoint(dTRIlong->updGeometryPath(), 3, *physFrame); + context->addPathPoint(dTRIlong->updPath(), 3, *physFrame); assert(pathPoints.getSize() == origSize); - std::string pathAfterReinsertionInXML = dTRIlong->updGeometryPath().dump(); + std::string pathAfterReinsertionInXML = dTRIlong->updPath().dump(); std::cout << pathAfterReinsertionInXML << endl; // Test changing type to ConditionalPathPoint @@ -217,10 +218,10 @@ int main() AbstractPathPoint& oldPoint = pathPoints.get(2); newPoint->setCoordinate(model->getCoordinateSet().get(0)); newPoint->setParentFrame(oldPoint.getParentFrame()); - context->replacePathPoint(dTRIlong->updGeometryPath(), oldPoint, *newPoint); + context->replacePathPoint(dTRIlong->updPath(), oldPoint, *newPoint); assert(pathPoints.getSize() == origSize); - std::string pathAfterTypeChangeToViaInXML = dTRIlong->updGeometryPath().dump(); + std::string pathAfterTypeChangeToViaInXML = dTRIlong->updPath().dump(); std::cout << pathAfterTypeChangeToViaInXML << endl; // Make a change to a socket that is invalid and verify that we can recover diff --git a/Bindings/Java/tests/TestBasics.java b/Bindings/Java/tests/TestBasics.java index 919ab4aba4..79483cd421 100644 --- a/Bindings/Java/tests/TestBasics.java +++ b/Bindings/Java/tests/TestBasics.java @@ -35,12 +35,14 @@ public static void testMuscleList() { Ground ground = model.getGround(); Thelen2003Muscle thelenMuscle = new Thelen2003Muscle("Darryl", 1, 0.5, 0.5, 0); - thelenMuscle.addNewPathPoint("muscle1-point1", ground, new Vec3(0.0,0.0,0.0)); - thelenMuscle.addNewPathPoint("muscle1-point2", ground, new Vec3(1.0,0.0,0.0)); + GeometryPath pathThelen = thelenMuscle.initGeometryPath(); + pathThelen.appendNewPathPoint("muscle1-point1", ground, new Vec3(0.0,0.0,0.0)); + pathThelen.appendNewPathPoint("muscle1-point2", ground, new Vec3(1.0,0.0,0.0)); Millard2012EquilibriumMuscle millardMuscle = new Millard2012EquilibriumMuscle("Matt", 1, 0.5, 0.5, 0); - millardMuscle.addNewPathPoint("muscle1-point1", ground, new Vec3(0.0,0.0,0.0)); - millardMuscle.addNewPathPoint("muscle1-point2", ground, new Vec3(1.0,0.0,0.0)); + GeometryPath pathMillard = millardMuscle.initGeometryPath(); + pathMillard.appendNewPathPoint("muscle1-point1", ground, new Vec3(0.0,0.0,0.0)); + pathMillard.appendNewPathPoint("muscle1-point2", ground, new Vec3(1.0,0.0,0.0)); model.addComponent(thelenMuscle); model.addComponent(millardMuscle); diff --git a/Bindings/Java/tests/TestModelBuilding.java b/Bindings/Java/tests/TestModelBuilding.java index fdf9cce6c9..a85252eb02 100644 --- a/Bindings/Java/tests/TestModelBuilding.java +++ b/Bindings/Java/tests/TestModelBuilding.java @@ -26,8 +26,9 @@ public static void main(String[] args) { 0.6, // Optimal fibre length 0.55, // Tendon slack length 0.0); // Pennation angle - biceps.addNewPathPoint("origin", hum, ArrayDouble.createVec3(new double[]{0, 0.8, 0})); - biceps.addNewPathPoint("insert", rad, ArrayDouble.createVec3(new double[]{0, 0.7, 0})); + GeometryPath pathBiceps = biceps.initGeometryPath(); + pathBiceps.appendNewPathPoint("origin", hum, ArrayDouble.createVec3(new double[]{0, 0.8, 0})); + pathBiceps.appendNewPathPoint("insert", rad, ArrayDouble.createVec3(new double[]{0, 0.7, 0})); PrescribedController cns = new PrescribedController(); cns.addActuator(biceps); From 5e98a45c1a6b1ac01e2f1ee711afcf0ff3a163f2 Mon Sep 17 00:00:00 2001 From: Nicholas Bianco Date: Tue, 29 Aug 2023 10:31:57 -0700 Subject: [PATCH 06/24] Revert Appearance to unnamed property --- OpenSim/Simulation/Model/AbstractPath.cpp | 12 ++++++------ OpenSim/Simulation/Model/AbstractPath.h | 2 +- OpenSim/Simulation/Model/GeometryPath.cpp | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/OpenSim/Simulation/Model/AbstractPath.cpp b/OpenSim/Simulation/Model/AbstractPath.cpp index 9071c1aa2a..839a5e7744 100644 --- a/OpenSim/Simulation/Model/AbstractPath.cpp +++ b/OpenSim/Simulation/Model/AbstractPath.cpp @@ -31,7 +31,7 @@ AbstractPath::AbstractPath() : ModelComponent() { Appearance appearance; appearance.set_color(SimTK::Gray); - constructProperty_appearance(appearance); + constructProperty_Appearance(appearance); } AbstractPath::AbstractPath(AbstractPath const&) = default; @@ -43,21 +43,21 @@ AbstractPath& AbstractPath::operator=(const AbstractPath&) = default; // DEFAULTED METHODS const SimTK::Vec3& AbstractPath::getDefaultColor() const { - return get_appearance().get_color(); + return get_Appearance().get_color(); } void AbstractPath::setDefaultColor(const SimTK::Vec3& color) { - updProperty_appearance().setValueIsDefault(false); - upd_appearance().set_color(color); + updProperty_Appearance().setValueIsDefault(false); + upd_Appearance().set_color(color); } -double OpenSim::AbstractPath::getPreScaleLength(const SimTK::State&) const +double AbstractPath::getPreScaleLength(const SimTK::State&) const { return _preScaleLength; } -void OpenSim::AbstractPath::setPreScaleLength(const SimTK::State&, +void AbstractPath::setPreScaleLength(const SimTK::State&, double preScaleLength) { _preScaleLength = preScaleLength; diff --git a/OpenSim/Simulation/Model/AbstractPath.h b/OpenSim/Simulation/Model/AbstractPath.h index c4abef4eca..ac687464c1 100644 --- a/OpenSim/Simulation/Model/AbstractPath.h +++ b/OpenSim/Simulation/Model/AbstractPath.h @@ -70,7 +70,7 @@ OpenSim_DECLARE_ABSTRACT_OBJECT(AbstractPath, ModelComponent); //============================================================================= // PROPERTIES //============================================================================= - OpenSim_DECLARE_PROPERTY(appearance, Appearance, + OpenSim_DECLARE_UNNAMED_PROPERTY(Appearance, "Default appearance attributes for this AbstractPath."); //============================================================================= diff --git a/OpenSim/Simulation/Model/GeometryPath.cpp b/OpenSim/Simulation/Model/GeometryPath.cpp index cb0e49fa17..ce23159179 100644 --- a/OpenSim/Simulation/Model/GeometryPath.cpp +++ b/OpenSim/Simulation/Model/GeometryPath.cpp @@ -191,7 +191,7 @@ void GeometryPath::extendConnectToModel(Model& aModel) // We consider this cache entry valid any time after it has been created // and first marked valid, and we won't ever invalidate it. - this->_colorCV = addCacheVariable("color", get_appearance().get_color(), SimTK::Stage::Topology); + this->_colorCV = addCacheVariable("color", get_Appearance().get_color(), SimTK::Stage::Topology); } void GeometryPath::extendInitStateFromProperties(SimTK::State& s) const From 4f811053f5ad8258405ccaffb51be763d36eacc1 Mon Sep 17 00:00:00 2001 From: Nicholas Bianco Date: Tue, 29 Aug 2023 11:53:05 -0700 Subject: [PATCH 07/24] Add deprecated functions (e.g., getGeometryPath()) back in --- Applications/Scale/test/testScale.cpp | 6 ++-- Bindings/Java/OpenSimJNI/Test/testContext.cpp | 20 +++++------ OpenSim/Actuators/Test/testActuators.cpp | 8 ++--- .../Model/Blankevoort1991Ligament.cpp | 19 ++++++++++- .../Model/Blankevoort1991Ligament.h | 34 ++++++++++++++++--- OpenSim/Simulation/Model/Ligament.cpp | 1 - OpenSim/Simulation/Model/Ligament.h | 24 +++++++++++-- OpenSim/Simulation/Model/Muscle.cpp | 8 ++++- OpenSim/Simulation/Model/Muscle.h | 2 ++ OpenSim/Simulation/Model/PathActuator.cpp | 15 +++++++- OpenSim/Simulation/Model/PathActuator.h | 33 ++++++++++++++++-- OpenSim/Simulation/Model/PathSpring.cpp | 1 - OpenSim/Simulation/Model/PathSpring.h | 24 +++++++++++-- OpenSim/Simulation/Test/testForces.cpp | 28 ++++++++------- OpenSim/Simulation/Test/testMomentArms.cpp | 12 +++---- .../Test/testMuscleMetabolicsProbes.cpp | 15 ++++---- OpenSim/Simulation/Test/testProbes.cpp | 5 ++- .../Tests/AddComponents/testAddComponents.cpp | 10 +++--- OpenSim/Tests/README/testREADME.cpp | 5 ++- OpenSim/Tests/Wrapping/testWrapCylinder.cpp | 15 ++++---- OpenSim/Tests/Wrapping/testWrapping.cpp | 28 +++++++-------- .../Tests/Wrapping/testWrappingAlgorithm.cpp | 18 +++++----- 22 files changed, 223 insertions(+), 108 deletions(-) diff --git a/Applications/Scale/test/testScale.cpp b/Applications/Scale/test/testScale.cpp index 042711cacf..af6fd731ca 100644 --- a/Applications/Scale/test/testScale.cpp +++ b/Applications/Scale/test/testScale.cpp @@ -595,11 +595,9 @@ void scalePhysicalOffsetFrames() model->getComponent(pathToAct1); const PathActuator& pa2 = model->getComponent(pathToAct2); - const auto& path1 = dynamic_cast(pa1.getPath()); - const auto& path2 = dynamic_cast(pa2.getPath()); - const PathPointSet& pps1 = path1.getPathPointSet(); - const PathPointSet& pps2 = path2.getPathPointSet(); + const PathPointSet& pps1 = pa1.getGeometryPath().getPathPointSet(); + const PathPointSet& pps2 = pa2.getGeometryPath().getPathPointSet(); for (int i = 0; i < 2; ++i) { diff --git a/Bindings/Java/OpenSimJNI/Test/testContext.cpp b/Bindings/Java/OpenSimJNI/Test/testContext.cpp index 0d914687cd..e26aaf2828 100644 --- a/Bindings/Java/OpenSimJNI/Test/testContext.cpp +++ b/Bindings/Java/OpenSimJNI/Test/testContext.cpp @@ -122,7 +122,7 @@ int main() cout << "Prop after create system is " << dProp2.toString() << endl; bool after = PropertyHelper::getValueBool(dProp); SimTK_ASSERT_ALWAYS(!after, "Property has wrong value!!"); - dTRIlong->updPath().updateGeometry(context->getCurrentStateRef()); + dTRIlong->updGeometryPath().updateGeometry(context->getCurrentStateRef()); const OpenSim::Array& path = context->getCurrentPath(*dTRIlong); cout << "Muscle Path" << endl; cout << path.getSize() << endl; @@ -157,7 +157,7 @@ int main() cout << "After setting coordinate to 100 deg." << endl; cout << xform << endl; // Compare to known xform - dTRIlong->updPath().updateGeometry(context->getCurrentStateRef()); + dTRIlong->updGeometryPath().updateGeometry(context->getCurrentStateRef()); const OpenSim::Array& newPath = context->getCurrentPath(*dTRIlong); context->realizePosition(); // Compare to known path @@ -191,8 +191,8 @@ int main() context->restoreStateFromCachedModel(); // Exercise PathPoint operations used to edit Path in GUI - PathPointSet& pathPoints = dTRIlong->updPath().updPathPointSet(); - std::string pathBeforeInXML = dTRIlong->updPath().dump(); + PathPointSet& pathPoints = dTRIlong->updGeometryPath().updPathPointSet(); + std::string pathBeforeInXML = dTRIlong->updGeometryPath().dump(); std::cout << pathBeforeInXML << endl; int origSize = pathPoints.getSize(); AbstractPathPoint& savePoint = pathPoints.get("TRIlong-P2"); @@ -200,17 +200,17 @@ int main() AbstractPathPoint* clonedPoint = savePoint.clone(); // Test delete second PathPoint from TRIlong muscle - context->deletePathPoint(dTRIlong->updPath(), 2); + context->deletePathPoint(dTRIlong->updGeometryPath(), 2); assert(pathPoints.getSize() == origSize - 1); - std::string pathAfterDeletionInXML = dTRIlong->updPath().dump(); + std::string pathAfterDeletionInXML = dTRIlong->updGeometryPath().dump(); std::cout << pathAfterDeletionInXML << endl; // Test adding PathPoint to TRIlong muscle (Stationary) Component& frame = model->updBodySet().updComponent(saveFrameName); PhysicalFrame* physFrame = PhysicalFrame::safeDownCast(&frame); - context->addPathPoint(dTRIlong->updPath(), 3, *physFrame); + context->addPathPoint(dTRIlong->updGeometryPath(), 3, *physFrame); assert(pathPoints.getSize() == origSize); - std::string pathAfterReinsertionInXML = dTRIlong->updPath().dump(); + std::string pathAfterReinsertionInXML = dTRIlong->updGeometryPath().dump(); std::cout << pathAfterReinsertionInXML << endl; // Test changing type to ConditionalPathPoint @@ -218,10 +218,10 @@ int main() AbstractPathPoint& oldPoint = pathPoints.get(2); newPoint->setCoordinate(model->getCoordinateSet().get(0)); newPoint->setParentFrame(oldPoint.getParentFrame()); - context->replacePathPoint(dTRIlong->updPath(), oldPoint, *newPoint); + context->replacePathPoint(dTRIlong->updGeometryPath(), oldPoint, *newPoint); assert(pathPoints.getSize() == origSize); - std::string pathAfterTypeChangeToViaInXML = dTRIlong->updPath().dump(); + std::string pathAfterTypeChangeToViaInXML = dTRIlong->updGeometryPath().dump(); std::cout << pathAfterTypeChangeToViaInXML << endl; // Make a change to a socket that is invalid and verify that we can recover diff --git a/OpenSim/Actuators/Test/testActuators.cpp b/OpenSim/Actuators/Test/testActuators.cpp index f0fc23cace..45d7a2e3f1 100644 --- a/OpenSim/Actuators/Test/testActuators.cpp +++ b/OpenSim/Actuators/Test/testActuators.cpp @@ -332,18 +332,18 @@ void testClutchedPathSpring() ClutchedPathSpring* spring = new ClutchedPathSpring("clutch_spring", stiffness, dissipation, 0.01); - auto& path = spring->updPath(); - path.appendNewPathPoint("origin", *block, Vec3(-0.1, 0.0 ,0.0)); + + spring->updGeometryPath().appendNewPathPoint("origin", *block, Vec3(-0.1, 0.0 ,0.0)); int N = 10; for(int i=1; iupdGeometryPath().appendNewPathPoint("", *pulleyBody, Vec3(-x, y ,0.0)); } - path.appendNewPathPoint("insertion", *block, Vec3(0.1, 0.0 ,0.0)); + spring->updGeometryPath().appendNewPathPoint("insertion", *block, Vec3(0.1, 0.0 ,0.0)); // BUG in defining wrapping API requires that the Force containing the GeometryPath be // connected to the model before the wrap can be added diff --git a/OpenSim/Simulation/Model/Blankevoort1991Ligament.cpp b/OpenSim/Simulation/Model/Blankevoort1991Ligament.cpp index 1545fbdecc..60c1cd8e0d 100644 --- a/OpenSim/Simulation/Model/Blankevoort1991Ligament.cpp +++ b/OpenSim/Simulation/Model/Blankevoort1991Ligament.cpp @@ -23,7 +23,6 @@ #include #include "Blankevoort1991Ligament.h" -#include "GeometryPath.h" using namespace OpenSim; @@ -36,6 +35,24 @@ Blankevoort1991Ligament::Blankevoort1991Ligament() : Force() { setNull(); } +Blankevoort1991Ligament::Blankevoort1991Ligament(std::string name, + const PhysicalFrame& frame1, SimTK::Vec3 point1, + const PhysicalFrame& frame2, SimTK::Vec3 point2) + : Blankevoort1991Ligament() { + setName(name); + updGeometryPath().appendNewPathPoint("p1", frame1, point1); + updGeometryPath().appendNewPathPoint("p2", frame2, point2); +} + +Blankevoort1991Ligament::Blankevoort1991Ligament(std::string name, + const PhysicalFrame& frame1, SimTK::Vec3 point1, + const PhysicalFrame& frame2, SimTK::Vec3 point2, + double linear_stiffness, double slack_length) + : Blankevoort1991Ligament(name, frame1, point1, frame2, point2) { + set_linear_stiffness(linear_stiffness); + set_slack_length(slack_length); +} + Blankevoort1991Ligament::Blankevoort1991Ligament( std::string name, double linear_stiffness, double slack_length) : Blankevoort1991Ligament() { diff --git a/OpenSim/Simulation/Model/Blankevoort1991Ligament.h b/OpenSim/Simulation/Model/Blankevoort1991Ligament.h index 7bc0625c2f..b611dfcc61 100644 --- a/OpenSim/Simulation/Model/Blankevoort1991Ligament.h +++ b/OpenSim/Simulation/Model/Blankevoort1991Ligament.h @@ -25,6 +25,7 @@ #include #include +#include namespace OpenSim { @@ -169,8 +170,6 @@ affected by scaling the model. */ -class GeometryPath; - class OSIMSIMULATION_API Blankevoort1991Ligament : public Force { OpenSim_DECLARE_CONCRETE_OBJECT(Blankevoort1991Ligament, Force) @@ -223,22 +222,49 @@ OpenSim_DECLARE_CONCRETE_OBJECT(Blankevoort1991Ligament, Force) public: // Constructors Blankevoort1991Ligament(); + + Blankevoort1991Ligament(std::string name, + const PhysicalFrame& frame1, SimTK::Vec3 point1, + const PhysicalFrame& frame2, SimTK::Vec3 point2); + + Blankevoort1991Ligament(std::string name, + const PhysicalFrame& frame1, SimTK::Vec3 point1, + const PhysicalFrame& frame2, SimTK::Vec3 point2, + double linear_stiffness, double slack_length); Blankevoort1991Ligament(std::string name, double linear_stiffness, double slack_length); // Path + bool hasPath() const override { return true;}; + AbstractPath& updPath() { return upd_path(); } const AbstractPath& getPath() const { return get_path(); } + template PathType& updPath() { return dynamic_cast(upd_path()); } template const PathType& getPath() const { - return dynamic_cast(get_path()); + return dynamic_cast(get_path()); + } + + template + PathType* tryUpdPath() { + return dynamic_cast(&upd_path()); + } + template + const PathType* tryGetPath() const { + return dynamic_cast(&get_path()); + } + + GeometryPath& updGeometryPath() { + return updPath(); + } + const GeometryPath& getGeometryPath() const { + return getPath(); } - bool hasPath() const override { return true;}; /// Initialize the path of the PathActuator with a GeometryPath. This /// returns a reference to the newly created GeometryPath, which you can diff --git a/OpenSim/Simulation/Model/Ligament.cpp b/OpenSim/Simulation/Model/Ligament.cpp index 875a86f52c..c02db44b9b 100644 --- a/OpenSim/Simulation/Model/Ligament.cpp +++ b/OpenSim/Simulation/Model/Ligament.cpp @@ -25,7 +25,6 @@ // INCLUDES //============================================================================= #include "Ligament.h" -#include "GeometryPath.h" #include "PointForceDirection.h" #include diff --git a/OpenSim/Simulation/Model/Ligament.h b/OpenSim/Simulation/Model/Ligament.h index c5a89b6616..23e91dda48 100644 --- a/OpenSim/Simulation/Model/Ligament.h +++ b/OpenSim/Simulation/Model/Ligament.h @@ -29,6 +29,7 @@ //============================================================================= #include "Force.h" #include "AbstractPath.h" +#include "GeometryPath.h" #ifdef SWIG #ifdef OSIMACTUATORS_API @@ -41,7 +42,6 @@ namespace OpenSim { class Function; class ScaleSet; -class GeometryPath; //============================================================================= //============================================================================= @@ -74,17 +74,35 @@ OpenSim_DECLARE_CONCRETE_OBJECT(Ligament, Force); //-------------------------------------------------------------------------- // PATH //-------------------------------------------------------------------------- + bool hasPath() const override { return true;}; + AbstractPath& updPath() { return upd_path(); } const AbstractPath& getPath() const { return get_path(); } + template PathType& updPath() { return dynamic_cast(upd_path()); } template const PathType& getPath() const { - return dynamic_cast(get_path()); + return dynamic_cast(get_path()); + } + + template + PathType* tryUpdPath() { + return dynamic_cast(&upd_path()); + } + template + const PathType* tryGetPath() const { + return dynamic_cast(&get_path()); + } + + GeometryPath& updGeometryPath() { + return updPath(); + } + const GeometryPath& getGeometryPath() const { + return getPath(); } - bool hasPath() const override { return true;}; /// Initialize the path of the PathActuator with a GeometryPath. This /// returns a reference to the newly created GeometryPath, which you can diff --git a/OpenSim/Simulation/Model/Muscle.cpp b/OpenSim/Simulation/Model/Muscle.cpp index 04ef81eb7f..754cb8676e 100644 --- a/OpenSim/Simulation/Model/Muscle.cpp +++ b/OpenSim/Simulation/Model/Muscle.cpp @@ -155,7 +155,7 @@ void Muscle::constructProperties() // By default the min and max controls on muscle are 0.0 and 1.0 setMinControl(0.0); setMaxControl(1.0); - upd_path().setDefaultColor(DefaultMuscleColor); + updPath().setDefaultColor(DefaultMuscleColor); } @@ -679,6 +679,12 @@ SimTK::Vec3 Muscle::computePathColor(const SimTK::State& state) const { } +void Muscle::updateGeometry(const SimTK::State& s) +{ + updGeometryPath().updateGeometry(s); +} + + //_____________________________________________________________________________ /** * Utility function to calculate the current pennation angle in a diff --git a/OpenSim/Simulation/Model/Muscle.h b/OpenSim/Simulation/Model/Muscle.h index 3dbfa6e389..5011a33e7f 100644 --- a/OpenSim/Simulation/Model/Muscle.h +++ b/OpenSim/Simulation/Model/Muscle.h @@ -441,6 +441,8 @@ OpenSim_DECLARE_ABSTRACT_OBJECT(Muscle, PathActuator); void extendSetPropertiesFromState(const SimTK::State &s) override; void extendInitStateFromProperties(SimTK::State& state) const override; + // Update the display geometry attached to the muscle + virtual void updateGeometry(const SimTK::State& s); // End of Interfaces imposed by parent classes. //@} diff --git a/OpenSim/Simulation/Model/PathActuator.cpp b/OpenSim/Simulation/Model/PathActuator.cpp index 398529a1e8..ba0bca9594 100644 --- a/OpenSim/Simulation/Model/PathActuator.cpp +++ b/OpenSim/Simulation/Model/PathActuator.cpp @@ -25,7 +25,6 @@ // INCLUDES //============================================================================= #include "PathActuator.h" -#include "GeometryPath.h" using namespace OpenSim; using namespace std; @@ -140,6 +139,20 @@ double PathActuator::getStress( const SimTK::State& s) const return fabs(getActuation(s)/get_optimal_force()); } +//_____________________________________________________________________________ +/** + * Add a Path point to the _path of the actuator. The new point is appended + * to the end of the current path + * + */ +void PathActuator::addNewPathPoint( + const std::string& proposedName, + const PhysicalFrame& aBody, + const SimTK::Vec3& aPositionOnBody) { + // Create new PathPoint already appended to the PathPointSet for the path + updGeometryPath().appendNewPathPoint(proposedName, aBody, aPositionOnBody); +} + //============================================================================= // COMPUTATIONS //============================================================================= diff --git a/OpenSim/Simulation/Model/PathActuator.h b/OpenSim/Simulation/Model/PathActuator.h index f8900d739b..baa05e71d6 100644 --- a/OpenSim/Simulation/Model/PathActuator.h +++ b/OpenSim/Simulation/Model/PathActuator.h @@ -25,6 +25,7 @@ #include "Actuator.h" #include "AbstractPath.h" +#include "GeometryPath.h" //============================================================================= //============================================================================= @@ -34,7 +35,6 @@ namespace OpenSim { class Coordinate; class ForceSet; class Model; -class GeometryPath; /** * This is the base class for actuators that apply controllable tension along @@ -66,17 +66,35 @@ class OSIMSIMULATION_API PathActuator : public ScalarActuator { // GET AND SET //-------------------------------------------------------------------------- // Path + bool hasPath() const override { return true;}; + AbstractPath& updPath() { return upd_path(); } const AbstractPath& getPath() const { return get_path(); } + template PathType& updPath() { return dynamic_cast(upd_path()); } template const PathType& getPath() const { - return dynamic_cast(get_path()); + return dynamic_cast(get_path()); + } + + template + PathType* tryUpdPath() { + return dynamic_cast(&upd_path()); + } + template + const PathType* tryGetPath() const { + return dynamic_cast(&get_path()); + } + + GeometryPath& updGeometryPath() { + return updPath(); + } + const GeometryPath& getGeometryPath() const { + return getPath(); } - bool hasPath() const override { return true;}; /// Initialize the path of the PathActuator with a GeometryPath. This /// returns a reference to the newly created GeometryPath, which you can @@ -100,6 +118,15 @@ class OSIMSIMULATION_API PathActuator : public ScalarActuator { // STRESS double getStress( const SimTK::State& s ) const override; + // Convenience method to add PathPoints + /** @note This function does not maintain the State and so should be used + * only before a valid State is created. + * @note Only valid if the `path` owned by this PathActuator supports + * PathPoint%s (e.g., GeometryPath). */ + void addNewPathPoint(const std::string& proposedName, + const PhysicalFrame& aBody, + const SimTK::Vec3& aPositionOnBody); + //-------------------------------------------------------------------------- // APPLICATION //-------------------------------------------------------------------------- diff --git a/OpenSim/Simulation/Model/PathSpring.cpp b/OpenSim/Simulation/Model/PathSpring.cpp index 6861f79691..4ca1165f30 100644 --- a/OpenSim/Simulation/Model/PathSpring.cpp +++ b/OpenSim/Simulation/Model/PathSpring.cpp @@ -25,7 +25,6 @@ // INCLUDES //============================================================================= #include "PathSpring.h" -#include "GeometryPath.h" //============================================================================= // STATICS diff --git a/OpenSim/Simulation/Model/PathSpring.h b/OpenSim/Simulation/Model/PathSpring.h index 4e3ca94e13..cdbd1eecc1 100644 --- a/OpenSim/Simulation/Model/PathSpring.h +++ b/OpenSim/Simulation/Model/PathSpring.h @@ -29,10 +29,10 @@ //============================================================================= #include "Force.h" #include "AbstractPath.h" +#include "GeometryPath.h" namespace OpenSim { -class GeometryPath; class ScaleSet; //============================================================================= @@ -117,17 +117,35 @@ OpenSim_DECLARE_CONCRETE_OBJECT(PathSpring, Force); void setDissipation(double dissipation); /** get/set the path object */ + bool hasPath() const override { return true;}; + AbstractPath& updPath() { return upd_path(); } const AbstractPath& getPath() const { return get_path(); } + template PathType& updPath() { return dynamic_cast(upd_path()); } template const PathType& getPath() const { - return dynamic_cast(get_path()); + return dynamic_cast(get_path()); + } + + template + PathType* tryUpdPath() { + return dynamic_cast(&upd_path()); + } + template + const PathType* tryGetPath() const { + return dynamic_cast(&get_path()); + } + + GeometryPath& updGeometryPath() { + return updPath(); + } + const GeometryPath& getGeometryPath() const { + return getPath(); } - bool hasPath() const override { return true;}; /// Initialize the path of the PathActuator with a GeometryPath. This /// returns a reference to the newly created GeometryPath, which you can diff --git a/OpenSim/Simulation/Test/testForces.cpp b/OpenSim/Simulation/Test/testForces.cpp index 519c0ebc23..c897702bb1 100644 --- a/OpenSim/Simulation/Test/testForces.cpp +++ b/OpenSim/Simulation/Test/testForces.cpp @@ -431,18 +431,20 @@ void testPathSpring() { osimModel.setGravity(gravity_vec); PathSpring spring("spring", restlength, stiffness, dissipation); - auto& path = spring.updPath(); - path.appendNewPathPoint("origin", block, Vec3(-0.1, 0.0, 0.0)); + spring.updGeometryPath().appendNewPathPoint( + "origin", block, Vec3(-0.1, 0.0, 0.0)); int N = 10; for (int i = 1; i < N; ++i) { double angle = i * Pi / N; double x = 0.1 * cos(angle); double y = 0.1 * sin(angle); - path.appendNewPathPoint("", pulleyBody, Vec3(-x, y, 0.0)); + spring.updGeometryPath().appendNewPathPoint( + "", pulleyBody, Vec3(-x, y, 0.0)); } - path.appendNewPathPoint("insertion", block, Vec3(0.1, 0.0, 0.0)); + spring.updGeometryPath().appendNewPathPoint( + "insertion", block, Vec3(0.1, 0.0, 0.0)); // BUG in defining wrapping API requires that the Force containing the // GeometryPath be connected to the model before the wrap can be added @@ -2091,12 +2093,14 @@ void testBlankevoort1991Ligament() { new Blankevoort1991Ligament("ligament", stiffness, restlength); ligament->set_damping_coefficient(0.0); - auto& path = ligament->updPath(); - path.appendNewPathPoint("origin", ground, Vec3(0.0, 0.0, 0.0)); - path.addPathWrap(*pulley1); - path.appendNewPathPoint("midpoint", ground, Vec3(0.1, 0.6, 0.0)); - path.addPathWrap(*pulley2); - path.appendNewPathPoint("insertion", *block, Vec3(0.0, 0.0, 0.0)); + ligament->updGeometryPath().appendNewPathPoint( + "origin", ground, Vec3(0.0, 0.0, 0.0)); + ligament->updGeometryPath().addPathWrap(*pulley1); + ligament->updGeometryPath().appendNewPathPoint( + "midpoint", ground, Vec3(0.1, 0.6, 0.0)); + ligament->updGeometryPath().addPathWrap(*pulley2); + ligament->updGeometryPath().appendNewPathPoint( + "insertion", *block, Vec3(0.0, 0.0, 0.0)); osimModel.addForce(ligament); @@ -2206,10 +2210,8 @@ void testBlankevoort1991Ligament() { double lig_slack_length = 1.0; Blankevoort1991Ligament* lig = new Blankevoort1991Ligament("ligament", + model.updGround(), SimTK::Vec3(0), *brick, SimTK::Vec3(0), lig_stiffness, lig_slack_length); - auto& path2 = lig->updPath(); - path2.appendNewPathPoint("origin", model.updGround(), SimTK::Vec3(0)); - path2.appendNewPathPoint("insertion", *brick, SimTK::Vec3(0)); model.addForce(lig); SimTK::State state = model.initSystem(); diff --git a/OpenSim/Simulation/Test/testMomentArms.cpp b/OpenSim/Simulation/Test/testMomentArms.cpp index 6273ee5381..ab9af57578 100644 --- a/OpenSim/Simulation/Test/testMomentArms.cpp +++ b/OpenSim/Simulation/Test/testMomentArms.cpp @@ -152,9 +152,8 @@ void testMomentArmsAcrossCompoundJoint() model.addComponent(hip); Thelen2003Muscle* musc = new Thelen2003Muscle("muscle", 10., 0.1, 0.2, 0.); - auto& path = musc->updPath(); - path.appendNewPathPoint("p1", model.updGround(), SimTK::Vec3(0.05, 0, 0)); - path.appendNewPathPoint("p2", *leg, SimTK::Vec3(0.05, 0.25, 0.01)); + musc->addNewPathPoint("p1", model.updGround(), SimTK::Vec3(0.05, 0, 0)); + musc->addNewPathPoint("p2", *leg, SimTK::Vec3(0.05, 0.25, 0.01)); model.addForce(musc); SimTK::State& s = model.initSystem(); @@ -253,7 +252,7 @@ SimTK::Vector computeGenForceScaling(const Model &osimModel, const SimTK::State && (ac.getJoint().getName() != "tib_pat_r") ){ MobilizedBodyIndex modbodIndex = ac.getBodyIndex(); const MobilizedBody& mobod = osimModel.getMatterSubsystem().getMobilizedBody(modbodIndex); - SpatialVec Hcol = mobod.getHCol(s, SimTK::MobilizerUIndex(0)); //ac.getMobilizerQIndex())); // get n�th column of H + SpatialVec Hcol = mobod.getHCol(s, SimTK::MobilizerUIndex(0)); //ac.getMobilizerQIndex())); // get nth column of H /*double thetaScale = */Hcol[0].norm(); // magnitude of the rotational part of this column of H @@ -350,9 +349,8 @@ void testMomentArmDefinitionForModel(const string &filename, const string &coord //cout << "muscle force: " << muscle.getForce(s) << endl; //double ma = muscle.computeMomentArm(s, coord); - const auto& path = dynamic_cast(muscle.updPath()); - double ma = maSolver.solve(s, coord, path); - double ma_dldtheta = computeMomentArmFromDefinition(s, path, coord); + double ma = maSolver.solve(s, coord, muscle.getGeometryPath()); + double ma_dldtheta = computeMomentArmFromDefinition(s, muscle.getGeometryPath(), coord); cout << "r's = " << ma << "::" << ma_dldtheta <<" at q = " << coord.getValue(s)*180/Pi; diff --git a/OpenSim/Simulation/Test/testMuscleMetabolicsProbes.cpp b/OpenSim/Simulation/Test/testMuscleMetabolicsProbes.cpp index e12cc420fa..1017d32f38 100644 --- a/OpenSim/Simulation/Test/testMuscleMetabolicsProbes.cpp +++ b/OpenSim/Simulation/Test/testMuscleMetabolicsProbes.cpp @@ -385,9 +385,8 @@ void generateUmbergerMuscleData(const std::string& muscleName, // Create muscle attached to ground and block. UmbergerMuscle *muscle = new UmbergerMuscle(muscleName, maxIsometricForce, optimalFiberLength, width, Arel, Brel, FmaxEccentric); - auto& path = muscle->updPath(); - path.appendNewPathPoint("muscle-ground", ground, Vec3(0)); - path.appendNewPathPoint("muscle-block", *block, Vec3(0)); + muscle->addNewPathPoint("muscle-ground", ground, Vec3(0)); + muscle->addNewPathPoint("muscle-block", *block, Vec3(0)); model.addForce(muscle); // Attach muscle controller. @@ -697,17 +696,15 @@ void testProbesUsingMillardMuscleSimulation() Millard2012EquilibriumMuscle *muscle1 = new Millard2012EquilibriumMuscle( "muscle1", 100, optimalFiberLength, tendonSlackLength, 0); - auto& path1 = muscle1->updPath(); - path1.appendNewPathPoint("m1_ground", ground, Vec3(-anchorDistance,0,0)); - path1.appendNewPathPoint("m1_block", *block, Vec3(-blockSideLength/2,0,0)); + muscle1->addNewPathPoint("m1_ground", ground, Vec3(-anchorDistance,0,0)); + muscle1->addNewPathPoint("m1_block", *block, Vec3(-blockSideLength/2,0,0)); muscle1->setDefaultActivation(desiredActivation); model.addForce(muscle1); Millard2012EquilibriumMuscle *muscle2 = new Millard2012EquilibriumMuscle( "muscle2", 100, optimalFiberLength, tendonSlackLength, 0); - auto& path2 = muscle2->updPath(); - path2.appendNewPathPoint("m2_ground", ground, Vec3(anchorDistance,0,0)); - path2.appendNewPathPoint("m2_block", *block, Vec3(blockSideLength/2,0,0)); + muscle2->addNewPathPoint("m2_ground", ground, Vec3(anchorDistance,0,0)); + muscle2->addNewPathPoint("m2_block", *block, Vec3(blockSideLength/2,0,0)); muscle2->setDefaultActivation(desiredActivation); model.addForce(muscle2); diff --git a/OpenSim/Simulation/Test/testProbes.cpp b/OpenSim/Simulation/Test/testProbes.cpp index 12e73e962d..232de3b022 100644 --- a/OpenSim/Simulation/Test/testProbes.cpp +++ b/OpenSim/Simulation/Test/testProbes.cpp @@ -247,9 +247,8 @@ void simulateMuscle( //Attach the muscle /*const string &actuatorType = */aMuscle->getConcreteClassName(); aMuscle->setName("muscle"); - auto& path = aMuscle->updPath(); - path.appendNewPathPoint("muscle-box", ground, Vec3(anchorWidth / 2, 0, 0)); - path.appendNewPathPoint("muscle-ball", *ball, Vec3(-ballRadius, 0, 0)); + aMuscle->addNewPathPoint("muscle-box", ground, Vec3(anchorWidth / 2, 0, 0)); + aMuscle->addNewPathPoint("muscle-ball", *ball, Vec3(-ballRadius, 0, 0)); ActivationFiberLengthMuscle_Deprecated *aflMuscle = dynamic_cast(aMuscle); diff --git a/OpenSim/Tests/AddComponents/testAddComponents.cpp b/OpenSim/Tests/AddComponents/testAddComponents.cpp index dba917d4cc..429da8eb62 100644 --- a/OpenSim/Tests/AddComponents/testAddComponents.cpp +++ b/OpenSim/Tests/AddComponents/testAddComponents.cpp @@ -199,13 +199,11 @@ void addComponentsToModel(Model& osimModel) // Specify the paths for the two muscles // Path for muscle 1 - auto& path1 = muscle1->updPath(); - path1.appendNewPathPoint("muscle1-point1", ground, Vec3(0.0,0.05,-0.35)); - path1.appendNewPathPoint("muscle1-point2", *block, Vec3(0.0,0.0,-0.05)); + muscle1->addNewPathPoint("muscle1-point1", ground, Vec3(0.0,0.05,-0.35)); + muscle1->addNewPathPoint("muscle1-point2", *block, Vec3(0.0,0.0,-0.05)); // Path for muscle 2 - auto& path2 = muscle2->updPath(); - path2.appendNewPathPoint("muscle2-point1", ground, Vec3(0.0,0.05,0.35)); - path2.appendNewPathPoint("muscle2-point2", *block, Vec3(0.0,0.0,0.05)); + muscle2->addNewPathPoint("muscle2-point1", ground, Vec3(0.0,0.05,0.35)); + muscle2->addNewPathPoint("muscle2-point2", *block, Vec3(0.0,0.0,0.05)); // Add the two muscles (as forces) to the model osimModel.addComponent(muscle1); diff --git a/OpenSim/Tests/README/testREADME.cpp b/OpenSim/Tests/README/testREADME.cpp index cfa74eac13..dfded913dc 100644 --- a/OpenSim/Tests/README/testREADME.cpp +++ b/OpenSim/Tests/README/testREADME.cpp @@ -76,9 +76,8 @@ int main() { // Add a muscle that flexes the elbow. Millard2012EquilibriumMuscle* biceps = new Millard2012EquilibriumMuscle("biceps", 100, 0.6, 0.55, 0); - auto& path = biceps->updPath(); - path.appendNewPathPoint("origin", *humerus, Vec3(0, 0.3, 0)); - path.appendNewPathPoint("insertion", *radius, Vec3(0, 0.2, 0)); + biceps->addNewPathPoint("origin", *humerus, Vec3(0, 0.3, 0)); + biceps->addNewPathPoint("insertion", *radius, Vec3(0, 0.2, 0)); // Add a controller that specifies the excitation of the muscle. PrescribedController* brain = new PrescribedController(); diff --git a/OpenSim/Tests/Wrapping/testWrapCylinder.cpp b/OpenSim/Tests/Wrapping/testWrapCylinder.cpp index 8a548c4c1b..4e6667eb1c 100644 --- a/OpenSim/Tests/Wrapping/testWrapCylinder.cpp +++ b/OpenSim/Tests/Wrapping/testWrapCylinder.cpp @@ -413,12 +413,11 @@ namespace { { std::unique_ptr spring( new PathSpring("spring", 1., 1., 1.)); - auto& path = spring->updPath(); - path.appendNewPathPoint( + spring->updGeometryPath().appendNewPathPoint( "startPoint", model.get_ground(), input.path.start); - path.appendNewPathPoint( + spring->updGeometryPath().appendNewPathPoint( "endPoint", model.get_ground(), input.path.end); @@ -436,9 +435,8 @@ namespace { cylinder->set_xyz_body_rotation(input.eulerRotations); cylinder->setFrame(model.getGround()); - auto& path = model.updComponent("spring") - .updPath(); - path.addPathWrap(*cylinder.get()); + model.updComponent("spring") + .updGeometryPath().addPathWrap(*cylinder.get()); model.updGround().addWrapObject(cylinder.release()); } @@ -453,9 +451,8 @@ namespace { // Trigger computing the wrapping path (realizing the state will not). model.getComponent("spring").getLength(state); - const auto& path = dynamic_cast( - model.getComponent("spring").getPath()); - const WrapResult wrapResult = path + const WrapResult wrapResult = model.getComponent("spring") + .getPath() .getWrapSet() .get("pathwrap") .getPreviousWrap(); diff --git a/OpenSim/Tests/Wrapping/testWrapping.cpp b/OpenSim/Tests/Wrapping/testWrapping.cpp index 7b37730f73..7034a25b3c 100644 --- a/OpenSim/Tests/Wrapping/testWrapping.cpp +++ b/OpenSim/Tests/Wrapping/testWrapping.cpp @@ -356,10 +356,11 @@ void testWrapCylinder() // One spring has wrap cylinder with respect to ground origin PathSpring* spring1 = new PathSpring("spring1", 1.0, 0.1, 0.01); - auto& path1 = spring1->updPath(); - path1.appendNewPathPoint("origin", ground, Vec3(-off, 0, 0)); - path1.appendNewPathPoint("insert", *body, Vec3(0)); - path1.addPathWrap(*pulley1); + spring1->updGeometryPath(). + appendNewPathPoint("origin", ground, Vec3(-off, 0, 0)); + spring1->updGeometryPath(). + appendNewPathPoint("insert", *body, Vec3(0)); + spring1->updGeometryPath().addPathWrap(*pulley1); model.addComponent(spring1); @@ -374,11 +375,12 @@ void testWrapCylinder() // Second spring has wrap cylinder with respect to bodyOffse origin PathSpring* spring2 = new PathSpring("spring2", 1.0, 0.1, 0.01); - auto& path2 = spring2->updPath(); - path2.appendNewPathPoint("origin", ground, Vec3(-off, 0, 0)); - path2.appendNewPathPoint("insert", *body, Vec3(0)); - path2.addPathWrap(*pulley2); - path2.setDefaultColor(Vec3(0, 0.8, 0)); + spring2->updGeometryPath(). + appendNewPathPoint("origin", ground, Vec3(-off, 0, 0)); + spring2->updGeometryPath(). + appendNewPathPoint("insert", *body, Vec3(0)); + spring2->updGeometryPath().addPathWrap(*pulley2); + spring2->updGeometryPath().setDefaultColor(Vec3(0, 0.8, 0)); model.addComponent(spring2); @@ -534,8 +536,7 @@ void simulateModelWithCables(const string &modelFile, double finalTime) Ligament* lig = dynamic_cast(&osimModel.getForceSet()[i]); if (lig != 0) { numLigaments++; - auto& ligPath = lig->updPath(); - paths.append(&ligPath); + paths.append(&lig->updGeometryPath()); pathNames.append(lig->getName()); continue; } @@ -543,10 +544,9 @@ void simulateModelWithCables(const string &modelFile, double finalTime) Muscle* mus = dynamic_cast(&osimModel.getForceSet()[i]); if (mus != 0) { numMuscles++; - auto& musPath = mus->updPath(); - paths.append(&musPath); + paths.append(&mus->updGeometryPath()); pathNames.append(mus->getName()); - cout << mus->getName() << ": " << musPath.getWrapSet().getSize() << endl; + cout << mus->getName() << ": " << mus->updGeometryPath().getWrapSet().getSize() << endl; continue; } } diff --git a/OpenSim/Tests/Wrapping/testWrappingAlgorithm.cpp b/OpenSim/Tests/Wrapping/testWrappingAlgorithm.cpp index 3163c92b11..12687b4e7a 100644 --- a/OpenSim/Tests/Wrapping/testWrappingAlgorithm.cpp +++ b/OpenSim/Tests/Wrapping/testWrappingAlgorithm.cpp @@ -151,10 +151,11 @@ void testSingleWrapObjectPerpendicular(WrapObject* wrapObject, Vec3 axisRotation PathSpring* spring1 = new PathSpring("spring1", 1.0, 0.1, 0.01); //offset in X direction to avoid ambiguous scenario where path passes through center - auto& path1 = spring1->updPath(); - path1.appendNewPathPoint("origin", ground, Vec3(r-.1, r, 0)); - path1.appendNewPathPoint("insert", *body, Vec3(-r, r, 0)); - path1.addPathWrap(*wObj); + spring1->updGeometryPath(). + appendNewPathPoint("origin", ground, Vec3(r-.1, r, 0)); + spring1->updGeometryPath(). + appendNewPathPoint("insert", *body, Vec3(-r, r, 0)); + spring1->updGeometryPath().addPathWrap(*wObj); model.addComponent(spring1); @@ -209,11 +210,12 @@ void testEllipsoidWrapLength(OpenSim::WrapEllipsoid* wrapObject) PathSpring* spring1 = new PathSpring("spring1", 1.0, 0.1, 0.01); //offset in X direction to avoid ambiguous scenario where path passes through center - auto& path1 = spring1->updPath(); - path1.appendNewPathPoint("origin", ground, Vec3(r - .1, r, 0)); + spring1->updGeometryPath(). + appendNewPathPoint("origin", ground, Vec3(r - .1, r, 0)); // insertion point is -r down from the tip of the long axis of the ellipsoid - path1.appendNewPathPoint("insert", *body, Vec3(-wrapObject->get_dimensions()[0], -r, 0)); - path1.addPathWrap(*wObj); + spring1->updGeometryPath(). + appendNewPathPoint("insert", *body, Vec3(-wrapObject->get_dimensions()[0], -r, 0)); + spring1->updGeometryPath().addPathWrap(*wObj); model.addComponent(spring1); From 016d8bd51559dda836013427e946fee9b1f0df13 Mon Sep 17 00:00:00 2001 From: Nicholas Bianco Date: Tue, 29 Aug 2023 12:06:00 -0700 Subject: [PATCH 08/24] Reverting API changes pt. 2 + diff clean up --- OpenSim/Examples/checkEnvironment/checkEnvironment.cpp | 10 ++++------ OpenSim/Moco/Test/testMocoActuators.cpp | 5 ++--- OpenSim/Moco/Test/testMocoInterface.cpp | 5 ++--- OpenSim/Moco/Test/testMocoMetabolics.cpp | 5 ++--- OpenSim/Simulation/Model/Blankevoort1991Ligament.h | 10 +++++----- OpenSim/Simulation/Model/PathActuator.cpp | 7 ++++--- OpenSim/Simulation/Model/PathActuator.h | 4 ++-- OpenSim/Tests/AddComponents/testAddComponents.cpp | 8 ++++---- OpenSim/Tests/Wrapping/testWrapCylinder.cpp | 2 +- OpenSim/Tests/Wrapping/testWrapping.cpp | 10 +++++----- OpenSim/Tests/Wrapping/testWrappingAlgorithm.cpp | 4 ++-- 11 files changed, 33 insertions(+), 37 deletions(-) diff --git a/OpenSim/Examples/checkEnvironment/checkEnvironment.cpp b/OpenSim/Examples/checkEnvironment/checkEnvironment.cpp index 2d8976ab62..48feb8dae2 100644 --- a/OpenSim/Examples/checkEnvironment/checkEnvironment.cpp +++ b/OpenSim/Examples/checkEnvironment/checkEnvironment.cpp @@ -133,13 +133,11 @@ int main() // Specify the paths for the two muscles // Path for muscle 1 - auto& path1 = muscle1->updPath(); - path1.appendNewPathPoint("muscle1-point1", ground, Vec3(0.0,0.05,-0.35)); - path1.appendNewPathPoint("muscle1-point2", *block, Vec3(0.0,0.0,-0.05)); + muscle1->addNewPathPoint("muscle1-point1", ground, Vec3(0.0,0.05,-0.35)); + muscle1->addNewPathPoint("muscle1-point2", *block, Vec3(0.0,0.0,-0.05)); // Path for muscle 2 - auto& path2 = muscle2->updPath(); - path2.appendNewPathPoint("muscle2-point1", ground, Vec3(0.0,0.05,0.35)); - path2.appendNewPathPoint("muscle2-point2", *block, Vec3(0.0,0.0,0.05)); + muscle2->addNewPathPoint("muscle2-point1", ground, Vec3(0.0,0.05,0.35)); + muscle2->addNewPathPoint("muscle2-point2", *block, Vec3(0.0,0.0,0.05)); // Add the two muscles (as forces) to the model osimModel.addForce(muscle1); diff --git a/OpenSim/Moco/Test/testMocoActuators.cpp b/OpenSim/Moco/Test/testMocoActuators.cpp index b4a4ad9765..4a2839e181 100644 --- a/OpenSim/Moco/Test/testMocoActuators.cpp +++ b/OpenSim/Moco/Test/testMocoActuators.cpp @@ -58,9 +58,8 @@ Model createHangingMuscleModel(double optimalFiberLength, } actu->set_max_contraction_velocity(10); actu->set_pennation_angle_at_optimal(0); - auto& path = actu->updPath(); - path.appendNewPathPoint("origin", model.updGround(), SimTK::Vec3(0)); - path.appendNewPathPoint("insertion", *body, SimTK::Vec3(0)); + actu->addNewPathPoint("origin", model.updGround(), SimTK::Vec3(0)); + actu->addNewPathPoint("insertion", *body, SimTK::Vec3(0)); model.addForce(actu); body->attachGeometry(new Sphere(0.05)); diff --git a/OpenSim/Moco/Test/testMocoInterface.cpp b/OpenSim/Moco/Test/testMocoInterface.cpp index 382d59db1f..e0a045560e 100644 --- a/OpenSim/Moco/Test/testMocoInterface.cpp +++ b/OpenSim/Moco/Test/testMocoInterface.cpp @@ -1965,9 +1965,8 @@ TEST_CASE("MocoPhase::bound_activation_from_excitation") { musclePtr->set_ignore_tendon_compliance(true); musclePtr->set_fiber_damping(0); musclePtr->setName("muscle"); - auto& path = musclePtr->updPath(); - path.appendNewPathPoint("origin", model.updGround(), SimTK::Vec3(0)); - path.appendNewPathPoint("insertion", *body, SimTK::Vec3(0)); + musclePtr->addNewPathPoint("origin", model.updGround(), SimTK::Vec3(0)); + musclePtr->addNewPathPoint("insertion", *body, SimTK::Vec3(0)); model.addComponent(musclePtr); model.finalizeConnections(); SECTION("bound_activation_from_excitation is false") { diff --git a/OpenSim/Moco/Test/testMocoMetabolics.cpp b/OpenSim/Moco/Test/testMocoMetabolics.cpp index d962a8e3af..e31c1b557c 100644 --- a/OpenSim/Moco/Test/testMocoMetabolics.cpp +++ b/OpenSim/Moco/Test/testMocoMetabolics.cpp @@ -37,9 +37,8 @@ TEST_CASE("Bhargava2004SmoothedMuscleMetabolics basics") { musclePtr->set_ignore_tendon_compliance(false); musclePtr->set_fiber_damping(0.01); musclePtr->setName("muscle"); - auto& path = musclePtr->updPath(); - path.appendNewPathPoint("origin", model.updGround(), SimTK::Vec3(0)); - path.appendNewPathPoint("insertion", *body, SimTK::Vec3(0)); + musclePtr->addNewPathPoint("origin", model.updGround(), SimTK::Vec3(0)); + musclePtr->addNewPathPoint("insertion", *body, SimTK::Vec3(0)); model.addComponent(musclePtr); auto& muscle = model.getComponent("muscle"); diff --git a/OpenSim/Simulation/Model/Blankevoort1991Ligament.h b/OpenSim/Simulation/Model/Blankevoort1991Ligament.h index b611dfcc61..7646342d3e 100644 --- a/OpenSim/Simulation/Model/Blankevoort1991Ligament.h +++ b/OpenSim/Simulation/Model/Blankevoort1991Ligament.h @@ -224,13 +224,13 @@ OpenSim_DECLARE_CONCRETE_OBJECT(Blankevoort1991Ligament, Force) Blankevoort1991Ligament(); Blankevoort1991Ligament(std::string name, - const PhysicalFrame& frame1, SimTK::Vec3 point1, - const PhysicalFrame& frame2, SimTK::Vec3 point2); + const PhysicalFrame& frame1, SimTK::Vec3 point1, + const PhysicalFrame& frame2, SimTK::Vec3 point2); Blankevoort1991Ligament(std::string name, - const PhysicalFrame& frame1, SimTK::Vec3 point1, - const PhysicalFrame& frame2, SimTK::Vec3 point2, - double linear_stiffness, double slack_length); + const PhysicalFrame& frame1, SimTK::Vec3 point1, + const PhysicalFrame& frame2, SimTK::Vec3 point2, + double linear_stiffness, double slack_length); Blankevoort1991Ligament(std::string name, double linear_stiffness, double slack_length); diff --git a/OpenSim/Simulation/Model/PathActuator.cpp b/OpenSim/Simulation/Model/PathActuator.cpp index ba0bca9594..313dcfeff3 100644 --- a/OpenSim/Simulation/Model/PathActuator.cpp +++ b/OpenSim/Simulation/Model/PathActuator.cpp @@ -139,6 +139,7 @@ double PathActuator::getStress( const SimTK::State& s) const return fabs(getActuation(s)/get_optimal_force()); } + //_____________________________________________________________________________ /** * Add a Path point to the _path of the actuator. The new point is appended @@ -146,9 +147,9 @@ double PathActuator::getStress( const SimTK::State& s) const * */ void PathActuator::addNewPathPoint( - const std::string& proposedName, - const PhysicalFrame& aBody, - const SimTK::Vec3& aPositionOnBody) { + const std::string& proposedName, + const PhysicalFrame& aBody, + const SimTK::Vec3& aPositionOnBody) { // Create new PathPoint already appended to the PathPointSet for the path updGeometryPath().appendNewPathPoint(proposedName, aBody, aPositionOnBody); } diff --git a/OpenSim/Simulation/Model/PathActuator.h b/OpenSim/Simulation/Model/PathActuator.h index baa05e71d6..f634a9e669 100644 --- a/OpenSim/Simulation/Model/PathActuator.h +++ b/OpenSim/Simulation/Model/PathActuator.h @@ -124,8 +124,8 @@ class OSIMSIMULATION_API PathActuator : public ScalarActuator { * @note Only valid if the `path` owned by this PathActuator supports * PathPoint%s (e.g., GeometryPath). */ void addNewPathPoint(const std::string& proposedName, - const PhysicalFrame& aBody, - const SimTK::Vec3& aPositionOnBody); + const PhysicalFrame& aBody, + const SimTK::Vec3& aPositionOnBody); //-------------------------------------------------------------------------- // APPLICATION diff --git a/OpenSim/Tests/AddComponents/testAddComponents.cpp b/OpenSim/Tests/AddComponents/testAddComponents.cpp index 429da8eb62..5f43a8bcb2 100644 --- a/OpenSim/Tests/AddComponents/testAddComponents.cpp +++ b/OpenSim/Tests/AddComponents/testAddComponents.cpp @@ -199,11 +199,11 @@ void addComponentsToModel(Model& osimModel) // Specify the paths for the two muscles // Path for muscle 1 - muscle1->addNewPathPoint("muscle1-point1", ground, Vec3(0.0,0.05,-0.35)); - muscle1->addNewPathPoint("muscle1-point2", *block, Vec3(0.0,0.0,-0.05)); + muscle1->addNewPathPoint("muscle1-point1", ground, Vec3(0.0, 0.05, -0.35)); + muscle1->addNewPathPoint("muscle1-point2", *block, Vec3(0.0, 0.0, -0.05)); // Path for muscle 2 - muscle2->addNewPathPoint("muscle2-point1", ground, Vec3(0.0,0.05,0.35)); - muscle2->addNewPathPoint("muscle2-point2", *block, Vec3(0.0,0.0,0.05)); + muscle2->addNewPathPoint("muscle2-point1", ground, Vec3(0.0, 0.05, 0.35)); + muscle2->addNewPathPoint("muscle2-point2", *block, Vec3(0.0, 0.0, 0.05)); // Add the two muscles (as forces) to the model osimModel.addComponent(muscle1); diff --git a/OpenSim/Tests/Wrapping/testWrapCylinder.cpp b/OpenSim/Tests/Wrapping/testWrapCylinder.cpp index 4e6667eb1c..30030e712d 100644 --- a/OpenSim/Tests/Wrapping/testWrapCylinder.cpp +++ b/OpenSim/Tests/Wrapping/testWrapCylinder.cpp @@ -436,7 +436,7 @@ namespace { cylinder->setFrame(model.getGround()); model.updComponent("spring") - .updGeometryPath().addPathWrap(*cylinder.get()); + .updGeometryPath().addPathWrap(*cylinder.get()); model.updGround().addWrapObject(cylinder.release()); } diff --git a/OpenSim/Tests/Wrapping/testWrapping.cpp b/OpenSim/Tests/Wrapping/testWrapping.cpp index 7034a25b3c..cf4e0dc6dc 100644 --- a/OpenSim/Tests/Wrapping/testWrapping.cpp +++ b/OpenSim/Tests/Wrapping/testWrapping.cpp @@ -357,9 +357,9 @@ void testWrapCylinder() PathSpring* spring1 = new PathSpring("spring1", 1.0, 0.1, 0.01); spring1->updGeometryPath(). - appendNewPathPoint("origin", ground, Vec3(-off, 0, 0)); + appendNewPathPoint("origin", ground, Vec3(-off, 0, 0)); spring1->updGeometryPath(). - appendNewPathPoint("insert", *body, Vec3(0)); + appendNewPathPoint("insert", *body, Vec3(0)); spring1->updGeometryPath().addPathWrap(*pulley1); model.addComponent(spring1); @@ -376,9 +376,9 @@ void testWrapCylinder() PathSpring* spring2 = new PathSpring("spring2", 1.0, 0.1, 0.01); spring2->updGeometryPath(). - appendNewPathPoint("origin", ground, Vec3(-off, 0, 0)); + appendNewPathPoint("origin", ground, Vec3(-off, 0, 0)); spring2->updGeometryPath(). - appendNewPathPoint("insert", *body, Vec3(0)); + appendNewPathPoint("insert", *body, Vec3(0)); spring2->updGeometryPath().addPathWrap(*pulley2); spring2->updGeometryPath().setDefaultColor(Vec3(0, 0.8, 0)); @@ -546,7 +546,7 @@ void simulateModelWithCables(const string &modelFile, double finalTime) numMuscles++; paths.append(&mus->updGeometryPath()); pathNames.append(mus->getName()); - cout << mus->getName() << ": " << mus->updGeometryPath().getWrapSet().getSize() << endl; + cout << mus->getName() << ": " << mus->getGeometryPath().getWrapSet().getSize() << endl; continue; } } diff --git a/OpenSim/Tests/Wrapping/testWrappingAlgorithm.cpp b/OpenSim/Tests/Wrapping/testWrappingAlgorithm.cpp index 12687b4e7a..b7e08f13b4 100644 --- a/OpenSim/Tests/Wrapping/testWrappingAlgorithm.cpp +++ b/OpenSim/Tests/Wrapping/testWrappingAlgorithm.cpp @@ -152,9 +152,9 @@ void testSingleWrapObjectPerpendicular(WrapObject* wrapObject, Vec3 axisRotation new PathSpring("spring1", 1.0, 0.1, 0.01); //offset in X direction to avoid ambiguous scenario where path passes through center spring1->updGeometryPath(). - appendNewPathPoint("origin", ground, Vec3(r-.1, r, 0)); + appendNewPathPoint("origin", ground, Vec3(r-.1, r, 0)); spring1->updGeometryPath(). - appendNewPathPoint("insert", *body, Vec3(-r, r, 0)); + appendNewPathPoint("insert", *body, Vec3(-r, r, 0)); spring1->updGeometryPath().addPathWrap(*wObj); model.addComponent(spring1); From bb4b8be066edac69f1d4b0835541573174ee87d3 Mon Sep 17 00:00:00 2001 From: Nicholas Bianco Date: Tue, 29 Aug 2023 14:44:00 -0700 Subject: [PATCH 09/24] Reverting API changes pt. 3 + more diff clean up --- Applications/Scale/test/testScale.cpp | 10 +++--- Bindings/Java/OpenSimJNI/Test/testContext.cpp | 1 - Bindings/Java/tests/TestBasics.java | 10 +++--- Bindings/Java/tests/TestModelBuilding.java | 5 ++- OpenSim/Actuators/Test/testActuators.cpp | 5 ++- OpenSim/Actuators/Test/testModelProcessor.cpp | 6 ++-- OpenSim/Actuators/Test/testMuscles.cpp | 35 ++++++++----------- OpenSim/Analyses/Test/testOutputReporter.cpp | 5 ++- .../ExampleHopperDevice/buildDeviceModel.cpp | 3 +- .../buildDeviceModel_answers.cpp | 5 ++- .../ExampleHopperDevice/buildHopperModel.cpp | 7 ++-- .../exampleHopperDevice.cpp | 3 +- .../exampleHopperDevice_answers.cpp | 3 +- .../LuxoMuscle_create_and_simulate.cpp | 25 ++++++------- .../OutputReference/TugOfWar_Complete.cpp | 10 +++--- .../exampleHangingMuscle.cpp | 5 ++- .../Examples/MuscleExample/mainFatigue.cpp | 10 +++--- 17 files changed, 59 insertions(+), 89 deletions(-) diff --git a/Applications/Scale/test/testScale.cpp b/Applications/Scale/test/testScale.cpp index af6fd731ca..b42af1e408 100644 --- a/Applications/Scale/test/testScale.cpp +++ b/Applications/Scale/test/testScale.cpp @@ -35,7 +35,6 @@ #include #include #include -#include #include #include #include @@ -562,9 +561,8 @@ void scalePhysicalOffsetFrames() const Vec3 offset1 = Vec3(0.2, 0.4, 0.6); PathActuator* act1 = new PathActuator(); act1->setName("pathActuator1"); - auto& path = act1->updPath(); - path.appendNewPathPoint("point1a", model->updGround(), Vec3(0)); - path.appendNewPathPoint("point1b", *body, offset1); + act1->addNewPathPoint("point1a", model->updGround(), Vec3(0)); + act1->addNewPathPoint("point1b", *body, offset1); body->addComponent(act1); // Second PathActuator is attached to the Body via a POF. Both new @@ -578,8 +576,8 @@ void scalePhysicalOffsetFrames() PathActuator* act2 = new PathActuator(); act2->setName("pathActuator2"); auto& path2 = act2->updPath(); - path2.appendNewPathPoint("point2a", model->updGround(), Vec3(0)); - path2.appendNewPathPoint("point2b", *pof2, offset2); + act2->addNewPathPoint("point2a", model->updGround(), Vec3(0)); + act2->addNewPathPoint("point2b", *pof2, offset2); act1->addComponent(act2); State& s = model->initSystem(); diff --git a/Bindings/Java/OpenSimJNI/Test/testContext.cpp b/Bindings/Java/OpenSimJNI/Test/testContext.cpp index e26aaf2828..fc380b8269 100644 --- a/Bindings/Java/OpenSimJNI/Test/testContext.cpp +++ b/Bindings/Java/OpenSimJNI/Test/testContext.cpp @@ -33,7 +33,6 @@ #include #include #include -#include #include #include #include diff --git a/Bindings/Java/tests/TestBasics.java b/Bindings/Java/tests/TestBasics.java index 79483cd421..919ab4aba4 100644 --- a/Bindings/Java/tests/TestBasics.java +++ b/Bindings/Java/tests/TestBasics.java @@ -35,14 +35,12 @@ public static void testMuscleList() { Ground ground = model.getGround(); Thelen2003Muscle thelenMuscle = new Thelen2003Muscle("Darryl", 1, 0.5, 0.5, 0); - GeometryPath pathThelen = thelenMuscle.initGeometryPath(); - pathThelen.appendNewPathPoint("muscle1-point1", ground, new Vec3(0.0,0.0,0.0)); - pathThelen.appendNewPathPoint("muscle1-point2", ground, new Vec3(1.0,0.0,0.0)); + thelenMuscle.addNewPathPoint("muscle1-point1", ground, new Vec3(0.0,0.0,0.0)); + thelenMuscle.addNewPathPoint("muscle1-point2", ground, new Vec3(1.0,0.0,0.0)); Millard2012EquilibriumMuscle millardMuscle = new Millard2012EquilibriumMuscle("Matt", 1, 0.5, 0.5, 0); - GeometryPath pathMillard = millardMuscle.initGeometryPath(); - pathMillard.appendNewPathPoint("muscle1-point1", ground, new Vec3(0.0,0.0,0.0)); - pathMillard.appendNewPathPoint("muscle1-point2", ground, new Vec3(1.0,0.0,0.0)); + millardMuscle.addNewPathPoint("muscle1-point1", ground, new Vec3(0.0,0.0,0.0)); + millardMuscle.addNewPathPoint("muscle1-point2", ground, new Vec3(1.0,0.0,0.0)); model.addComponent(thelenMuscle); model.addComponent(millardMuscle); diff --git a/Bindings/Java/tests/TestModelBuilding.java b/Bindings/Java/tests/TestModelBuilding.java index a85252eb02..fdf9cce6c9 100644 --- a/Bindings/Java/tests/TestModelBuilding.java +++ b/Bindings/Java/tests/TestModelBuilding.java @@ -26,9 +26,8 @@ public static void main(String[] args) { 0.6, // Optimal fibre length 0.55, // Tendon slack length 0.0); // Pennation angle - GeometryPath pathBiceps = biceps.initGeometryPath(); - pathBiceps.appendNewPathPoint("origin", hum, ArrayDouble.createVec3(new double[]{0, 0.8, 0})); - pathBiceps.appendNewPathPoint("insert", rad, ArrayDouble.createVec3(new double[]{0, 0.7, 0})); + biceps.addNewPathPoint("origin", hum, ArrayDouble.createVec3(new double[]{0, 0.8, 0})); + biceps.addNewPathPoint("insert", rad, ArrayDouble.createVec3(new double[]{0, 0.7, 0})); PrescribedController cns = new PrescribedController(); cns.addActuator(biceps); diff --git a/OpenSim/Actuators/Test/testActuators.cpp b/OpenSim/Actuators/Test/testActuators.cpp index 45d7a2e3f1..3816d32a0e 100644 --- a/OpenSim/Actuators/Test/testActuators.cpp +++ b/OpenSim/Actuators/Test/testActuators.cpp @@ -480,9 +480,8 @@ void testMcKibbenActuator() OpenSim::Body* ball = new OpenSim::Body("ball", mass, Vec3(0), mass*SimTK::Inertia::sphere(0.1)); ball->scale(Vec3(ball_radius), false); - auto& path = actuator->updPath(); - path.appendNewPathPoint("mck_ground", ground, Vec3(0)); - path.appendNewPathPoint("mck_ball", *ball, Vec3(ball_radius)); + actuator->addNewPathPoint("mck_ground", ground, Vec3(0)); + actuator->addNewPathPoint("mck_ball", *ball, Vec3(ball_radius)); Vec3 locationInParent(0, ball_radius, 0), orientationInParent(0), locationInBody(0), orientationInBody(0); SliderJoint *ballToGround = new SliderJoint("ballToGround", ground, locationInParent, orientationInParent, *ball, locationInBody, orientationInBody); diff --git a/OpenSim/Actuators/Test/testModelProcessor.cpp b/OpenSim/Actuators/Test/testModelProcessor.cpp index 8129e9a989..7097cfa089 100644 --- a/OpenSim/Actuators/Test/testModelProcessor.cpp +++ b/OpenSim/Actuators/Test/testModelProcessor.cpp @@ -92,10 +92,8 @@ Model createElbowModel() { // Add a muscle that flexes the elbow. auto* biceps = new Millard2012EquilibriumMuscle("biceps", 200, 0.6, 0.55, 0); - - auto& path = biceps->updPath(); - path.appendNewPathPoint("origin", model.getGround(), Vec3(0, 0.8, 0)); - path.appendNewPathPoint("insertion", *body, Vec3(0, 0.7, 0)); + biceps->addNewPathPoint("origin", model.getGround(), Vec3(0, 0.8, 0)); + biceps->addNewPathPoint("insertion", *body, Vec3(0, 0.7, 0)); model.addBody(body); model.addJoint(joint); diff --git a/OpenSim/Actuators/Test/testMuscles.cpp b/OpenSim/Actuators/Test/testMuscles.cpp index 3eeeb44536..32b56799be 100644 --- a/OpenSim/Actuators/Test/testMuscles.cpp +++ b/OpenSim/Actuators/Test/testMuscles.cpp @@ -255,9 +255,8 @@ void simulateMuscle( //Attach the muscle const string &actuatorType = aMuscle->getConcreteClassName(); aMuscle->setName("muscle"); - auto& path = aMuscle->updPath(); - path.appendNewPathPoint("muscle-box", ground, Vec3(anchorWidth/2,0,0)); - path.appendNewPathPoint("muscle-ball", *ball, Vec3(-ballRadius,0,0)); + aMuscle->addNewPathPoint("muscle-box", ground, Vec3(anchorWidth/2,0,0)); + aMuscle->addNewPathPoint("muscle-ball", *ball, Vec3(-ballRadius,0,0)); ActivationFiberLengthMuscle_Deprecated *aflMuscle = dynamic_cast(aMuscle); @@ -608,9 +607,8 @@ void testThelen2003Muscle() false); Model m; - auto& path = muscle.updPath(); - path.appendNewPathPoint("p1", m.getGround(), SimTK::Vec3(0.0)); - path.appendNewPathPoint("p2", m.getGround(), SimTK::Vec3(1.0)); + muscle.addNewPathPoint("p1", m.getGround(), SimTK::Vec3(0.0)); + muscle.addNewPathPoint("p2", m.getGround(), SimTK::Vec3(1.0)); // Test property bounds. { Thelen2003Muscle musc = muscle; @@ -700,9 +698,8 @@ void testThelen2003Muscle() MaxIsometricForce0, OptimalFiberLength0, TendonSlackLength0, PennationAngle0); - auto& path = myMcl->updPath(); - path.appendNewPathPoint("p1", myModel.getGround(), SimTK::Vec3(0.0)); - path.appendNewPathPoint("p2", myModel.getGround(), SimTK::Vec3(1.0)); + myMcl->addNewPathPoint("p1", myModel.getGround(), SimTK::Vec3(0.0)); + myMcl->addNewPathPoint("p2", myModel.getGround(), SimTK::Vec3(1.0)); myModel.addForce(myMcl); // Set properties of Thelen2003Muscle. @@ -786,9 +783,8 @@ void testThelen2003Muscle() const double tendonSlackLength = 0.001; auto muscle = new Thelen2003Muscle("muscle", 1., optimalFiberLength, tendonSlackLength, 0.); - auto& path = muscle->updPath(); - path.appendNewPathPoint("p1", model.updGround(), SimTK::Vec3(0)); - path.appendNewPathPoint("p2", model.updGround(), SimTK::Vec3(0,0,1)); + muscle->addNewPathPoint("p1", model.updGround(), SimTK::Vec3(0)); + muscle->addNewPathPoint("p2", model.updGround(), SimTK::Vec3(0,0,1)); model.addForce(muscle); SimTK::State& state = model.initSystem(); @@ -802,9 +798,8 @@ void testThelen2003Muscle() { Model model; auto muscle = new Thelen2003Muscle("muscle", 1., 0.5, 0.5, 0.); - auto& path = muscle->updPath(); - path.appendNewPathPoint("p1", model.updGround(), SimTK::Vec3(0)); - path.appendNewPathPoint("p2", model.updGround(), SimTK::Vec3(0,0,1)); + muscle->addNewPathPoint("p1", model.updGround(), SimTK::Vec3(0)); + muscle->addNewPathPoint("p2", model.updGround(), SimTK::Vec3(0,0,1)); model.addForce(muscle); model.finalizeFromProperties(); @@ -897,9 +892,8 @@ void testMillard2012EquilibriumMuscle() const double tendonSlackLength = 0.1; //short tendon auto muscle = new Millard2012EquilibriumMuscle("muscle", 1., optimalFiberLength, tendonSlackLength, 0.); - auto& path = muscle->updPath(); - path.appendNewPathPoint("p1", model.updGround(), SimTK::Vec3(0)); - path.appendNewPathPoint("p2", model.updGround(), SimTK::Vec3(0, 0, 1)); + muscle->addNewPathPoint("p1", model.updGround(), SimTK::Vec3(0)); + muscle->addNewPathPoint("p2", model.updGround(), SimTK::Vec3(0, 0, 1)); model.addForce(muscle); SimTK::State& state = model.initSystem(); @@ -914,9 +908,8 @@ void testMillard2012EquilibriumMuscle() { Model model; auto muscle = new Millard2012EquilibriumMuscle("mcl", 1., 0.5, 0.5, 0.); - auto& path = muscle->updPath(); - path.appendNewPathPoint("p1", model.updGround(), SimTK::Vec3(0)); - path.appendNewPathPoint("p2", model.updGround(), SimTK::Vec3(0,0,1)); + muscle->addNewPathPoint("p1", model.updGround(), SimTK::Vec3(0)); + muscle->addNewPathPoint("p2", model.updGround(), SimTK::Vec3(0,0,1)); model.addForce(muscle); model.finalizeFromProperties(); diff --git a/OpenSim/Analyses/Test/testOutputReporter.cpp b/OpenSim/Analyses/Test/testOutputReporter.cpp index a54832dd51..822fd0b7b1 100644 --- a/OpenSim/Analyses/Test/testOutputReporter.cpp +++ b/OpenSim/Analyses/Test/testOutputReporter.cpp @@ -161,9 +161,8 @@ void simulateMuscle( //Attach the muscle /*const string &actuatorType = */muscle->getConcreteClassName(); muscle->setName("muscle"); - auto& path = muscle->updPath(); - path.appendNewPathPoint("muscle-box", ground, Vec3(anchorWidth / 2, 0, 0)); - path.appendNewPathPoint("muscle-ball", *ball, Vec3(-ballRadius, 0, 0)); + muscle->addNewPathPoint("muscle-box", ground, Vec3(anchorWidth / 2, 0, 0)); + muscle->addNewPathPoint("muscle-ball", *ball, Vec3(-ballRadius, 0, 0)); model.addForce(muscle); diff --git a/OpenSim/Examples/ExampleHopperDevice/buildDeviceModel.cpp b/OpenSim/Examples/ExampleHopperDevice/buildDeviceModel.cpp index 8cbb7f2751..901dd35389 100644 --- a/OpenSim/Examples/ExampleHopperDevice/buildDeviceModel.cpp +++ b/OpenSim/Examples/ExampleHopperDevice/buildDeviceModel.cpp @@ -82,8 +82,7 @@ Device* buildDevice() { auto pathActuator = new PathActuator(); pathActuator->setName("cableAtoB"); pathActuator->set_optimal_force(OPTIMAL_FORCE); - auto& path = pathActuator->updPath(); - path.appendNewPathPoint("pointA", *cuffA, Vec3(0)); + pathActuator->addNewPathPoint("pointA", *cuffA, Vec3(0)); //pathActuator->addNewPathPoint("pointB", *cuffB, Vec3(0)); device->addComponent(pathActuator); diff --git a/OpenSim/Examples/ExampleHopperDevice/buildDeviceModel_answers.cpp b/OpenSim/Examples/ExampleHopperDevice/buildDeviceModel_answers.cpp index 7ac3053f7e..58c2ec8a37 100644 --- a/OpenSim/Examples/ExampleHopperDevice/buildDeviceModel_answers.cpp +++ b/OpenSim/Examples/ExampleHopperDevice/buildDeviceModel_answers.cpp @@ -111,9 +111,8 @@ Device* buildDevice() { auto pathActuator = new PathActuator(); pathActuator->setName("cableAtoB"); pathActuator->set_optimal_force(OPTIMAL_FORCE); - auto& path = pathActuator->updPath(); - path.appendNewPathPoint("pointA", *cuffA, Vec3(0)); - path.appendNewPathPoint("pointB", *cuffB, Vec3(0)); + pathActuator->addNewPathPoint("pointA", *cuffA, Vec3(0)); + pathActuator->addNewPathPoint("pointB", *cuffB, Vec3(0)); device->addComponent(pathActuator); // Create a PropMyoController. diff --git a/OpenSim/Examples/ExampleHopperDevice/buildHopperModel.cpp b/OpenSim/Examples/ExampleHopperDevice/buildHopperModel.cpp index 49dc116244..b32f5de02e 100644 --- a/OpenSim/Examples/ExampleHopperDevice/buildHopperModel.cpp +++ b/OpenSim/Examples/ExampleHopperDevice/buildHopperModel.cpp @@ -144,9 +144,8 @@ Model buildHopper(bool showVisualizer) { mclPennAng = 0.; auto vastus = new Thelen2003Muscle("vastus", mclFmax, mclOptFibLen, mclTendonSlackLen, mclPennAng); - auto& path = vastus->updPath(); - path.appendNewPathPoint("origin", *thigh, Vec3(linkRadius, 0.1, 0)); - path.appendNewPathPoint("insertion", *shank, Vec3(linkRadius, 0.15, 0)); + vastus->addNewPathPoint("origin", *thigh, Vec3(linkRadius, 0.1, 0)); + vastus->addNewPathPoint("insertion", *shank, Vec3(linkRadius, 0.15, 0)); hopper.addForce(vastus); // Attach a cylinder (patella) to the distal end of the thigh over which the @@ -163,7 +162,7 @@ Model buildHopper(bool showVisualizer) { thigh->addComponent(patellaFrame); // Configure the vastus muscle to wrap over the patella. - path.addPathWrap(*patella); + vastus->updGeometryPath().addPathWrap(*patella); // Create a controller to excite the vastus muscle. auto brain = new PrescribedController(); diff --git a/OpenSim/Examples/ExampleHopperDevice/exampleHopperDevice.cpp b/OpenSim/Examples/ExampleHopperDevice/exampleHopperDevice.cpp index bbc23bff52..983b3fb1fa 100644 --- a/OpenSim/Examples/ExampleHopperDevice/exampleHopperDevice.cpp +++ b/OpenSim/Examples/ExampleHopperDevice/exampleHopperDevice.cpp @@ -99,8 +99,7 @@ void connectDeviceToModel(OpenSim::Device& device, OpenSim::Model& model, if (model.hasComponent(patellaPath)) { auto& cable = model.updComponent("device/cableAtoB"); auto& wrapObject = model.updComponent(patellaPath); - auto& path = cable.updPath(); - path.addPathWrap(wrapObject); + cable.updGeometryPath().addPathWrap(wrapObject); } } diff --git a/OpenSim/Examples/ExampleHopperDevice/exampleHopperDevice_answers.cpp b/OpenSim/Examples/ExampleHopperDevice/exampleHopperDevice_answers.cpp index 6a6384f324..429deffb2f 100644 --- a/OpenSim/Examples/ExampleHopperDevice/exampleHopperDevice_answers.cpp +++ b/OpenSim/Examples/ExampleHopperDevice/exampleHopperDevice_answers.cpp @@ -131,8 +131,7 @@ void connectDeviceToModel(OpenSim::Device& device, OpenSim::Model& model, if (model.hasComponent(patellaPath)) { auto& cable = model.updComponent("device/cableAtoB"); auto& wrapObject = model.updComponent(patellaPath); - auto& path = cable.updPath(); - path.addPathWrap(wrapObject); + cable.updGeometryPath().addPathWrap(wrapObject); } } diff --git a/OpenSim/Examples/ExampleLuxoMuscle/LuxoMuscle_create_and_simulate.cpp b/OpenSim/Examples/ExampleLuxoMuscle/LuxoMuscle_create_and_simulate.cpp index 86a318b62a..bdb3567aea 100644 --- a/OpenSim/Examples/ExampleLuxoMuscle/LuxoMuscle_create_and_simulate.cpp +++ b/OpenSim/Examples/ExampleLuxoMuscle/LuxoMuscle_create_and_simulate.cpp @@ -713,10 +713,9 @@ void createLuxoJr(OpenSim::Model& model){ "knee_extensor_right", knee_extensor_F0, knee_extensor_lm0, knee_extensor_lts, pennationAngle); - auto& pathKneeRight = kneeExtensorRight->updPath(); - pathKneeRight.appendNewPathPoint("knee_extensor_right_origin", *leg_Hlink, + kneeExtensorRight->addNewPathPoint("knee_extensor_right_origin", *leg_Hlink, knee_extensor_origin); - pathKneeRight.appendNewPathPoint("knee_extensor_right_insertion", + kneeExtensorRight->addNewPathPoint("knee_extensor_right_insertion", *bottom_bracket, knee_extensor_insertion); kneeExtensorRight->set_ignore_tendon_compliance(true); @@ -728,15 +727,14 @@ void createLuxoJr(OpenSim::Model& model){ knee_extensor_F0, knee_extensor_lm0, knee_extensor_lts, pennationAngle); - auto& pathKneeLeft = kneeExtensorLeft->updPath(); - pathKneeLeft.appendNewPathPoint("knee_extensor_left_origin", *leg_Hlink, + kneeExtensorLeft->addNewPathPoint("knee_extensor_left_origin", *leg_Hlink, knee_extensor_origin); - pathKneeLeft.appendNewPathPoint("knee_extensor_left_insertion", + kneeExtensorLeft->addNewPathPoint("knee_extensor_left_insertion", *bottom_bracket, knee_extensor_insertion); // flip the z coordinates of all path points - PathPointSet& points = pathKneeLeft.updPathPointSet(); + PathPointSet& points = kneeExtensorLeft->updGeometryPath().updPathPointSet(); for (int i=0; i(points[i]).upd_location()[2] *= -1; } @@ -750,10 +748,9 @@ void createLuxoJr(OpenSim::Model& model){ back_extensor_F0, back_extensor_lm0, back_extensor_lts, pennationAngle); - auto& pathBackRight = backExtensorRight->updPath(); - pathBackRight.appendNewPathPoint("back_extensor_right_origin", *chest, + backExtensorRight->addNewPathPoint("back_extensor_right_origin", *chest, back_extensor_origin); - pathBackRight.appendNewPathPoint("back_extensor_right_insertion", *back, + backExtensorRight->addNewPathPoint("back_extensor_right_insertion", *back, back_extensor_insertion); backExtensorRight->set_ignore_tendon_compliance(true); model.addForce(backExtensorRight); @@ -764,13 +761,13 @@ void createLuxoJr(OpenSim::Model& model){ back_extensor_F0, back_extensor_lm0, back_extensor_lts, pennationAngle); - auto& pathBackLeft = backExtensorLeft->updPath(); - pathBackLeft.appendNewPathPoint("back_extensor_left_origin", *chest, + backExtensorLeft->addNewPathPoint("back_extensor_left_origin", *chest, back_extensor_origin); - pathBackLeft.appendNewPathPoint("back_extensor_left_insertion", *back, + backExtensorLeft->addNewPathPoint("back_extensor_left_insertion", *back, back_extensor_insertion); - PathPointSet& pointsLeft = pathBackLeft.updPathPointSet(); + PathPointSet& pointsLeft = backExtensorLeft->updGeometryPath() + .updPathPointSet(); for (int i=0; i(pointsLeft[i]).upd_location()[2] *= -1; } diff --git a/OpenSim/Examples/ExampleMain/OutputReference/TugOfWar_Complete.cpp b/OpenSim/Examples/ExampleMain/OutputReference/TugOfWar_Complete.cpp index 09837028a1..fd9b3009ed 100644 --- a/OpenSim/Examples/ExampleMain/OutputReference/TugOfWar_Complete.cpp +++ b/OpenSim/Examples/ExampleMain/OutputReference/TugOfWar_Complete.cpp @@ -201,13 +201,11 @@ int main() // Specify the paths for the two muscles // Path for muscle 1 - auto& path1 = muscle1->updPath(); - path1.appendNewPathPoint("muscle1-point1", ground, Vec3(0.0,0.05,-0.35)); - path1.appendNewPathPoint("muscle1-point2", *block, Vec3(0.0,0.0,-0.05)); + muscle1->addNewPathPoint("muscle1-point1", ground, Vec3(0.0,0.05,-0.35)); + muscle1->addNewPathPoint("muscle1-point2", *block, Vec3(0.0,0.0,-0.05)); // Path for muscle 2 - auto& path2 = muscle2->updPath(); - path2.appendNewPathPoint("muscle2-point1", ground, Vec3(0.0,0.05,0.35)); - path2.appendNewPathPoint("muscle2-point2", *block, Vec3(0.0,0.0,0.05)); + muscle2->addNewPathPoint("muscle2-point1", ground, Vec3(0.0,0.05,0.35)); + muscle2->addNewPathPoint("muscle2-point2", *block, Vec3(0.0,0.0,0.05)); // Add the two muscles (as forces) to the model osimModel.addForce(muscle1); diff --git a/OpenSim/Examples/Moco/exampleHangingMuscle/exampleHangingMuscle.cpp b/OpenSim/Examples/Moco/exampleHangingMuscle/exampleHangingMuscle.cpp index ec7d102053..68f3c364b5 100644 --- a/OpenSim/Examples/Moco/exampleHangingMuscle/exampleHangingMuscle.cpp +++ b/OpenSim/Examples/Moco/exampleHangingMuscle/exampleHangingMuscle.cpp @@ -63,9 +63,8 @@ Model createHangingMuscleModel(bool ignoreActivationDynamics, actu->set_tendon_compliance_dynamics_mode("implicit"); actu->set_max_contraction_velocity(10); actu->set_pennation_angle_at_optimal(0.10); - auto& path = actu->updPath(); - path.appendNewPathPoint("origin", model.updGround(), SimTK::Vec3(0)); - path.appendNewPathPoint("insertion", *body, SimTK::Vec3(0)); + actu->addNewPathPoint("origin", model.updGround(), SimTK::Vec3(0)); + actu->addNewPathPoint("insertion", *body, SimTK::Vec3(0)); model.addForce(actu); // Add metabolics probes: one for the total metabolic rate, diff --git a/OpenSim/Examples/MuscleExample/mainFatigue.cpp b/OpenSim/Examples/MuscleExample/mainFatigue.cpp index 28ef25ab38..31a113d86e 100644 --- a/OpenSim/Examples/MuscleExample/mainFatigue.cpp +++ b/OpenSim/Examples/MuscleExample/mainFatigue.cpp @@ -133,16 +133,14 @@ int main() pennationAngle); // Define the path of the muscles - auto& fatigablePath = fatigable->updPath(); - fatigablePath.appendNewPathPoint("fatigable-point1", ground, + fatigable->addNewPathPoint("fatigable-point1", ground, Vec3(0.0, halfLength, -0.35)); - fatigablePath.appendNewPathPoint("fatigable-point2", *block, + fatigable->addNewPathPoint("fatigable-point2", *block, Vec3(0.0, halfLength, -halfLength)); - auto& originalPath = original->updPath(); - originalPath.appendNewPathPoint("original-point1", ground, + original->addNewPathPoint("original-point1", ground, Vec3(0.0, halfLength, 0.35)); - originalPath.appendNewPathPoint("original-point2", *block, + original->addNewPathPoint("original-point2", *block, Vec3(0.0, halfLength, halfLength)); // Define the default states for the two muscles From 5a74515b4730794bb9ab7919a601082283d795ea Mon Sep 17 00:00:00 2001 From: Nicholas Bianco Date: Tue, 29 Aug 2023 15:36:01 -0700 Subject: [PATCH 10/24] More diff clean up --- Applications/Scale/test/testScale.cpp | 1 - Bindings/Java/OpenSimJNI/OpenSimContext.cpp | 17 ++++------------- Bindings/Java/OpenSimJNI/OpenSimContext.h | 1 - CHANGELOG.md | 2 +- .../Test/testDeGrooteFregly2016Muscle.cpp | 5 ++--- OpenSim/Actuators/Test/testMuscles.cpp | 5 ++--- .../LuxoMuscle_create_and_simulate.cpp | 1 - 7 files changed, 9 insertions(+), 23 deletions(-) diff --git a/Applications/Scale/test/testScale.cpp b/Applications/Scale/test/testScale.cpp index b42af1e408..0046f7c432 100644 --- a/Applications/Scale/test/testScale.cpp +++ b/Applications/Scale/test/testScale.cpp @@ -575,7 +575,6 @@ void scalePhysicalOffsetFrames() PathActuator* act2 = new PathActuator(); act2->setName("pathActuator2"); - auto& path2 = act2->updPath(); act2->addNewPathPoint("point2a", model->updGround(), Vec3(0)); act2->addNewPathPoint("point2b", *pof2, offset2); act1->addComponent(act2); diff --git a/Bindings/Java/OpenSimJNI/OpenSimContext.cpp b/Bindings/Java/OpenSimJNI/OpenSimContext.cpp index 360478b686..c52213df80 100644 --- a/Bindings/Java/OpenSimJNI/OpenSimContext.cpp +++ b/Bindings/Java/OpenSimJNI/OpenSimContext.cpp @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include @@ -125,21 +124,13 @@ double OpenSimContext::getMuscleLength(Muscle& m) { } const Array& OpenSimContext::getCurrentPath(Muscle& m) { - if (auto* p = dynamic_cast(&m.getPath())) { - return p->getCurrentPath(*_configState); - } else { - OPENSIM_THROW(Exception, "Muscle path is not a GeometryPath.") - } + return m.getGeometryPath().getCurrentPath(*_configState); } void OpenSimContext::copyMuscle(Muscle& from, Muscle& to) { - if (auto* p = dynamic_cast(&from.getPath())) { - to = from; - recreateSystemKeepStage(); - to.updPath().updateGeometry(*_configState); - } else { - OPENSIM_THROW(Exception, "Muscle path is not a GeometryPath.") - } + to = from; + recreateSystemKeepStage(); + to.updPath().updateGeometry(*_configState); } // Muscle Points diff --git a/Bindings/Java/OpenSimJNI/OpenSimContext.h b/Bindings/Java/OpenSimJNI/OpenSimContext.h index 60694317dc..7eded75a6d 100644 --- a/Bindings/Java/OpenSimJNI/OpenSimContext.h +++ b/Bindings/Java/OpenSimJNI/OpenSimContext.h @@ -48,7 +48,6 @@ class GeometryPath; class AbstractPathPoint; class PathWrap; class ConditionalPathPoint; -class PathPoint; class WrapObject; class Analysis; class AnalyzeTool; diff --git a/CHANGELOG.md b/CHANGELOG.md index ba5726f138..3a8f903ae2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ This is not a comprehensive list of changes but rather a hand-curated collection v4.5 ==== -- Added `AbstractPath` which is a base class for `GeometryPath` and other path types (#3388). TODO: add API changes. +- Added `AbstractPath` which is a base class for `GeometryPath` and other path types (#3388). v4.4.1 ====== diff --git a/OpenSim/Actuators/Test/testDeGrooteFregly2016Muscle.cpp b/OpenSim/Actuators/Test/testDeGrooteFregly2016Muscle.cpp index 1342d6f5a3..36b724b248 100644 --- a/OpenSim/Actuators/Test/testDeGrooteFregly2016Muscle.cpp +++ b/OpenSim/Actuators/Test/testDeGrooteFregly2016Muscle.cpp @@ -142,9 +142,8 @@ TEST_CASE("DeGrooteFregly2016Muscle basics") { musclePtr->set_ignore_tendon_compliance(true); musclePtr->set_fiber_damping(0); musclePtr->setName("muscle"); - auto& path = musclePtr->updPath(); - path.appendNewPathPoint("origin", model.updGround(), SimTK::Vec3(0)); - path.appendNewPathPoint("insertion", *body, SimTK::Vec3(0)); + musclePtr->addNewPathPoint("origin", model.updGround(), SimTK::Vec3(0)); + musclePtr->addNewPathPoint("insertion", *body, SimTK::Vec3(0)); model.addComponent(musclePtr); auto& muscle = model.updComponent("muscle"); diff --git a/OpenSim/Actuators/Test/testMuscles.cpp b/OpenSim/Actuators/Test/testMuscles.cpp index 32b56799be..5a9b4b3864 100644 --- a/OpenSim/Actuators/Test/testMuscles.cpp +++ b/OpenSim/Actuators/Test/testMuscles.cpp @@ -873,9 +873,8 @@ void testMillard2012EquilibriumMuscle() const double tendonSlackLength = 100.0; //long tendon auto muscle = new Millard2012EquilibriumMuscle("muscle", 1., optimalFiberLength, tendonSlackLength, 0.); - auto& path = muscle->updPath(); - path.appendNewPathPoint("p1", model.updGround(), SimTK::Vec3(0)); - path.appendNewPathPoint("p2", model.updGround(), SimTK::Vec3(0,0,1)); + muscle->addNewPathPoint("p1", model.updGround(), SimTK::Vec3(0)); + muscle->addNewPathPoint("p2", model.updGround(), SimTK::Vec3(0,0,1)); model.addForce(muscle); SimTK::State& state = model.initSystem(); diff --git a/OpenSim/Examples/ExampleLuxoMuscle/LuxoMuscle_create_and_simulate.cpp b/OpenSim/Examples/ExampleLuxoMuscle/LuxoMuscle_create_and_simulate.cpp index bdb3567aea..279ec4bdb5 100644 --- a/OpenSim/Examples/ExampleLuxoMuscle/LuxoMuscle_create_and_simulate.cpp +++ b/OpenSim/Examples/ExampleLuxoMuscle/LuxoMuscle_create_and_simulate.cpp @@ -760,7 +760,6 @@ void createLuxoJr(OpenSim::Model& model){ new Millard2012EquilibriumMuscle("back_extensor_left", back_extensor_F0, back_extensor_lm0, back_extensor_lts, pennationAngle); - backExtensorLeft->addNewPathPoint("back_extensor_left_origin", *chest, back_extensor_origin); backExtensorLeft->addNewPathPoint("back_extensor_left_insertion", *back, From ce3b0c47607331519b57b4dd48d6eeef90bfb909 Mon Sep 17 00:00:00 2001 From: Nicholas Bianco Date: Tue, 29 Aug 2023 15:59:29 -0700 Subject: [PATCH 11/24] Stop IDE from removing trailing whitespaces... --- Bindings/Java/OpenSimJNI/OpenSimContext.cpp | 2 +- Bindings/Java/OpenSimJNI/Test/testContext.cpp | 2 +- OpenSim/Actuators/Test/testMuscles.cpp | 2 +- .../ExampleLuxoMuscle/LuxoMuscle_create_and_simulate.cpp | 1 - OpenSim/Examples/MuscleExample/mainFatigue.cpp | 8 ++++---- OpenSim/Simulation/Model/Blankevoort1991Ligament.cpp | 6 +++--- OpenSim/Simulation/Model/Blankevoort1991Ligament.h | 4 ++-- OpenSim/Simulation/Model/Muscle.h | 2 +- OpenSim/Simulation/MomentArmSolver.cpp | 1 - OpenSim/Simulation/RegisterTypes_osimSimulation.cpp | 1 - OpenSim/Tests/Wrapping/testWrappingAlgorithm.cpp | 4 ++-- OpenSim/Tests/testIterators/testIterators.cpp | 1 - 12 files changed, 15 insertions(+), 19 deletions(-) diff --git a/Bindings/Java/OpenSimJNI/OpenSimContext.cpp b/Bindings/Java/OpenSimJNI/OpenSimContext.cpp index c52213df80..9f64c6ac53 100644 --- a/Bindings/Java/OpenSimJNI/OpenSimContext.cpp +++ b/Bindings/Java/OpenSimJNI/OpenSimContext.cpp @@ -130,7 +130,7 @@ const Array& OpenSimContext::getCurrentPath(Muscle& m) { void OpenSimContext::copyMuscle(Muscle& from, Muscle& to) { to = from; recreateSystemKeepStage(); - to.updPath().updateGeometry(*_configState); + to.updGeometryPath().updateGeometry(*_configState); } // Muscle Points diff --git a/Bindings/Java/OpenSimJNI/Test/testContext.cpp b/Bindings/Java/OpenSimJNI/Test/testContext.cpp index fc380b8269..54bed517b2 100644 --- a/Bindings/Java/OpenSimJNI/Test/testContext.cpp +++ b/Bindings/Java/OpenSimJNI/Test/testContext.cpp @@ -199,7 +199,7 @@ int main() AbstractPathPoint* clonedPoint = savePoint.clone(); // Test delete second PathPoint from TRIlong muscle - context->deletePathPoint(dTRIlong->updGeometryPath(), 2); + context->deletePathPoint(dTRIlong->updGeometryPath(), 2); assert(pathPoints.getSize() == origSize - 1); std::string pathAfterDeletionInXML = dTRIlong->updGeometryPath().dump(); std::cout << pathAfterDeletionInXML << endl; diff --git a/OpenSim/Actuators/Test/testMuscles.cpp b/OpenSim/Actuators/Test/testMuscles.cpp index 5a9b4b3864..d4cebd341a 100644 --- a/OpenSim/Actuators/Test/testMuscles.cpp +++ b/OpenSim/Actuators/Test/testMuscles.cpp @@ -697,7 +697,7 @@ void testThelen2003Muscle() Thelen2003Muscle* myMcl = new Thelen2003Muscle("myMuscle", MaxIsometricForce0, OptimalFiberLength0, TendonSlackLength0, PennationAngle0); - + myMcl->addNewPathPoint("p1", myModel.getGround(), SimTK::Vec3(0.0)); myMcl->addNewPathPoint("p2", myModel.getGround(), SimTK::Vec3(1.0)); myModel.addForce(myMcl); diff --git a/OpenSim/Examples/ExampleLuxoMuscle/LuxoMuscle_create_and_simulate.cpp b/OpenSim/Examples/ExampleLuxoMuscle/LuxoMuscle_create_and_simulate.cpp index 279ec4bdb5..ab179a9fe1 100644 --- a/OpenSim/Examples/ExampleLuxoMuscle/LuxoMuscle_create_and_simulate.cpp +++ b/OpenSim/Examples/ExampleLuxoMuscle/LuxoMuscle_create_and_simulate.cpp @@ -747,7 +747,6 @@ void createLuxoJr(OpenSim::Model& model){ "back_extensor_right", back_extensor_F0, back_extensor_lm0, back_extensor_lts, pennationAngle); - backExtensorRight->addNewPathPoint("back_extensor_right_origin", *chest, back_extensor_origin); backExtensorRight->addNewPathPoint("back_extensor_right_insertion", *back, diff --git a/OpenSim/Examples/MuscleExample/mainFatigue.cpp b/OpenSim/Examples/MuscleExample/mainFatigue.cpp index 31a113d86e..7b64fda44b 100644 --- a/OpenSim/Examples/MuscleExample/mainFatigue.cpp +++ b/OpenSim/Examples/MuscleExample/mainFatigue.cpp @@ -133,14 +133,14 @@ int main() pennationAngle); // Define the path of the muscles - fatigable->addNewPathPoint("fatigable-point1", ground, + fatigable->addNewPathPoint("fatigable-point1", ground, Vec3(0.0, halfLength, -0.35)); - fatigable->addNewPathPoint("fatigable-point2", *block, + fatigable->addNewPathPoint("fatigable-point2", *block, Vec3(0.0, halfLength, -halfLength)); - original->addNewPathPoint("original-point1", ground, + original->addNewPathPoint("original-point1", ground, Vec3(0.0, halfLength, 0.35)); - original->addNewPathPoint("original-point2", *block, + original->addNewPathPoint("original-point2", *block, Vec3(0.0, halfLength, halfLength)); // Define the default states for the two muscles diff --git a/OpenSim/Simulation/Model/Blankevoort1991Ligament.cpp b/OpenSim/Simulation/Model/Blankevoort1991Ligament.cpp index 60c1cd8e0d..a0b77570c3 100644 --- a/OpenSim/Simulation/Model/Blankevoort1991Ligament.cpp +++ b/OpenSim/Simulation/Model/Blankevoort1991Ligament.cpp @@ -36,7 +36,7 @@ Blankevoort1991Ligament::Blankevoort1991Ligament() : Force() { } Blankevoort1991Ligament::Blankevoort1991Ligament(std::string name, - const PhysicalFrame& frame1, SimTK::Vec3 point1, + const PhysicalFrame& frame1, SimTK::Vec3 point1, const PhysicalFrame& frame2, SimTK::Vec3 point2) : Blankevoort1991Ligament() { setName(name); @@ -45,8 +45,8 @@ Blankevoort1991Ligament::Blankevoort1991Ligament(std::string name, } Blankevoort1991Ligament::Blankevoort1991Ligament(std::string name, - const PhysicalFrame& frame1, SimTK::Vec3 point1, - const PhysicalFrame& frame2, SimTK::Vec3 point2, + const PhysicalFrame& frame1, SimTK::Vec3 point1, + const PhysicalFrame& frame2, SimTK::Vec3 point2, double linear_stiffness, double slack_length) : Blankevoort1991Ligament(name, frame1, point1, frame2, point2) { set_linear_stiffness(linear_stiffness); diff --git a/OpenSim/Simulation/Model/Blankevoort1991Ligament.h b/OpenSim/Simulation/Model/Blankevoort1991Ligament.h index 7646342d3e..62797fcb93 100644 --- a/OpenSim/Simulation/Model/Blankevoort1991Ligament.h +++ b/OpenSim/Simulation/Model/Blankevoort1991Ligament.h @@ -223,11 +223,11 @@ OpenSim_DECLARE_CONCRETE_OBJECT(Blankevoort1991Ligament, Force) // Constructors Blankevoort1991Ligament(); - Blankevoort1991Ligament(std::string name, + Blankevoort1991Ligament(std::string name, const PhysicalFrame& frame1, SimTK::Vec3 point1, const PhysicalFrame& frame2, SimTK::Vec3 point2); - Blankevoort1991Ligament(std::string name, + Blankevoort1991Ligament(std::string name, const PhysicalFrame& frame1, SimTK::Vec3 point1, const PhysicalFrame& frame2, SimTK::Vec3 point2, double linear_stiffness, double slack_length); diff --git a/OpenSim/Simulation/Model/Muscle.h b/OpenSim/Simulation/Model/Muscle.h index 5011a33e7f..6f35d27fef 100644 --- a/OpenSim/Simulation/Model/Muscle.h +++ b/OpenSim/Simulation/Model/Muscle.h @@ -430,7 +430,7 @@ OpenSim_DECLARE_ABSTRACT_OBJECT(Muscle, PathActuator); /** Potential energy stored by the muscle */ double computePotentialEnergy(const SimTK::State& state) const override; - + /** Override PathActuator virtual to calculate a preferred color for the muscle path based on activation. **/ SimTK::Vec3 computePathColor(const SimTK::State& state) const override; diff --git a/OpenSim/Simulation/MomentArmSolver.cpp b/OpenSim/Simulation/MomentArmSolver.cpp index c65fa9622d..807b796475 100644 --- a/OpenSim/Simulation/MomentArmSolver.cpp +++ b/OpenSim/Simulation/MomentArmSolver.cpp @@ -24,7 +24,6 @@ #include "MomentArmSolver.h" #include "Model/PointForceDirection.h" #include "Model/Model.h" -#include "Model/GeometryPath.h" using namespace std; using namespace SimTK; diff --git a/OpenSim/Simulation/RegisterTypes_osimSimulation.cpp b/OpenSim/Simulation/RegisterTypes_osimSimulation.cpp index ed2fb76075..4ac2a3f7d0 100644 --- a/OpenSim/Simulation/RegisterTypes_osimSimulation.cpp +++ b/OpenSim/Simulation/RegisterTypes_osimSimulation.cpp @@ -59,7 +59,6 @@ #include "Model/PathPointSet.h" #include "Model/ConditionalPathPoint.h" #include "Model/MovingPathPoint.h" -#include "Model/AbstractPath.h" #include "Model/GeometryPath.h" #include "Model/PrescribedForce.h" #include "Model/ExternalForce.h" diff --git a/OpenSim/Tests/Wrapping/testWrappingAlgorithm.cpp b/OpenSim/Tests/Wrapping/testWrappingAlgorithm.cpp index b7e08f13b4..040e793753 100644 --- a/OpenSim/Tests/Wrapping/testWrappingAlgorithm.cpp +++ b/OpenSim/Tests/Wrapping/testWrappingAlgorithm.cpp @@ -152,7 +152,7 @@ void testSingleWrapObjectPerpendicular(WrapObject* wrapObject, Vec3 axisRotation new PathSpring("spring1", 1.0, 0.1, 0.01); //offset in X direction to avoid ambiguous scenario where path passes through center spring1->updGeometryPath(). - appendNewPathPoint("origin", ground, Vec3(r-.1, r, 0)); + appendNewPathPoint("origin", ground, Vec3(r-.1, r, 0)); spring1->updGeometryPath(). appendNewPathPoint("insert", *body, Vec3(-r, r, 0)); spring1->updGeometryPath().addPathWrap(*wObj); @@ -211,7 +211,7 @@ void testEllipsoidWrapLength(OpenSim::WrapEllipsoid* wrapObject) new PathSpring("spring1", 1.0, 0.1, 0.01); //offset in X direction to avoid ambiguous scenario where path passes through center spring1->updGeometryPath(). - appendNewPathPoint("origin", ground, Vec3(r - .1, r, 0)); + appendNewPathPoint("origin", ground, Vec3(r - .1, r, 0)); // insertion point is -r down from the tip of the long axis of the ellipsoid spring1->updGeometryPath(). appendNewPathPoint("insert", *body, Vec3(-wrapObject->get_dimensions()[0], -r, 0)); diff --git a/OpenSim/Tests/testIterators/testIterators.cpp b/OpenSim/Tests/testIterators/testIterators.cpp index 0f7f51ee1a..a3b837b9b8 100644 --- a/OpenSim/Tests/testIterators/testIterators.cpp +++ b/OpenSim/Tests/testIterators/testIterators.cpp @@ -23,7 +23,6 @@ * -------------------------------------------------------------------------- */ #include #include -#include #include "OpenSim/Simulation/SimbodyEngine/PinJoint.h" #include #include From c383f64758d2157930d660e2e1931552405777f4 Mon Sep 17 00:00:00 2001 From: Nicholas Bianco Date: Wed, 30 Aug 2023 10:04:46 -0700 Subject: [PATCH 12/24] Rule of five; more code clean up --- OpenSim/Actuators/ModelFactory.cpp | 3 +-- OpenSim/Simulation/Model/AbstractPath.cpp | 6 +++++- OpenSim/Simulation/Model/AbstractPath.h | 7 +++++-- OpenSim/Simulation/Model/Blankevoort1991Ligament.h | 2 +- OpenSim/Simulation/Model/Ligament.h | 2 +- OpenSim/Simulation/Model/Muscle.h | 4 ++-- OpenSim/Simulation/Model/PathActuator.h | 2 +- OpenSim/Simulation/Model/PathSpring.h | 2 +- OpenSim/Tests/Wrapping/testWrapCylinder.cpp | 2 +- 9 files changed, 18 insertions(+), 12 deletions(-) diff --git a/OpenSim/Actuators/ModelFactory.cpp b/OpenSim/Actuators/ModelFactory.cpp index a3a94c9d03..340e7d8609 100644 --- a/OpenSim/Actuators/ModelFactory.cpp +++ b/OpenSim/Actuators/ModelFactory.cpp @@ -173,8 +173,7 @@ void ModelFactory::replaceMusclesWithPathActuators(OpenSim::Model &model) { model.addForce(actu); // Copy the muscle's path. - AbstractPath& path = musc.updPath(); - if (auto* pGeometryPath = dynamic_cast(&path)) { + if (auto* pGeometryPath = musc.tryUpdPath()) { GeometryPath& thisGeometryPath = actu->initGeometryPath(); // For the connectee names in the PathPoints to be correct, we must diff --git a/OpenSim/Simulation/Model/AbstractPath.cpp b/OpenSim/Simulation/Model/AbstractPath.cpp index 839a5e7744..591d4eef49 100644 --- a/OpenSim/Simulation/Model/AbstractPath.cpp +++ b/OpenSim/Simulation/Model/AbstractPath.cpp @@ -40,6 +40,10 @@ AbstractPath::~AbstractPath() noexcept = default; AbstractPath& AbstractPath::operator=(const AbstractPath&) = default; +AbstractPath::AbstractPath(AbstractPath&& other) noexcept = default; + +AbstractPath& AbstractPath::operator=(AbstractPath&& other) noexcept = default; + // DEFAULTED METHODS const SimTK::Vec3& AbstractPath::getDefaultColor() const { @@ -61,4 +65,4 @@ void AbstractPath::setPreScaleLength(const SimTK::State&, double preScaleLength) { _preScaleLength = preScaleLength; -} \ No newline at end of file +} diff --git a/OpenSim/Simulation/Model/AbstractPath.h b/OpenSim/Simulation/Model/AbstractPath.h index ac687464c1..4ecca0c14f 100644 --- a/OpenSim/Simulation/Model/AbstractPath.h +++ b/OpenSim/Simulation/Model/AbstractPath.h @@ -77,10 +77,13 @@ OpenSim_DECLARE_ABSTRACT_OBJECT(AbstractPath, ModelComponent); // METHODS //============================================================================= AbstractPath(); - AbstractPath(const AbstractPath&); ~AbstractPath() noexcept; - + + AbstractPath(const AbstractPath&); AbstractPath& operator=(const AbstractPath&); + + AbstractPath(AbstractPath&& other) noexcept; + AbstractPath& operator=(AbstractPath&& other) noexcept; // INTERFACE METHODS // diff --git a/OpenSim/Simulation/Model/Blankevoort1991Ligament.h b/OpenSim/Simulation/Model/Blankevoort1991Ligament.h index 62797fcb93..13ac46a6b2 100644 --- a/OpenSim/Simulation/Model/Blankevoort1991Ligament.h +++ b/OpenSim/Simulation/Model/Blankevoort1991Ligament.h @@ -236,7 +236,7 @@ OpenSim_DECLARE_CONCRETE_OBJECT(Blankevoort1991Ligament, Force) double linear_stiffness, double slack_length); // Path - bool hasPath() const override { return true;}; + bool hasPath() const override { return true; }; AbstractPath& updPath() { return upd_path(); } const AbstractPath& getPath() const { return get_path(); } diff --git a/OpenSim/Simulation/Model/Ligament.h b/OpenSim/Simulation/Model/Ligament.h index 23e91dda48..f6da52bc22 100644 --- a/OpenSim/Simulation/Model/Ligament.h +++ b/OpenSim/Simulation/Model/Ligament.h @@ -74,7 +74,7 @@ OpenSim_DECLARE_CONCRETE_OBJECT(Ligament, Force); //-------------------------------------------------------------------------- // PATH //-------------------------------------------------------------------------- - bool hasPath() const override { return true;}; + bool hasPath() const override { return true; }; AbstractPath& updPath() { return upd_path(); } const AbstractPath& getPath() const { return get_path(); } diff --git a/OpenSim/Simulation/Model/Muscle.h b/OpenSim/Simulation/Model/Muscle.h index 6f35d27fef..bbcec228dc 100644 --- a/OpenSim/Simulation/Model/Muscle.h +++ b/OpenSim/Simulation/Model/Muscle.h @@ -430,7 +430,7 @@ OpenSim_DECLARE_ABSTRACT_OBJECT(Muscle, PathActuator); /** Potential energy stored by the muscle */ double computePotentialEnergy(const SimTK::State& state) const override; - + /** Override PathActuator virtual to calculate a preferred color for the muscle path based on activation. **/ SimTK::Vec3 computePathColor(const SimTK::State& state) const override; @@ -440,7 +440,7 @@ OpenSim_DECLARE_ABSTRACT_OBJECT(Muscle, PathActuator); void extendAddToSystem(SimTK::MultibodySystem& system) const override; void extendSetPropertiesFromState(const SimTK::State &s) override; void extendInitStateFromProperties(SimTK::State& state) const override; - + // Update the display geometry attached to the muscle virtual void updateGeometry(const SimTK::State& s); // End of Interfaces imposed by parent classes. diff --git a/OpenSim/Simulation/Model/PathActuator.h b/OpenSim/Simulation/Model/PathActuator.h index f634a9e669..a85a9370c0 100644 --- a/OpenSim/Simulation/Model/PathActuator.h +++ b/OpenSim/Simulation/Model/PathActuator.h @@ -66,7 +66,7 @@ class OSIMSIMULATION_API PathActuator : public ScalarActuator { // GET AND SET //-------------------------------------------------------------------------- // Path - bool hasPath() const override { return true;}; + bool hasPath() const override { return true; }; AbstractPath& updPath() { return upd_path(); } const AbstractPath& getPath() const { return get_path(); } diff --git a/OpenSim/Simulation/Model/PathSpring.h b/OpenSim/Simulation/Model/PathSpring.h index cdbd1eecc1..bb5f466406 100644 --- a/OpenSim/Simulation/Model/PathSpring.h +++ b/OpenSim/Simulation/Model/PathSpring.h @@ -117,7 +117,7 @@ OpenSim_DECLARE_CONCRETE_OBJECT(PathSpring, Force); void setDissipation(double dissipation); /** get/set the path object */ - bool hasPath() const override { return true;}; + bool hasPath() const override { return true; }; AbstractPath& updPath() { return upd_path(); } const AbstractPath& getPath() const { return get_path(); } diff --git a/OpenSim/Tests/Wrapping/testWrapCylinder.cpp b/OpenSim/Tests/Wrapping/testWrapCylinder.cpp index 30030e712d..5d01272b8c 100644 --- a/OpenSim/Tests/Wrapping/testWrapCylinder.cpp +++ b/OpenSim/Tests/Wrapping/testWrapCylinder.cpp @@ -452,7 +452,7 @@ namespace { // Trigger computing the wrapping path (realizing the state will not). model.getComponent("spring").getLength(state); const WrapResult wrapResult = model.getComponent("spring") - .getPath() + .getGeometryPath() .getWrapSet() .get("pathwrap") .getPreviousWrap(); From e57c1f6d91c70f94d72b077a0b24fc64ef730773 Mon Sep 17 00:00:00 2001 From: Nicholas Bianco Date: Wed, 30 Aug 2023 10:19:41 -0700 Subject: [PATCH 13/24] Handle unsupported path types when replacing muscles --- OpenSim/Actuators/DeGrooteFregly2016Muscle.cpp | 16 ++++++++++------ OpenSim/Actuators/ModelFactory.cpp | 13 +++++++++---- OpenSim/Simulation/Model/PathActuator.cpp | 6 +++--- 3 files changed, 22 insertions(+), 13 deletions(-) diff --git a/OpenSim/Actuators/DeGrooteFregly2016Muscle.cpp b/OpenSim/Actuators/DeGrooteFregly2016Muscle.cpp index 72bb79db3f..beab802644 100644 --- a/OpenSim/Actuators/DeGrooteFregly2016Muscle.cpp +++ b/OpenSim/Actuators/DeGrooteFregly2016Muscle.cpp @@ -1023,10 +1023,7 @@ void DeGrooteFregly2016Muscle::replaceMuscles( muscBase.get_ignore_activation_dynamics()); // Copy the muscle's path. - AbstractPath& path = muscBase.updPath(); - if (auto* pGeometryPath = dynamic_cast(&path)) { - auto& thisGeometryPath = actu->initGeometryPath(); - + if (auto* pGeometryPath = muscBase.tryUpdPath()) { const auto& pathPointSet = pGeometryPath->getPathPointSet(); for (int ipp = 0; ipp < pathPointSet.getSize(); ++ipp) { auto* pathPoint = pathPointSet.get(ipp).clone(); @@ -1037,7 +1034,8 @@ void DeGrooteFregly2016Muscle::replaceMuscles( .getSocket(socketName) .getConnecteeAsObject()); } - thisGeometryPath.updPathPointSet().adoptAndAppend(pathPoint); + actu->updGeometryPath().updPathPointSet() + .adoptAndAppend(pathPoint); } const auto& pathWrapSet = pGeometryPath->getWrapSet(); @@ -1050,8 +1048,14 @@ void DeGrooteFregly2016Muscle::replaceMuscles( .getSocket(socketName) .getConnecteeAsObject()); } - thisGeometryPath.updWrapSet().adoptAndAppend(pathWrap); + actu->updGeometryPath().updWrapSet() + .adoptAndAppend(pathWrap); } + } else { + OPENSIM_THROW(Exception, + "Muscle '{}' contains supported path type {}.", + muscBase.getName(), + muscBase.getPath().getConcreteClassName()) } std::string actname = actu->getName(); diff --git a/OpenSim/Actuators/ModelFactory.cpp b/OpenSim/Actuators/ModelFactory.cpp index 340e7d8609..d3aa60a70a 100644 --- a/OpenSim/Actuators/ModelFactory.cpp +++ b/OpenSim/Actuators/ModelFactory.cpp @@ -174,8 +174,6 @@ void ModelFactory::replaceMusclesWithPathActuators(OpenSim::Model &model) { // Copy the muscle's path. if (auto* pGeometryPath = musc.tryUpdPath()) { - GeometryPath& thisGeometryPath = actu->initGeometryPath(); - // For the connectee names in the PathPoints to be correct, we must // add the path points after adding the PathActuator to the model. const auto& pathPointSet = pGeometryPath->getPathPointSet(); @@ -188,7 +186,8 @@ void ModelFactory::replaceMusclesWithPathActuators(OpenSim::Model &model) { .getSocket(socketName) .getConnecteeAsObject()); } - thisGeometryPath.updPathPointSet().adoptAndAppend(pathPoint); + actu->updGeometryPath().updPathPointSet() + .adoptAndAppend(pathPoint); } // For the connectee names in the PathWraps to be correct, we must @@ -203,8 +202,14 @@ void ModelFactory::replaceMusclesWithPathActuators(OpenSim::Model &model) { .getSocket(socketName) .getConnecteeAsObject()); } - thisGeometryPath.updWrapSet().adoptAndAppend(pathWrap); + actu->updGeometryPath().updWrapSet() + .adoptAndAppend(pathWrap); } + } else { + OPENSIM_THROW(Exception, + "Muscle '{}' contains supported path type {}.", + musc.getName(), + musc.getPath().getConcreteClassName()) } musclesToDelete.push_back(&musc); diff --git a/OpenSim/Simulation/Model/PathActuator.cpp b/OpenSim/Simulation/Model/PathActuator.cpp index 313dcfeff3..c420cd9e27 100644 --- a/OpenSim/Simulation/Model/PathActuator.cpp +++ b/OpenSim/Simulation/Model/PathActuator.cpp @@ -142,13 +142,13 @@ double PathActuator::getStress( const SimTK::State& s) const //_____________________________________________________________________________ /** - * Add a Path point to the _path of the actuator. The new point is appended + * Add a Path point to the _path of the actuator. The new point is appended * to the end of the current path * */ void PathActuator::addNewPathPoint( - const std::string& proposedName, - const PhysicalFrame& aBody, + const std::string& proposedName, + const PhysicalFrame& aBody, const SimTK::Vec3& aPositionOnBody) { // Create new PathPoint already appended to the PathPointSet for the path updGeometryPath().appendNewPathPoint(proposedName, aBody, aPositionOnBody); From e53ea0b7738e4c80b860b2cfbd7d2d9e13b06b11 Mon Sep 17 00:00:00 2001 From: Nicholas Bianco Date: Wed, 30 Aug 2023 10:38:06 -0700 Subject: [PATCH 14/24] Remove initGeometryPath() for now --- OpenSim/Simulation/Model/Blankevoort1991Ligament.cpp | 5 ----- OpenSim/Simulation/Model/Blankevoort1991Ligament.h | 7 +------ OpenSim/Simulation/Model/Ligament.cpp | 7 ------- OpenSim/Simulation/Model/Ligament.h | 5 ----- OpenSim/Simulation/Model/PathActuator.cpp | 9 --------- OpenSim/Simulation/Model/PathActuator.h | 6 +----- OpenSim/Simulation/Model/PathSpring.cpp | 9 --------- OpenSim/Simulation/Model/PathSpring.h | 5 ----- 8 files changed, 2 insertions(+), 51 deletions(-) diff --git a/OpenSim/Simulation/Model/Blankevoort1991Ligament.cpp b/OpenSim/Simulation/Model/Blankevoort1991Ligament.cpp index a0b77570c3..af71594206 100644 --- a/OpenSim/Simulation/Model/Blankevoort1991Ligament.cpp +++ b/OpenSim/Simulation/Model/Blankevoort1991Ligament.cpp @@ -61,11 +61,6 @@ Blankevoort1991Ligament::Blankevoort1991Ligament( set_slack_length(slack_length); } -GeometryPath& Blankevoort1991Ligament::initGeometryPath() { - set_path(GeometryPath()); - return updPath(); -} - void Blankevoort1991Ligament::setNull() { setAuthors("Colin Smith"); diff --git a/OpenSim/Simulation/Model/Blankevoort1991Ligament.h b/OpenSim/Simulation/Model/Blankevoort1991Ligament.h index 13ac46a6b2..df9cc420df 100644 --- a/OpenSim/Simulation/Model/Blankevoort1991Ligament.h +++ b/OpenSim/Simulation/Model/Blankevoort1991Ligament.h @@ -265,12 +265,7 @@ OpenSim_DECLARE_CONCRETE_OBJECT(Blankevoort1991Ligament, Force) const GeometryPath& getGeometryPath() const { return getPath(); } - - /// Initialize the path of the PathActuator with a GeometryPath. This - /// returns a reference to the newly created GeometryPath, which you can - /// then edit. This deletes the previous path if one exists. - GeometryPath& initGeometryPath(); - + //------------------------------------------------------------------------- // SET //------------------------------------------------------------------------- diff --git a/OpenSim/Simulation/Model/Ligament.cpp b/OpenSim/Simulation/Model/Ligament.cpp index c02db44b9b..d2f76678a3 100644 --- a/OpenSim/Simulation/Model/Ligament.cpp +++ b/OpenSim/Simulation/Model/Ligament.cpp @@ -47,13 +47,6 @@ Ligament::Ligament() constructProperties(); } -//_____________________________________________________________________________ -// Initialize a GeometryPath. -GeometryPath& Ligament::initGeometryPath() { - set_path(GeometryPath()); - return updPath(); -} - //_____________________________________________________________________________ /* * Construct and initialize the properties for the ligament. diff --git a/OpenSim/Simulation/Model/Ligament.h b/OpenSim/Simulation/Model/Ligament.h index f6da52bc22..26d7f40dd5 100644 --- a/OpenSim/Simulation/Model/Ligament.h +++ b/OpenSim/Simulation/Model/Ligament.h @@ -104,11 +104,6 @@ OpenSim_DECLARE_CONCRETE_OBJECT(Ligament, Force); return getPath(); } - /// Initialize the path of the PathActuator with a GeometryPath. This - /// returns a reference to the newly created GeometryPath, which you can - /// then edit. This deletes the previous path if one exists. - GeometryPath& initGeometryPath(); - //-------------------------------------------------------------------------- // GET //-------------------------------------------------------------------------- diff --git a/OpenSim/Simulation/Model/PathActuator.cpp b/OpenSim/Simulation/Model/PathActuator.cpp index c420cd9e27..218e433ea9 100644 --- a/OpenSim/Simulation/Model/PathActuator.cpp +++ b/OpenSim/Simulation/Model/PathActuator.cpp @@ -70,15 +70,6 @@ void PathActuator::constructProperties() //============================================================================= // GET AND SET //============================================================================= -//----------------------------------------------------------------------------- -// PATH -//----------------------------------------------------------------------------- -//_____________________________________________________________________________ -GeometryPath& PathActuator::initGeometryPath() { - set_path(GeometryPath()); - return updPath(); -} - //----------------------------------------------------------------------------- // OPTIMAL FORCE //----------------------------------------------------------------------------- diff --git a/OpenSim/Simulation/Model/PathActuator.h b/OpenSim/Simulation/Model/PathActuator.h index a85a9370c0..539cb5c14f 100644 --- a/OpenSim/Simulation/Model/PathActuator.h +++ b/OpenSim/Simulation/Model/PathActuator.h @@ -95,11 +95,7 @@ class OSIMSIMULATION_API PathActuator : public ScalarActuator { const GeometryPath& getGeometryPath() const { return getPath(); } - - /// Initialize the path of the PathActuator with a GeometryPath. This - /// returns a reference to the newly created GeometryPath, which you can - /// then edit. This deletes the previous path if one exists. - GeometryPath& initGeometryPath(); + // OPTIMAL FORCE void setOptimalForce(double aOptimalForce); diff --git a/OpenSim/Simulation/Model/PathSpring.cpp b/OpenSim/Simulation/Model/PathSpring.cpp index 4ca1165f30..bfbf6a5f0a 100644 --- a/OpenSim/Simulation/Model/PathSpring.cpp +++ b/OpenSim/Simulation/Model/PathSpring.cpp @@ -93,15 +93,6 @@ void PathSpring::setDissipation(double dissipation) set_dissipation(dissipation); } -//_____________________________________________________________________________ -/* - * Initialize a GeometryPath. - */ -GeometryPath& PathSpring::initGeometryPath() { - set_path(GeometryPath()); - return updPath(); -} - //_____________________________________________________________________________ /** * Perform some setup functions that happen after the diff --git a/OpenSim/Simulation/Model/PathSpring.h b/OpenSim/Simulation/Model/PathSpring.h index bb5f466406..da1dd5757c 100644 --- a/OpenSim/Simulation/Model/PathSpring.h +++ b/OpenSim/Simulation/Model/PathSpring.h @@ -147,11 +147,6 @@ OpenSim_DECLARE_CONCRETE_OBJECT(PathSpring, Force); return getPath(); } - /// Initialize the path of the PathActuator with a GeometryPath. This - /// returns a reference to the newly created GeometryPath, which you can - /// then edit. This deletes the previous path if one exists. - GeometryPath& initGeometryPath(); - //-------------------------------------------------------------------------- // State dependent values //-------------------------------------------------------------------------- From c3ac610d2c7fb5f6e2b7fc4200a08d645c148aa0 Mon Sep 17 00:00:00 2001 From: Nicholas Bianco Date: Wed, 30 Aug 2023 16:11:46 -0700 Subject: [PATCH 15/24] Backwards compatibility for deserializing GeometryPath --- OpenSim/Actuators/ModelFactory.h | 2 +- OpenSim/Common/XMLDocument.cpp | 4 +- OpenSim/Simulation/Model/AbstractPath.h | 2 +- OpenSim/Simulation/Model/GeometryPath.cpp | 11 +----- OpenSim/Simulation/Model/GeometryPath.h | 7 +--- OpenSim/Simulation/Model/Model.cpp | 48 +++++++++++++++++++++++ 6 files changed, 56 insertions(+), 18 deletions(-) diff --git a/OpenSim/Actuators/ModelFactory.h b/OpenSim/Actuators/ModelFactory.h index c680841710..1d0b907791 100644 --- a/OpenSim/Actuators/ModelFactory.h +++ b/OpenSim/Actuators/ModelFactory.h @@ -60,7 +60,7 @@ class OSIMACTUATORS_API ModelFactory { /// @name Modify a Model /// @{ - /// Replace muscles in a model with a PathActuator of the same GeometryPath, + /// Replace muscles in a model with a PathActuator of the same path, /// optimal force, and min/max control defaults. /// @note This only replaces muscles within the model's ForceSet. static void replaceMusclesWithPathActuators(Model& model); diff --git a/OpenSim/Common/XMLDocument.cpp b/OpenSim/Common/XMLDocument.cpp index da02e5c9f9..4d92b87268 100644 --- a/OpenSim/Common/XMLDocument.cpp +++ b/OpenSim/Common/XMLDocument.cpp @@ -66,8 +66,10 @@ using namespace std; // 30516 for GeometryPath default_color -> Appearance // 30517 for removal of _connectee_name suffix to shorten XML for socket, input // 40000 for OpenSim 4.0 release 40000 +// 40500 for OpenSim 4.5 release, moving 'GeometryPath' nodes under the 'path' +// node for supporting generic path types. -const int XMLDocument::LatestVersion = 40000; +const int XMLDocument::LatestVersion = 40500; //============================================================================= // DESTRUCTOR AND CONSTRUCTOR(S) //============================================================================= diff --git a/OpenSim/Simulation/Model/AbstractPath.h b/OpenSim/Simulation/Model/AbstractPath.h index 4ecca0c14f..f521ff1b76 100644 --- a/OpenSim/Simulation/Model/AbstractPath.h +++ b/OpenSim/Simulation/Model/AbstractPath.h @@ -148,7 +148,7 @@ OpenSim_DECLARE_ABSTRACT_OBJECT(AbstractPath, ModelComponent); * @param[in,out] mobilityForces Vector of generalized forces */ virtual void addInEquivalentForces(const SimTK::State& state, - double tension, + const double& tension, SimTK::Vector_& bodyForces, SimTK::Vector& mobilityForces) const = 0; diff --git a/OpenSim/Simulation/Model/GeometryPath.cpp b/OpenSim/Simulation/Model/GeometryPath.cpp index ce23159179..ee20738984 100644 --- a/OpenSim/Simulation/Model/GeometryPath.cpp +++ b/OpenSim/Simulation/Model/GeometryPath.cpp @@ -133,7 +133,7 @@ static void PopulatePathElementLookup( /* * Default constructor. */ -GeometryPath::GeometryPath() : AbstractPath(), _preScaleLength(0.0) +GeometryPath::GeometryPath() : AbstractPath() { setAuthors("Peter Loan"); constructProperties(); @@ -382,7 +382,7 @@ getPointForceDirections(const SimTK::State& s, /* add in the equivalent spatial forces on bodies for an applied tension along the GeometryPath to a set of bodyForces */ void GeometryPath::addInEquivalentForces(const SimTK::State& s, - double tension, + const double& tension, SimTK::Vector_& bodyForces, SimTK::Vector& mobilityForces) const { @@ -564,13 +564,6 @@ void GeometryPath::setLengtheningSpeed( const SimTK::State& s, double speed ) co setCacheVariableValue(s, _speedCV, speed); } -void GeometryPath::setPreScaleLength( const SimTK::State& s, double length ) { - _preScaleLength = length; -} -double GeometryPath::getPreScaleLength( const SimTK::State& s) const { - return _preScaleLength; -} - //============================================================================= // UTILITY //============================================================================= diff --git a/OpenSim/Simulation/Model/GeometryPath.h b/OpenSim/Simulation/Model/GeometryPath.h index a84253feed..463a762960 100644 --- a/OpenSim/Simulation/Model/GeometryPath.h +++ b/OpenSim/Simulation/Model/GeometryPath.h @@ -69,9 +69,6 @@ OpenSim_DECLARE_CONCRETE_OBJECT(GeometryPath, AbstractPath); OpenSim_DECLARE_UNNAMED_PROPERTY(PathWrapSet, "The wrap objects that are associated with this path"); - // used for scaling tendon and fiber lengths - double _preScaleLength; - // Solver used to compute moment-arms. The GeometryPath owns this object, // but we cannot simply use a unique_ptr because we want the pointer to be // cleared on copy. @@ -143,8 +140,6 @@ OpenSim_DECLARE_CONCRETE_OBJECT(GeometryPath, AbstractPath); double getLength( const SimTK::State& s) const; void setLength( const SimTK::State& s, double length) const; - double getPreScaleLength( const SimTK::State& s) const; - void setPreScaleLength( const SimTK::State& s, double preScaleLength); const Array& getCurrentPath( const SimTK::State& s) const; double getLengtheningSpeed(const SimTK::State& s) const; @@ -163,7 +158,7 @@ OpenSim_DECLARE_CONCRETE_OBJECT(GeometryPath, AbstractPath); @param[in,out] mobilityForces Vector of generalized forces, one per mobility */ void addInEquivalentForces(const SimTK::State& state, - double tension, + const double& tension, SimTK::Vector_& bodyForces, SimTK::Vector& mobilityForces) const override; diff --git a/OpenSim/Simulation/Model/Model.cpp b/OpenSim/Simulation/Model/Model.cpp index 3c03689049..c7c161d242 100644 --- a/OpenSim/Simulation/Model/Model.cpp +++ b/OpenSim/Simulation/Model/Model.cpp @@ -323,6 +323,54 @@ void Model::updateFromXMLNode(SimTK::Xml::Element& aNode, int versionNumber) framesNode->getParentElement().eraseNode(framesNode); } } + if (versionNumber < 40500) { + // In version 40500, the XML syntax for components that own + // GeometryPath objects (PathActuator, PathSpring, Ligament, + // and Blankevoort1991Ligament) changed: the 'GeometryPath` unnamed + // property was replaced with the named property 'path', which is of + // type 'AbstractPath'. Since 'path' is still a one object property, + // the property will still be serialized using the concrete type + // (e.g., 'GeometryPath') and with name attribute set to 'path'. + // Therefore, we can simply update the name attribute of any + // existing 'GeometryPath' nodes to 'path'. + + // Components that own paths can be in the model's ForceSet or + // the components list. + SimTK::Xml::element_iterator forceSetNode = + aNode.element_begin("ForceSet"); + SimTK::Xml::element_iterator componentsNode = + aNode.element_begin("components"); + + // Loop through the ForceSet and update any GeometryPath nodes. + if (forceSetNode != aNode.element_end()) { + SimTK::Xml::element_iterator objects_node = + forceSetNode->element_begin("objects"); + SimTK::Xml::element_iterator forceIter = + objects_node->element_begin(); + for (; forceIter != objects_node->element_end(); ++forceIter) { + SimTK::Xml::element_iterator geometryPathNode = + forceIter->element_begin("GeometryPath"); + if (geometryPathNode != forceIter->element_end()) { + geometryPathNode->setAttributeValue("name", "path"); + } + } + } + + // Loop through the components list and update any GeometryPath + // nodes. + if (componentsNode != aNode.element_end()) { + SimTK::Xml::element_iterator forceIter = + componentsNode->element_begin(); + for (; forceIter != componentsNode->element_end(); ++forceIter) { + SimTK::Xml::element_iterator geometryPathNode = + forceIter->element_begin("GeometryPath"); + if (geometryPathNode != forceIter->element_end()) { + geometryPathNode->setAttributeValue("name", "path"); + } + } + } + + } } // Call base class now assuming _node has been corrected for current version Super::updateFromXMLNode(aNode, versionNumber); From df76b0a4719963680d6de170572fa883fc45de50 Mon Sep 17 00:00:00 2001 From: Nicholas Bianco Date: Thu, 31 Aug 2023 15:06:45 -0700 Subject: [PATCH 16/24] Add abstraction for path copying --- .../Actuators/DeGrooteFregly2016Muscle.cpp | 39 +-------------- OpenSim/Actuators/ModelFactory.cpp | 48 ++----------------- OpenSim/Simulation/Model/AbstractPath.cpp | 4 +- OpenSim/Simulation/Model/AbstractPath.h | 19 ++++++-- OpenSim/Simulation/Model/GeometryPath.cpp | 35 ++++++++++++++ OpenSim/Simulation/Model/GeometryPath.h | 11 ++++- 6 files changed, 66 insertions(+), 90 deletions(-) diff --git a/OpenSim/Actuators/DeGrooteFregly2016Muscle.cpp b/OpenSim/Actuators/DeGrooteFregly2016Muscle.cpp index beab802644..aa375aed71 100644 --- a/OpenSim/Actuators/DeGrooteFregly2016Muscle.cpp +++ b/OpenSim/Actuators/DeGrooteFregly2016Muscle.cpp @@ -1021,44 +1021,7 @@ void DeGrooteFregly2016Muscle::replaceMuscles( muscBase.get_ignore_tendon_compliance()); actu->set_ignore_activation_dynamics( muscBase.get_ignore_activation_dynamics()); - - // Copy the muscle's path. - if (auto* pGeometryPath = muscBase.tryUpdPath()) { - const auto& pathPointSet = pGeometryPath->getPathPointSet(); - for (int ipp = 0; ipp < pathPointSet.getSize(); ++ipp) { - auto* pathPoint = pathPointSet.get(ipp).clone(); - const auto& socketNames = pathPoint->getSocketNames(); - for (const auto& socketName : socketNames) { - pathPoint->updSocket(socketName) - .connect(pathPointSet.get(ipp) - .getSocket(socketName) - .getConnecteeAsObject()); - } - actu->updGeometryPath().updPathPointSet() - .adoptAndAppend(pathPoint); - } - - const auto& pathWrapSet = pGeometryPath->getWrapSet(); - for (int ipw = 0; ipw < pathWrapSet.getSize(); ++ipw) { - auto* pathWrap = pathWrapSet.get(ipw).clone(); - const auto& socketNames = pathWrap->getSocketNames(); - for (const auto& socketName : socketNames) { - pathWrap->updSocket(socketName) - .connect(pathWrapSet.get(ipw) - .getSocket(socketName) - .getConnecteeAsObject()); - } - actu->updGeometryPath().updWrapSet() - .adoptAndAppend(pathWrap); - } - } else { - OPENSIM_THROW(Exception, - "Muscle '{}' contains supported path type {}.", - muscBase.getName(), - muscBase.getPath().getConcreteClassName()) - } - - std::string actname = actu->getName(); + actu->updPath().copyFrom(muscBase.getPath()); model.addForce(actu.release()); musclesToDelete.push_back(&muscBase); diff --git a/OpenSim/Actuators/ModelFactory.cpp b/OpenSim/Actuators/ModelFactory.cpp index d3aa60a70a..be421eaec6 100644 --- a/OpenSim/Actuators/ModelFactory.cpp +++ b/OpenSim/Actuators/ModelFactory.cpp @@ -159,58 +159,20 @@ void ModelFactory::replaceMusclesWithPathActuators(OpenSim::Model &model) { // Create path actuators from muscle properties and add to the model. Save // a list of pointers of the muscles to delete. + model.finalizeConnections(); std::vector musclesToDelete; auto& muscleSet = model.updMuscles(); for (int im = 0; im < muscleSet.getSize(); ++im) { auto& musc = muscleSet.get(im); - auto* actu = new PathActuator(); + auto actu = OpenSim::make_unique(); actu->setName(musc.getName()); musc.setName(musc.getName() + "_delete"); + actu->set_appliesForce(musc.get_appliesForce()); actu->setOptimalForce(musc.getMaxIsometricForce()); actu->setMinControl(musc.getMinControl()); actu->setMaxControl(musc.getMaxControl()); - - model.addForce(actu); - - // Copy the muscle's path. - if (auto* pGeometryPath = musc.tryUpdPath()) { - // For the connectee names in the PathPoints to be correct, we must - // add the path points after adding the PathActuator to the model. - const auto& pathPointSet = pGeometryPath->getPathPointSet(); - for (int ip = 0; ip < pathPointSet.getSize(); ++ip) { - auto* pathPoint = pathPointSet.get(ip).clone(); - const auto& socketNames = pathPoint->getSocketNames(); - for (const auto& socketName : socketNames) { - pathPoint->updSocket(socketName) - .connect(pathPointSet.get(ip) - .getSocket(socketName) - .getConnecteeAsObject()); - } - actu->updGeometryPath().updPathPointSet() - .adoptAndAppend(pathPoint); - } - - // For the connectee names in the PathWraps to be correct, we must - // add the path wraps after adding the PathActuator to the model. - const auto& pathWrapSet = pGeometryPath->getWrapSet(); - for (int ipw = 0; ipw < pathWrapSet.getSize(); ++ipw) { - auto* pathWrap = pathWrapSet.get(ipw).clone(); - const auto& socketNames = pathWrap->getSocketNames(); - for (const auto& socketName : socketNames) { - pathWrap->updSocket(socketName) - .connect(pathWrapSet.get(ipw) - .getSocket(socketName) - .getConnecteeAsObject()); - } - actu->updGeometryPath().updWrapSet() - .adoptAndAppend(pathWrap); - } - } else { - OPENSIM_THROW(Exception, - "Muscle '{}' contains supported path type {}.", - musc.getName(), - musc.getPath().getConcreteClassName()) - } + actu->updPath().copyFrom(musc.getPath()); + model.addForce(actu.release()); musclesToDelete.push_back(&musc); } diff --git a/OpenSim/Simulation/Model/AbstractPath.cpp b/OpenSim/Simulation/Model/AbstractPath.cpp index 591d4eef49..4c048a6b63 100644 --- a/OpenSim/Simulation/Model/AbstractPath.cpp +++ b/OpenSim/Simulation/Model/AbstractPath.cpp @@ -40,9 +40,9 @@ AbstractPath::~AbstractPath() noexcept = default; AbstractPath& AbstractPath::operator=(const AbstractPath&) = default; -AbstractPath::AbstractPath(AbstractPath&& other) noexcept = default; +AbstractPath::AbstractPath(AbstractPath&& other) = default; -AbstractPath& AbstractPath::operator=(AbstractPath&& other) noexcept = default; +AbstractPath& AbstractPath::operator=(AbstractPath&& other) = default; // DEFAULTED METHODS const SimTK::Vec3& AbstractPath::getDefaultColor() const diff --git a/OpenSim/Simulation/Model/AbstractPath.h b/OpenSim/Simulation/Model/AbstractPath.h index f521ff1b76..50b86aec86 100644 --- a/OpenSim/Simulation/Model/AbstractPath.h +++ b/OpenSim/Simulation/Model/AbstractPath.h @@ -82,8 +82,8 @@ OpenSim_DECLARE_ABSTRACT_OBJECT(AbstractPath, ModelComponent); AbstractPath(const AbstractPath&); AbstractPath& operator=(const AbstractPath&); - AbstractPath(AbstractPath&& other) noexcept; - AbstractPath& operator=(AbstractPath&& other) noexcept; + AbstractPath(AbstractPath&& other); + AbstractPath& operator=(AbstractPath&& other); // INTERFACE METHODS // @@ -158,11 +158,20 @@ OpenSim_DECLARE_ABSTRACT_OBJECT(AbstractPath, ModelComponent); */ virtual double computeMomentArm(const SimTK::State& s, const Coordinate& aCoord) const = 0; + + /** + * Copy the properties of the source path into this path. + * + * Concrete implementations (e.g., `GeometryPath`) may use a variety of + * properties to define the path length and lengthening speed and therefore + * must provide a relevant implementation. + */ + virtual void copyFrom(const AbstractPath& source) = 0; // DEFAULTED METHODS // - // These are non-deprecated methods that for which AbstractPath provides a - // default implementation. + // These are methods that for which AbstractPath provides default + // implementation. /** * Get the default color of the path. @@ -198,7 +207,7 @@ OpenSim_DECLARE_ABSTRACT_OBJECT(AbstractPath, ModelComponent); */ double getPreScaleLength(const SimTK::State& s) const; void setPreScaleLength(const SimTK::State& s, double preScaleLength); - + private: // Used by `(get|set)PreLengthScale`. Used during `extend(Pre|Post)Scale` by // downstream users of AbstractPath to cache the length of the path before diff --git a/OpenSim/Simulation/Model/GeometryPath.cpp b/OpenSim/Simulation/Model/GeometryPath.cpp index ee20738984..c18705b82b 100644 --- a/OpenSim/Simulation/Model/GeometryPath.cpp +++ b/OpenSim/Simulation/Model/GeometryPath.cpp @@ -501,6 +501,41 @@ void GeometryPath::addInEquivalentForces(const SimTK::State& s, } } +void GeometryPath::copyFrom(const OpenSim::AbstractPath& source) { + if (const auto* src = dynamic_cast(&source)) { + // Copy the path points. + const auto& pathPointSet = src->getPathPointSet(); + for (int ipp = 0; ipp < pathPointSet.getSize(); ++ipp) { + auto* pathPoint = pathPointSet.get(ipp).clone(); + const auto& socketNames = pathPoint->getSocketNames(); + for (const auto& socketName : socketNames) { + pathPoint->updSocket(socketName) + .connect(pathPointSet.get(ipp) + .getSocket(socketName) + .getConnecteeAsObject()); + } + this->updPathPointSet().adoptAndAppend(pathPoint); + } + + // Copy the wrap objects. + const auto& pathWrapSet = src->getWrapSet(); + for (int ipw = 0; ipw < pathWrapSet.getSize(); ++ipw) { + auto* pathWrap = pathWrapSet.get(ipw).clone(); + const auto& socketNames = pathWrap->getSocketNames(); + for (const auto& socketName : socketNames) { + pathWrap->updSocket(socketName) + .connect(pathWrapSet.get(ipw) + .getSocket(socketName) + .getConnecteeAsObject()); + } + this->updWrapSet().adoptAndAppend(pathWrap); + } + } else { + throw Exception("GeometryPath::copyFrom(): expected a GeometryPath, " + "but got a " + source.getConcreteClassName()); + } +} + //_____________________________________________________________________________ /* * Update the geometric representation of the path. diff --git a/OpenSim/Simulation/Model/GeometryPath.h b/OpenSim/Simulation/Model/GeometryPath.h index 463a762960..0c35ba1d27 100644 --- a/OpenSim/Simulation/Model/GeometryPath.h +++ b/OpenSim/Simulation/Model/GeometryPath.h @@ -161,8 +161,15 @@ OpenSim_DECLARE_CONCRETE_OBJECT(GeometryPath, AbstractPath); const double& tension, SimTK::Vector_& bodyForces, SimTK::Vector& mobilityForces) const override; - - + + /** Copy the PathPoint%s and PathWrap%s of the source path into this path's + * PathPointSet and PathWrapSet, respectively. + * @note This *appends* PathPoint%s and PathWrap%s to this path's + * properties. If you wish to overwrite the path entirely, clear the + * PathPointSet and PathWrapSet first. + */ + void copyFrom(const AbstractPath& source) override; + //-------------------------------------------------------------------------- // COMPUTATIONS //-------------------------------------------------------------------------- From f64e3cdad82062aae6880103b9ca3dc05b80c7e8 Mon Sep 17 00:00:00 2001 From: Nicholas Bianco Date: Thu, 31 Aug 2023 15:15:48 -0700 Subject: [PATCH 17/24] Move path properties back to public scope --- OpenSim/Common/XMLDocument.cpp | 3 +-- .../ExampleLuxoMuscle/LuxoMuscle_create_and_simulate.cpp | 1 + OpenSim/Simulation/Model/Blankevoort1991Ligament.h | 9 ++++----- OpenSim/Simulation/Model/Ligament.h | 6 ++---- OpenSim/Simulation/Model/PathActuator.h | 7 ++----- OpenSim/Simulation/Model/PathSpring.h | 7 ++----- 6 files changed, 12 insertions(+), 21 deletions(-) diff --git a/OpenSim/Common/XMLDocument.cpp b/OpenSim/Common/XMLDocument.cpp index 4d92b87268..6c8136f7a9 100644 --- a/OpenSim/Common/XMLDocument.cpp +++ b/OpenSim/Common/XMLDocument.cpp @@ -66,8 +66,7 @@ using namespace std; // 30516 for GeometryPath default_color -> Appearance // 30517 for removal of _connectee_name suffix to shorten XML for socket, input // 40000 for OpenSim 4.0 release 40000 -// 40500 for OpenSim 4.5 release, moving 'GeometryPath' nodes under the 'path' -// node for supporting generic path types. +// 40500 for updating 'GeometryPath' nodes to have property name 'path'. const int XMLDocument::LatestVersion = 40500; //============================================================================= diff --git a/OpenSim/Examples/ExampleLuxoMuscle/LuxoMuscle_create_and_simulate.cpp b/OpenSim/Examples/ExampleLuxoMuscle/LuxoMuscle_create_and_simulate.cpp index ab179a9fe1..81ce50c5df 100644 --- a/OpenSim/Examples/ExampleLuxoMuscle/LuxoMuscle_create_and_simulate.cpp +++ b/OpenSim/Examples/ExampleLuxoMuscle/LuxoMuscle_create_and_simulate.cpp @@ -747,6 +747,7 @@ void createLuxoJr(OpenSim::Model& model){ "back_extensor_right", back_extensor_F0, back_extensor_lm0, back_extensor_lts, pennationAngle); + backExtensorRight->addNewPathPoint("back_extensor_right_origin", *chest, back_extensor_origin); backExtensorRight->addNewPathPoint("back_extensor_right_insertion", *back, diff --git a/OpenSim/Simulation/Model/Blankevoort1991Ligament.h b/OpenSim/Simulation/Model/Blankevoort1991Ligament.h index df9cc420df..52878461a2 100644 --- a/OpenSim/Simulation/Model/Blankevoort1991Ligament.h +++ b/OpenSim/Simulation/Model/Blankevoort1991Ligament.h @@ -177,7 +177,9 @@ OpenSim_DECLARE_CONCRETE_OBJECT(Blankevoort1991Ligament, Force) //============================================================================= // PROPERTIES //============================================================================= - + + OpenSim_DECLARE_PROPERTY(path, AbstractPath, + "The path defines the length and lengthening speed of the ligament.") OpenSim_DECLARE_PROPERTY(linear_stiffness, double, "The slope of the linear region of the force-strain curve. " "Units of force/strain (N).") @@ -348,10 +350,7 @@ OpenSim_DECLARE_CONCRETE_OBJECT(Blankevoort1991Ligament, Force) const SimTK::State& state) const override; protected: - OpenSim_DECLARE_PROPERTY(path, AbstractPath, - "The path defines the length and lengthening speed of the " - "ligament.") - + void extendFinalizeFromProperties() override; void extendAddToSystem(SimTK::MultibodySystem& system) const override; diff --git a/OpenSim/Simulation/Model/Ligament.h b/OpenSim/Simulation/Model/Ligament.h index 26d7f40dd5..1c0c46ae7c 100644 --- a/OpenSim/Simulation/Model/Ligament.h +++ b/OpenSim/Simulation/Model/Ligament.h @@ -55,6 +55,8 @@ OpenSim_DECLARE_CONCRETE_OBJECT(Ligament, Force); //============================================================================= // PROPERTIES //============================================================================= + OpenSim_DECLARE_PROPERTY(path, AbstractPath, + "The path defines the length and lengthening speed of the PathSpring"); OpenSim_DECLARE_PROPERTY(resting_length, double, "resting length of the ligament"); OpenSim_DECLARE_PROPERTY(pcsa_force, double, @@ -188,10 +190,6 @@ OpenSim_DECLARE_CONCRETE_OBJECT(Ligament, Force); return values; } - OpenSim_DECLARE_PROPERTY(path, AbstractPath, - "The path defines the length and lengthening speed of the " - "PathSpring"); - private: void constructProperties(); diff --git a/OpenSim/Simulation/Model/PathActuator.h b/OpenSim/Simulation/Model/PathActuator.h index 539cb5c14f..197712b570 100644 --- a/OpenSim/Simulation/Model/PathActuator.h +++ b/OpenSim/Simulation/Model/PathActuator.h @@ -49,6 +49,8 @@ class OSIMSIMULATION_API PathActuator : public ScalarActuator { //============================================================================= // PROPERTIES //============================================================================= + OpenSim_DECLARE_PROPERTY(path, AbstractPath, + "The path of the actuator which defines length and lengthening speed."); OpenSim_DECLARE_PROPERTY(optimal_force, double, "The maximum force this actuator can produce."); @@ -159,11 +161,6 @@ class OSIMSIMULATION_API PathActuator : public ScalarActuator { /** Extension of parent class method; derived classes may extend further. **/ void extendRealizeDynamics(const SimTK::State& state) const override; -protected: - OpenSim_DECLARE_PROPERTY(path, AbstractPath, - "The path of the actuator which defines length and lengthening " - "speed."); - private: void setNull(); void constructProperties(); diff --git a/OpenSim/Simulation/Model/PathSpring.h b/OpenSim/Simulation/Model/PathSpring.h index da1dd5757c..c8a691525d 100644 --- a/OpenSim/Simulation/Model/PathSpring.h +++ b/OpenSim/Simulation/Model/PathSpring.h @@ -63,6 +63,8 @@ OpenSim_DECLARE_CONCRETE_OBJECT(PathSpring, Force); "The linear stiffness (N/m) of the PathSpring"); OpenSim_DECLARE_PROPERTY(dissipation, double, "The dissipation factor (s/m) of the PathSpring"); + OpenSim_DECLARE_PROPERTY(path, AbstractPath, + "The path defines the length and lengthening speed of the PathSpring"); //============================================================================= // OUTPUTS @@ -207,11 +209,6 @@ OpenSim_DECLARE_CONCRETE_OBJECT(PathSpring, Force); return values; } -protected: - OpenSim_DECLARE_PROPERTY(path, AbstractPath, - "The path defines the length and lengthening speed of the " - "PathSpring"); - private: void constructProperties(); From f6e720899644e2b05131c1a09c8d9a212bd26713 Mon Sep 17 00:00:00 2001 From: Nicholas Bianco Date: Thu, 31 Aug 2023 15:30:33 -0700 Subject: [PATCH 18/24] More reverted code --- OpenSim/Actuators/DeGrooteFregly2016Muscle.cpp | 1 - OpenSim/ExampleComponents/HopperDevice.h | 2 +- .../Examples/ExampleHopperDevice/defineDeviceAndController.h | 2 +- .../ExampleHopperDevice/defineDeviceAndController_answers.h | 2 +- OpenSim/Simulation/Model/Blankevoort1991Ligament.h | 2 +- OpenSim/Simulation/Model/GeometryPath.h | 2 +- OpenSim/Simulation/Wrap/PathWrap.cpp | 1 - OpenSim/Tests/Wrapping/testMuscleLengthRegression.cpp | 4 ++-- 8 files changed, 7 insertions(+), 9 deletions(-) diff --git a/OpenSim/Actuators/DeGrooteFregly2016Muscle.cpp b/OpenSim/Actuators/DeGrooteFregly2016Muscle.cpp index aa375aed71..a323044141 100644 --- a/OpenSim/Actuators/DeGrooteFregly2016Muscle.cpp +++ b/OpenSim/Actuators/DeGrooteFregly2016Muscle.cpp @@ -27,7 +27,6 @@ #include #include #include -#include "OpenSim/Simulation/Model/GeometryPath.h" #include "OpenSim/Common/STOFileAdapter.h" using namespace OpenSim; diff --git a/OpenSim/ExampleComponents/HopperDevice.h b/OpenSim/ExampleComponents/HopperDevice.h index af8352a702..d63c6f6aa1 100644 --- a/OpenSim/ExampleComponents/HopperDevice.h +++ b/OpenSim/ExampleComponents/HopperDevice.h @@ -101,7 +101,7 @@ class OSIMEXAMPLECOMPONENTS_API HopperDevice : public ModelComponent { void extendRealizeDynamics(const SimTK::State& s) const override { const auto& actuator = getComponent(get_actuator_name()); double level = fmin(1., getTension(s) / actuator.get_optimal_force()); - actuator.getPath().setColor(s, SimTK::Vec3(level, 0.5, 0)); + actuator.getGeometryPath().setColor(s, SimTK::Vec3(level, 0.5, 0)); } }; // end of HopperDevice diff --git a/OpenSim/Examples/ExampleHopperDevice/defineDeviceAndController.h b/OpenSim/Examples/ExampleHopperDevice/defineDeviceAndController.h index cec133cceb..a786d6eab3 100644 --- a/OpenSim/Examples/ExampleHopperDevice/defineDeviceAndController.h +++ b/OpenSim/Examples/ExampleHopperDevice/defineDeviceAndController.h @@ -105,7 +105,7 @@ class Device : public ModelComponent { void extendRealizeDynamics(const SimTK::State& s) const override { const auto& actuator = getComponent("cableAtoB"); double level = fmin(1., getTension(s) / actuator.get_optimal_force()); - actuator.getPath().setColor(s, SimTK::Vec3(0.1, level, 0.1)); + actuator.getGeometryPath().setColor(s, SimTK::Vec3(0.1, level, 0.1)); } }; // end of Device diff --git a/OpenSim/Examples/ExampleHopperDevice/defineDeviceAndController_answers.h b/OpenSim/Examples/ExampleHopperDevice/defineDeviceAndController_answers.h index 9b71d7bfa0..9463b69d1b 100644 --- a/OpenSim/Examples/ExampleHopperDevice/defineDeviceAndController_answers.h +++ b/OpenSim/Examples/ExampleHopperDevice/defineDeviceAndController_answers.h @@ -154,7 +154,7 @@ class Device : public ModelComponent { void extendRealizeDynamics(const SimTK::State& s) const override { const auto& actuator = getComponent("cableAtoB"); double level = fmin(1., getTension(s) / actuator.get_optimal_force()); - actuator.getPath().setColor(s, SimTK::Vec3(0.1, level, 0.1)); + actuator.getGeometryPath().setColor(s, SimTK::Vec3(0.1, level, 0.1)); } }; // end of Device diff --git a/OpenSim/Simulation/Model/Blankevoort1991Ligament.h b/OpenSim/Simulation/Model/Blankevoort1991Ligament.h index 52878461a2..eb5b02de4b 100644 --- a/OpenSim/Simulation/Model/Blankevoort1991Ligament.h +++ b/OpenSim/Simulation/Model/Blankevoort1991Ligament.h @@ -350,7 +350,7 @@ OpenSim_DECLARE_CONCRETE_OBJECT(Blankevoort1991Ligament, Force) const SimTK::State& state) const override; protected: - + void extendFinalizeFromProperties() override; void extendAddToSystem(SimTK::MultibodySystem& system) const override; diff --git a/OpenSim/Simulation/Model/GeometryPath.h b/OpenSim/Simulation/Model/GeometryPath.h index 0c35ba1d27..d118edea01 100644 --- a/OpenSim/Simulation/Model/GeometryPath.h +++ b/OpenSim/Simulation/Model/GeometryPath.h @@ -158,7 +158,7 @@ OpenSim_DECLARE_CONCRETE_OBJECT(GeometryPath, AbstractPath); @param[in,out] mobilityForces Vector of generalized forces, one per mobility */ void addInEquivalentForces(const SimTK::State& state, - const double& tension, + const double& tension, SimTK::Vector_& bodyForces, SimTK::Vector& mobilityForces) const override; diff --git a/OpenSim/Simulation/Wrap/PathWrap.cpp b/OpenSim/Simulation/Wrap/PathWrap.cpp index 223d24e88f..9d2d81b36e 100644 --- a/OpenSim/Simulation/Wrap/PathWrap.cpp +++ b/OpenSim/Simulation/Wrap/PathWrap.cpp @@ -26,7 +26,6 @@ //============================================================================= #include "PathWrap.h" #include -#include //============================================================================= // STATICS diff --git a/OpenSim/Tests/Wrapping/testMuscleLengthRegression.cpp b/OpenSim/Tests/Wrapping/testMuscleLengthRegression.cpp index bf9799ae80..4f3a17221a 100644 --- a/OpenSim/Tests/Wrapping/testMuscleLengthRegression.cpp +++ b/OpenSim/Tests/Wrapping/testMuscleLengthRegression.cpp @@ -40,8 +40,8 @@ namespace { SimTK::RowVector lengthsRow(muscleSet.getSize()); for (int imuscle = 0; imuscle < muscleSet.getSize(); ++imuscle) { const auto& muscle = muscleSet.get(imuscle); - const auto& path = muscle.getPath(); - lengthsRow[imuscle] = path.getLength(state); + const auto& geometryPath = muscle.getGeometryPath(); + lengthsRow[imuscle] = geometryPath.getLength(state); } lengths.appendRow(state.getTime(), lengthsRow); } From 2940c77fae6500df602989d6a18eb2c44c998995 Mon Sep 17 00:00:00 2001 From: Nicholas Bianco Date: Thu, 31 Aug 2023 15:39:34 -0700 Subject: [PATCH 19/24] Remove unnecessary includes --- OpenSim/Simulation/Model/GeometryPath.h | 5 +---- OpenSim/Simulation/osimSimulation.h | 1 - 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/OpenSim/Simulation/Model/GeometryPath.h b/OpenSim/Simulation/Model/GeometryPath.h index d118edea01..a6f4692fff 100644 --- a/OpenSim/Simulation/Model/GeometryPath.h +++ b/OpenSim/Simulation/Model/GeometryPath.h @@ -25,8 +25,6 @@ // INCLUDE -#include -#include "OpenSim/Simulation/Model/ModelComponent.h" #include "OpenSim/Simulation/Model/AbstractPath.h" #include "PathPointSet.h" #include @@ -80,12 +78,11 @@ OpenSim_DECLARE_CONCRETE_OBJECT(GeometryPath, AbstractPath); mutable CacheVariable _lengthCV; mutable CacheVariable _speedCV; - mutable CacheVariable _colorCV; - public: class PathElementLookup; private: mutable CacheVariable> _currentPathCV; + mutable CacheVariable _colorCV; //============================================================================= // METHODS diff --git a/OpenSim/Simulation/osimSimulation.h b/OpenSim/Simulation/osimSimulation.h index 44d49f84ef..dc85551b82 100644 --- a/OpenSim/Simulation/osimSimulation.h +++ b/OpenSim/Simulation/osimSimulation.h @@ -52,7 +52,6 @@ #include "Model/PathPointSet.h" #include "Model/ConditionalPathPoint.h" #include "Model/MovingPathPoint.h" -#include "Model/AbstractPath.h" #include "Model/GeometryPath.h" #include "Model/PrescribedForce.h" #include "Model/PointToPointSpring.h" From 25ed001efb51f4f4b13a4f9f979841adc0efd787 Mon Sep 17 00:00:00 2001 From: Nicholas Bianco Date: Fri, 1 Sep 2023 11:44:31 -0700 Subject: [PATCH 20/24] Rename copyFrom() to assign(); change hasPath() to hasVisualPath() --- .../Actuators/DeGrooteFregly2016Muscle.cpp | 2 +- OpenSim/Actuators/ModelFactory.cpp | 2 +- OpenSim/Analyses/MuscleAnalysis.h | 1 - OpenSim/Simulation/Model/AbstractPath.h | 10 ++- .../Model/Blankevoort1991Ligament.h | 4 +- OpenSim/Simulation/Model/Force.h | 14 ++--- OpenSim/Simulation/Model/GeometryPath.cpp | 62 ++++++++++--------- OpenSim/Simulation/Model/GeometryPath.h | 4 +- OpenSim/Simulation/Model/Ligament.h | 4 +- OpenSim/Simulation/Model/PathActuator.h | 3 +- OpenSim/Simulation/Model/PathSpring.h | 4 +- 11 files changed, 59 insertions(+), 51 deletions(-) diff --git a/OpenSim/Actuators/DeGrooteFregly2016Muscle.cpp b/OpenSim/Actuators/DeGrooteFregly2016Muscle.cpp index a323044141..ec5ef6aee2 100644 --- a/OpenSim/Actuators/DeGrooteFregly2016Muscle.cpp +++ b/OpenSim/Actuators/DeGrooteFregly2016Muscle.cpp @@ -1020,7 +1020,7 @@ void DeGrooteFregly2016Muscle::replaceMuscles( muscBase.get_ignore_tendon_compliance()); actu->set_ignore_activation_dynamics( muscBase.get_ignore_activation_dynamics()); - actu->updPath().copyFrom(muscBase.getPath()); + actu->updPath().assign(muscBase.getPath()); model.addForce(actu.release()); musclesToDelete.push_back(&muscBase); diff --git a/OpenSim/Actuators/ModelFactory.cpp b/OpenSim/Actuators/ModelFactory.cpp index be421eaec6..03690f7caa 100644 --- a/OpenSim/Actuators/ModelFactory.cpp +++ b/OpenSim/Actuators/ModelFactory.cpp @@ -171,7 +171,7 @@ void ModelFactory::replaceMusclesWithPathActuators(OpenSim::Model &model) { actu->setOptimalForce(musc.getMaxIsometricForce()); actu->setMinControl(musc.getMinControl()); actu->setMaxControl(musc.getMaxControl()); - actu->updPath().copyFrom(musc.getPath()); + actu->updPath().assign(musc.getPath()); model.addForce(actu.release()); musclesToDelete.push_back(&musc); diff --git a/OpenSim/Analyses/MuscleAnalysis.h b/OpenSim/Analyses/MuscleAnalysis.h index df30dcc4dc..28361a2c50 100644 --- a/OpenSim/Analyses/MuscleAnalysis.h +++ b/OpenSim/Analyses/MuscleAnalysis.h @@ -28,7 +28,6 @@ //============================================================================= // INCLUDES //============================================================================= -#include #include #include #include "osimAnalysesDLL.h" diff --git a/OpenSim/Simulation/Model/AbstractPath.h b/OpenSim/Simulation/Model/AbstractPath.h index 50b86aec86..669ddfc3b6 100644 --- a/OpenSim/Simulation/Model/AbstractPath.h +++ b/OpenSim/Simulation/Model/AbstractPath.h @@ -166,7 +166,15 @@ OpenSim_DECLARE_ABSTRACT_OBJECT(AbstractPath, ModelComponent); * properties to define the path length and lengthening speed and therefore * must provide a relevant implementation. */ - virtual void copyFrom(const AbstractPath& source) = 0; + virtual void assign(const AbstractPath& source) = 0; + + /** + * Return whether or not a path can be visualized. + * + * Concrete implementations may be visualizable (e.g., `GeometryPath`) or + * they may not be and therefore must provide a relevant implementation. + */ + virtual bool isVisualPath() const = 0; // DEFAULTED METHODS // diff --git a/OpenSim/Simulation/Model/Blankevoort1991Ligament.h b/OpenSim/Simulation/Model/Blankevoort1991Ligament.h index eb5b02de4b..eef8ceff5a 100644 --- a/OpenSim/Simulation/Model/Blankevoort1991Ligament.h +++ b/OpenSim/Simulation/Model/Blankevoort1991Ligament.h @@ -238,8 +238,6 @@ OpenSim_DECLARE_CONCRETE_OBJECT(Blankevoort1991Ligament, Force) double linear_stiffness, double slack_length); // Path - bool hasPath() const override { return true; }; - AbstractPath& updPath() { return upd_path(); } const AbstractPath& getPath() const { return get_path(); } @@ -268,6 +266,8 @@ OpenSim_DECLARE_CONCRETE_OBJECT(Blankevoort1991Ligament, Force) return getPath(); } + bool hasVisualPath() const override { return getPath().isVisualPath(); }; + //------------------------------------------------------------------------- // SET //------------------------------------------------------------------------- diff --git a/OpenSim/Simulation/Model/Force.h b/OpenSim/Simulation/Model/Force.h index fcb72a33be..7a85da6af1 100644 --- a/OpenSim/Simulation/Model/Force.h +++ b/OpenSim/Simulation/Model/Force.h @@ -99,14 +99,12 @@ OpenSim_DECLARE_ABSTRACT_OBJECT(Force, ModelComponent); getRecordValues(const SimTK::State& state) const { return OpenSim::Array(); }; - - - /** Return a flag indicating whether the Force is applied along a Path. If - you override this method to return true for a specific subclass, it must - also implement the getPath() method. **/ - virtual bool hasPath() const { - return getPropertyIndex("path").isValid(); - }; + + /** Return a flag indicating whether the Force is applied along a path that + * can be visualized. If you override this method to return true for a + * specific subclass, it must also implement the getPath() method. + */ + virtual bool hasVisualPath() const { return false; } protected: /** Default constructor sets up Force-level properties; can only be diff --git a/OpenSim/Simulation/Model/GeometryPath.cpp b/OpenSim/Simulation/Model/GeometryPath.cpp index c18705b82b..e4c9d71b68 100644 --- a/OpenSim/Simulation/Model/GeometryPath.cpp +++ b/OpenSim/Simulation/Model/GeometryPath.cpp @@ -501,38 +501,40 @@ void GeometryPath::addInEquivalentForces(const SimTK::State& s, } } -void GeometryPath::copyFrom(const OpenSim::AbstractPath& source) { - if (const auto* src = dynamic_cast(&source)) { - // Copy the path points. - const auto& pathPointSet = src->getPathPointSet(); - for (int ipp = 0; ipp < pathPointSet.getSize(); ++ipp) { - auto* pathPoint = pathPointSet.get(ipp).clone(); - const auto& socketNames = pathPoint->getSocketNames(); - for (const auto& socketName : socketNames) { - pathPoint->updSocket(socketName) - .connect(pathPointSet.get(ipp) - .getSocket(socketName) - .getConnecteeAsObject()); - } - this->updPathPointSet().adoptAndAppend(pathPoint); +void GeometryPath::assign(const OpenSim::AbstractPath& source) +{ + const auto* src = dynamic_cast(&source); + if (!src) { + OPENSIM_THROW(Exception, "GeometryPath::copyFrom(): expected a " + "GeometryPath, but got a " + source.getConcreteClassName()); + } + + // Copy the path points. + const auto& pathPointSet = src->getPathPointSet(); + for (int ipp = 0; ipp < pathPointSet.getSize(); ++ipp) { + auto* pathPoint = pathPointSet.get(ipp).clone(); + const auto& socketNames = pathPoint->getSocketNames(); + for (const auto& socketName : socketNames) { + pathPoint->updSocket(socketName) + .connect(pathPointSet.get(ipp) + .getSocket(socketName) + .getConnecteeAsObject()); } - - // Copy the wrap objects. - const auto& pathWrapSet = src->getWrapSet(); - for (int ipw = 0; ipw < pathWrapSet.getSize(); ++ipw) { - auto* pathWrap = pathWrapSet.get(ipw).clone(); - const auto& socketNames = pathWrap->getSocketNames(); - for (const auto& socketName : socketNames) { - pathWrap->updSocket(socketName) - .connect(pathWrapSet.get(ipw) - .getSocket(socketName) - .getConnecteeAsObject()); - } - this->updWrapSet().adoptAndAppend(pathWrap); + this->updPathPointSet().adoptAndAppend(pathPoint); + } + + // Copy the wrap objects. + const auto& pathWrapSet = src->getWrapSet(); + for (int ipw = 0; ipw < pathWrapSet.getSize(); ++ipw) { + auto* pathWrap = pathWrapSet.get(ipw).clone(); + const auto& socketNames = pathWrap->getSocketNames(); + for (const auto& socketName : socketNames) { + pathWrap->updSocket(socketName) + .connect(pathWrapSet.get(ipw) + .getSocket(socketName) + .getConnecteeAsObject()); } - } else { - throw Exception("GeometryPath::copyFrom(): expected a GeometryPath, " - "but got a " + source.getConcreteClassName()); + this->updWrapSet().adoptAndAppend(pathWrap); } } diff --git a/OpenSim/Simulation/Model/GeometryPath.h b/OpenSim/Simulation/Model/GeometryPath.h index a6f4692fff..7b456996eb 100644 --- a/OpenSim/Simulation/Model/GeometryPath.h +++ b/OpenSim/Simulation/Model/GeometryPath.h @@ -165,7 +165,9 @@ OpenSim_DECLARE_CONCRETE_OBJECT(GeometryPath, AbstractPath); * properties. If you wish to overwrite the path entirely, clear the * PathPointSet and PathWrapSet first. */ - void copyFrom(const AbstractPath& source) override; + void assign(const AbstractPath& source) override; + + bool isVisualPath() const override { return true; } //-------------------------------------------------------------------------- // COMPUTATIONS diff --git a/OpenSim/Simulation/Model/Ligament.h b/OpenSim/Simulation/Model/Ligament.h index 1c0c46ae7c..54c08f293b 100644 --- a/OpenSim/Simulation/Model/Ligament.h +++ b/OpenSim/Simulation/Model/Ligament.h @@ -76,8 +76,6 @@ OpenSim_DECLARE_CONCRETE_OBJECT(Ligament, Force); //-------------------------------------------------------------------------- // PATH //-------------------------------------------------------------------------- - bool hasPath() const override { return true; }; - AbstractPath& updPath() { return upd_path(); } const AbstractPath& getPath() const { return get_path(); } @@ -105,6 +103,8 @@ OpenSim_DECLARE_CONCRETE_OBJECT(Ligament, Force); const GeometryPath& getGeometryPath() const { return getPath(); } + + bool hasVisualPath() const override { return getPath().isVisualPath(); }; //-------------------------------------------------------------------------- // GET diff --git a/OpenSim/Simulation/Model/PathActuator.h b/OpenSim/Simulation/Model/PathActuator.h index 197712b570..18c2401964 100644 --- a/OpenSim/Simulation/Model/PathActuator.h +++ b/OpenSim/Simulation/Model/PathActuator.h @@ -68,8 +68,6 @@ class OSIMSIMULATION_API PathActuator : public ScalarActuator { // GET AND SET //-------------------------------------------------------------------------- // Path - bool hasPath() const override { return true; }; - AbstractPath& updPath() { return upd_path(); } const AbstractPath& getPath() const { return get_path(); } @@ -98,6 +96,7 @@ class OSIMSIMULATION_API PathActuator : public ScalarActuator { return getPath(); } + bool hasVisualPath() const override { return getPath().isVisualPath(); }; // OPTIMAL FORCE void setOptimalForce(double aOptimalForce); diff --git a/OpenSim/Simulation/Model/PathSpring.h b/OpenSim/Simulation/Model/PathSpring.h index c8a691525d..bc6f5922c7 100644 --- a/OpenSim/Simulation/Model/PathSpring.h +++ b/OpenSim/Simulation/Model/PathSpring.h @@ -119,8 +119,6 @@ OpenSim_DECLARE_CONCRETE_OBJECT(PathSpring, Force); void setDissipation(double dissipation); /** get/set the path object */ - bool hasPath() const override { return true; }; - AbstractPath& updPath() { return upd_path(); } const AbstractPath& getPath() const { return get_path(); } @@ -148,6 +146,8 @@ OpenSim_DECLARE_CONCRETE_OBJECT(PathSpring, Force); const GeometryPath& getGeometryPath() const { return getPath(); } + + bool hasVisualPath() const override { return getPath().isVisualPath(); }; //-------------------------------------------------------------------------- // State dependent values From e9e0008c4ccd40d2a38561ce22c32b76016ffb9e Mon Sep 17 00:00:00 2001 From: Nicholas Bianco Date: Fri, 1 Sep 2023 14:28:00 -0700 Subject: [PATCH 21/24] Move backwards compatibility for GeometryPath deserialization to Force --- .../Model/Blankevoort1991Ligament.h | 2 +- OpenSim/Simulation/Model/Force.cpp | 16 +++++++ OpenSim/Simulation/Model/Model.cpp | 48 ------------------- 3 files changed, 17 insertions(+), 49 deletions(-) diff --git a/OpenSim/Simulation/Model/Blankevoort1991Ligament.h b/OpenSim/Simulation/Model/Blankevoort1991Ligament.h index eef8ceff5a..78eda1f8f1 100644 --- a/OpenSim/Simulation/Model/Blankevoort1991Ligament.h +++ b/OpenSim/Simulation/Model/Blankevoort1991Ligament.h @@ -177,7 +177,7 @@ OpenSim_DECLARE_CONCRETE_OBJECT(Blankevoort1991Ligament, Force) //============================================================================= // PROPERTIES //============================================================================= - + OpenSim_DECLARE_PROPERTY(path, AbstractPath, "The path defines the length and lengthening speed of the ligament.") OpenSim_DECLARE_PROPERTY(linear_stiffness, double, diff --git a/OpenSim/Simulation/Model/Force.cpp b/OpenSim/Simulation/Model/Force.cpp index b78e8e23d7..121fde2094 100644 --- a/OpenSim/Simulation/Model/Force.cpp +++ b/OpenSim/Simulation/Model/Force.cpp @@ -78,6 +78,22 @@ Force::updateFromXMLNode(SimTK::Xml::Element& node, int versionNumber) { elem.setValue(SimTK::String(!isDisabled)); } } + if (versionNumber < 40500) { + // In version 40500, the XML syntax for components that own + // GeometryPath objects (PathActuator, PathSpring, Ligament, + // and Blankevoort1991Ligament) changed: the 'GeometryPath` unnamed + // property was replaced with the named property 'path', which is of + // type 'AbstractPath'. Since 'path' is still a one object property, + // the property will still be serialized using the concrete type + // (e.g., 'GeometryPath') and with name attribute set to 'path'. + // Therefore, we can simply update the name attribute of any + // existing 'GeometryPath' nodes to 'path'. + SimTK::Xml::element_iterator geometryPathNode = + node.element_begin("GeometryPath"); + if (geometryPathNode != node.element_end()) { + geometryPathNode->setAttributeValue("name", "path"); + } + } } Super::updateFromXMLNode(node, versionNumber); diff --git a/OpenSim/Simulation/Model/Model.cpp b/OpenSim/Simulation/Model/Model.cpp index c7c161d242..3c03689049 100644 --- a/OpenSim/Simulation/Model/Model.cpp +++ b/OpenSim/Simulation/Model/Model.cpp @@ -323,54 +323,6 @@ void Model::updateFromXMLNode(SimTK::Xml::Element& aNode, int versionNumber) framesNode->getParentElement().eraseNode(framesNode); } } - if (versionNumber < 40500) { - // In version 40500, the XML syntax for components that own - // GeometryPath objects (PathActuator, PathSpring, Ligament, - // and Blankevoort1991Ligament) changed: the 'GeometryPath` unnamed - // property was replaced with the named property 'path', which is of - // type 'AbstractPath'. Since 'path' is still a one object property, - // the property will still be serialized using the concrete type - // (e.g., 'GeometryPath') and with name attribute set to 'path'. - // Therefore, we can simply update the name attribute of any - // existing 'GeometryPath' nodes to 'path'. - - // Components that own paths can be in the model's ForceSet or - // the components list. - SimTK::Xml::element_iterator forceSetNode = - aNode.element_begin("ForceSet"); - SimTK::Xml::element_iterator componentsNode = - aNode.element_begin("components"); - - // Loop through the ForceSet and update any GeometryPath nodes. - if (forceSetNode != aNode.element_end()) { - SimTK::Xml::element_iterator objects_node = - forceSetNode->element_begin("objects"); - SimTK::Xml::element_iterator forceIter = - objects_node->element_begin(); - for (; forceIter != objects_node->element_end(); ++forceIter) { - SimTK::Xml::element_iterator geometryPathNode = - forceIter->element_begin("GeometryPath"); - if (geometryPathNode != forceIter->element_end()) { - geometryPathNode->setAttributeValue("name", "path"); - } - } - } - - // Loop through the components list and update any GeometryPath - // nodes. - if (componentsNode != aNode.element_end()) { - SimTK::Xml::element_iterator forceIter = - componentsNode->element_begin(); - for (; forceIter != componentsNode->element_end(); ++forceIter) { - SimTK::Xml::element_iterator geometryPathNode = - forceIter->element_begin("GeometryPath"); - if (geometryPathNode != forceIter->element_end()) { - geometryPathNode->setAttributeValue("name", "path"); - } - } - } - - } } // Call base class now assuming _node has been corrected for current version Super::updateFromXMLNode(aNode, versionNumber); From 507e4e191f0dda13977106bead155475ab2da02c Mon Sep 17 00:00:00 2001 From: Nicholas Bianco Date: Fri, 1 Sep 2023 14:46:01 -0700 Subject: [PATCH 22/24] Minor whitespace cleanup --- OpenSim/Simulation/Model/Blankevoort1991Ligament.h | 2 +- OpenSim/Simulation/Model/GeometryPath.cpp | 2 +- OpenSim/Simulation/Model/GeometryPath.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/OpenSim/Simulation/Model/Blankevoort1991Ligament.h b/OpenSim/Simulation/Model/Blankevoort1991Ligament.h index 78eda1f8f1..eef8ceff5a 100644 --- a/OpenSim/Simulation/Model/Blankevoort1991Ligament.h +++ b/OpenSim/Simulation/Model/Blankevoort1991Ligament.h @@ -177,7 +177,7 @@ OpenSim_DECLARE_CONCRETE_OBJECT(Blankevoort1991Ligament, Force) //============================================================================= // PROPERTIES //============================================================================= - + OpenSim_DECLARE_PROPERTY(path, AbstractPath, "The path defines the length and lengthening speed of the ligament.") OpenSim_DECLARE_PROPERTY(linear_stiffness, double, diff --git a/OpenSim/Simulation/Model/GeometryPath.cpp b/OpenSim/Simulation/Model/GeometryPath.cpp index e4c9d71b68..cb3948b790 100644 --- a/OpenSim/Simulation/Model/GeometryPath.cpp +++ b/OpenSim/Simulation/Model/GeometryPath.cpp @@ -382,7 +382,7 @@ getPointForceDirections(const SimTK::State& s, /* add in the equivalent spatial forces on bodies for an applied tension along the GeometryPath to a set of bodyForces */ void GeometryPath::addInEquivalentForces(const SimTK::State& s, - const double& tension, + const double& tension, SimTK::Vector_& bodyForces, SimTK::Vector& mobilityForces) const { diff --git a/OpenSim/Simulation/Model/GeometryPath.h b/OpenSim/Simulation/Model/GeometryPath.h index 7b456996eb..0189f441b0 100644 --- a/OpenSim/Simulation/Model/GeometryPath.h +++ b/OpenSim/Simulation/Model/GeometryPath.h @@ -83,7 +83,7 @@ OpenSim_DECLARE_CONCRETE_OBJECT(GeometryPath, AbstractPath); private: mutable CacheVariable> _currentPathCV; mutable CacheVariable _colorCV; - + //============================================================================= // METHODS //============================================================================= From 83577ea42b33da4ba19972108400b83e561025e9 Mon Sep 17 00:00:00 2001 From: Nicholas Bianco Date: Wed, 6 Sep 2023 14:15:53 -0700 Subject: [PATCH 23/24] Use AbstractProperty::assign() instead of a new virtual method --- .../Actuators/DeGrooteFregly2016Muscle.cpp | 2 +- OpenSim/Actuators/ModelFactory.cpp | 3 +- OpenSim/Simulation/Model/AbstractPath.h | 9 ----- OpenSim/Simulation/Model/GeometryPath.cpp | 37 ------------------- OpenSim/Simulation/Model/GeometryPath.h | 8 ---- 5 files changed, 3 insertions(+), 56 deletions(-) diff --git a/OpenSim/Actuators/DeGrooteFregly2016Muscle.cpp b/OpenSim/Actuators/DeGrooteFregly2016Muscle.cpp index ec5ef6aee2..6aef818887 100644 --- a/OpenSim/Actuators/DeGrooteFregly2016Muscle.cpp +++ b/OpenSim/Actuators/DeGrooteFregly2016Muscle.cpp @@ -1020,7 +1020,7 @@ void DeGrooteFregly2016Muscle::replaceMuscles( muscBase.get_ignore_tendon_compliance()); actu->set_ignore_activation_dynamics( muscBase.get_ignore_activation_dynamics()); - actu->updPath().assign(muscBase.getPath()); + actu->updProperty_path().assign(muscBase.getProperty_path()); model.addForce(actu.release()); musclesToDelete.push_back(&muscBase); diff --git a/OpenSim/Actuators/ModelFactory.cpp b/OpenSim/Actuators/ModelFactory.cpp index 03690f7caa..4cacb6980b 100644 --- a/OpenSim/Actuators/ModelFactory.cpp +++ b/OpenSim/Actuators/ModelFactory.cpp @@ -171,7 +171,8 @@ void ModelFactory::replaceMusclesWithPathActuators(OpenSim::Model &model) { actu->setOptimalForce(musc.getMaxIsometricForce()); actu->setMinControl(musc.getMinControl()); actu->setMaxControl(musc.getMaxControl()); - actu->updPath().assign(musc.getPath()); + actu->updProperty_path().assign(musc.getProperty_path()); + actu->upd_path().setDefaultColor({0.5, 0.5, 0.5}); model.addForce(actu.release()); musclesToDelete.push_back(&musc); diff --git a/OpenSim/Simulation/Model/AbstractPath.h b/OpenSim/Simulation/Model/AbstractPath.h index 669ddfc3b6..8f0d678bcb 100644 --- a/OpenSim/Simulation/Model/AbstractPath.h +++ b/OpenSim/Simulation/Model/AbstractPath.h @@ -159,15 +159,6 @@ OpenSim_DECLARE_ABSTRACT_OBJECT(AbstractPath, ModelComponent); virtual double computeMomentArm(const SimTK::State& s, const Coordinate& aCoord) const = 0; - /** - * Copy the properties of the source path into this path. - * - * Concrete implementations (e.g., `GeometryPath`) may use a variety of - * properties to define the path length and lengthening speed and therefore - * must provide a relevant implementation. - */ - virtual void assign(const AbstractPath& source) = 0; - /** * Return whether or not a path can be visualized. * diff --git a/OpenSim/Simulation/Model/GeometryPath.cpp b/OpenSim/Simulation/Model/GeometryPath.cpp index cb3948b790..c7db2882d7 100644 --- a/OpenSim/Simulation/Model/GeometryPath.cpp +++ b/OpenSim/Simulation/Model/GeometryPath.cpp @@ -501,43 +501,6 @@ void GeometryPath::addInEquivalentForces(const SimTK::State& s, } } -void GeometryPath::assign(const OpenSim::AbstractPath& source) -{ - const auto* src = dynamic_cast(&source); - if (!src) { - OPENSIM_THROW(Exception, "GeometryPath::copyFrom(): expected a " - "GeometryPath, but got a " + source.getConcreteClassName()); - } - - // Copy the path points. - const auto& pathPointSet = src->getPathPointSet(); - for (int ipp = 0; ipp < pathPointSet.getSize(); ++ipp) { - auto* pathPoint = pathPointSet.get(ipp).clone(); - const auto& socketNames = pathPoint->getSocketNames(); - for (const auto& socketName : socketNames) { - pathPoint->updSocket(socketName) - .connect(pathPointSet.get(ipp) - .getSocket(socketName) - .getConnecteeAsObject()); - } - this->updPathPointSet().adoptAndAppend(pathPoint); - } - - // Copy the wrap objects. - const auto& pathWrapSet = src->getWrapSet(); - for (int ipw = 0; ipw < pathWrapSet.getSize(); ++ipw) { - auto* pathWrap = pathWrapSet.get(ipw).clone(); - const auto& socketNames = pathWrap->getSocketNames(); - for (const auto& socketName : socketNames) { - pathWrap->updSocket(socketName) - .connect(pathWrapSet.get(ipw) - .getSocket(socketName) - .getConnecteeAsObject()); - } - this->updWrapSet().adoptAndAppend(pathWrap); - } -} - //_____________________________________________________________________________ /* * Update the geometric representation of the path. diff --git a/OpenSim/Simulation/Model/GeometryPath.h b/OpenSim/Simulation/Model/GeometryPath.h index 0189f441b0..5dc552cdbf 100644 --- a/OpenSim/Simulation/Model/GeometryPath.h +++ b/OpenSim/Simulation/Model/GeometryPath.h @@ -159,14 +159,6 @@ OpenSim_DECLARE_CONCRETE_OBJECT(GeometryPath, AbstractPath); SimTK::Vector_& bodyForces, SimTK::Vector& mobilityForces) const override; - /** Copy the PathPoint%s and PathWrap%s of the source path into this path's - * PathPointSet and PathWrapSet, respectively. - * @note This *appends* PathPoint%s and PathWrap%s to this path's - * properties. If you wish to overwrite the path entirely, clear the - * PathPointSet and PathWrapSet first. - */ - void assign(const AbstractPath& source) override; - bool isVisualPath() const override { return true; } //-------------------------------------------------------------------------- From 83959bbef2eef8652f86c6c1cea5fac2975e44cb Mon Sep 17 00:00:00 2001 From: Nicholas Bianco Date: Thu, 7 Sep 2023 11:40:25 -0700 Subject: [PATCH 24/24] Flesh out changelog --- CHANGELOG.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3a8f903ae2..d592d8c83b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,11 @@ This is not a comprehensive list of changes but rather a hand-curated collection v4.5 ==== -- Added `AbstractPath` which is a base class for `GeometryPath` and other path types (#3388). +- Added `AbstractPath` which is a base class for `GeometryPath` and other path types (#3388). All path-based forces now +own the property `path` of type `AbstractPath` instead of the `GeometryPath` unnamed property. Getters and setters have +been added to these forces to provide access to concrete path types (e.g., `updPath`). In `Ligament` and +`Blankevoort1991Ligament`, usages of `get_GeometryPath`, `upd_GeometryPath`, etc., need to be been updated to +`getGeometryPath`, `updGeometryPath`, etc., or a suitable alternative. v4.4.1 ======