1 #ifndef SimTK_SIMBODY_FORCE_H_
2 #define SimTK_SIMBODY_FORCE_H_
3 
4 /* -------------------------------------------------------------------------- *
5  *                               Simbody(tm)                                  *
6  * -------------------------------------------------------------------------- *
7  * This is part of the SimTK biosimulation toolkit originating from           *
8  * Simbios, the NIH National Center for Physics-Based Simulation of           *
9  * Biological Structures at Stanford, funded under the NIH Roadmap for        *
10  * Medical Research, grant U54 GM072970. See https://simtk.org/home/simbody.  *
11  *                                                                            *
12  * Portions copyright (c) 2008-13 Stanford University and the Authors.        *
13  * Authors: Peter Eastman, Michael Sherman                                    *
14  * Contributors:                                                              *
15  *                                                                            *
16  * Licensed under the Apache License, Version 2.0 (the "License"); you may    *
17  * not use this file except in compliance with the License. You may obtain a  *
18  * copy of the License at http://www.apache.org/licenses/LICENSE-2.0.         *
19  *                                                                            *
20  * Unless required by applicable law or agreed to in writing, software        *
21  * distributed under the License is distributed on an "AS IS" BASIS,          *
22  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   *
23  * See the License for the specific language governing permissions and        *
24  * limitations under the License.                                             *
25  * -------------------------------------------------------------------------- */
26 
27 #include "SimTKcommon.h"
28 #include "simbody/internal/common.h"
29 #include "simbody/internal/GeneralForceSubsystem.h"
30 
31 namespace SimTK {
32 
33 class SimbodyMatterSubsystem;
34 class GeneralForceSubsystem;
35 class MobilizedBody;
36 class Force;
37 class ForceImpl;
38 
39 // We only want the template instantiation to occur once. This symbol is defined
40 // in the SimTK core compilation unit that defines the Force class but should
41 // not be defined any other time.
42 #ifndef SimTK_SIMBODY_DEFINING_FORCE
43     extern template class PIMPLHandle<Force, ForceImpl, true>;
44 #endif
45 
46 /** This is the base class from which all Force element handle classes derive.
47 A Force object applies forces to some or all of the bodies, particles, and
48 mobilities in a System. There are subclasses for various standard types of
49 forces, or you can create your own forces by deriving from Force::Custom. **/
50 class SimTK_SIMBODY_EXPORT Force : public PIMPLHandle<Force, ForceImpl, true> {
51 public:
52     /**@name                   Enabling and disabling
53     These methods determine whether this force element is active in a given
54     State. When disabled, the Force element is completely ignored and will
55     not be updated during realization. Normally force elements are enabled
56     when defined unless explicitly disabled; you can reverse that using the
57     setDisabledByDefault() method below. **/
58     /*@{*/
59     /** Disable this force element, effectively removing it from the System
60     for computational purposes (it is still using its ForceIndex, however).
61     This is an Instance-stage change. **/
62     void disable(State&) const;
63     /** Enable this force element if it was previously disabled. This is an
64     Instance-stage change. Nothing happens if the force element was already
65     enabled. **/
66     void enable(State&) const;
67     /** Test whether this force element is currently disabled in the supplied
68     State. If it is disabled you cannot depend on any computations it
69     normally performs being available. **/
70     bool isDisabled(const State&) const;
71     /** Normally force elements are enabled when defined and can be disabled
72     later. If you want to define this force element but have it be off by
73     default, use this method. Note that this is a Topology-stage (construction)
74     change; you will have to call realizeTopology() before using the containing
75     System after a change to this setting has been made. **/
76     void setDisabledByDefault(bool shouldBeDisabled);
77     /** Test whether this force element is disabled by default in which case it
78     must be explicitly enabled before it will take effect.
79     @see enable() **/
80     bool isDisabledByDefault() const;
81     /*@}*/
82 
83     /**@name                   Advanced methods
84     Don't use these unless you're sure you know what you're doing. They aren't
85     normally necessary but can be handy sometimes, especially when debugging
86     newly-developed force elements. **/
87     /*@{*/
88     /** Calculate the force that would be applied by this force element if
89     the given \a state were realized to Dynamics stage. This sizes the given
90     arrays if necessary, zeroes them, and then calls the force element's
91     calcForce() method which adds its force contributions if any to the
92     appropriate array elements for bodies, particles, and mobilities. Note that
93     in general we have no idea what elements of the system are affected by a
94     force element, and in fact that can change based on state and time (consider
95     contact forces, for example). A disabled force element will return all
96     zeroes without invoking calcForce(), since that method may depend on
97     earlier computations which may not have been performed in that case.
98     @param[in]      state
99         The State containing information to be used by the force element to
100         calculate the current force. This must have already been realized to
101         a high enough stage for the force element to get what it needs; if you
102         don't know then realize it to Stage::Velocity.
103     @param[out]     bodyForces
104         This is a Vector of spatial forces, one per mobilized body in the
105         matter subsystem associated with this force element. This Vector is
106         indexed by MobilizedBodyIndex so it has a 0th entry corresponding
107         to Ground. A spatial force contains two Vec3's; index with [0] to get
108         the moment vector, with [1] to get the force vector. This argument is
109         resized if necessary to match the number of mobilized bodies and any
110         unused entry will be set to zero on return.
111     @param[out]     particleForces
112         This is a Vector of force vectors, one per particle in the
113         matter subsystem associated with this force element. This vector is
114         indexed by ParticleIndex; the 0th entry is the 1st particle, not Ground.
115         This argument is resized if necessary to match the number of particles
116         and any unused entry will be set to zero on return. (As of March 2010
117         Simbody treats particles as mobilized bodies so this is unused.)
118     @param[out]     mobilityForces
119         This is a Vector of scalar generalized forces, one per mobility in
120         the matter subsystem associated with this force element. This is the
121         same as the number of generalized speeds u that collectively represent
122         all the mobilities of the mobilizers. To determine the per-mobilizer
123         correspondence, you must call methods of MobilizedBody; there is no
124         hint here.
125     @note This method must zero out the passed in arrays, and in most cases
126     almost all returned entries will be zero, so this is \e not the most
127     efficent way to calculate forces; use it sparingly. **/
128     void calcForceContribution(const State&          state,
129                                Vector_<SpatialVec>&  bodyForces,
130                                Vector_<Vec3>&        particleForces,
131                                Vector&               mobilityForces) const;
132     /** Calculate the potential energy contribution that is made by this
133     force element at the given \a state. This calls the force element's
134     calcPotentialEnergy() method. A disabled force element will return zero
135     without invoking calcPotentialEnergy().
136     @param[in]      state
137         The State containing information to be used by the force element to
138         calculate the current potential energy. This must have already been
139         realized to a high enough stage for the force element to get what it
140         needs; if you don't know then realize it to Stage::Position.
141     @return The potential energy contribution of this force element at this
142     \a state value. **/
143     Real calcPotentialEnergyContribution(const State& state) const;
144     /*@}*/
145 
146     /**@name                   Bookkeeping
147     These methods are not normally needed. They provide bookkeeping
148     information such as access to the parent force subsystem and the force
149     index assigned to this force element. **/
150     /*@{*/
151     /** Default constructor for Force handle base class does nothing. **/
Force()152     Force() {}
153     /** Implicit conversion to ForceIndex when needed. This will throw an
154     exception if the force element has not yet been adopted by a force
155     subsystem. **/
ForceIndex()156     operator ForceIndex() const {return getForceIndex();}
157     /** Get the GeneralForceSubsystem of which this Force is an element.
158     This will throw an exception if the force element has not yet been
159     adopted by a force subsystem. **/
160     const GeneralForceSubsystem& getForceSubsystem() const;
161     /** Get the index of this force element within its parent force subsystem.
162     The returned index will be invalid if the force element has not yet been
163     adopted by any subsystem (test with the index.isValid() method). **/
164     ForceIndex getForceIndex() const;
165     /*@}*/
166 
167     class TwoPointLinearSpring;
168     class TwoPointLinearDamper;
169     class TwoPointConstantForce;
170     class MobilityLinearSpring;
171     class MobilityLinearDamper;
172     class MobilityConstantForce;
173     class MobilityLinearStop;
174     class MobilityDiscreteForce;
175     class DiscreteForces;
176     class LinearBushing;
177     class ConstantForce;
178     class ConstantTorque;
179     class GlobalDamper;
180     class Thermostat;
181     class UniformGravity;
182     class Gravity;
183     class Custom;
184 
185     class TwoPointLinearSpringImpl;
186     class TwoPointLinearDamperImpl;
187     class TwoPointConstantForceImpl;
188     class MobilityLinearSpringImpl;
189     class MobilityLinearDamperImpl;
190     class MobilityConstantForceImpl;
191     class MobilityLinearStopImpl;
192     class MobilityDiscreteForceImpl;
193     class DiscreteForcesImpl;
194     class LinearBushingImpl;
195     class ConstantForceImpl;
196     class ConstantTorqueImpl;
197     class GlobalDamperImpl;
198     class ThermostatImpl;
199     class UniformGravityImpl;
200     class GravityImpl;
201     class CustomImpl;
202 
203 protected:
204     /** Use this in a derived Force handle class constructor to supply the
205     concrete implementation object to be stored in the handle base. **/
Force(ForceImpl * r)206     explicit Force(ForceImpl* r) : HandleBase(r) { }
207 };
208 
209 
210 /**
211  * A linear spring between two points, specified as a station on
212  * each of two bodies. The stiffness k and
213  * unstretched length x0 are provided. Then if d is the unit vector
214  * from point1 to point2, and x the current separation, we have
215  * f = k(x-x0) and we apply a force f*d to point1 and -f*d to point2.
216  * This contributes to potential energy: pe = 1/2 k (x-x0)^2.
217  * It is an error if the two points become coincident, since we
218  * are unable to determine a direction for the force in that case.
219  */
220 
221 class SimTK_SIMBODY_EXPORT Force::TwoPointLinearSpring : public Force {
222 public:
223     /**
224      * Create a TwoPointLinearSpring.
225      *
226      * @param forces     the subsystem to which this force should be added
227      * @param body1      the first body to which the force should be applied
228      * @param station1   the location on the first body at which the force should be applied
229      * @param body2      the second body to which the force should be applied
230      * @param station2   the location on the second body at which the force should be applied
231      * @param k          the spring constant
232      * @param x0         the distance at which the force is 0
233      */
234     TwoPointLinearSpring(GeneralForceSubsystem& forces, const MobilizedBody& body1, const Vec3& station1, const MobilizedBody& body2, const Vec3& station2, Real k, Real x0);
235 
236     /** Default constructor creates an empty handle. **/
TwoPointLinearSpring()237     TwoPointLinearSpring() {}
238 
239     SimTK_INSERT_DERIVED_HANDLE_DECLARATIONS(TwoPointLinearSpring, TwoPointLinearSpringImpl, Force);
240 };
241 
242 /**
243  * A force which resists changes in the distance between
244  * two points, acting along the line between those points. The points
245  * are specified as a station on each of two bodies. A damping constant
246  * c >= 0 is given. If the relative (scalar) velocity between the points
247  * is v, then we apply a force of magnitude f=c*|v| to each point in
248  * a direction which opposes their separation. This is not a potential
249  * force and thus does not contribute to the potential energy calculation.
250  * It is an error if the two points become coincident, since we
251  * are unable to determine a direction for the force in that case.
252  */
253 
254 class SimTK_SIMBODY_EXPORT Force::TwoPointLinearDamper: public Force {
255 public:
256     /**
257      * Create a TwoPointLinearDamper.
258      *
259      * @param forces     the subsystem to which this force should be added
260      * @param body1      the first body to which the force should be applied
261      * @param station1   the location on the first body at which the force should be applied
262      * @param body2      the second body to which the force should be applied
263      * @param station2   the location on the second body at which the force should be applied
264      * @param damping    the damping constant
265      */
266     TwoPointLinearDamper(GeneralForceSubsystem& forces, const MobilizedBody& body1, const Vec3& station1, const MobilizedBody& body2, const Vec3& station2, Real damping);
267 
268     /** Default constructor creates an empty handle. **/
TwoPointLinearDamper()269     TwoPointLinearDamper() {}
270 
271     SimTK_INSERT_DERIVED_HANDLE_DECLARATIONS(TwoPointLinearDamper, TwoPointLinearDamperImpl, Force);
272 };
273 
274 /**
275  * A constant force f (a signed scalar) which acts along the line between
276  * two points, specified as a station on each of two bodies. A positive
277  * force acts to separate the points; negative pulls them together. The
278  * force magnitude is independent of the separation between the points.
279  * This force does not contribute to the potential energy, so adding it to
280  * a system will cause energy not to be conserved.
281  * It is an error if the two points become coincident, since we
282  * are unable to determine a direction for the force in that case.
283  */
284 
285 class SimTK_SIMBODY_EXPORT Force::TwoPointConstantForce: public Force {
286 public:
287     /**
288      * Create a TwoPointConstantForce.
289      *
290      * @param forces     the subsystem to which this force should be added
291      * @param body1      the first body to which the force should be applied
292      * @param station1   the location on the first body at which the force should be applied
293      * @param body2      the second body to which the force should be applied
294      * @param station2   the location on the second body at which the force should be applied
295      * @param force      the magnitude of the force to apply
296      */
297     TwoPointConstantForce(GeneralForceSubsystem& forces, const MobilizedBody& body1, const Vec3& station1, const MobilizedBody& body2, const Vec3& station2, Real force);
298 
299     /** Default constructor creates an empty handle. **/
TwoPointConstantForce()300     TwoPointConstantForce() {}
301 
302     SimTK_INSERT_DERIVED_HANDLE_DECLARATIONS(TwoPointConstantForce, TwoPointConstantForceImpl, Force);
303 };
304 
305 
306 /**
307  * A constant force applied to a body station. The force is a
308  * vector fixed forever in the Ground frame.
309  * This force does not contribute to the potential energy, so adding it to
310  * a system will cause energy not to be conserved.
311  */
312 
313 class SimTK_SIMBODY_EXPORT Force::ConstantForce: public Force {
314 public:
315     ConstantForce(GeneralForceSubsystem& forces, const MobilizedBody& body, const Vec3& station, const Vec3& force);
316 
317     /** Default constructor creates an empty handle. **/
ConstantForce()318     ConstantForce() {}
319 
320     SimTK_INSERT_DERIVED_HANDLE_DECLARATIONS(ConstantForce, ConstantForceImpl, Force);
321 };
322 
323 /**
324  * A constant torque to a body. The torque is a
325  * vector fixed forever in the Ground frame.
326  * This force does not contribute to the potential energy, so adding it to
327  * a system will cause energy not to be conserved.
328  */
329 
330 class SimTK_SIMBODY_EXPORT Force::ConstantTorque: public Force {
331 public:
332     ConstantTorque(GeneralForceSubsystem& forces, const MobilizedBody& body, const Vec3& torque);
333 
334     /** Default constructor creates an empty handle. **/
ConstantTorque()335     ConstantTorque() {}
336 
337     SimTK_INSERT_DERIVED_HANDLE_DECLARATIONS(ConstantTorque, ConstantTorqueImpl, Force);
338 };
339 
340 /**
341  * A general energy "drain" on the system. This is
342  * done by effectively adding a damper to every generalized
343  * speed (mobility) in the system. Each generalized speed
344  * u_i feels a force -dampingFactor*u_i.
345  * This usually is not physically meaningful, but it can be useful in some
346  * circumstances just to drain energy out of the model when
347  * the specific energy-draining mechanism is not important.
348  * You can have more than one of these in which case the
349  * dampingFactors are added. No individual dampingFactor is
350  * allowed to be negative. This is not a potential force and
351  * hence does not contribute to potential energy.
352  */
353 
354 class SimTK_SIMBODY_EXPORT Force::GlobalDamper : public Force {
355 public:
356     GlobalDamper(GeneralForceSubsystem& forces, const SimbodyMatterSubsystem& matter, Real damping);
357 
358     /** Default constructor creates an empty handle. **/
GlobalDamper()359     GlobalDamper() {}
360 
361     SimTK_INSERT_DERIVED_HANDLE_DECLARATIONS(GlobalDamper, GlobalDamperImpl, Force);
362 };
363 
364 /**
365  * A uniform gravitational force applied to every body in the system.\ See
366  * Force::Gravity for a more flexible option.
367  *
368  * The %UniformGravity force is specified by a vector in the Ground frame. You
369  * can optionally specify a height at which the gravitational potential energy
370  * is zero.
371  * @see SimTK::Force::Gravity
372  */
373 
374 class SimTK_SIMBODY_EXPORT Force::UniformGravity : public Force {
375 public:
376     UniformGravity(GeneralForceSubsystem& forces,
377                    const SimbodyMatterSubsystem& matter,
378                    const Vec3& g, Real zeroHeight=0);
379 
380     /** Default constructor creates an empty handle. **/
UniformGravity()381     UniformGravity() {}
382 
383     Vec3 getGravity() const;
384     void setGravity(const Vec3& g);
385     Real getZeroHeight() const;
386     void setZeroHeight(Real height);
387     SimTK_INSERT_DERIVED_HANDLE_DECLARATIONS(UniformGravity, UniformGravityImpl, Force);
388 };
389 
390 } // namespace SimTK
391 
392 #endif // SimTK_SIMBODY_FORCE_H_
393