Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Exponential Contact #3310

Open
wants to merge 62 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
ff5fb01
Draft of OpenSim::ExponentialSpringForce
fcanderson May 19, 2022
60a82d6
First draft.
fcanderson May 24, 2022
39aeed4
Minor. Just line length corrections.
fcanderson May 24, 2022
9f73ff3
Completed the basic framework.
fcanderson May 24, 2022
569e1cf
Added draft of a Visualizer class.
fcanderson May 25, 2022
eb632ca
Adding 8 HuntCrossley at corners.
fcanderson May 25, 2022
3064448
Constructing based on "BodyName" instead of Body.
fcanderson May 27, 2022
ab3aeda
Added Exponential Springs and an ExternalForce.
fcanderson May 27, 2022
94f1b81
Minor Changes + Bug Fixes
fcanderson May 28, 2022
b5812da
Added Parameters. Changed name.
fcanderson Jun 5, 2022
8f339cd
Bug fix, plus minor tweaks
fcanderson Jun 5, 2022
6a9563f
Non-default params working + comments and tweaks.
fcanderson Jun 7, 2022
110d356
File rename: "ExpoentialSpringForce" to "ExponentialContact"
fcanderson Jun 7, 2022
4a0d4a7
Improved documentation comments.
fcanderson Jun 7, 2022
1ffa6e3
Cleaned up code, removed memory leaks, polished comments.
fcanderson Jun 18, 2022
814f974
Added detailed Doxygen comments.
fcanderson Jun 18, 2022
fa57ae2
Enhanced reported information.
fcanderson Jun 18, 2022
52c95bc
Registered class ExponentialContact.
fcanderson Jun 18, 2022
9e710a4
Bug fix and some internal testing.
fcanderson Jun 18, 2022
a4f91aa
Made naming more consistent.
fcanderson Jun 19, 2022
fd85ee5
Removed unused method.
fcanderson Jun 19, 2022
a5d5793
Tweaked/shortened command-line options.
fcanderson Jun 19, 2022
e5d97e1
Minor name change: FxES -> FxEC
fcanderson Jun 19, 2022
ff07658
Polished documentation comments.
fcanderson Jun 22, 2022
e4b3411
Memory management and simplifications.
fcanderson Jun 22, 2022
94ac923
Added ExponentialContact.h to include file.
fcanderson Jun 24, 2022
882e83f
Minor name changes.
fcanderson Jun 24, 2022
ccb4258
Added test routine for class ExponentialContact.
fcanderson Jun 24, 2022
9eca269
Added two new initial conditions.
fcanderson Sep 11, 2022
fc38ee5
Improved output formatting.
fcanderson Sep 11, 2022
56f4e22
Added resetAnchorPoint(), removed props, polished comments.
fcanderson Sep 16, 2022
82cf83d
Added resetAnchorPoint(), removed props, polished comments.
fcanderson Sep 16, 2022
11c8f36
Added accessors for states.
fcanderson Sep 17, 2022
fd02274
Added accessors for data cache entries.
fcanderson Sep 18, 2022
e7a006b
Added static method for resetting anchor points.
fcanderson Sep 18, 2022
e2a172b
ExponentialContact: Using monograph notation
fcanderson Oct 28, 2022
af8eb21
Merge branch 'opensim-org:master' into exponential_springs
fcanderson Oct 30, 2022
36145fc
Typo Fix: corrected volume of block.
fcanderson Nov 1, 2022
783c16f
testForce: enhanced test for ExponentialContact
fcanderson Nov 1, 2022
d2fbce2
Modified ExponentialContact::getRecordValues()
fcanderson Jan 6, 2023
7f8bdf1
Modified testExponentialContact() in testForces.cpp
fcanderson Jan 6, 2023
e24d170
Merge branch 'opensim-org:main' into exponential_springs
fcanderson Jan 6, 2023
2583850
Merge branch 'opensim-org:main' into exponential_springs
fcanderson Jan 17, 2023
540da3f
Dependencies updated to build against latest Simbody build.
fcanderson Jan 17, 2023
e7b17b1
Commented out some cout statements.
fcanderson Jan 18, 2023
eb6752f
updateFromXMLNode() now declared as override
fcanderson Jan 18, 2023
75e87c9
Ubuntu build fix?: Catching exception std::bad_cast
fcanderson Jan 18, 2023
f74c4d8
Merge branch 'opensim-org:main' into exponential_springs
fcanderson Jan 28, 2023
d1a605c
Minor changes to comments.
fcanderson Jan 28, 2023
855b73a
Added tests for Discrete Variable accessors.
fcanderson Jan 28, 2023
cf84b90
ExponentialContact:: added methods related to Discrete States.
fcanderson Jan 28, 2023
e114e54
Component: modifications to accommodate externally allocated Discrete…
fcanderson Jan 28, 2023
b1cf08d
Merge branch 'opensim-org:main' into exponential_springs
fcanderson Feb 5, 2023
0e67551
Merge branch 'exponential_springs' of https://github.com/fcanderson/o…
fcanderson Feb 5, 2023
0ea90bc
ExponentialContact: Exported elastic anchor point as a discrete varia…
fcanderson Feb 12, 2023
437feb7
[WIP] Modifications to support serializing Discrete Variables.
fcanderson Feb 12, 2023
63ff32f
Removed wip methods for traversing to a DiscreteVariable.
fcanderson Apr 27, 2023
69e747e
Discrete variables can now be accessed by path.
fcanderson May 6, 2023
9f2ee6d
Component.h: fixed a few typos
fcanderson May 9, 2023
19d99e7
testExponentialContact: output simulated states
fcanderson May 9, 2023
3f8e4d4
testExponentialContact: added StatesTrajectoryReporter
fcanderson May 15, 2023
eefb305
Merge branch 'opensim-org:main' into exponential_springs
fcanderson May 16, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 63 additions & 33 deletions OpenSim/Common/Component.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -812,6 +812,7 @@ const Component::StateVariable* Component::traverseToStateVariable(
return found;
}


