1 /* -------------------------------------------------------------------------- *
2  *                         OpenSim:  BushingForce.cpp                         *
3  * -------------------------------------------------------------------------- *
4  * The OpenSim API is a toolkit for musculoskeletal modeling and simulation.  *
5  * See http://opensim.stanford.edu and the NOTICE file for more information.  *
6  * OpenSim is developed at Stanford University and supported by the US        *
7  * National Institutes of Health (U54 GM072970, R24 HD065690) and by DARPA    *
8  * through the Warrior Web program.                                           *
9  *                                                                            *
10  * Copyright (c) 2005-2017 Stanford University and the Authors                *
11  * Author(s): Ajay Seth                                                       *
12  *                                                                            *
13  * Licensed under the Apache License, Version 2.0 (the "License"); you may    *
14  * not use this file except in compliance with the License. You may obtain a  *
15  * copy of the License at http://www.apache.org/licenses/LICENSE-2.0.         *
16  *                                                                            *
17  * Unless required by applicable law or agreed to in writing, software        *
18  * distributed under the License is distributed on an "AS IS" BASIS,          *
19  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   *
20  * See the License for the specific language governing permissions and        *
21  * limitations under the License.                                             *
22  * -------------------------------------------------------------------------- */
23 
24 //=============================================================================
25 // INCLUDES
26 //=============================================================================
27 #include <OpenSim/Simulation/Model/Model.h>
28 #include "simbody/internal/Force_LinearBushing.h"
29 
30 #include "BushingForce.h"
31 
32 using namespace std;
33 using namespace SimTK;
34 using namespace OpenSim;
35 
36 //=============================================================================
37 // CONSTRUCTOR(S) AND DESTRUCTOR
38 //=============================================================================
39 // Uses default (compiler-generated) destructor, copy constructor, and copy
40 // assignment operator.
41 
42 //_____________________________________________________________________________
43 // Default constructor.
BushingForce()44 BushingForce::BushingForce() : TwoFrameLinker<Force, PhysicalFrame>()
45 {
46     setNull();
47     constructProperties();
48 }
49 
BushingForce(const std::string & name,const PhysicalFrame & frame1,const PhysicalFrame & frame2)50 BushingForce::BushingForce(const std::string& name,
51                            const PhysicalFrame& frame1,
52                            const PhysicalFrame& frame2)
53     : Super(name, frame1, frame2)
54 {
55     setNull();
56     constructProperties();
57 }
58 
BushingForce(const std::string & name,const std::string & frame1Name,const std::string & frame2Name)59 BushingForce::BushingForce( const std::string& name,
60                             const std::string& frame1Name,
61                             const std::string& frame2Name)
62     : Super(name, frame1Name, frame2Name)
63 {
64     setNull();
65     constructProperties();
66 }
67 
BushingForce(const std::string & name,const PhysicalFrame & frame1,const PhysicalFrame & frame2,const SimTK::Vec3 & transStiffness,const SimTK::Vec3 & rotStiffness,const SimTK::Vec3 & transDamping,const SimTK::Vec3 & rotDamping)68 BushingForce::BushingForce(const std::string& name,
69                            const PhysicalFrame& frame1,
70                            const PhysicalFrame& frame2,
71                            const SimTK::Vec3& transStiffness,
72                            const SimTK::Vec3& rotStiffness,
73                            const SimTK::Vec3& transDamping,
74                            const SimTK::Vec3& rotDamping)
75         : BushingForce(name, frame1, frame2)
76 {
77     set_rotational_stiffness(rotStiffness);
78     set_translational_stiffness(transStiffness);
79     set_rotational_damping(rotDamping);
80     set_translational_damping(transDamping);
81 }
82 
BushingForce(const std::string & name,const std::string & frame1Name,const std::string & frame2Name,const SimTK::Vec3 & transStiffness,const SimTK::Vec3 & rotStiffness,const SimTK::Vec3 & transDamping,const SimTK::Vec3 & rotDamping)83 BushingForce::BushingForce( const std::string &name,
84                             const std::string& frame1Name,
85                             const std::string& frame2Name,
86                             const SimTK::Vec3& transStiffness,
87                             const SimTK::Vec3& rotStiffness,
88                             const SimTK::Vec3& transDamping,
89                             const SimTK::Vec3& rotDamping )
90     : BushingForce(name, frame1Name, frame2Name)
91 {
92     set_rotational_stiffness(rotStiffness);
93     set_translational_stiffness(transStiffness);
94     set_rotational_damping(rotDamping);
95     set_translational_damping(transDamping);
96 }
97 
BushingForce(const std::string & name,const PhysicalFrame & frame1,const SimTK::Transform & transformInFrame1,const PhysicalFrame & frame2,const SimTK::Transform & transformInFrame2,const SimTK::Vec3 & transStiffness,const SimTK::Vec3 & rotStiffness,const SimTK::Vec3 & transDamping,const SimTK::Vec3 & rotDamping)98 BushingForce::BushingForce(const std::string& name, const PhysicalFrame& frame1,
99                            const SimTK::Transform& transformInFrame1,
100                            const PhysicalFrame& frame2,
101                            const SimTK::Transform& transformInFrame2,
102                            const SimTK::Vec3& transStiffness,
103                            const SimTK::Vec3& rotStiffness,
104                            const SimTK::Vec3& transDamping,
105                            const SimTK::Vec3& rotDamping)
106     : Super(name, frame1, transformInFrame1, frame2, transformInFrame2)
107 {
108     setNull();
109     constructProperties();
110     set_rotational_stiffness(rotStiffness);
111     set_translational_stiffness(transStiffness);
112     set_rotational_damping(rotDamping);
113     set_translational_damping(transDamping);
114 }
115 
BushingForce(const std::string & name,const std::string & frame1Name,const SimTK::Transform & transformInFrame1,const std::string & frame2Name,const SimTK::Transform & transformInFrame2,const SimTK::Vec3 & transStiffness,const SimTK::Vec3 & rotStiffness,const SimTK::Vec3 & transDamping,const SimTK::Vec3 & rotDamping)116 BushingForce::BushingForce(const std::string& name,
117     const std::string& frame1Name, const SimTK::Transform& transformInFrame1,
118     const std::string& frame2Name, const SimTK::Transform& transformInFrame2,
119     const SimTK::Vec3& transStiffness,
120     const SimTK::Vec3& rotStiffness,
121     const SimTK::Vec3& transDamping,
122     const SimTK::Vec3& rotDamping)
123     : Super(name,frame1Name, transformInFrame1, frame2Name, transformInFrame2)
124 {
125     setNull();
126     constructProperties();
127     set_rotational_stiffness(rotStiffness);
128     set_translational_stiffness(transStiffness);
129     set_rotational_damping(rotDamping);
130     set_translational_damping(transDamping);
131 }
132 
BushingForce(const std::string & name,const std::string & frame1Name,const SimTK::Vec3 & locationInFrame1,const SimTK::Vec3 & orientationInFrame1,const std::string & frame2Name,const SimTK::Vec3 & locationInFrame2,const SimTK::Vec3 & orientationInFrame2,const SimTK::Vec3 & transStiffness,const SimTK::Vec3 & rotStiffness,const SimTK::Vec3 & transDamping,const SimTK::Vec3 & rotDamping)133 BushingForce::BushingForce(const std::string& name,
134     const std::string& frame1Name,
135     const SimTK::Vec3& locationInFrame1, const SimTK::Vec3& orientationInFrame1,
136     const std::string& frame2Name,
137     const SimTK::Vec3& locationInFrame2, const SimTK::Vec3& orientationInFrame2,
138     const SimTK::Vec3& transStiffness,
139     const SimTK::Vec3& rotStiffness,
140     const SimTK::Vec3& transDamping,
141     const SimTK::Vec3& rotDamping)
142     : TwoFrameLinker<Force, PhysicalFrame>(name,
143         frame1Name, locationInFrame1, orientationInFrame1,
144         frame2Name, locationInFrame2, orientationInFrame1)
145 {
146     setNull();
147     constructProperties();
148     set_rotational_stiffness(rotStiffness);
149     set_translational_stiffness(transStiffness);
150     set_rotational_damping(rotDamping);
151     set_translational_damping(transDamping);
152 }
153 
154 //_____________________________________________________________________________
155 // Set the data members of this BushingForce to their null values.
setNull()156 void BushingForce::setNull()
157 {
158     setAuthors("Ajay Seth");
159 }
160 
161 //_____________________________________________________________________________
162 // Allocate and initialize properties.
constructProperties()163 void BushingForce::constructProperties()
164 {
165     // default bushing material properties
166     constructProperty_rotational_stiffness(Vec3(0));
167     constructProperty_translational_stiffness(Vec3(0));
168     constructProperty_rotational_damping(Vec3(0));
169     constructProperty_translational_damping(Vec3(0));
170 }
171 
172 // Add underly Simbody elements to the System after subcomponents
173 void BushingForce::
extendAddToSystemAfterSubcomponents(SimTK::MultibodySystem & system) const174     extendAddToSystemAfterSubcomponents(SimTK::MultibodySystem& system) const
175 {
176     Super::extendAddToSystemAfterSubcomponents(system);
177 
178     const SimTK::Vec3& rotStiffness   = get_rotational_stiffness();
179     const SimTK::Vec3& transStiffness = get_translational_stiffness();
180     const SimTK::Vec3& rotDamping     = get_rotational_damping();
181     const SimTK::Vec3& transDamping   = get_translational_damping();
182 
183     // get connected frames
184     const PhysicalFrame& frame1 = getFrame1();
185     const PhysicalFrame& frame2 = getFrame2();
186 
187     // Get underlying mobilized bodies
188     const SimTK::MobilizedBody& b1 = frame1.getMobilizedBody();
189     const SimTK::MobilizedBody& b2 = frame2.getMobilizedBody();
190 
191     Vec6 stiffness(rotStiffness[0], rotStiffness[1], rotStiffness[2],
192                    transStiffness[0], transStiffness[1], transStiffness[2]);
193     Vec6 damping(rotDamping[0], rotDamping[1], rotDamping[2],
194                  transDamping[0], transDamping[1], transDamping[2]);
195 
196     // Now create a Simbody Force::LinearBushing
197     SimTK::Force::LinearBushing simtkForce
198         (_model->updForceSubsystem(), b1, frame1.findTransformInBaseFrame(),
199                                       b2, frame2.findTransformInBaseFrame(),
200                                       stiffness, damping );
201 
202     // Beyond the const Component get the index so we can access the
203     // SimTK::Force later.
204     BushingForce* mutableThis = const_cast<BushingForce *>(this);
205     mutableThis->_index = simtkForce.getForceIndex();
206 }
207 
208 //=============================================================================
209 // SET
210 //=============================================================================
211 //_____________________________________________________________________________
212 // The following methods set properties of the bushing Force.
213 
214 
215 /* Potential energy is computed by underlying SimTK::Force. */
computePotentialEnergy(const SimTK::State & s) const216 double BushingForce::computePotentialEnergy(const SimTK::State& s) const
217 {
218     return _model->getForceSubsystem().getForce(_index)
219                                       .calcPotentialEnergyContribution(s);
220 }
221 
222 //=============================================================================
223 // Reporting
224 //=============================================================================
225 /*
226  * Provide names of the quantities (column labels) of the force value(s) to be
227  * reported.
228  */
getRecordLabels() const229 OpenSim::Array<std::string> BushingForce::getRecordLabels() const
230 {
231     const string& frame1Name = getFrame1().getName();
232     const string& frame2Name = getFrame2().getName();
233 
234     OpenSim::Array<std::string> labels("");
235     labels.append(getName()+"."+frame1Name+".force.X");
236     labels.append(getName()+"."+frame1Name+".force.Y");
237     labels.append(getName()+"."+frame1Name+".force.Z");
238     labels.append(getName()+"."+frame1Name+".torque.X");
239     labels.append(getName()+"."+frame1Name+".torque.Y");
240     labels.append(getName()+"."+frame1Name+".torque.Z");
241     labels.append(getName()+"."+frame2Name+".force.X");
242     labels.append(getName()+"."+frame2Name+".force.Y");
243     labels.append(getName()+"."+frame2Name+".force.Z");
244     labels.append(getName()+"."+frame2Name+".torque.X");
245     labels.append(getName()+"."+frame2Name+".torque.Y");
246     labels.append(getName()+"."+frame2Name+".torque.Z");
247 
248     return labels;
249 }
250 /*
251  * Provide the value(s) to be reported that correspond to the labels
252  */
253 OpenSim::Array<double> BushingForce::
getRecordValues(const SimTK::State & state) const254 getRecordValues(const SimTK::State& state) const
255 {
256     const PhysicalFrame& frame1 = getFrame1();
257     const PhysicalFrame& frame2 = getFrame2();
258 
259     //const string& frame1Name = frame1.getName();
260     //const string& frame2Name = frame2.getName();
261 
262     OpenSim::Array<double> values(1);
263 
264     const SimTK::Force::LinearBushing &simtkSpring =
265         (SimTK::Force::LinearBushing &)(_model->getForceSubsystem().getForce(_index));
266 
267     SimTK::Vector_<SimTK::SpatialVec> bodyForces(0);
268     SimTK::Vector_<SimTK::Vec3> particleForces(0);
269     SimTK::Vector mobilityForces(0);
270 
271     //get the net force added to the system contributed by the bushing
272     simtkSpring.calcForceContribution(state, bodyForces, particleForces, mobilityForces);
273     SimTK::Vec3 forces = bodyForces[frame1.getMobilizedBodyIndex()][1];
274     SimTK::Vec3 torques = bodyForces[frame1.getMobilizedBodyIndex()][0];
275     values.append(3, &forces[0]);
276     values.append(3, &torques[0]);
277 
278     forces = bodyForces[frame2.getMobilizedBodyIndex()][1];
279     torques = bodyForces[frame2.getMobilizedBodyIndex()][0];
280 
281     values.append(3, &forces[0]);
282     values.append(3, &torques[0]);
283 
284     return values;
285 }
286