Skip to content
This repository was archived by the owner on Apr 10, 2025. It is now read-only.

Commit c305700

Browse files
authored
Merge branch 'master' into prep-release-0.2.0
2 parents e8fec2a + ca220db commit c305700

16 files changed

+315
-22
lines changed

CHANGELOG.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
0.2.0
22
=====
3+
- 2019-12-12: Added MocoFrameDistanceConstraint.
34

45
- 2019-12-11: Add MocoOutputGoal, allowing any scalar model output to be used as
56
as a goal.
@@ -41,16 +42,16 @@
4142
"iterate".
4243

4344
- 2019-11-25: Update SmoothSphereHalfSpaceForce to visualize contact forces in
44-
the Simbody visualizer (not the OpenSim GUI).
45+
the Simbody visualizer (not the OpenSim GUI).
4546

46-
- 2019-11-22: Introduce TabOpUseAbsoluteStateNames to convert column labels
47-
from IK solutions pre-4.0 states files to use new-style column
48-
labels.
47+
- 2019-11-22: Introduce TabOpUseAbsoluteStateNames to convert column labels
48+
from IK solutions pre-4.0 states files to use new-style column
49+
labels.
4950

5051
- 2019-11-20: Added MocoAngularVelocityTrackingGoal and
5152
MocoAccelerationTrackingGoal in anticipation of supporting
5253
applications using IMU data in the future.
53-
54+
5455
- 2019-11-18: Updates to report.py linewidth and legend formatting.
5556

5657
- 2019-11-18: Exporting controls to TimeSeriesTable via

Moco/Bindings/OpenSimHeaders_moco.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include <Moco/MocoBounds.h>
1515
#include <Moco/MocoCasADiSolver/MocoCasADiSolver.h>
1616
#include <Moco/MocoControlBoundConstraint.h>
17+
#include <Moco/MocoFrameDistanceConstraint.h>
1718
#include <Moco/MocoGoal/MocoControlGoal.h>
1819
#include <Moco/MocoGoal/MocoGoal.h>
1920
#include <Moco/MocoGoal/MocoInitialActivationGoal.h>