// Get the names of "continuous" state variables maintained by the Component and
// its subcomponents.
Array<std::string> Component::getStateVariableNames() const
Expand Down Expand Up @@ -1090,13 +1091,12 @@ getDiscreteVariableValue(const SimTK::State& s, const std::string& name) const
}

//_____________________________________________________________________________
// F. C. Anderson (Jan 2023)
// This method was added in order to handle Discrete Variables that are not
// type double.
const SimTK::AbstractValue&
// Set the value (assumed to be double) of a discrete variable allocated by
// this Component by name.
void
Component::
getDiscreteVariableAbstractValue(const SimTK::State& s,
const std::string& name) const
setDiscreteVariableValue(SimTK::State& s, const std::string& name,
double value) const
{
// Must have already called initSystem.
OPENSIM_THROW_IF_FRMOBJ(!hasSystem(), ComponentHasNoSystem);
Expand All @@ -1120,35 +1120,62 @@ getDiscreteVariableAbstractValue(const SimTK::State& s,
// default value, then the default Subsystem is used.
const SimTK::Subsystem* subsystem = it->second.subsystem;
if (subsystem == nullptr) subsystem = &getDefaultSubsystem();
return subsystem->getDiscreteVariable(s, dvIndex);
SimTK::Value<double>::downcast(
subsystem->updDiscreteVariable(s, dvIndex)).upd() = value;

} else {
std::stringstream msg;
msg << "Component::getDiscreteVariable: ERR- name '" << name
msg << "Component::setDiscreteVariable: ERR- name '" << name
<< "' not found.\n "
<< "for component '"<< getName() << "' of type "
<< getConcreteClassName();
throw Exception(msg.str(),__FILE__,__LINE__);
}
}

