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