00001 #ifndef SimTK_SIMBODY_MATTER_SUBTREE_H_ 00002 #define SimTK_SIMBODY_MATTER_SUBTREE_H_ 00003 00004 /* -------------------------------------------------------------------------- * 00005 * SimTK Core: SimTK Simbody(tm) * 00006 * -------------------------------------------------------------------------- * 00007 * This is part of the SimTK Core biosimulation toolkit originating from * 00008 * Simbios, the NIH National Center for Physics-Based Simulation of * 00009 * Biological Structures at Stanford, funded under the NIH Roadmap for * 00010 * Medical Research, grant U54 GM072970. See https://simtk.org. * 00011 * * 00012 * Portions copyright (c) 2007-8 Stanford University and the Authors. * 00013 * Authors: Michael Sherman * 00014 * Contributors: * 00015 * * 00016 * Permission is hereby granted, free of charge, to any person obtaining a * 00017 * copy of this software and associated documentation files (the "Software"), * 00018 * to deal in the Software without restriction, including without limitation * 00019 * the rights to use, copy, modify, merge, publish, distribute, sublicense, * 00020 * and/or sell copies of the Software, and to permit persons to whom the * 00021 * Software is furnished to do so, subject to the following conditions: * 00022 * * 00023 * The above copyright notice and this permission notice shall be included in * 00024 * all copies or substantial portions of the Software. * 00025 * * 00026 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * 00027 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * 00028 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * 00029 * THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * 00030 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * 00031 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE * 00032 * USE OR OTHER DEALINGS IN THE SOFTWARE. * 00033 * -------------------------------------------------------------------------- */ 00034 00035 #include "SimTKcommon.h" 00036 #include "simbody/internal/common.h" 00037 00038 #include <cassert> 00039 #include <vector> 00040 #include <iosfwd> 00041 00042 namespace SimTK { 00043 00044 class SimbodyMatterSubsystem; 00045 class MobilizedBody; 00046 class SimbodyMatterSubtree; 00047 class SimbodyMatterSubtreeResults; 00048 00116 class SimTK_SIMBODY_EXPORT SimbodyMatterSubtree { 00117 public: 00118 SimbodyMatterSubtree(); 00119 SimbodyMatterSubtree(const SimbodyMatterSubtree&); 00120 SimbodyMatterSubtree& operator=(const SimbodyMatterSubtree&); 00121 ~SimbodyMatterSubtree(); 00122 00123 explicit SimbodyMatterSubtree(const SimbodyMatterSubsystem&); 00124 SimbodyMatterSubtree(const SimbodyMatterSubsystem&, 00125 const std::vector<MobilizedBodyIndex>& terminalBodies); 00126 00127 void setSimbodyMatterSubsystem(const SimbodyMatterSubsystem& matter); 00128 const SimbodyMatterSubsystem& getSimbodyMatterSubsystem() const; 00129 00130 // This doesn't change the associated SimbodyMatterSubsystem if there 00131 // is one, but does remove all the bodies from the SimbodyMatterSubtree. 00132 void clear(); 00133 00134 SimbodyMatterSubtree& addTerminalBody(MobilizedBodyIndex); 00135 00136 void realizeTopology(); 00137 00138 int getNumSubtreeBodies() const; // includes ancestor 00139 MobilizedBodyIndex getAncestorMobilizedBodyIndex() const; 00140 00141 // These are in the same order they were added; body[i] is the terminus 00142 // of branch i. 00143 const std::vector<MobilizedBodyIndex>& getTerminalBodies() const; 00144 00145 // These are indexed by SubtreeBodyIndex starting with 0 for the ancestor body 00146 // and monotonically increasing outwards along a branch. 00147 const std::vector<MobilizedBodyIndex>& getAllBodies() const; 00148 00149 SubtreeBodyIndex getParentSubtreeBodyIndex(SubtreeBodyIndex) const; // 0 returns an invalid Index 00150 const std::vector<SubtreeBodyIndex>& getChildSubtreeBodyIndices(SubtreeBodyIndex) const; 00151 00152 // MODEL STAGE 00153 00154 // State must be realized to at least Stage::Model for this call to work. 00155 // The supplied SimbodyMatterSubtreeResults object is allocated and properly initialized to 00156 // be able to hold computation results from this SimbodyMatterSubtree. 00157 void initializeSubtreeResults(const State&, SimbodyMatterSubtreeResults&) const; 00158 00159 // This can be used as a sanity check that initializeSubtreeResults() was already called 00160 // in this SimbodyMatterSubtree to produce these SimbodyMatterSubtreeResults. It is by no means exhaustive but 00161 // will catch egregious errors. 00162 bool isCompatibleSubtreeResults(const SimbodyMatterSubtreeResults&) const; 00163 00164 // POSITION STAGE 00165 00166 // State must be realized to at least Stage::Position for this to work. SimbodyMatterSubtreeResults 00167 // must have already been initialized to work with this SimbodyMatterSubtree. SimbodyMatterSubtreeResults stage 00168 // will be Stage::Position after this call. All body transforms will be the same as 00169 // the corresponding ones in the state, except they will be measured from the ancestor 00170 // frame instead of ground. SimbodyMatterSubtree q's will be identical to corresponding State q's. 00171 void copyPositionsFromState(const State&, SimbodyMatterSubtreeResults&) const; 00172 00173 // State must be realized to Stage::Instance. subQ must be the right length for this 00174 // SimbodyMatterSubtree, and SimbodyMatterSubtreeResults must have been properly initialized. SimbodyMatterSubtreeResults 00175 // stage will be Stage::Position after this call. 00176 void calcPositionsFromSubtreeQ(const State&, const Vector& subQ, SimbodyMatterSubtreeResults&) const; 00177 00178 // Calculates a perturbed position result starting with the subQ's and position results 00179 // which must already be in SimbodyMatterSubtreeResults. 00180 void perturbPositions(const State&, SubtreeQIndex subQIndex, Real perturbation, SimbodyMatterSubtreeResults&) const; 00181 00182 00183 // VELOCITY STAGE 00184 00185 // State must be realized to at least Stage::Velocity for this to work. SimbodyMatterSubtreeResults 00186 // must already be at Stage::Position. SimbodyMatterSubtreeResults stage 00187 // will be Stage::Velocity after this call. All subtree body spatial velocities will be 00188 // the same as in the State, except measured relative to A and expressed in A. SimbodyMatterSubtree u's 00189 // will be identical to corresponding State u's. 00190 void copyVelocitiesFromState(const State&, SimbodyMatterSubtreeResults&) const; 00191 00192 // State must be realized to Stage::Instance. subU must be the right length for this 00193 // SimbodyMatterSubtree, and SimbodyMatterSubtreeResults must already be at Stage::Position. SimbodyMatterSubtreeResults 00194 // stage will be Stage::Velocity after this call. 00195 void calcVelocitiesFromSubtreeU(const State&, const Vector& subU, SimbodyMatterSubtreeResults&) const; 00196 00197 // State must be realized to Stage::Instance and SimbodyMatterSubtreeResults must already be at 00198 // Stage::Position. SimbodyMatterSubtreeResults stage will be Stage::Velocity after this call, but 00199 // all SimbodyMatterSubtree u's and body velocities will be zero. 00200 void calcVelocitiesFromZeroU(const State&, SimbodyMatterSubtreeResults&) const; 00201 00202 // Calculates a perturbed velocity result starting with the subU's and velocity results 00203 // which must already be in SimbodyMatterSubtreeResults. 00204 void perturbVelocities(const State&, SubtreeUIndex subUIndex, Real perturbation, SimbodyMatterSubtreeResults&) const; 00205 00206 00207 // ACCELERATION STAGE 00208 00209 // State must be realized to at least Stage::Acceleration for this to work. SimbodyMatterSubtreeResults 00210 // must already be at Stage::Velocity. SimbodyMatterSubtreeResults stage 00211 // will be Stage::Acceleration after this call. All subtree body spatial accelerations will be 00212 // the same as in the State, except measured relative to A and expressed in A. SimbodyMatterSubtree udots 00213 // will be identical to corresponding State udots. 00214 void copyAccelerationsFromState(const State&, SimbodyMatterSubtreeResults&) const; 00215 00216 // State must be realized to Stage::Instance. subUDot must be the right length for this 00217 // SimbodyMatterSubtree, and SimbodyMatterSubtreeResults must already be at Stage::Velocity. SimbodyMatterSubtreeResults 00218 // stage will be Stage::Acceleration after this call. 00219 void calcAccelerationsFromSubtreeUDot(const State&, const Vector& subUDot, SimbodyMatterSubtreeResults&) const; 00220 00221 // State must be realized to Stage::Instance and SimbodyMatterSubtreeResults must already be at 00222 // Stage::Velocity. SimbodyMatterSubtreeResults stage will be Stage::Acceleration after this call. 00223 // All SimbodyMatterSubtree udots's will be zero, body accelerations will have only their bias values 00224 // (coriolis accelerations from nonzero u's). 00225 void calcAccelerationsFromZeroUDot(const State&, SimbodyMatterSubtreeResults&) const; 00226 00227 // Calculates a perturbed velocity result starting with the subUDot's and acceleration results 00228 // which must already be in SimbodyMatterSubtreeResults. 00229 void perturbAccelerations(const State&, SubtreeUIndex subUDotIndex, Real perturbation, SimbodyMatterSubtreeResults&) const; 00230 00231 class SubtreeRep; 00232 private: 00233 SubtreeRep* rep; 00234 const SubtreeRep& getRep() const {assert(rep);return *rep;} 00235 SubtreeRep& updRep() {assert(rep);return *rep;} 00236 }; 00237 00238 SimTK_SIMBODY_EXPORT std::ostream& 00239 operator<<(std::ostream&, const SimbodyMatterSubtree&); 00240 00241 /* 00242 * This is the writable "cache" for a SimbodyMatterSubtree. Once the full State has 00243 * been realized to the Model stage, a SimbodyMatterSubtree can initialize one of these 00244 * objects and then use it to hold operator results. 00245 */ 00246 class SimTK_SIMBODY_EXPORT SimbodyMatterSubtreeResults { 00247 public: 00248 SimbodyMatterSubtreeResults(); 00249 SimbodyMatterSubtreeResults(const SimbodyMatterSubtreeResults&); 00250 SimbodyMatterSubtreeResults& operator=(const SimbodyMatterSubtreeResults&); 00251 ~SimbodyMatterSubtreeResults(); 00252 00253 void clear(); 00254 00255 void reallocateBodies(int nBodies); 00256 void addMobilities(SubtreeBodyIndex, QIndex qStart, int nq, UIndex uStart, int nu); 00257 void realizeModel(const Vector& stateQ, const Vector& stateU); 00258 00259 Stage getStage() const; 00260 00261 int getNumSubtreeBodies() const; 00262 int getNumSubtreeQs() const; 00263 int getNumSubtreeUs() const; 00264 00265 const Vector& getSubtreeQ() const; 00266 const Transform& getSubtreeBodyTransform(SubtreeBodyIndex) const; // from ancestor frame 00267 00268 const Vector& getSubtreeU() const; 00269 const SpatialVec& getSubtreeBodyVelocity(SubtreeBodyIndex) const; // measured & expressed in ancestor frame 00270 00271 const Vector& getSubtreeUDot() const; 00272 const SpatialVec& getSubtreeBodyAcceleration(SubtreeBodyIndex) const; // measured & expressed in ancestor frame 00273 00274 // These are indexed by SubtreeQIndex and SubtreeUIndex. 00275 const std::vector<QIndex>& getQSubset() const; // subset of Subsystem Qs used by this SimbodyMatterSubtree 00276 const std::vector<UIndex>& getUSubset() const; // subset of Subsystem Us used by this SimbodyMatterSubtree 00277 00278 void findSubtreeBodyQ(SubtreeBodyIndex, SubtreeQIndex& qStart, int& nq) const; // indices into QSubset 00279 void findSubtreeBodyU(SubtreeBodyIndex, SubtreeUIndex& uStart, int& nu) const; // indices into USubset 00280 00281 class SubtreeResultsRep; 00282 private: 00283 friend class SimbodyMatterSubtree; 00284 SubtreeResultsRep* rep; 00285 const SubtreeResultsRep& getRep() const {assert(rep);return *rep;} 00286 SubtreeResultsRep& updRep() {assert(rep);return *rep;} 00287 }; 00288 00289 SimTK_SIMBODY_EXPORT std::ostream& 00290 operator<<(std::ostream&, const SimbodyMatterSubtreeResults&); 00291 00292 } // namespace SimTK 00293 00294 #endif // SimTK_SIMBODY_MATTER_SUBTREE_H_