//_____________________________________________________________________________
// F. C. Anderson (May 2023)
// Added so that a discrete variable can be accessed based on a specified path.
const Component*
Component::
resolveDiscreteVariableNameAndOwner(const std::string& pathName,
std::string& dvName) const
{
ComponentPath path{pathName};
size_t nLevels = path.getNumPathLevels();
dvName = path.getSubcomponentNameAtLevel(nLevels - 1);
const Component* owner = this;
if (nLevels > 1) {
// Need to traverse to the owner of the DV based on the path.
const ComponentPath& ownerPath = path.getParentPath();
owner = traversePathToComponent<Component>(ownerPath);
}
return owner;
}

//_____________________________________________________________________________
// F. C. Anderson (Jan 2023)
// This method was added in order to handle Discrete Variables that
// are not type double.
SimTK::AbstractValue&
// F. C. Anderson (Jan 2023, May 2023)
// This method was added in order to handle Discrete Variables (DV) that are
// not type double. In addition, a DV can be accessed by specifying its path
// instead of just the name of the DV.
const SimTK::AbstractValue&
Component::
updDiscreteVariableAbstractValue(SimTK::State& s,
const std::string& name) const
getDiscreteVariableAbstractValue(const SimTK::State& s,
const std::string& pathName) const
{
// Must have already called initSystem.
OPENSIM_THROW_IF_FRMOBJ(!hasSystem(), ComponentHasNoSystem);

// Resolve the name of the DV and its owner.
std::string dvName{""};
const Component* owner =
resolveDiscreteVariableNameAndOwner(pathName, dvName);

// Find the variable.
std::map<std::string, DiscreteVariableInfo>::const_iterator it;
it = _namedDiscreteVariableInfo.find(name);
it = owner->_namedDiscreteVariableInfo.find(dvName);

if (it != _namedDiscreteVariableInfo.end()) {
if (it != owner->_namedDiscreteVariableInfo.end()) {
SimTK::DiscreteVariableIndex dvIndex = it->second.index;

// F. C. Anderson (Jan 2023)
Expand All @@ -1164,34 +1191,40 @@ updDiscreteVariableAbstractValue(SimTK::State& s,
// default value, then the default Subsystem is used.
const SimTK::Subsystem* subsystem = it->second.subsystem;
if (subsystem == nullptr) subsystem = &getDefaultSubsystem();
return subsystem->updDiscreteVariable(s, dvIndex);
return subsystem->getDiscreteVariable(s, dvIndex);

} else {
std::stringstream msg;
msg << "Component::getDiscreteVariable: ERR- name '" << name
msg << "Component::getDiscreteVariable: ERR- name '" << pathName
<< "' not found.\n "
<< "for component '" << getName() << "' of type "
<< getConcreteClassName();
throw Exception(msg.str(), __FILE__, __LINE__);
}
}


//_____________________________________________________________________________
// Set the value (assumed to be double) of a discrete variable allocated by
// this Component by name.
void
// F. C. Anderson (Jan 2023, May 2023)
// This method was added in order to handle Discrete Variables (DV) that are
// not type double and, in addition, to allow a path to be specified instead
// of just the name of the DV.
SimTK::AbstractValue&
Component::
setDiscreteVariableValue(SimTK::State& s, const std::string& name,
double value) const
updDiscreteVariableAbstractValue(SimTK::State& s,
const std::string& pathName) const
{
// Must have already called initSystem.
OPENSIM_THROW_IF_FRMOBJ(!hasSystem(), ComponentHasNoSystem);

// Resolve the name of the DV and its owner.
std::string dvName{""};
const Component* owner =
resolveDiscreteVariableNameAndOwner(pathName, dvName);

std::map<std::string, DiscreteVariableInfo>::const_iterator it;
it = _namedDiscreteVariableInfo.find(name);
it = owner->_namedDiscreteVariableInfo.find(dvName);

if(it != _namedDiscreteVariableInfo.end()) {
if (it != owner->_namedDiscreteVariableInfo.end()) {
SimTK::DiscreteVariableIndex dvIndex = it->second.index;

// F. C. Anderson (Jan 2023)
Expand All @@ -1207,22 +1240,19 @@ setDiscreteVariableValue(SimTK::State& s, const std::string& name,
// default value, then the default Subsystem is used.
const SimTK::Subsystem* subsystem = it->second.subsystem;
if (subsystem == nullptr) subsystem = &getDefaultSubsystem();
SimTK::Value<double>::downcast(
subsystem->updDiscreteVariable(s, dvIndex)).upd() = value;
return subsystem->updDiscreteVariable(s, dvIndex);

} else {
std::stringstream msg;
msg << "Component::setDiscreteVariable: ERR- name '" << name
msg << "Component::updDiscreteVariable: ERR- name '" << pathName
<< "' not found.\n "
<< "for component '"<< getName() << "' of type "
<< "for component '" << getName() << "' of type "
<< getConcreteClassName();
throw Exception(msg.str(),__FILE__,__LINE__);
throw Exception(msg.str(), __FILE__, __LINE__);
}
}




SimTK::CacheEntryIndex Component::getCacheVariableIndex(const std::string& name) const
{
auto it = this->_namedCacheVariables.find(name);
Expand Down
132 changes: 107 additions & 25 deletions OpenSim/Common/Component.h
Original file line number Diff line number Diff line change
Expand Up @@ -1389,44 +1389,117 @@ OpenSim_DECLARE_ABSTRACT_OBJECT(Component, Object);
const std::string& name) const;

/**
* Retrieve a read-only reference to the abstract value of the discrete
* variable of a specified name. This method provides a more general
* interface to handle discrete variables that may not be type double.
* %Set the value of a discrete variable allocated by this Component by name.
*
* @param state the State from which to get the value
* @param name the name of the discrete state variable
* @return value the discrete variable value as a SimTK::AbstractValue
* @param state the State for which to set the value
* @param name the name of the discrete variable
* @param value the value to set
* @throws ComponentHasNoSystem if this Component has not been added to a
* System (i.e., if initSystem has not been called)
*/
void setDiscreteVariableValue(SimTK::State& state, const std::string& name,
double value) const;


//-------------------------------------------------------------------------
// F. C. Anderson (January 2023, May 2023)
// Added the ability to get the value of a discrete variable as a
// SimTK::AbstractValue, thereby allowing types like Vec3.
// In addition, getDiscreteVariableAbstractValue() and
// updDiscreteVariableAbstractValue() accept the path of a discrete
// variable, not just its name.

/**
* Based on a specified path, resolve the name of a discrete variable and
* the component that owns it (i.e., its parent).
*
* @param pathName Specified path of the discrete variable in the Model
* heirarchy.
* @param dvName Returned name of the discrete variable. This string is
* simply the last string in the specified pathName.
* @return Pointer to the Component that owns the discrete variable.
*/
const Component* resolveDiscreteVariableNameAndOwner(
const std::string& pathName, std::string& dvName) const;

/**
* Retrieve a read-only reference to the abstract value of the discrete
* variable at a specified path. This method provides a more general
* interface that is not limited to values of type double.
*
* To obtain the type-specific value of a discrete variable, perform
* a cast using the template methods provided in class SimTK::Value<T>.
* When the type is unknow, it can be querried using the
Copy link
Member

@nickbianco nickbianco May 7, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A couple of typos here: unknow --> unknown and querried -- > queried.

* SimTK::Value<T>::isA() method. For example,
*
* ```
* const SimTK::AbstractValue& valAbstract =
* getDiscreteVariableAbstractValue(state, pathName);
*
* if (SimTK::Value<double>::isA(valAbstract)) {
* const SimTK::Value<double>& valDbl =
* SimTK::Value<double>::downcast(valAbstract);
* double x = valDbl + 0.4;
*
* } else if (SimTK::Value<Vec3>::isA(valAbstract)) {
* const SimTK::Value<Vec3>& valVec3 =
* SimTK::Value<Vec3>::downcast(valAbstract);
* Vec3 x = valDbl + Vec3(0.4);
* }
* ```
*
* @param state State from which to get the value.
* @param pathName Specified path of the discrete variable in the Model
* heirarchy.
* @return Value of the discrete variable as a reference to an
* AbstractValue.
* @throws ComponentHasNoSystem if this Component has not been added to a
* System (i.e., if initSystem has not been called).
* @throws Exception if the discrete variable is not found.
*/
const SimTK::AbstractValue& getDiscreteVariableAbstractValue(
const SimTK::State& state, const std::string& name) const;
const SimTK::State& state, const std::string& pathName) const;

/**
* Retrieve a writable reference to the abstract value of the discrete
* variable of a specified name. This method provides a more general
* interface to handle discrete variables that may not be type double.
*
* @param state the State from which to get the value
* @param name the name of the discrete state variable
* @return value the discrete variable value as a SimTK::AbstractValue
* variable at a specified path. This method provides a more general
* interface that is not limited to values of type double.
*
* To obtain the type-specific value of a discrete variable, perform
* a cast using the template methods provided in class SimTK::Value<T>.
* When the type is unknow, it can be querried using the
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same typos here.

* SimTK::Value<T>::isA() method. For example,
*
* ```
* SimTK::AbstractValue& valAbstract =
* updDiscreteVariableAbstractValue(state, pathName);
*
* if (SimTK::Value<double>::isA(valAbstract)) {
* SimTK::Value<double>& valDbl =
* SimTK::Value<double>::updDowncast(valAbstract);
* valDbl = 0.4;
*
* } else if (SimTK::Value<Vec3>::isA(valAbstract)) {
* SimTK::Value<Vec3>& valVec3 =
* SimTK::Value<Vec3>::updDowncast(valAbstract);
* valDbl = Vec3(0.4);
* }
* ```
*
* @param state State from which to get the value.
* @param pathName Specified path of the discrete variable in the Model
* heirarchy.
* @return Value of the discrete variable as a reference to an
* AbstractValue.
* @throws ComponentHasNoSystem if this Component has not been added to a
* System (i.e., if initSystem has not been called)
* System (i.e., if initSystem has not been called).
* @throws Exception if the discrete variable is not found.
*/
SimTK::AbstractValue& updDiscreteVariableAbstractValue(
SimTK::State& state, const std::string& name) const;
//--------------------------------------------------------------------------


/**
* %Set the value of a discrete variable allocated by this Component by name.
*
* @param state the State for which to set the value
* @param name the name of the discrete variable
* @param value the value to set
* @throws ComponentHasNoSystem if this Component has not been added to a
* System (i.e., if initSystem has not been called)
*/
void setDiscreteVariableValue(SimTK::State& state, const std::string& name,
double value) const;

/**
* %Set the value of a discrete variable allocated by this Component by
Expand Down Expand Up @@ -2034,6 +2107,12 @@ OpenSim_DECLARE_ABSTRACT_OBJECT(Component, Object);

protected:
class StateVariable;

// F. C. Anderson (May 2023)
// Need declaration up front to support new methods for traversing the
// Component graph to Discrete Variables.
//struct DiscreteVariableInfo;

//template <class T> friend class ComponentSet;
// Give the ComponentMeasure access to the realize() methods.
template <class T> friend class ComponentMeasure;
Expand Down Expand Up @@ -2748,6 +2827,8 @@ OpenSim_DECLARE_ABSTRACT_OBJECT(Component, Object);
*/
const StateVariable* traverseToStateVariable(
const ComponentPath& path) const;


#endif

/// @name Access to the owning component (advanced).
Expand Down Expand Up @@ -3316,6 +3397,7 @@ OpenSim_DECLARE_ABSTRACT_OBJECT(Component, Object);
bool allocate{true};
};


/**
* A cache variable, as stored internally by Component.
*/
Expand Down
Loading