Moco/Bindings/moco.i

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ namespace OpenSim {
5858
%include <Moco/MocoConstraint.h>
5959

6060
%include <Moco/MocoControlBoundConstraint.h>
61+
%include <Moco/MocoFrameDistanceConstraint.h>
6162

6263
// unique_ptr
6364
// ----------
@@ -221,4 +222,4 @@ moco_unique_ptr(OpenSim::PositionMotion);
221222
%include <Moco/Components/SmoothSphereHalfSpaceForce.h>
222223
%include <Moco/Components/MultivariatePolynomialFunction.h>
223224

224-
%include <Moco/ModelOperators.h>
225+
%include <Moco/ModelOperators.h>

Moco/Moco/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ set(MOCO_SOURCES
6868
MocoConstraint.cpp
6969
MocoControlBoundConstraint.cpp
7070
MocoControlBoundConstraint.h
71+
MocoFrameDistanceConstraint.h
72+
MocoFrameDistanceConstraint.cpp
7173
Components/DeGrooteFregly2016Muscle.h
7274
Components/DeGrooteFregly2016Muscle.cpp
7375
Components/SmoothSphereHalfSpaceForce.h

Moco/Moco/Components/ModelFactory.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,8 @@ Model ModelFactory::createPlanarPointMass() {
105105
model.addJoint(jointX);
106106

107107
// The joint's x axis must point in the global "+y" direction.
108-
auto* jointY = new SliderJoint("ty",
109-
*intermed, Vec3(0), Vec3(0, 0, 0.5 * SimTK::Pi),
108+
auto* jointY = new SliderJoint("ty",
109+
*intermed, Vec3(0), Vec3(0, 0, 0.5 * SimTK::Pi),
110110
*body, Vec3(0), Vec3(0, 0, .5 * SimTK::Pi));
111111
auto& coordY = jointY->updCoordinate(SliderJoint::Coord::TranslationX);
112112
coordY.setName("ty");

Moco/Moco/MocoConstraint.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,6 @@ enum class KinematicLevel {
5959
/// Objects of this class can only be instantiated by a MocoPhase, since
6060
/// information from each constraint in the model is required to ensure that
6161
/// the correct values are assigned to internal variables during construction.
62-
/// @ingroup mococonstraint
6362
class OSIMMOCO_API MocoKinematicConstraint {
6463
public:
6564
const MocoConstraintInfo& getConstraintInfo() const {
@@ -146,7 +145,7 @@ class OSIMMOCO_API MocoKinematicConstraint {
146145
/// Therefore, there is no need to clear cache variables that you create in
147146
/// initializeImpl(). Also, information stored in this constraint does not
148147
/// persist across multiple solves.
149-
/// @ingroup mococonstraint
148+
/// @ingroup mocopathcon
150149
class OSIMMOCO_API MocoPathConstraint : public Object {
151150
OpenSim_DECLARE_ABSTRACT_OBJECT(MocoPathConstraint, Object);
152151

Moco/Moco/MocoControlBoundConstraint.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ class MocoProblemInfo;
3838
/// constrain any control signals, even if you have provided control paths.
3939
///
4040
/// @note This class can only constrain control signals for ScalarActuator%s.
41+
/// @ingroup mocopathcon
4142
class OSIMMOCO_API MocoControlBoundConstraint : public MocoPathConstraint {
4243
OpenSim_DECLARE_CONCRETE_OBJECT(
4344
MocoControlBoundConstraint, MocoPathConstraint);
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
/* -------------------------------------------------------------------------- *
2+
* OpenSim Moco: MocoFrameDistanceConstraint.cpp *
3+
* -------------------------------------------------------------------------- *
4+
* Copyright (c) 2019 Stanford University and the Authors *
5+
* *
6+
* Author(s): Nicholas Bianco *
7+
* *
8+
* Licensed under the Apache License, Version 2.0 (the "License"); you may *
9+
* not use this file except in compliance with the License. You may obtain a *
10+
* copy of the License at http://www.apache.org/licenses/LICENSE-2.0 *
11+
* *
12+
* Unless required by applicable law or agreed to in writing, software *
13+
* distributed under the License is distributed on an "AS IS" BASIS, *
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
15+
* See the License for the specific language governing permissions and *
16+
* limitations under the License. *
17+
* -------------------------------------------------------------------------- */
18+
19+
#include "MocoFrameDistanceConstraint.h"
20+
21+
using namespace OpenSim;
22+
23+
//=============================================================================
24+
// MocoFrameDistanceConstraintPair
25+
//=============================================================================
26+
27+
MocoFrameDistanceConstraintPair::MocoFrameDistanceConstraintPair() {
28+
constructProperties();
29+
}
30+
31+
MocoFrameDistanceConstraintPair::MocoFrameDistanceConstraintPair(
32+
std::string frame1Path, std::string frame2Path,
33+
double minimum_distance, double maximum_distance) {
34+
constructProperties();
35+
set_frame1_path(frame1Path);
36+
set_frame2_path(frame2Path);
37+
set_minimum_distance(minimum_distance);
38+
set_maximum_distance(maximum_distance);
39+
}
40+
41+
void MocoFrameDistanceConstraintPair::constructProperties() {
42+
constructProperty_frame1_path("");
43+
constructProperty_frame2_path("");
44+
constructProperty_minimum_distance(0);
45+
constructProperty_maximum_distance(SimTK::Infinity);
46+
}
47+
48+
//=============================================================================
49+
// MocoFrameDistanceConstraint
50+
//=============================================================================
51+
52+
MocoFrameDistanceConstraint::MocoFrameDistanceConstraint(){
53+
constructProperties();
54+
}
55+
56+
void MocoFrameDistanceConstraint::initializeOnModelImpl(
57+
const Model& model, const MocoProblemInfo&) const {
58+
int nFramePairs = getProperty_frame_pairs().size();
59+
60+
// TODO: setConstraintInfo() is not really intended for use here.
61+
MocoConstraintInfo info;
62+
std::vector<MocoBounds> bounds;
63+
for (int i = 0; i < nFramePairs; ++i) {
64+
const auto frame1_path = get_frame_pairs(i).get_frame1_path();
65+
OPENSIM_THROW_IF(!model.hasComponent<Frame>(frame1_path), Exception,
66+
format("Could not find frame '%s'.", frame1_path));
67+
auto& frame1 = model.getComponent<Frame>(frame1_path);
68+
const auto frame2_path = get_frame_pairs(i).get_frame2_path();
69+
OPENSIM_THROW_IF(!model.hasComponent<Frame>(frame2_path), Exception,
70+
format("Could not find frame '%s'.", frame2_path));
71+
auto& frame2 = model.getComponent<Frame>(frame2_path);
72+
m_frame_pairs.emplace_back(&frame1, &frame2);
73+
74+
const double& minimum = get_frame_pairs(i).get_minimum_distance();
75+
const double& maximum = get_frame_pairs(i).get_maximum_distance();
76+
OPENSIM_THROW_IF(minimum < 0, Exception,
77+
format("Expected the minimum distance for this frame pair to "
78+
"non-negative, but it is %d.", minimum));
79+
OPENSIM_THROW_IF(maximum < 0, Exception,
80+
format("Expected the maximum distance for this frame pair to "
81+
"non-negative, but it is %d.", maximum));
82+
OPENSIM_THROW_IF(minimum > maximum, Exception,
83+
format("Expected the minimum distance for this frame pair to "
84+
"be less than or equal to the maximum distance, but "
85+
"they are %d and %d, respectively.", minimum, maximum));
86+
bounds.emplace_back(SimTK::square(minimum), SimTK::square(maximum));
87+
}
88+
89+
setNumEquations(nFramePairs);
90+
info.setBounds(bounds);
91+
const_cast<MocoFrameDistanceConstraint*>(this)->setConstraintInfo(info);
92+
}
93+
94+
void MocoFrameDistanceConstraint::calcPathConstraintErrorsImpl(
95+
const SimTK::State& state, SimTK::Vector& errors) const {
96+
getModel().realizePosition(state);
97+
int iconstr = 0;
98+
SimTK::Vec3 relative_position;
99+
for (const auto& frame_pair : m_frame_pairs) {
100+
const auto& frame1_pos = frame_pair.first->getPositionInGround(state);
101+
const auto& frame2_pos = frame_pair.second->getPositionInGround(state);
102+
relative_position = frame2_pos - frame1_pos;
103+
errors[iconstr++] = relative_position.normSqr();
104+
}
105+
}
106+
107+
void MocoFrameDistanceConstraint::constructProperties() {
108+
constructProperty_frame_pairs();
109+
}
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
#ifndef MOCO_MOCOFRAMEDISTANCECONSTRAINT_H
2+
#define MOCO_MOCOFRAMEDISTANCECONSTRAINT_H
3+
/* -------------------------------------------------------------------------- *
4+
* OpenSim Moco: MocoFrameDistanceConstraint.h *
5+
* -------------------------------------------------------------------------- *
6+
* Copyright (c) 2019 Stanford University and the Authors *
7+
* *
8+
* Author(s): Nicholas Bianco *
9+
* *
10+
* Licensed under the Apache License, Version 2.0 (the "License"); you may *
11+
* not use this file except in compliance with the License. You may obtain a *
12+
* copy of the License at http://www.apache.org/licenses/LICENSE-2.0 *
13+
* *
14+
* Unless required by applicable law or agreed to in writing, software *
15+
* distributed under the License is distributed on an "AS IS" BASIS, *
16+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
17+
* See the License for the specific language governing permissions and *
18+
* limitations under the License. *
19+
* -------------------------------------------------------------------------- */
20+
21+
#include "MocoConstraint.h"
22+
#include "osimMocoDLL.h"
23+
24+
namespace OpenSim {
25+
26+
class OSIMMOCO_API MocoFrameDistanceConstraintPair : public Object {
27+
OpenSim_DECLARE_CONCRETE_OBJECT(MocoFrameDistanceConstraintPair, Object);
28+
29+
public:
30+
OpenSim_DECLARE_PROPERTY(frame1_path, std::string,
31+
"The first model frame path of the pair.");
32+
OpenSim_DECLARE_PROPERTY(frame2_path, std::string,
33+
"The second model frame path of the pair.");
34+
OpenSim_DECLARE_PROPERTY(minimum_distance, double,
35+
"The minimum distance apart that the two frame origins can be.");
36+
OpenSim_DECLARE_PROPERTY(maximum_distance, double,
37+
"The maximum distance apart that the two frame origins can be.")
38+
39+
MocoFrameDistanceConstraintPair();
40+
MocoFrameDistanceConstraintPair(std::string firstFramePath,
41+
std::string secondFramePath, double minimum_distance,
42+
double maximum_distance);
43+
44+
private:
45+
void constructProperties();
46+
};
47+
48+
/// This path constraint enforces that the distance between the origins of pairs
49+
/// of model frames is kept between minimum and maximum bounds. Frame pairs and
50+
/// their bounds are specified via a MocoFrameDistancConstraintPair.
51+
/// Any model component derived from Frame is valid to be included in a frame
52+
/// pair, and any number of frame pairs may be append to this constraint via
53+
/// addFramePair().
54+
///
55+
/// This constraint can be used as a simple method for preventing bodies in your
56+
/// model from intersecting during an optimization. For example, the
57+
/// following prevents feet from intersecting during a walking optimization:
58+
/// @code
59+
/// distance = problem.addPathConstraint<MocoFrameDistanceConstraint>();
60+
/// distance.setName("minimum_distance");
61+
/// SimTK::Real inf = SimTK::Infinity;
62+
/// distance.addFramePair('/bodyset/calcn_l', '/bodyset/calcn_r', 0.1, inf);
63+
/// distance.addFramePair('/bodyset/toes_l', '/bodyset/toes_r', 0.1, inf);
64+
/// distance.addFramePair('/bodyset/calcn_l', '/bodyset/toes_r', 0.1, inf);
65+
/// distance.addFramePair('/bodyset/toes_l', '/bodyset/calcn_r', 0.1, inf);
66+
/// @endcode
67+
///
68+
/// @note This class represents a path constraint, *not* a model kinematic
69+
/// constraint. Therefore, there are no Lagrange multipliers or constraint
70+
/// forces associated with this constraint. The model's force elements
71+
/// (including actuators) must generate the forces necessary for satisfying this
72+
/// constraint.
73+
///
74+
/// @ingroup mocopathcon
75+
class OSIMMOCO_API MocoFrameDistanceConstraint : public MocoPathConstraint {
76+
OpenSim_DECLARE_CONCRETE_OBJECT(
77+
MocoFrameDistanceConstraint, MocoPathConstraint);
78+
79+
public:
80+
MocoFrameDistanceConstraint();
81+
82+
void addFramePair(MocoFrameDistanceConstraintPair pair) {
83+
append_frame_pairs(std::move(pair));
84+
}
85+
void addFramePair(const std::string& frame1_path,
86+
const std::string& frame2_path, double minimum_distance,
87+
double maximum_distance) {
88+
append_frame_pairs(MocoFrameDistanceConstraintPair(frame1_path,
89+
frame2_path, minimum_distance, maximum_distance));
90+
}
91+
92+
protected:
93+
void initializeOnModelImpl(
94+
const Model& model, const MocoProblemInfo&) const override;
95+
void calcPathConstraintErrorsImpl(
96+
const SimTK::State& state, SimTK::Vector& errors) const override;
97+
98+
private:
99+
OpenSim_DECLARE_LIST_PROPERTY(frame_pairs,
100+
MocoFrameDistanceConstraintPair,
101+
"Pairs of frames whose origins are constrained to be within minimum "
102+
"and maximum bounds.");
103+
104+
void constructProperties();
105+
mutable std::vector<std::pair<SimTK::ReferencePtr<const Frame>,
106+
SimTK::ReferencePtr<const Frame>>> m_frame_pairs;
107+
};
108+
109+
} // namespace OpenSim
110+
111+
#endif // MOCO_MOCOFRAMEDISTANCECONSTRAINT_H

Moco/Moco/MocoGoal/MocoPeriodicityGoal.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,8 @@ class OSIMMOCO_API MocoPeriodicityGoal : public MocoGoal {
101101
OpenSim_DECLARE_CONCRETE_OBJECT(MocoPeriodicityGoal, MocoGoal);
102102

103103
public:
104-
OpenSim_DECLARE_LIST_PROPERTY(
105-
state_pairs, MocoPeriodicityGoalPair, "Periodic pairs of states.");
104+
OpenSim_DECLARE_LIST_PROPERTY(state_pairs, MocoPeriodicityGoalPair,
105+
"Periodic pairs of states.");
106106
OpenSim_DECLARE_LIST_PROPERTY(control_pairs, MocoPeriodicityGoalPair,
107107
"Periodic pairs of controls.");
108108

0 commit comments

Comments
 (0)