Skip to content

Commit 80129b8

Browse files
author
mmillard
committed
Merge remote-tracking branch 'upstream/master': so that the proposed Thelen2003Muscle::initMuscleState fix is on the branch that has the test case
2 parents 468779b + 511775e commit 80129b8

18 files changed

+322
-472
lines changed

Applications/IK/ik.cpp

-3
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,6 @@ int main(int argc,char **argv)
6868
)";
6969
std::cout << deprecationNotice << std::endl;
7070

71-
// REGISTER TYPES
72-
InverseKinematicsTool::registerTypes();
73-
7471
// PARSE COMMAND LINE
7572
string option = "";
7673
string setupFileName;

Bindings/OpenSimHeaders_actuators.h

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
#include <OpenSim/Actuators/osimActuatorsDLL.h>
77
#include <OpenSim/Actuators/CoordinateActuator.h>
8+
#include <OpenSim/Actuators/ActivationCoordinateActuator.h>
89
#include <OpenSim/Actuators/PointActuator.h>
910
#include <OpenSim/Actuators/TorqueActuator.h>
1011
#include <OpenSim/Actuators/BodyActuator.h>

Bindings/SWIGSimTK/Rotation.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ class Rotation_ : public Mat<3, 3, P> {
229229
/* SimTK_SimTKCOMMON_EXPORT */ Vec3 convertThreeAxesRotationToThreeAngles( BodyOrSpaceType bodyOrSpace, const CoordinateAxis& axis1, const CoordinateAxis& axis2, const CoordinateAxis& axis3 ) const;
230230
/// Converts rotation matrix to a quaternion.
231231

232-
/* SimTK_SimTKCOMMON_EXPORT */ Quaternion convertRotationToQuaternion() const;
232+
/* SimTK_SimTKCOMMON_EXPORT */ Quaternion_<double> convertRotationToQuaternion() const;
233233

234234
/// Converts rotation matrix to angle-axis form.
235235
Vec4 convertRotationToAngleAxis() const { return convertRotationToQuaternion().convertQuaternionToAngleAxis(); }

Bindings/actuators.i

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//osimActuators
22
%include <OpenSim/Actuators/osimActuatorsDLL.h>
33
%include <OpenSim/Actuators/CoordinateActuator.h>
4+
%include <OpenSim/Actuators/ActivationCoordinateActuator.h>
45
%include <OpenSim/Actuators/PointActuator.h>
56
%include <OpenSim/Actuators/TorqueActuator.h>
67
%include <OpenSim/Actuators/BodyActuator.h>

CHANGELOG.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ This is not a comprehensive list of changes but rather a hand-curated collection
88

99
v4.2
1010
====
11-
-
11+
- Add the ActivationCoordinateActuator component, which is a CoordinateActuator with simple activation dynamics (PR #2699).
1212

1313
v4.1
1414
====
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
#ifndef OPENSIM_ACTIVATION_COORDINATE_ACTUATOR_H
2+
#define OPENSIM_ACTIVATION_COORDINATE_ACTUATOR_H
3+
/* -------------------------------------------------------------------------- *
4+
* OpenSim: ActivationCoordinateActuator.h *
5+
* -------------------------------------------------------------------------- *
6+
* The OpenSim API is a toolkit for musculoskeletal modeling and simulation. *
7+
* See http://opensim.stanford.edu and the NOTICE file for more information. *
8+
* OpenSim is developed at Stanford University and supported by the US *
9+
* National Institutes of Health (U54 GM072970, R24 HD065690) and by DARPA *
10+
* through the Warrior Web program. *
11+
* *
12+
* Copyright (c) 2005-2020 Stanford University and the Authors *
13+
* Author(s): Christopher Dembia *
14+
* *
15+
* Licensed under the Apache License, Version 2.0 (the "License"); you may *
16+
* not use this file except in compliance with the License. You may obtain a *
17+
* copy of the License at http://www.apache.org/licenses/LICENSE-2.0. *
18+
* *
19+
* Unless required by applicable law or agreed to in writing, software *
20+
* distributed under the License is distributed on an "AS IS" BASIS, *
21+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
22+
* See the License for the specific language governing permissions and *
23+
* limitations under the License. *
24+
* -------------------------------------------------------------------------- */
25+
26+
#include "osimActuatorsDLL.h"
27+
28+
#include "CoordinateActuator.h"
29+
30+
namespace OpenSim {
31+
32+
/// Similar to CoordinateActuator (simply produces a generalized force) but
33+
/// with first-order linear activation dynamics. This actuator has one state
34+
/// variable, `activation`, with \f$ \dot{a} = (x - a) / \tau \f$, where
35+
/// \f$ a \f$ is activation, \f$ x \f$ is excitation, and \f$ \tau \f$ is the
36+
/// activation time constant (there is no separate deactivation time constant).
37+
/// The statebounds_activation output is used in Moco to set default values for
38+
/// the activation state variable.
39+
/// <b>Default %Property Values</b>
40+
/// @verbatim
41+
/// activation_time_constant: 0.01
42+
/// default_activation: 0.5
43+
/// @endverbatim
44+
class OSIMACTUATORS_API ActivationCoordinateActuator
45+
: public CoordinateActuator {
46+
OpenSim_DECLARE_CONCRETE_OBJECT(ActivationCoordinateActuator,
47+
CoordinateActuator);
48+
public:
49+
OpenSim_DECLARE_PROPERTY(activation_time_constant, double,
50+
"Larger value means activation can change more rapidly "
51+
"(units: seconds; default: 0.01 seconds).");
52+
53+
OpenSim_DECLARE_PROPERTY(default_activation, double,
54+
"Value of activation in the default state returned by initSystem() "
55+
"(default: 0.5).");
56+
57+
OpenSim_DECLARE_OUTPUT(statebounds_activation, SimTK::Vec2,
58+
getBoundsActivation, SimTK::Stage::Model);
59+
60+
ActivationCoordinateActuator() {
61+
constructProperties();
62+
}
63+
64+
/// Provide the coordinate name.
65+
explicit ActivationCoordinateActuator(const std::string& coordinateName)
66+
: ActivationCoordinateActuator() {
67+
if (!coordinateName.empty()) {
68+
set_coordinate(coordinateName);
69+
}
70+
}
71+
72+
/// The lower bound on activation is getMinControl() and the upper bound is
73+
/// getMaxControl().
74+
/// Whether these bounds are enforced is determined by the solver used.
75+
SimTK::Vec2 getBoundsActivation(const SimTK::State&) const {
76+
return SimTK::Vec2(getMinControl(), getMaxControl());
77+
}
78+
79+
protected:
80+
void extendAddToSystem(SimTK::MultibodySystem& system) const override {
81+
Super::extendAddToSystem(system);
82+
addStateVariable("activation", SimTK::Stage::Dynamics);
83+
}
84+
85+
void extendInitStateFromProperties(SimTK::State& s) const override {
86+
Super::extendInitStateFromProperties(s);
87+
setStateVariableValue(s, "activation", get_default_activation());
88+
}
89+
90+
void extendSetPropertiesFromState(const SimTK::State& s) override {
91+
Super::extendSetPropertiesFromState(s);
92+
set_default_activation(getStateVariableValue(s, "activation"));
93+
}
94+
95+
void computeStateVariableDerivatives(const SimTK::State& s) const override {
96+
// No need to do clamping, etc; CoordinateActuator is bidirectional.
97+
const auto& tau = get_activation_time_constant();
98+
const auto& x = getControl(s);
99+
const auto& a = getStateVariableValue(s, "activation");
100+
const SimTK::Real adot = (x - a) / tau;
101+
setStateVariableDerivativeValue(s, "activation", adot);
102+
}
103+
104+
double computeActuation(const SimTK::State& s) const override {
105+
return getStateVariableValue(s, "activation") * getOptimalForce();
106+
}
107+
private:
108+
void constructProperties() {
109+
constructProperty_activation_time_constant(0.010);
110+
constructProperty_default_activation(0.5);
111+
}
112+
};
113+
114+
} // namespace OpenSim
115+
116+
#endif // OPENSIM_ACTIVATION_COORDINATE_ACTUATOR_H

OpenSim/Actuators/RegisterTypes_osimActuators.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "RegisterTypes_osimActuators.h"
2828

2929
#include "CoordinateActuator.h"
30+
#include "ActivationCoordinateActuator.h"
3031
#include "PointActuator.h"
3132
#include "TorqueActuator.h"
3233
#include "BodyActuator.h"
@@ -78,6 +79,7 @@ OSIMACTUATORS_API void RegisterTypes_osimActuators()
7879
try {
7980

8081
Object::registerType( CoordinateActuator() );
82+
Object::registerType( ActivationCoordinateActuator() );
8183
Object::registerType( PointActuator() );
8284
Object::registerType( TorqueActuator() );
8385
Object::registerType( BodyActuator() );

OpenSim/Actuators/Test/testActuators.cpp

+51-2
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@
2828
// 3. testClutchedPathSpring()
2929
// 4. testMcKibbenActuator()
3030
// 5. testActuatorsCombination()
31-
//
31+
// 6. testActivationCoordinateActuator()
32+
//
3233
// Add tests here as Actuators are added to OpenSim
3334
//
3435
//=============================================================================
@@ -55,6 +56,7 @@ void testBodyActuator();
5556
void testClutchedPathSpring();
5657
void testMcKibbenActuator();
5758
void testActuatorsCombination();
59+
void testActivationCoordinateActuator();
5860

5961

6062
int main()
@@ -81,6 +83,10 @@ int main()
8183
catch (const std::exception& e) {
8284
cout << e.what() << endl; failures.push_back("testActuatorsCombination");
8385
}
86+
try { testActivationCoordinateActuator(); }
87+
catch (const std::exception& e) {
88+
cout << e.what() << endl; failures.push_back("testActivationCoordinateActuator");
89+
}
8490
if (!failures.empty()) {
8591
cout << "Done, with failure(s): " << failures << endl;
8692
return 1;
@@ -709,7 +715,7 @@ void testBodyActuator()
709715
//==================================================================================
710716
/**
711717
* This test verifies if using a BodyActuator generates equivalent result in the body
712-
* acceleration compared to when using a combination of PointActuaor, TorqueActuaor
718+
* acceleration compared to when using a combination of PointActuaor, TorqueActuator
713719
* and BodyActuator.
714720
* It therefore also verifies model consistency when user defines and uses a
715721
* combination of these 3 actuators.
@@ -918,3 +924,46 @@ void testActuatorsCombination()
918924
std::cout << " ********** Test Actuator Combination time = ********** " <<
919925
1.e3*(std::clock() - startTime) / CLOCKS_PER_SEC << "ms\n" << endl;
920926
}
927+
928+
// Test de/serialization and numerical integration of
929+
// ActivationCoordinateActautor.
930+
void testActivationCoordinateActuator() {
931+
Model model;
932+
auto* body = new Body("body", 1, SimTK::Vec3(0), SimTK::Inertia(0));
933+
auto* joint = new PinJoint("joint", *body, model.getGround());
934+
joint->updCoordinate().setName("coord");
935+
model.addBody(body);
936+
model.addJoint(joint);
937+
auto* aca = new ActivationCoordinateActuator("coord");
938+
aca->setName("aca");
939+
const double a0 = 0.7;
940+
const double tau = 0.20;
941+
aca->set_default_activation(a0);
942+
aca->set_activation_time_constant(tau);
943+
model.addForce(aca);
944+
model.finalizeFromProperties();
945+
model.finalizeConnections();
946+
model.print("Model_ActivationCoordinateActuator.osim");
947+
948+
Model modelDeserialized("Model_ActivationCoordinateActuator.osim");
949+
ASSERT(model == modelDeserialized);
950+
951+
auto* controller = new PrescribedController();
952+
controller->addActuator(*aca);
953+
const double x = 0.15;
954+
controller->prescribeControlForActuator("aca", new Constant(x));
955+
model.addController(controller);
956+
957+
auto state = model.initSystem();
958+
959+
Manager manager(model);
960+
manager.initialize(state);
961+
const double tf = 0.10;
962+
state = manager.integrate(tf);
963+
964+
const double expectedFinalActivation =
965+
(a0 - x) * exp(-tf / tau) + x;
966+
const double foundFinalActivation =
967+
aca->getStateVariableValue(state, "activation");
968+
ASSERT_EQUAL(expectedFinalActivation, foundFinalActivation, 1e-4);
969+
}

OpenSim/Actuators/osimActuators.h

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
* -------------------------------------------------------------------------- */
2525

2626
#include "CoordinateActuator.h"
27+
#include "ActivationCoordinateActuator.h"
2728
#include "PointActuator.h"
2829
#include "TorqueActuator.h"
2930
#include "BodyActuator.h"

OpenSim/Examples/CMakeLists.txt

+2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ if(BUILD_API_EXAMPLES)
2121
add_subdirectory(ExampleHopperDevice)
2222
add_subdirectory(SymbolicExpressionReporter)
2323
add_subdirectory(DataTable)
24+
add_subdirectory(DataAdapter)
2425

2526
elseif()
2627

@@ -31,6 +32,7 @@ elseif()
3132
add_subdirectory(CustomActuatorExample)
3233
add_subdirectory(MuscleExample)
3334
add_subdirectory(checkEnvironment)
35+
add_subdirectory(DataAdapter)
3436

3537
endif()
3638

OpenSim/Examples/DataAdapter/CMakeLists.txt

+1-7
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,10 @@ set_target_properties(exampleTRCFileAdapter PROPERTIES FOLDER "Examples")
44
file(COPY ${CMAKE_SOURCE_DIR}/OpenSim/Common/Test/dataWithNaNsOfDifferentCases.trc
55
DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
66

7-
add_executable(exampleMOTFileAdapter exampleMOTFileAdapter.cpp)
8-
target_link_libraries(exampleMOTFileAdapter ${Simbody_LIBRARIES} osimCommon)
9-
set_target_properties(exampleMOTFileAdapter PROPERTIES FOLDER "Examples")
10-
file(COPY ${CMAKE_SOURCE_DIR}/OpenSim/Tests/ExampleMain/std_tugOfWar_forces.mot
11-
DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
12-
137
if(WITH_BTK)
148
add_executable(exampleC3DFileAdapter exampleC3DFileAdapter.cpp)
159
target_link_libraries(exampleC3DFileAdapter ${Simbody_LIBRARIES} osimCommon)
1610
set_target_properties(exampleC3DFileAdapter PROPERTIES FOLDER "Examples")
17-
file(COPY ${CMAKE_SOURCE_DIR}/OpenSim/Tests/shared/singleLeglanding_2.c3d
11+
file(COPY ${CMAKE_SOURCE_DIR}/OpenSim/Tests/shared/walking2.c3d
1812
DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
1913
endif()

OpenSim/Examples/DataAdapter/exampleC3DFileAdapter.cpp

+4-4
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* National Institutes of Health (U54 GM072970, R24 HD065690) and by DARPA *
88
* through the Warrior Web program. *
99
* *
10-
* Copyright (c) 2005-2017 Stanford University and the Authors *
10+
* Copyright (c) 2005-2020 Stanford University and the Authors *
1111
* *
1212
* Licensed under the Apache License, Version 2.0 (the "License"); you may *
1313
* not use this file except in compliance with the License. You may obtain a *
@@ -32,13 +32,13 @@
3232
int main() {
3333
using namespace OpenSim;
3434

35-
std::string filename{"OpenSim/Examples/DataAdapter/singleLeglanding_2.c3d"};
35+
std::string filename{"walking2.c3d"};
3636

3737
C3DFileAdapter c3d_adapter{};
3838
auto tables = c3d_adapter.read(filename);
3939

40-
auto& marker_table = tables.at("markers");
41-
auto& force_table = tables.at("forces");
40+
auto marker_table = c3d_adapter.getMarkersTable(tables);
41+
auto force_table = c3d_adapter.getForcesTable(tables);
4242

4343
if(marker_table->getNumRows() != 0) {
4444
std::cout << "--------------Markers-----------------" << std::endl;

0 commit comments

Comments
 (0)