1 /*
2  * Copyright (c) 2011-2021, The DART development contributors
3  * All rights reserved.
4  *
5  * The list of contributors can be found at:
6  *   https://github.com/dartsim/dart/blob/master/LICENSE
7  *
8  * This file is provided under the following "BSD-style" License:
9  *   Redistribution and use in source and binary forms, with or
10  *   without modification, are permitted provided that the following
11  *   conditions are met:
12  *   * Redistributions of source code must retain the above copyright
13  *     notice, this list of conditions and the following disclaimer.
14  *   * Redistributions in binary form must reproduce the above
15  *     copyright notice, this list of conditions and the following
16  *     disclaimer in the documentation and/or other materials provided
17  *     with the distribution.
18  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
19  *   CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
20  *   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21  *   MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22  *   DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23  *   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
26  *   USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27  *   AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  *   LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29  *   ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  *   POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 #include "dart/dynamics/Skeleton.hpp"
34 
35 #include <algorithm>
36 #include <queue>
37 #include <string>
38 #include <vector>
39 
40 #include "dart/common/Console.hpp"
41 #include "dart/common/Deprecated.hpp"
42 #include "dart/common/StlHelpers.hpp"
43 #include "dart/dynamics/BodyNode.hpp"
44 #include "dart/dynamics/DegreeOfFreedom.hpp"
45 #include "dart/dynamics/EndEffector.hpp"
46 #include "dart/dynamics/InverseKinematics.hpp"
47 #include "dart/dynamics/Joint.hpp"
48 #include "dart/dynamics/Marker.hpp"
49 #include "dart/dynamics/PointMass.hpp"
50 #include "dart/dynamics/ShapeNode.hpp"
51 #include "dart/dynamics/SoftBodyNode.hpp"
52 #include "dart/math/Geometry.hpp"
53 #include "dart/math/Helpers.hpp"
54 
55 #define SET_ALL_FLAGS(X)                                                       \
56   for (auto& cache : mTreeCache)                                               \
57     cache.mDirty.X = true;                                                     \
58   mSkelCache.mDirty.X = true;
59 
60 #define SET_FLAG(Y, X)                                                         \
61   mTreeCache[Y].mDirty.X = true;                                               \
62   mSkelCache.mDirty.X = true;
63 
64 #define ON_ALL_TREES(X)                                                        \
65   for (std::size_t i = 0; i < mTreeCache.size(); ++i)                          \
66     X(i);
67 
68 #define CHECK_CONFIG_VECTOR_SIZE(V)                                            \
69   if (V.size() > 0)                                                            \
70   {                                                                            \
71     if (nonzero_size != INVALID_INDEX                                          \
72         && V.size() != static_cast<int>(nonzero_size))                         \
73     {                                                                          \
74       dterr << "[Skeleton::Configuration] Mismatch in size of vector [" << #V  \
75             << "] (expected " << nonzero_size << " | found " << V.size()       \
76             << "\n";                                                           \
77       assert(false);                                                           \
78     }                                                                          \
79     else if (nonzero_size == INVALID_INDEX)                                    \
80       nonzero_size = V.size();                                                 \
81   }
82 
83 namespace dart {
84 namespace dynamics {
85 
86 namespace detail {
87 
88 //==============================================================================
89 /// Templated function for passing each entry in a std::vector<Data> into each
90 /// member of an array of Objects belonging to some Owner class.
91 ///
92 /// The ObjectBase argument should be the base class of Object in which the
93 /// setData function is defined. In many cases, ObjectBase may be the same as
94 /// Object, but it is not always.
95 //
96 // TODO(MXG): Consider putting this in an accessible header if it might be
97 // useful in other places.
98 template <
99     class Owner,
100     class Object,
101     class ObjectBase,
102     class Data,
103     std::size_t (Owner::*getNumObjects)() const,
104     Object* (Owner::*getObject)(std::size_t),
105     void (ObjectBase::*setData)(const Data&)>
setAllMemberObjectData(Owner * owner,const std::vector<Data> & data)106 void setAllMemberObjectData(Owner* owner, const std::vector<Data>& data)
107 {
108   if (!owner)
109   {
110     dterr << "[setAllMemberObjectData] Attempting to set ["
111           << typeid(Data).name() << "] of every [" << typeid(Object).name()
112           << "] in a nullptr [" << typeid(Owner).name() << "]. Please report "
113           << "this as a bug!\n";
114     assert(false);
115     return;
116   }
117 
118   std::size_t numObjects = (owner->*getNumObjects)();
119 
120   if (data.size() != numObjects)
121   {
122     dtwarn << "[setAllMemberObjectData] Mismatch between the number of ["
123            << typeid(Object).name() << "] member objects (" << numObjects
124            << ") in the [" << typeid(Owner).name() << "] named ["
125            << owner->getName() << "] (" << owner << ") and the number of ["
126            << typeid(Object).name() << "] which is (" << data.size()
127            << ") while setting [" << typeid(Data).name() << "]\n"
128            << " -- We will set (" << std::min(numObjects, data.size())
129            << ") of them.\n";
130     numObjects = std::min(numObjects, data.size());
131   }
132 
133   for (std::size_t i = 0; i < numObjects; ++i)
134     ((owner->*getObject)(i)->*setData)(data[i]);
135 }
136 
137 //==============================================================================
138 /// Templated function for aggregating a std::vector<Data> out of each member of
139 /// an array of Objects belonging to some Owner class.
140 ///
141 /// The ObjectBase argument should be the base class of Object in which the
142 /// getData function is defined. In many cases, ObjectBase may be the same as
143 /// Object, but it is not always.
144 //
145 // TODO(MXG): Consider putting this in an accessible header if it might be
146 // useful in other places.
147 template <
148     class Owner,
149     class Object,
150     class ObjectBase,
151     class Data,
152     std::size_t (Owner::*getNumObjects)() const,
153     const Object* (Owner::*getObject)(std::size_t) const,
154     Data (ObjectBase::*getData)() const>
getAllMemberObjectData(const Owner * owner)155 std::vector<Data> getAllMemberObjectData(const Owner* owner)
156 {
157   if (!owner)
158   {
159     dterr << "[getAllMemberObjectData] Attempting to get the ["
160           << typeid(Data).name() << "] from every [" << typeid(Object).name()
161           << "] in a nullptr [" << typeid(Owner).name() << "]. Please report "
162           << "this as a bug!\n";
163     assert(false);
164     return std::vector<Data>();
165   }
166 
167   const std::size_t numObjects = (owner->*getNumObjects)();
168   std::vector<Data> data;
169   data.reserve(numObjects);
170 
171   for (std::size_t i = 0; i < numObjects; ++i)
172     data.push_back(((owner->*getObject)(i)->*getData)());
173 
174   return data;
175 }
176 
177 //==============================================================================
SkeletonAspectProperties(const std::string & _name,bool _isMobile,const Eigen::Vector3d & _gravity,double _timeStep,bool _enabledSelfCollisionCheck,bool _enableAdjacentBodyCheck)178 SkeletonAspectProperties::SkeletonAspectProperties(
179     const std::string& _name,
180     bool _isMobile,
181     const Eigen::Vector3d& _gravity,
182     double _timeStep,
183     bool _enabledSelfCollisionCheck,
184     bool _enableAdjacentBodyCheck)
185   : mName(_name),
186     mIsMobile(_isMobile),
187     mGravity(_gravity),
188     mTimeStep(_timeStep),
189     mEnabledSelfCollisionCheck(_enabledSelfCollisionCheck),
190     mEnabledAdjacentBodyCheck(_enableAdjacentBodyCheck)
191 {
192   // Do nothing
193 }
194 
195 //==============================================================================
setAllBodyNodeStates(Skeleton * skel,const BodyNodeStateVector & states)196 void setAllBodyNodeStates(Skeleton* skel, const BodyNodeStateVector& states)
197 {
198   setAllMemberObjectData<
199       Skeleton,
200       BodyNode,
201       common::Composite,
202       common::Composite::State,
203       &Skeleton::getNumBodyNodes,
204       &Skeleton::getBodyNode,
205       &common::Composite::setCompositeState>(skel, states);
206 }
207 
208 //==============================================================================
getAllBodyNodeStates(const Skeleton * skel)209 BodyNodeStateVector getAllBodyNodeStates(const Skeleton* skel)
210 {
211   return getAllMemberObjectData<
212       Skeleton,
213       BodyNode,
214       common::Composite,
215       common::Composite::State,
216       &Skeleton::getNumBodyNodes,
217       &Skeleton::getBodyNode,
218       &common::Composite::getCompositeState>(skel);
219 }
220 
221 //==============================================================================
setAllBodyNodeProperties(Skeleton * skel,const BodyNodePropertiesVector & properties)222 void setAllBodyNodeProperties(
223     Skeleton* skel, const BodyNodePropertiesVector& properties)
224 {
225   setAllMemberObjectData<
226       Skeleton,
227       BodyNode,
228       common::Composite,
229       common::Composite::Properties,
230       &Skeleton::getNumBodyNodes,
231       &Skeleton::getBodyNode,
232       &common::Composite::setCompositeProperties>(skel, properties);
233 }
234 
235 //==============================================================================
getAllBodyNodeProperties(const Skeleton * skel)236 BodyNodePropertiesVector getAllBodyNodeProperties(const Skeleton* skel)
237 {
238   return getAllMemberObjectData<
239       Skeleton,
240       BodyNode,
241       common::Composite,
242       common::Composite::Properties,
243       &Skeleton::getNumBodyNodes,
244       &Skeleton::getBodyNode,
245       &common::Composite::getCompositeProperties>(skel);
246 }
247 
248 //==============================================================================
setAllJointStates(Skeleton * skel,const BodyNodeStateVector & states)249 void setAllJointStates(Skeleton* skel, const BodyNodeStateVector& states)
250 {
251   setAllMemberObjectData<
252       Skeleton,
253       Joint,
254       common::Composite,
255       common::Composite::State,
256       &Skeleton::getNumJoints,
257       &Skeleton::getJoint,
258       &common::Composite::setCompositeState>(skel, states);
259 }
260 
261 //==============================================================================
getAllJointStates(const Skeleton * skel)262 BodyNodeStateVector getAllJointStates(const Skeleton* skel)
263 {
264   return getAllMemberObjectData<
265       Skeleton,
266       Joint,
267       common::Composite,
268       common::Composite::State,
269       &Skeleton::getNumJoints,
270       &Skeleton::getJoint,
271       &common::Composite::getCompositeState>(skel);
272 }
273 
274 //==============================================================================
setAllJointProperties(Skeleton * skel,const BodyNodePropertiesVector & properties)275 void setAllJointProperties(
276     Skeleton* skel, const BodyNodePropertiesVector& properties)
277 {
278   setAllMemberObjectData<
279       Skeleton,
280       Joint,
281       common::Composite,
282       common::Composite::Properties,
283       &Skeleton::getNumJoints,
284       &Skeleton::getJoint,
285       &common::Composite::setCompositeProperties>(skel, properties);
286 }
287 
288 //==============================================================================
getAllJointProperties(const Skeleton * skel)289 BodyNodePropertiesVector getAllJointProperties(const Skeleton* skel)
290 {
291   return getAllMemberObjectData<
292       Skeleton,
293       Joint,
294       common::Composite,
295       common::Composite::Properties,
296       &Skeleton::getNumJoints,
297       &Skeleton::getJoint,
298       &common::Composite::getCompositeProperties>(skel);
299 }
300 
301 } // namespace detail
302 
303 //==============================================================================
Configuration(const Eigen::VectorXd & positions,const Eigen::VectorXd & velocities,const Eigen::VectorXd & accelerations,const Eigen::VectorXd & forces,const Eigen::VectorXd & commands)304 Skeleton::Configuration::Configuration(
305     const Eigen::VectorXd& positions,
306     const Eigen::VectorXd& velocities,
307     const Eigen::VectorXd& accelerations,
308     const Eigen::VectorXd& forces,
309     const Eigen::VectorXd& commands)
310   : mPositions(positions),
311     mVelocities(velocities),
312     mAccelerations(accelerations),
313     mForces(forces),
314     mCommands(commands)
315 {
316   std::size_t nonzero_size = INVALID_INDEX;
317 
318   CHECK_CONFIG_VECTOR_SIZE(positions);
319   CHECK_CONFIG_VECTOR_SIZE(velocities);
320   CHECK_CONFIG_VECTOR_SIZE(accelerations);
321   CHECK_CONFIG_VECTOR_SIZE(forces);
322   CHECK_CONFIG_VECTOR_SIZE(commands);
323 
324   if (nonzero_size != INVALID_INDEX)
325   {
326     for (std::size_t i = 0; i < nonzero_size; ++i)
327       mIndices.push_back(i);
328   }
329 }
330 
331 //==============================================================================
Configuration(const std::vector<std::size_t> & indices,const Eigen::VectorXd & positions,const Eigen::VectorXd & velocities,const Eigen::VectorXd & accelerations,const Eigen::VectorXd & forces,const Eigen::VectorXd & commands)332 Skeleton::Configuration::Configuration(
333     const std::vector<std::size_t>& indices,
334     const Eigen::VectorXd& positions,
335     const Eigen::VectorXd& velocities,
336     const Eigen::VectorXd& accelerations,
337     const Eigen::VectorXd& forces,
338     const Eigen::VectorXd& commands)
339   : mIndices(indices),
340     mPositions(positions),
341     mVelocities(velocities),
342     mAccelerations(accelerations),
343     mForces(forces),
344     mCommands(commands)
345 {
346   std::size_t nonzero_size = indices.size();
347 
348   CHECK_CONFIG_VECTOR_SIZE(positions);
349   CHECK_CONFIG_VECTOR_SIZE(velocities);
350   CHECK_CONFIG_VECTOR_SIZE(accelerations);
351   CHECK_CONFIG_VECTOR_SIZE(forces);
352   CHECK_CONFIG_VECTOR_SIZE(commands);
353 }
354 
355 //==============================================================================
356 #define RETURN_IF_CONFIG_VECTOR_IS_INEQ(V)                                     \
357   if (V.size() != other.V.size())                                              \
358     return false;                                                              \
359   if (V != other.V)                                                            \
360     return false;
361 
362 //==============================================================================
operator ==(const Configuration & other) const363 bool Skeleton::Configuration::operator==(const Configuration& other) const
364 {
365   if (mIndices != other.mIndices)
366     return false;
367 
368   RETURN_IF_CONFIG_VECTOR_IS_INEQ(mPositions);
369   RETURN_IF_CONFIG_VECTOR_IS_INEQ(mVelocities);
370   RETURN_IF_CONFIG_VECTOR_IS_INEQ(mAccelerations);
371   RETURN_IF_CONFIG_VECTOR_IS_INEQ(mForces);
372   RETURN_IF_CONFIG_VECTOR_IS_INEQ(mCommands);
373 
374   return true;
375 }
376 
377 //==============================================================================
operator !=(const Configuration & other) const378 bool Skeleton::Configuration::operator!=(const Configuration& other) const
379 {
380   return !(*this == other);
381 }
382 
383 //==============================================================================
create(const std::string & _name)384 SkeletonPtr Skeleton::create(const std::string& _name)
385 {
386   return create(AspectPropertiesData(_name));
387 }
388 
389 //==============================================================================
create(const AspectPropertiesData & properties)390 SkeletonPtr Skeleton::create(const AspectPropertiesData& properties)
391 {
392   SkeletonPtr skel(new Skeleton(properties));
393   skel->setPtr(skel);
394   return skel;
395 }
396 
397 //==============================================================================
getPtr()398 SkeletonPtr Skeleton::getPtr()
399 {
400   return mPtr.lock();
401 }
402 
403 //==============================================================================
getPtr() const404 ConstSkeletonPtr Skeleton::getPtr() const
405 {
406   return mPtr.lock();
407 }
408 
409 //==============================================================================
getSkeleton()410 SkeletonPtr Skeleton::getSkeleton()
411 {
412   return mPtr.lock();
413 }
414 
415 //==============================================================================
getSkeleton() const416 ConstSkeletonPtr Skeleton::getSkeleton() const
417 {
418   return mPtr.lock();
419 }
420 
421 //==============================================================================
getMutex() const422 std::mutex& Skeleton::getMutex() const
423 {
424   return mMutex;
425 }
426 
427 //==============================================================================
getLockableReference() const428 std::unique_ptr<common::LockableReference> Skeleton::getLockableReference()
429     const
430 {
431   return std::make_unique<common::SingleLockableReference<std::mutex>>(
432       mPtr, mMutex);
433 }
434 
435 //==============================================================================
~Skeleton()436 Skeleton::~Skeleton()
437 {
438   for (BodyNode* bn : mSkelCache.mBodyNodes)
439     delete bn;
440 }
441 
442 //==============================================================================
clone() const443 SkeletonPtr Skeleton::clone() const
444 {
445   return cloneSkeleton(getName());
446 }
447 
448 //==============================================================================
clone(const std::string & cloneName) const449 SkeletonPtr Skeleton::clone(const std::string& cloneName) const
450 {
451   return cloneSkeleton(cloneName);
452 }
453 
454 //==============================================================================
cloneSkeleton() const455 SkeletonPtr Skeleton::cloneSkeleton() const
456 {
457   return cloneSkeleton(getName());
458 }
459 
460 //==============================================================================
cloneSkeleton(const std::string & cloneName) const461 SkeletonPtr Skeleton::cloneSkeleton(const std::string& cloneName) const
462 {
463   SkeletonPtr skelClone = Skeleton::create(cloneName);
464 
465   for (std::size_t i = 0; i < getNumBodyNodes(); ++i)
466   {
467     // Create a clone of the parent Joint
468     Joint* joint = getJoint(i)->clone();
469 
470     // Identify the original parent BodyNode
471     const BodyNode* originalParent = getBodyNode(i)->getParentBodyNode();
472 
473     // Grab the parent BodyNode clone (using its name, which is guaranteed to be
474     // unique), or use nullptr if this is a root BodyNode
475     BodyNode* parentClone
476         = (originalParent == nullptr)
477               ? nullptr
478               : skelClone->getBodyNode(originalParent->getName());
479 
480     if ((nullptr != originalParent) && (nullptr == parentClone))
481     {
482       dterr << "[Skeleton::clone] Failed to find a clone of BodyNode named ["
483             << originalParent->getName() << "] which is needed as the parent "
484             << "of the BodyNode named [" << getBodyNode(i)->getName()
485             << "] and should already have been created. Please report this as "
486             << "a bug!\n";
487     }
488 
489     BodyNode* newBody = getBodyNode(i)->clone(parentClone, joint, false);
490 
491     // The IK module gets cloned by the Skeleton and not by the BodyNode,
492     // because IK modules rely on the Skeleton's structure and indexing. If the
493     // IK was cloned by the BodyNode into a Skeleton that has a different
494     // structure, then there is no guarantee that it will continue to work
495     // correctly.
496     if (getBodyNode(i)->getIK())
497       newBody->mIK = getBodyNode(i)->getIK()->clone(newBody);
498 
499     skelClone->registerBodyNode(newBody);
500   }
501 
502   // Clone over the nodes in such a way that their indexing will match up with
503   // the original
504   for (const auto& nodeType : mNodeMap)
505   {
506     for (const auto& node : nodeType.second)
507     {
508       const BodyNode* originalBn = node->getBodyNodePtr();
509       BodyNode* newBn = skelClone->getBodyNode(originalBn->getName());
510       node->cloneNode(newBn)->attach();
511     }
512   }
513 
514   skelClone->setProperties(getAspectProperties());
515   skelClone->setName(cloneName);
516   skelClone->setState(getState());
517 
518   // Fix mimic joint references
519   for (std::size_t i = 0; i < getNumJoints(); ++i)
520   {
521     Joint* joint = skelClone->getJoint(i);
522     if (joint->getActuatorType() == Joint::MIMIC)
523     {
524       const Joint* mimicJoint
525           = skelClone->getJoint(joint->getMimicJoint()->getName());
526       if (mimicJoint)
527       {
528         joint->setMimicJoint(
529             mimicJoint, joint->getMimicMultiplier(), joint->getMimicOffset());
530       }
531       else
532       {
533         dterr << "[Skeleton::clone] Failed to clone mimic joint successfully: "
534               << "Unable to find the mimic joint ["
535               << joint->getMimicJoint()->getName()
536               << "] in the cloned Skeleton. Please report this as a bug!\n";
537       }
538     }
539   }
540 
541   return skelClone;
542 }
543 
544 //==============================================================================
cloneMetaSkeleton(const std::string & cloneName) const545 MetaSkeletonPtr Skeleton::cloneMetaSkeleton(const std::string& cloneName) const
546 {
547   return cloneSkeleton(cloneName);
548 }
549 
550 //==============================================================================
551 #define SET_CONFIG_VECTOR(V)                                                   \
552   if (configuration.m##V.size() > 0)                                           \
553   {                                                                            \
554     if (static_cast<int>(configuration.mIndices.size())                        \
555         != configuration.m##V.size())                                          \
556     {                                                                          \
557       dterr << "[Skeleton::setConfiguration] Mismatch in size of vector ["     \
558             << #V << "] (expected " << configuration.mIndices.size()           \
559             << " | found " << configuration.m##V.size() << "\n";               \
560       assert(false);                                                           \
561     }                                                                          \
562     else                                                                       \
563       set##V(configuration.mIndices, configuration.m##V);                      \
564   }
565 
566 //==============================================================================
setConfiguration(const Configuration & configuration)567 void Skeleton::setConfiguration(const Configuration& configuration)
568 {
569   SET_CONFIG_VECTOR(Positions);
570   SET_CONFIG_VECTOR(Velocities);
571   SET_CONFIG_VECTOR(Accelerations);
572   SET_CONFIG_VECTOR(Forces);
573   SET_CONFIG_VECTOR(Commands);
574 }
575 
576 //==============================================================================
getConfiguration(int flags) const577 Skeleton::Configuration Skeleton::getConfiguration(int flags) const
578 {
579   std::vector<std::size_t> indices;
580   for (std::size_t i = 0; i < getNumDofs(); ++i)
581     indices.push_back(i);
582 
583   return getConfiguration(indices, flags);
584 }
585 
586 //==============================================================================
getConfiguration(const std::vector<std::size_t> & indices,int flags) const587 Skeleton::Configuration Skeleton::getConfiguration(
588     const std::vector<std::size_t>& indices, int flags) const
589 {
590   Configuration config(indices);
591   if (flags == CONFIG_NOTHING)
592     return config;
593 
594   if ((flags & CONFIG_POSITIONS) == CONFIG_POSITIONS)
595     config.mPositions = getPositions(indices);
596 
597   if ((flags & CONFIG_VELOCITIES) == CONFIG_VELOCITIES)
598     config.mVelocities = getVelocities(indices);
599 
600   if ((flags & CONFIG_ACCELERATIONS) == CONFIG_ACCELERATIONS)
601     config.mAccelerations = getAccelerations(indices);
602 
603   if ((flags & CONFIG_FORCES) == CONFIG_FORCES)
604     config.mForces = getForces(indices);
605 
606   if ((flags & CONFIG_COMMANDS) == CONFIG_COMMANDS)
607     config.mCommands = getCommands(indices);
608 
609   return config;
610 }
611 
612 //==============================================================================
setState(const State & state)613 void Skeleton::setState(const State& state)
614 {
615   setCompositeState(state);
616 }
617 
618 //==============================================================================
getState() const619 Skeleton::State Skeleton::getState() const
620 {
621   return getCompositeState();
622 }
623 
624 //==============================================================================
setProperties(const Properties & properties)625 void Skeleton::setProperties(const Properties& properties)
626 {
627   setCompositeProperties(properties);
628 }
629 
630 //==============================================================================
getProperties() const631 Skeleton::Properties Skeleton::getProperties() const
632 {
633   return getCompositeProperties();
634 }
635 
636 //==============================================================================
setProperties(const AspectProperties & properties)637 void Skeleton::setProperties(const AspectProperties& properties)
638 {
639   setAspectProperties(properties);
640 }
641 
642 //==============================================================================
setAspectProperties(const AspectProperties & properties)643 void Skeleton::setAspectProperties(const AspectProperties& properties)
644 {
645   setName(properties.mName);
646   setMobile(properties.mIsMobile);
647   setGravity(properties.mGravity);
648   setTimeStep(properties.mTimeStep);
649   setSelfCollisionCheck(properties.mEnabledSelfCollisionCheck);
650   setAdjacentBodyCheck(properties.mEnabledAdjacentBodyCheck);
651 }
652 
653 //==============================================================================
getSkeletonProperties() const654 const Skeleton::AspectProperties& Skeleton::getSkeletonProperties() const
655 {
656   return mAspectProperties;
657 }
658 
659 //==============================================================================
setName(const std::string & _name)660 const std::string& Skeleton::setName(const std::string& _name)
661 {
662   if (_name == mAspectProperties.mName && !_name.empty())
663     return mAspectProperties.mName;
664 
665   const std::string oldName = mAspectProperties.mName;
666   mAspectProperties.mName = _name;
667 
668   updateNameManagerNames();
669 
670   ConstMetaSkeletonPtr me = mPtr.lock();
671   mNameChangedSignal.raise(me, oldName, mAspectProperties.mName);
672 
673   return mAspectProperties.mName;
674 }
675 
676 //==============================================================================
getName() const677 const std::string& Skeleton::getName() const
678 {
679   return mAspectProperties.mName;
680 }
681 
682 //==============================================================================
addEntryToBodyNodeNameMgr(BodyNode * _newNode)683 const std::string& Skeleton::addEntryToBodyNodeNameMgr(BodyNode* _newNode)
684 {
685   _newNode->BodyNode::mAspectProperties.mName
686       = mNameMgrForBodyNodes.issueNewNameAndAdd(_newNode->getName(), _newNode);
687 
688   return _newNode->BodyNode::mAspectProperties.mName;
689 }
690 
691 //==============================================================================
addEntryToJointNameMgr(Joint * _newJoint,bool _updateDofNames)692 const std::string& Skeleton::addEntryToJointNameMgr(
693     Joint* _newJoint, bool _updateDofNames)
694 {
695   _newJoint->mAspectProperties.mName
696       = mNameMgrForJoints.issueNewNameAndAdd(_newJoint->getName(), _newJoint);
697 
698   if (_updateDofNames)
699     _newJoint->updateDegreeOfFreedomNames();
700 
701   return _newJoint->mAspectProperties.mName;
702 }
703 
704 //==============================================================================
addEntryToSoftBodyNodeNameMgr(SoftBodyNode * _newNode)705 void Skeleton::addEntryToSoftBodyNodeNameMgr(SoftBodyNode* _newNode)
706 {
707   // Note: This doesn't need the same checks as BodyNode and Joint, because
708   // its name has already been resolved against all the BodyNodes, which
709   // includes all SoftBodyNodes.
710   mNameMgrForSoftBodyNodes.addName(_newNode->getName(), _newNode);
711 }
712 
713 //==============================================================================
updateNameManagerNames()714 void Skeleton::updateNameManagerNames()
715 {
716   mNameMgrForBodyNodes.setManagerName(
717       "Skeleton::BodyNode | " + mAspectProperties.mName);
718   mNameMgrForSoftBodyNodes.setManagerName(
719       "Skeleton::SoftBodyNode | " + mAspectProperties.mName);
720   mNameMgrForJoints.setManagerName(
721       "Skeleton::Joint | " + mAspectProperties.mName);
722   mNameMgrForDofs.setManagerName(
723       "Skeleton::DegreeOfFreedom | " + mAspectProperties.mName);
724 
725   for (auto& mgr : mNodeNameMgrMap)
726   {
727     mgr.second.setManagerName(
728         std::string("Skeleton::") + mgr.first.name() + " | "
729         + mAspectProperties.mName);
730   }
731 }
732 
733 //==============================================================================
enableSelfCollision(bool enableAdjacentBodyCheck)734 void Skeleton::enableSelfCollision(bool enableAdjacentBodyCheck)
735 {
736   enableSelfCollisionCheck();
737   setAdjacentBodyCheck(enableAdjacentBodyCheck);
738 }
739 
740 //==============================================================================
disableSelfCollision()741 void Skeleton::disableSelfCollision()
742 {
743   disableSelfCollisionCheck();
744   setAdjacentBodyCheck(false);
745 }
746 
747 //==============================================================================
setSelfCollisionCheck(bool enable)748 void Skeleton::setSelfCollisionCheck(bool enable)
749 {
750   mAspectProperties.mEnabledSelfCollisionCheck = enable;
751 }
752 
753 //==============================================================================
getSelfCollisionCheck() const754 bool Skeleton::getSelfCollisionCheck() const
755 {
756   return mAspectProperties.mEnabledSelfCollisionCheck;
757 }
758 
759 //==============================================================================
enableSelfCollisionCheck()760 void Skeleton::enableSelfCollisionCheck()
761 {
762   setSelfCollisionCheck(true);
763 }
764 
765 //==============================================================================
disableSelfCollisionCheck()766 void Skeleton::disableSelfCollisionCheck()
767 {
768   setSelfCollisionCheck(false);
769 }
770 
771 //==============================================================================
isEnabledSelfCollisionCheck() const772 bool Skeleton::isEnabledSelfCollisionCheck() const
773 {
774   return getSelfCollisionCheck();
775 }
776 
777 //==============================================================================
setAdjacentBodyCheck(bool enable)778 void Skeleton::setAdjacentBodyCheck(bool enable)
779 {
780   mAspectProperties.mEnabledAdjacentBodyCheck = enable;
781 }
782 
783 //==============================================================================
getAdjacentBodyCheck() const784 bool Skeleton::getAdjacentBodyCheck() const
785 {
786   return mAspectProperties.mEnabledAdjacentBodyCheck;
787 }
788 
789 //==============================================================================
enableAdjacentBodyCheck()790 void Skeleton::enableAdjacentBodyCheck()
791 {
792   setAdjacentBodyCheck(true);
793 }
794 
795 //==============================================================================
disableAdjacentBodyCheck()796 void Skeleton::disableAdjacentBodyCheck()
797 {
798   setAdjacentBodyCheck(false);
799 }
800 
801 //==============================================================================
isEnabledAdjacentBodyCheck() const802 bool Skeleton::isEnabledAdjacentBodyCheck() const
803 {
804   return getAdjacentBodyCheck();
805 }
806 
807 //==============================================================================
setMobile(bool _isMobile)808 void Skeleton::setMobile(bool _isMobile)
809 {
810   mAspectProperties.mIsMobile = _isMobile;
811 }
812 
813 //==============================================================================
isMobile() const814 bool Skeleton::isMobile() const
815 {
816   return mAspectProperties.mIsMobile;
817 }
818 
819 //==============================================================================
setTimeStep(double _timeStep)820 void Skeleton::setTimeStep(double _timeStep)
821 {
822   assert(_timeStep > 0.0);
823   mAspectProperties.mTimeStep = _timeStep;
824 
825   for (std::size_t i = 0; i < mTreeCache.size(); ++i)
826     dirtyArticulatedInertia(i);
827 }
828 
829 //==============================================================================
getTimeStep() const830 double Skeleton::getTimeStep() const
831 {
832   return mAspectProperties.mTimeStep;
833 }
834 
835 //==============================================================================
setGravity(const Eigen::Vector3d & _gravity)836 void Skeleton::setGravity(const Eigen::Vector3d& _gravity)
837 {
838   mAspectProperties.mGravity = _gravity;
839   SET_ALL_FLAGS(mGravityForces);
840   SET_ALL_FLAGS(mCoriolisAndGravityForces);
841   ON_ALL_TREES(dirtySupportPolygon);
842 }
843 
844 //==============================================================================
getGravity() const845 const Eigen::Vector3d& Skeleton::getGravity() const
846 {
847   return mAspectProperties.mGravity;
848 }
849 
850 //==============================================================================
getNumBodyNodes() const851 std::size_t Skeleton::getNumBodyNodes() const
852 {
853   return mSkelCache.mBodyNodes.size();
854 }
855 
856 //==============================================================================
getNumRigidBodyNodes() const857 std::size_t Skeleton::getNumRigidBodyNodes() const
858 {
859   return mSkelCache.mBodyNodes.size() - mSoftBodyNodes.size();
860 }
861 
862 //==============================================================================
getNumSoftBodyNodes() const863 std::size_t Skeleton::getNumSoftBodyNodes() const
864 {
865   return mSoftBodyNodes.size();
866 }
867 
868 //==============================================================================
getNumTrees() const869 std::size_t Skeleton::getNumTrees() const
870 {
871   return mTreeCache.size();
872 }
873 
874 //==============================================================================
getRootBodyNode(std::size_t _treeIdx)875 BodyNode* Skeleton::getRootBodyNode(std::size_t _treeIdx)
876 {
877   if (mTreeCache.size() > _treeIdx)
878     return mTreeCache[_treeIdx].mBodyNodes[0];
879 
880   if (mTreeCache.size() == 0)
881   {
882     dterr << "[Skeleton::getRootBodyNode] Requested a root BodyNode from a "
883           << "Skeleton with no BodyNodes!\n";
884     assert(false);
885   }
886   else
887   {
888     dterr << "[Skeleton::getRootBodyNode] Requested invalid root BodyNode "
889           << "index (" << _treeIdx << ")! Must be less than "
890           << mTreeCache.size() << ".\n";
891     assert(false);
892   }
893 
894   return nullptr;
895 }
896 
897 //==============================================================================
getRootBodyNode(std::size_t _treeIdx) const898 const BodyNode* Skeleton::getRootBodyNode(std::size_t _treeIdx) const
899 {
900   return const_cast<Skeleton*>(this)->getRootBodyNode(_treeIdx);
901 }
902 
903 //==============================================================================
getRootJoint(std::size_t treeIdx)904 Joint* Skeleton::getRootJoint(std::size_t treeIdx)
905 {
906   auto rootBodyNode = getRootBodyNode(treeIdx);
907 
908   if (rootBodyNode)
909     return rootBodyNode->getParentJoint();
910 
911   return nullptr;
912 }
913 
914 //==============================================================================
getRootJoint(std::size_t treeIdx) const915 const Joint* Skeleton::getRootJoint(std::size_t treeIdx) const
916 {
917   return const_cast<Skeleton*>(this)->getRootJoint(treeIdx);
918 }
919 
920 //==============================================================================
getBodyNode(std::size_t _idx)921 BodyNode* Skeleton::getBodyNode(std::size_t _idx)
922 {
923   return common::getVectorObjectIfAvailable<BodyNode*>(
924       _idx, mSkelCache.mBodyNodes);
925 }
926 
927 //==============================================================================
getBodyNode(std::size_t _idx) const928 const BodyNode* Skeleton::getBodyNode(std::size_t _idx) const
929 {
930   return common::getVectorObjectIfAvailable<BodyNode*>(
931       _idx, mSkelCache.mBodyNodes);
932 }
933 
934 //==============================================================================
getSoftBodyNode(std::size_t _idx)935 SoftBodyNode* Skeleton::getSoftBodyNode(std::size_t _idx)
936 {
937   return common::getVectorObjectIfAvailable<SoftBodyNode*>(
938       _idx, mSoftBodyNodes);
939 }
940 
941 //==============================================================================
getSoftBodyNode(std::size_t _idx) const942 const SoftBodyNode* Skeleton::getSoftBodyNode(std::size_t _idx) const
943 {
944   return common::getVectorObjectIfAvailable<SoftBodyNode*>(
945       _idx, mSoftBodyNodes);
946 }
947 
948 //==============================================================================
getBodyNode(const std::string & _name)949 BodyNode* Skeleton::getBodyNode(const std::string& _name)
950 {
951   return mNameMgrForBodyNodes.getObject(_name);
952 }
953 
954 //==============================================================================
getBodyNode(const std::string & _name) const955 const BodyNode* Skeleton::getBodyNode(const std::string& _name) const
956 {
957   return mNameMgrForBodyNodes.getObject(_name);
958 }
959 
960 //==============================================================================
getSoftBodyNode(const std::string & _name)961 SoftBodyNode* Skeleton::getSoftBodyNode(const std::string& _name)
962 {
963   return mNameMgrForSoftBodyNodes.getObject(_name);
964 }
965 
966 //==============================================================================
getSoftBodyNode(const std::string & _name) const967 const SoftBodyNode* Skeleton::getSoftBodyNode(const std::string& _name) const
968 {
969   return mNameMgrForSoftBodyNodes.getObject(_name);
970 }
971 
972 //==============================================================================
973 template <class T>
convertToConstPtrVector(const std::vector<T * > & vec,std::vector<const T * > & const_vec)974 static std::vector<const T*>& convertToConstPtrVector(
975     const std::vector<T*>& vec, std::vector<const T*>& const_vec)
976 {
977   const_vec.resize(vec.size());
978   for (std::size_t i = 0; i < vec.size(); ++i)
979     const_vec[i] = vec[i];
980   return const_vec;
981 }
982 
983 //==============================================================================
getBodyNodes()984 const std::vector<BodyNode*>& Skeleton::getBodyNodes()
985 {
986   return mSkelCache.mBodyNodes;
987 }
988 
989 //==============================================================================
getBodyNodes() const990 const std::vector<const BodyNode*>& Skeleton::getBodyNodes() const
991 {
992   return convertToConstPtrVector<BodyNode>(
993       mSkelCache.mBodyNodes, mSkelCache.mConstBodyNodes);
994 }
995 
996 //==============================================================================
getBodyNodes(const std::string & name)997 std::vector<BodyNode*> Skeleton::getBodyNodes(const std::string& name)
998 {
999   auto bodyNode = getBodyNode(name);
1000 
1001   if (bodyNode)
1002     return {bodyNode};
1003   else
1004     return std::vector<BodyNode*>();
1005 }
1006 
1007 //==============================================================================
getBodyNodes(const std::string & name) const1008 std::vector<const BodyNode*> Skeleton::getBodyNodes(
1009     const std::string& name) const
1010 {
1011   const auto bodyNode = getBodyNode(name);
1012 
1013   if (bodyNode)
1014     return {bodyNode};
1015   else
1016     return std::vector<const BodyNode*>();
1017 }
1018 
1019 //==============================================================================
hasBodyNode(const BodyNode * bodyNode) const1020 bool Skeleton::hasBodyNode(const BodyNode* bodyNode) const
1021 {
1022   return std::find(
1023              mSkelCache.mBodyNodes.begin(),
1024              mSkelCache.mBodyNodes.end(),
1025              bodyNode)
1026          != mSkelCache.mBodyNodes.end();
1027 }
1028 
1029 //==============================================================================
1030 template <class ObjectT, std::size_t (ObjectT::*getIndexInSkeleton)() const>
templatedGetIndexOf(const Skeleton * _skel,const ObjectT * _obj,const std::string & _type,bool _warning)1031 static std::size_t templatedGetIndexOf(
1032     const Skeleton* _skel,
1033     const ObjectT* _obj,
1034     const std::string& _type,
1035     bool _warning)
1036 {
1037   if (nullptr == _obj)
1038   {
1039     if (_warning)
1040     {
1041       dterr << "[Skeleton::getIndexOf] Requesting the index of a nullptr "
1042             << _type << " within the Skeleton [" << _skel->getName() << "] ("
1043             << _skel << ")!\n";
1044       assert(false);
1045     }
1046     return INVALID_INDEX;
1047   }
1048 
1049   if (_skel == _obj->getSkeleton().get())
1050     return (_obj->*getIndexInSkeleton)();
1051 
1052   if (_warning)
1053   {
1054     dterr << "[Skeleton::getIndexOf] Requesting the index of a " << _type
1055           << " [" << _obj->getName() << "] (" << _obj
1056           << ") from a Skeleton that it does "
1057           << "not belong to!\n";
1058     assert(false);
1059   }
1060 
1061   return INVALID_INDEX;
1062 }
1063 
1064 //==============================================================================
getIndexOf(const BodyNode * _bn,bool _warning) const1065 std::size_t Skeleton::getIndexOf(const BodyNode* _bn, bool _warning) const
1066 {
1067   return templatedGetIndexOf<BodyNode, &BodyNode::getIndexInSkeleton>(
1068       this, _bn, "BodyNode", _warning);
1069 }
1070 
1071 //==============================================================================
getTreeBodyNodes(std::size_t _treeIdx)1072 const std::vector<BodyNode*>& Skeleton::getTreeBodyNodes(std::size_t _treeIdx)
1073 {
1074   if (_treeIdx >= mTreeCache.size())
1075   {
1076     std::size_t count = mTreeCache.size();
1077     dterr << "[Skeleton::getTreeBodyNodes] Requesting an invalid tree ("
1078           << _treeIdx << ") "
1079           << (count > 0
1080                   ? (std::string("when the max tree index is (")
1081                      + std::to_string(count - 1) + ")\n")
1082                   : std::string("when there are no trees in this Skeleton\n"));
1083     assert(false);
1084   }
1085 
1086   return mTreeCache[_treeIdx].mBodyNodes;
1087 }
1088 
1089 //==============================================================================
getTreeBodyNodes(std::size_t _treeIdx) const1090 std::vector<const BodyNode*> Skeleton::getTreeBodyNodes(
1091     std::size_t _treeIdx) const
1092 {
1093   return convertToConstPtrVector<BodyNode>(
1094       mTreeCache[_treeIdx].mBodyNodes, mTreeCache[_treeIdx].mConstBodyNodes);
1095 }
1096 
1097 //==============================================================================
getNumJoints() const1098 std::size_t Skeleton::getNumJoints() const
1099 {
1100   // The number of joints and body nodes are identical
1101   return getNumBodyNodes();
1102 }
1103 
1104 //==============================================================================
getJoint(std::size_t _idx)1105 Joint* Skeleton::getJoint(std::size_t _idx)
1106 {
1107   BodyNode* bn = common::getVectorObjectIfAvailable<BodyNode*>(
1108       _idx, mSkelCache.mBodyNodes);
1109   if (bn)
1110     return bn->getParentJoint();
1111 
1112   return nullptr;
1113 }
1114 
1115 //==============================================================================
getJoint(std::size_t _idx) const1116 const Joint* Skeleton::getJoint(std::size_t _idx) const
1117 {
1118   return const_cast<Skeleton*>(this)->getJoint(_idx);
1119 }
1120 
1121 //==============================================================================
getJoint(const std::string & name)1122 Joint* Skeleton::getJoint(const std::string& name)
1123 {
1124   return mNameMgrForJoints.getObject(name);
1125 }
1126 
1127 //==============================================================================
getJoint(const std::string & name) const1128 const Joint* Skeleton::getJoint(const std::string& name) const
1129 {
1130   return mNameMgrForJoints.getObject(name);
1131 }
1132 
1133 //==============================================================================
getJoints()1134 std::vector<Joint*> Skeleton::getJoints()
1135 {
1136   const auto& bodyNodes = getBodyNodes();
1137 
1138   std::vector<Joint*> joints;
1139   joints.reserve(bodyNodes.size());
1140   for (const auto& bodyNode : bodyNodes)
1141     joints.emplace_back(bodyNode->getParentJoint());
1142 
1143   return joints;
1144 }
1145 
1146 //==============================================================================
getJoints() const1147 std::vector<const Joint*> Skeleton::getJoints() const
1148 {
1149   const auto& bodyNodes = getBodyNodes();
1150 
1151   std::vector<const Joint*> joints;
1152   joints.reserve(bodyNodes.size());
1153   for (const auto& bodyNode : bodyNodes)
1154     joints.emplace_back(bodyNode->getParentJoint());
1155 
1156   return joints;
1157 }
1158 
1159 //==============================================================================
getJoints(const std::string & name)1160 std::vector<Joint*> Skeleton::getJoints(const std::string& name)
1161 {
1162   auto joint = getJoint(name);
1163 
1164   if (joint)
1165     return {joint};
1166   else
1167     return std::vector<Joint*>();
1168 }
1169 
1170 //==============================================================================
getJoints(const std::string & name) const1171 std::vector<const Joint*> Skeleton::getJoints(const std::string& name) const
1172 {
1173   const auto joint = getJoint(name);
1174 
1175   if (joint)
1176     return {joint};
1177   else
1178     return std::vector<const Joint*>();
1179 }
1180 
1181 //==============================================================================
hasJoint(const Joint * joint) const1182 bool Skeleton::hasJoint(const Joint* joint) const
1183 {
1184   return std::find_if(
1185              mSkelCache.mBodyNodes.begin(),
1186              mSkelCache.mBodyNodes.end(),
1187              [&joint](const BodyNode* bodyNode) {
1188                return bodyNode->getParentJoint() == joint;
1189              })
1190          != mSkelCache.mBodyNodes.end();
1191 }
1192 
1193 //==============================================================================
getIndexOf(const Joint * _joint,bool _warning) const1194 std::size_t Skeleton::getIndexOf(const Joint* _joint, bool _warning) const
1195 {
1196   return templatedGetIndexOf<Joint, &Joint::getJointIndexInSkeleton>(
1197       this, _joint, "Joint", _warning);
1198 }
1199 
1200 //==============================================================================
getNumDofs() const1201 std::size_t Skeleton::getNumDofs() const
1202 {
1203   return mSkelCache.mDofs.size();
1204 }
1205 
1206 //==============================================================================
getDof(std::size_t _idx)1207 DegreeOfFreedom* Skeleton::getDof(std::size_t _idx)
1208 {
1209   return common::getVectorObjectIfAvailable<DegreeOfFreedom*>(
1210       _idx, mSkelCache.mDofs);
1211 }
1212 
1213 //==============================================================================
getDof(std::size_t _idx) const1214 const DegreeOfFreedom* Skeleton::getDof(std::size_t _idx) const
1215 {
1216   return common::getVectorObjectIfAvailable<DegreeOfFreedom*>(
1217       _idx, mSkelCache.mDofs);
1218 }
1219 
1220 //==============================================================================
getDof(const std::string & _name)1221 DegreeOfFreedom* Skeleton::getDof(const std::string& _name)
1222 {
1223   return mNameMgrForDofs.getObject(_name);
1224 }
1225 
1226 //==============================================================================
getDof(const std::string & _name) const1227 const DegreeOfFreedom* Skeleton::getDof(const std::string& _name) const
1228 {
1229   return mNameMgrForDofs.getObject(_name);
1230 }
1231 
1232 //==============================================================================
getDofs()1233 const std::vector<DegreeOfFreedom*>& Skeleton::getDofs()
1234 {
1235   return mSkelCache.mDofs;
1236 }
1237 
1238 //==============================================================================
getDofs() const1239 std::vector<const DegreeOfFreedom*> Skeleton::getDofs() const
1240 {
1241   return convertToConstPtrVector<DegreeOfFreedom>(
1242       mSkelCache.mDofs, mSkelCache.mConstDofs);
1243 }
1244 
1245 //==============================================================================
getIndexOf(const DegreeOfFreedom * _dof,bool _warning) const1246 std::size_t Skeleton::getIndexOf(
1247     const DegreeOfFreedom* _dof, bool _warning) const
1248 {
1249   return templatedGetIndexOf<
1250       DegreeOfFreedom,
1251       &DegreeOfFreedom::getIndexInSkeleton>(
1252       this, _dof, "DegreeOfFreedom", _warning);
1253 }
1254 
1255 //==============================================================================
getTreeDofs(std::size_t _treeIdx)1256 const std::vector<DegreeOfFreedom*>& Skeleton::getTreeDofs(std::size_t _treeIdx)
1257 {
1258   return mTreeCache[_treeIdx].mDofs;
1259 }
1260 
1261 //==============================================================================
getTreeDofs(std::size_t _treeIdx) const1262 const std::vector<const DegreeOfFreedom*>& Skeleton::getTreeDofs(
1263     std::size_t _treeIdx) const
1264 {
1265   return convertToConstPtrVector<DegreeOfFreedom>(
1266       mTreeCache[_treeIdx].mDofs, mTreeCache[_treeIdx].mConstDofs);
1267 }
1268 
1269 //==============================================================================
checkIndexingConsistency() const1270 bool Skeleton::checkIndexingConsistency() const
1271 {
1272   bool consistent = true;
1273 
1274   // Check each BodyNode in the Skeleton cache
1275   for (std::size_t i = 0; i < mSkelCache.mBodyNodes.size(); ++i)
1276   {
1277     const BodyNode* bn = mSkelCache.mBodyNodes[i];
1278     if (bn->mIndexInSkeleton != i)
1279     {
1280       dterr << "[Skeleton::checkIndexingConsistency] BodyNode named ["
1281             << bn->getName() << "] in Skeleton [" << getName() << "] is "
1282             << "mistaken about its index in the Skeleton (" << i << " | "
1283             << bn->mIndexInSkeleton << "). Please report this as a bug!"
1284             << std::endl;
1285       consistent = false;
1286       assert(false);
1287     }
1288 
1289     const BodyNode* nameEntryForBodyNode = getBodyNode(bn->getName());
1290     if (nameEntryForBodyNode != bn)
1291     {
1292       dterr << "[Skeleton::checkIndexingConsistency] Skeleton named ["
1293             << getName() << "] (" << this << ") is mistaken about the name of "
1294             << "BodyNode [" << bn->getName() << "] (" << bn << "). The name "
1295             << "instead maps to [" << nameEntryForBodyNode->getName() << "] ("
1296             << nameEntryForBodyNode << "). Please report this as a bug!"
1297             << std::endl;
1298       consistent = false;
1299       assert(false);
1300     }
1301 
1302     const Joint* joint = bn->getParentJoint();
1303     const Joint* nameEntryForJoint = getJoint(joint->getName());
1304     if (nameEntryForJoint != joint)
1305     {
1306       dterr << "[Skeleton::checkIndexingConsistency] Skeleton named ["
1307             << getName() << "] (" << this << ") is mistaken about the name of "
1308             << "Joint [" << joint->getName() << "] (" << joint << "). The name "
1309             << "instead maps to [" << nameEntryForJoint->getName() << "] ("
1310             << nameEntryForJoint << "). Please report this as a bug!"
1311             << std::endl;
1312       consistent = false;
1313       assert(false);
1314     }
1315 
1316     const BodyNode::NodeMap& nodeMap = bn->mNodeMap;
1317     for (const auto& nodeType : nodeMap)
1318     {
1319       const std::vector<Node*>& nodes = nodeType.second;
1320       for (std::size_t k = 0; k < nodes.size(); ++k)
1321       {
1322         const Node* node = nodes[k];
1323         if (node->getBodyNodePtr() != bn)
1324         {
1325           dterr << "[Skeleton::checkIndexingConsistency] Node named ["
1326                 << node->getName() << "] (" << node << ") in Skeleton ["
1327                 << getName() << "] (" << this << ") is mistaken about its "
1328                 << "BodyNode [" << node->getBodyNodePtr()->getName() << "] ("
1329                 << node->getBodyNodePtr() << "). Please report this as a bug!"
1330                 << std::endl;
1331           consistent = false;
1332           assert(false);
1333         }
1334 
1335         if (node->mIndexInBodyNode != k)
1336         {
1337           dterr << "[Skeleton::checkIndexingConsistency] Node named ["
1338                 << node->getName() << "] (" << node << ") in Skeleton ["
1339                 << getName() << "] (" << this << ") is mistaken about its "
1340                 << "index in its BodyNode (" << k << "|"
1341                 << node->mIndexInBodyNode << "). Please report this as a bug!"
1342                 << std::endl;
1343           consistent = false;
1344           assert(false);
1345         }
1346 
1347         // TODO(MXG): Consider checking Node names here
1348       }
1349     }
1350   }
1351 
1352   // Check DegreesOfFreedom indexing
1353   for (std::size_t i = 0; i < getNumDofs(); ++i)
1354   {
1355     const DegreeOfFreedom* dof = getDof(i);
1356     if (dof->getIndexInSkeleton() != i)
1357     {
1358       dterr << "[Skeleton::checkIndexingConsistency] DegreeOfFreedom named ["
1359             << dof->getName() << "] (" << dof << ") in Skeleton [" << getName()
1360             << "] (" << this << ") is mistaken about its index "
1361             << "in its Skeleton (" << i << "|" << dof->getIndexInSkeleton()
1362             << "). Please report this as a bug!" << std::endl;
1363       consistent = false;
1364       assert(false);
1365     }
1366 
1367     const DegreeOfFreedom* nameEntryForDof = getDof(dof->getName());
1368     if (nameEntryForDof != dof)
1369     {
1370       dterr << "[Skeleton::checkIndexingConsistency] Skeleton named ["
1371             << getName() << "] (" << this << ") is mistaken about the name of "
1372             << "DegreeOfFreedom [" << dof->getName() << "] (" << dof << "). "
1373             << "The name instead maps to [" << nameEntryForDof->getName()
1374             << "] (" << nameEntryForDof << "). Please report this as a bug!"
1375             << std::endl;
1376       consistent = false;
1377       assert(false);
1378     }
1379   }
1380 
1381   // Check each Node in the Skeleton-scope NodeMap
1382   {
1383     const Skeleton::NodeMap& nodeMap = mNodeMap;
1384     for (const auto& nodeType : nodeMap)
1385     {
1386       const std::vector<Node*>& nodes = nodeType.second;
1387       for (std::size_t k = 0; k < nodes.size(); ++k)
1388       {
1389         const Node* node = nodes[k];
1390         if (node->getSkeleton().get() != this)
1391         {
1392           dterr << "[Skeleton::checkIndexingConsistency] Node named ["
1393                 << node->getName() << "] (" << node << ") in Skeleton ["
1394                 << getName() << "] (" << this << ") is mistaken about its "
1395                 << "Skeleton [" << node->getSkeleton()->getName() << "] ("
1396                 << node->getSkeleton() << "). Please report this as a bug!"
1397                 << std::endl;
1398           consistent = false;
1399           assert(false);
1400         }
1401 
1402         if (node->mIndexInSkeleton != k)
1403         {
1404           dterr << "[Skeleton::checkIndexingConsistency] Node named ["
1405                 << node->getName() << "] (" << node << ") in Skeleton ["
1406                 << getName() << "] (" << this << ") is mistaken about its "
1407                 << "index in its Skeleton (" << k << "|"
1408                 << node->mIndexInSkeleton << "). Please report this as a bug!"
1409                 << std::endl;
1410           consistent = false;
1411           assert(false);
1412         }
1413       }
1414     }
1415   }
1416 
1417   // Check each BodyNode in each Tree cache
1418   for (std::size_t i = 0; i < mTreeCache.size(); ++i)
1419   {
1420     const DataCache& cache = mTreeCache[i];
1421     for (std::size_t j = 0; j < cache.mBodyNodes.size(); ++j)
1422     {
1423       const BodyNode* bn = cache.mBodyNodes[j];
1424       if (bn->mTreeIndex != i)
1425       {
1426         dterr << "[Skeleton::checkIndexingConsistency] BodyNode named ["
1427               << bn->getName() << "] in Skeleton [" << getName() << "] is "
1428               << "mistaken about its tree's index (" << i << "|"
1429               << bn->mTreeIndex << "). Please report this as a bug!"
1430               << std::endl;
1431         consistent = false;
1432         assert(false);
1433       }
1434 
1435       if (bn->mIndexInTree != j)
1436       {
1437         dterr << "[Skeleton::checkIndexingConsistency] BodyNode named ["
1438               << bn->getName() << "] (" << bn << ") in Skeleton [" << getName()
1439               << "] (" << this << ") is mistaken about its index "
1440               << "in the tree (" << j << "|" << bn->mIndexInTree << "). Please "
1441               << "report this as a bug!" << std::endl;
1442         consistent = false;
1443         assert(false);
1444       }
1445     }
1446 
1447     for (std::size_t j = 0; j < cache.mDofs.size(); ++j)
1448     {
1449       const DegreeOfFreedom* dof = cache.mDofs[j];
1450       if (dof->getTreeIndex() != i)
1451       {
1452         dterr << "[Skeleton::checkIndexingConsistency] DegreeOfFreedom named ["
1453               << dof->getName() << "] (" << dof << ") in Skeleton ["
1454               << getName() << "] (" << this << ") is mistaken about its tree's "
1455               << "index (" << i << "|" << dof->getTreeIndex() << "). Please "
1456               << "report this as a bug!" << std::endl;
1457         consistent = false;
1458         assert(false);
1459       }
1460     }
1461   }
1462 
1463   // Check that the Tree cache and the number of Tree NodeMaps match up
1464   if (mTreeCache.size() != mTreeNodeMaps.size())
1465   {
1466     consistent = false;
1467     dterr << "[Skeleton::checkIndexingConsistency] Skeleton named ["
1468           << getName() << "] (" << this << ") has inconsistent tree cache "
1469           << " and tree Node map sizes (" << mTreeCache.size() << "|"
1470           << mTreeNodeMaps.size() << "). Please report this as a bug!"
1471           << std::endl;
1472     assert(false);
1473   }
1474 
1475   // Check each Node in the NodeMap of each Tree
1476   for (std::size_t i = 0; i < mTreeNodeMaps.size(); ++i)
1477   {
1478     const NodeMap& nodeMap = mTreeNodeMaps[i];
1479 
1480     for (const auto& nodeType : nodeMap)
1481     {
1482       const std::vector<Node*>& nodes = nodeType.second;
1483       for (std::size_t k = 0; k < nodes.size(); ++k)
1484       {
1485         const Node* node = nodes[k];
1486         if (node->getBodyNodePtr()->mTreeIndex != i)
1487         {
1488           dterr << "[Skeleton::checkIndexingConsistency] Node named ["
1489                 << node->getName() << "] (" << node << ") in Skeleton ["
1490                 << getName() << "] (" << this << ") is mistaken about its "
1491                 << "Tree Index (" << i << "|"
1492                 << node->getBodyNodePtr()->mTreeIndex << "). Please report "
1493                 << "this as a bug!" << std::endl;
1494           consistent = false;
1495           assert(false);
1496         }
1497 
1498         if (node->mIndexInTree != k)
1499         {
1500           dterr << "[Skeleton::checkIndexingConsistency] Node named ["
1501                 << node->getName() << "] (" << node << ") in Skeleton ["
1502                 << getName() << "] (" << this << ") is mistaken about its "
1503                 << "index in its tree (" << k << "|" << node->mIndexInTree
1504                 << "). Please report this as a bug!" << std::endl;
1505           consistent = false;
1506           assert(false);
1507         }
1508       }
1509     }
1510   }
1511 
1512   return consistent;
1513 }
1514 
1515 //==============================================================================
getIK(bool _createIfNull)1516 const std::shared_ptr<WholeBodyIK>& Skeleton::getIK(bool _createIfNull)
1517 {
1518   if (nullptr == mWholeBodyIK && _createIfNull)
1519     createIK();
1520 
1521   return mWholeBodyIK;
1522 }
1523 
1524 //==============================================================================
getOrCreateIK()1525 const std::shared_ptr<WholeBodyIK>& Skeleton::getOrCreateIK()
1526 {
1527   return getIK(true);
1528 }
1529 
1530 //==============================================================================
getIK() const1531 std::shared_ptr<const WholeBodyIK> Skeleton::getIK() const
1532 {
1533   return mWholeBodyIK;
1534 }
1535 
1536 //==============================================================================
createIK()1537 const std::shared_ptr<WholeBodyIK>& Skeleton::createIK()
1538 {
1539   mWholeBodyIK = WholeBodyIK::create(mPtr.lock());
1540   return mWholeBodyIK;
1541 }
1542 
1543 //==============================================================================
clearIK()1544 void Skeleton::clearIK()
1545 {
1546   mWholeBodyIK = nullptr;
1547 }
1548 
1549 //==============================================================================
DART_BAKE_SPECIALIZED_NODE_SKEL_DEFINITIONS(Skeleton,Marker)1550 DART_BAKE_SPECIALIZED_NODE_SKEL_DEFINITIONS(Skeleton, Marker)
1551 
1552 //==============================================================================
1553 DART_BAKE_SPECIALIZED_NODE_SKEL_DEFINITIONS(Skeleton, ShapeNode)
1554 
1555 //==============================================================================
1556 DART_BAKE_SPECIALIZED_NODE_SKEL_DEFINITIONS(Skeleton, EndEffector)
1557 
1558 //==============================================================================
1559 void Skeleton::integratePositions(double _dt)
1560 {
1561   for (std::size_t i = 0; i < mSkelCache.mBodyNodes.size(); ++i)
1562     mSkelCache.mBodyNodes[i]->getParentJoint()->integratePositions(_dt);
1563 
1564   for (std::size_t i = 0; i < mSoftBodyNodes.size(); ++i)
1565   {
1566     for (std::size_t j = 0; j < mSoftBodyNodes[i]->getNumPointMasses(); ++j)
1567       mSoftBodyNodes[i]->getPointMass(j)->integratePositions(_dt);
1568   }
1569 }
1570 
1571 //==============================================================================
integrateVelocities(double _dt)1572 void Skeleton::integrateVelocities(double _dt)
1573 {
1574   for (std::size_t i = 0; i < mSkelCache.mBodyNodes.size(); ++i)
1575     mSkelCache.mBodyNodes[i]->getParentJoint()->integrateVelocities(_dt);
1576 
1577   for (std::size_t i = 0; i < mSoftBodyNodes.size(); ++i)
1578   {
1579     for (std::size_t j = 0; j < mSoftBodyNodes[i]->getNumPointMasses(); ++j)
1580       mSoftBodyNodes[i]->getPointMass(j)->integrateVelocities(_dt);
1581   }
1582 }
1583 
1584 //==============================================================================
getPositionDifferences(const Eigen::VectorXd & _q2,const Eigen::VectorXd & _q1) const1585 Eigen::VectorXd Skeleton::getPositionDifferences(
1586     const Eigen::VectorXd& _q2, const Eigen::VectorXd& _q1) const
1587 {
1588   if (static_cast<std::size_t>(_q2.size()) != getNumDofs()
1589       || static_cast<std::size_t>(_q1.size()) != getNumDofs())
1590   {
1591     dterr << "Skeleton::getPositionsDifference: q1's size[" << _q1.size()
1592           << "] or q2's size[" << _q2.size() << "is different with the dof ["
1593           << getNumDofs() << "]." << std::endl;
1594     return Eigen::VectorXd::Zero(getNumDofs());
1595   }
1596 
1597   Eigen::VectorXd dq(getNumDofs());
1598 
1599   for (const auto& bodyNode : mSkelCache.mBodyNodes)
1600   {
1601     const Joint* joint = bodyNode->getParentJoint();
1602     const std::size_t dof = joint->getNumDofs();
1603 
1604     if (dof)
1605     {
1606       std::size_t index = joint->getDof(0)->getIndexInSkeleton();
1607       const Eigen::VectorXd& q2Seg = _q2.segment(index, dof);
1608       const Eigen::VectorXd& q1Seg = _q1.segment(index, dof);
1609       dq.segment(index, dof) = joint->getPositionDifferences(q2Seg, q1Seg);
1610     }
1611   }
1612 
1613   return dq;
1614 }
1615 
1616 //==============================================================================
getVelocityDifferences(const Eigen::VectorXd & _dq2,const Eigen::VectorXd & _dq1) const1617 Eigen::VectorXd Skeleton::getVelocityDifferences(
1618     const Eigen::VectorXd& _dq2, const Eigen::VectorXd& _dq1) const
1619 {
1620   if (static_cast<std::size_t>(_dq2.size()) != getNumDofs()
1621       || static_cast<std::size_t>(_dq1.size()) != getNumDofs())
1622   {
1623     dterr << "Skeleton::getPositionsDifference: dq1's size[" << _dq1.size()
1624           << "] or dq2's size[" << _dq2.size() << "is different with the dof ["
1625           << getNumDofs() << "]." << std::endl;
1626     return Eigen::VectorXd::Zero(getNumDofs());
1627   }
1628 
1629   // All the tangent spaces of Joint's configuration spaces are vector spaces.
1630   return _dq2 - _dq1;
1631 }
1632 
1633 //==============================================================================
isValidBodyNode(const Skeleton * _skeleton,const JacobianNode * _node,const std::string & _fname)1634 static bool isValidBodyNode(
1635     const Skeleton* _skeleton,
1636     const JacobianNode* _node,
1637     const std::string& _fname)
1638 {
1639   if (nullptr == _node)
1640   {
1641     dtwarn << "[Skeleton::" << _fname << "] Invalid BodyNode pointer: "
1642            << "nullptr. Returning zero Jacobian.\n";
1643     assert(false);
1644     return false;
1645   }
1646 
1647   // The given BodyNode should be in the Skeleton
1648   if (_node->getSkeleton().get() != _skeleton)
1649   {
1650     dtwarn << "[Skeleton::" << _fname
1651            << "] Attempting to get a Jacobian for a "
1652               "BodyNode ["
1653            << _node->getName() << "] (" << _node
1654            << ") that is not in this Skeleton [" << _skeleton->getName()
1655            << "] (" << _skeleton << "). Returning zero Jacobian.\n";
1656     assert(false);
1657     return false;
1658   }
1659 
1660   return true;
1661 }
1662 
1663 //==============================================================================
1664 template <typename JacobianType>
assignJacobian(JacobianType & _J,const JacobianNode * _node,const JacobianType & _JBodyNode)1665 void assignJacobian(
1666     JacobianType& _J, const JacobianNode* _node, const JacobianType& _JBodyNode)
1667 {
1668   // Assign the BodyNode's Jacobian to the result Jacobian.
1669   std::size_t localIndex = 0;
1670   const auto& indices = _node->getDependentGenCoordIndices();
1671   for (const auto& index : indices)
1672   {
1673     // Each index should be less than the number of dofs of this Skeleton.
1674     assert(index < _node->getSkeleton()->getNumDofs());
1675 
1676     _J.col(index) = _JBodyNode.col(localIndex++);
1677   }
1678 }
1679 
1680 //==============================================================================
1681 template <typename... Args>
variadicGetJacobian(const Skeleton * _skel,const JacobianNode * _node,Args...args)1682 math::Jacobian variadicGetJacobian(
1683     const Skeleton* _skel, const JacobianNode* _node, Args... args)
1684 {
1685   math::Jacobian J = math::Jacobian::Zero(6, _skel->getNumDofs());
1686 
1687   if (!isValidBodyNode(_skel, _node, "getJacobian"))
1688     return J;
1689 
1690   const math::Jacobian JBodyNode = _node->getJacobian(args...);
1691 
1692   assignJacobian<math::Jacobian>(J, _node, JBodyNode);
1693 
1694   return J;
1695 }
1696 
1697 //==============================================================================
getJacobian(const JacobianNode * _node) const1698 math::Jacobian Skeleton::getJacobian(const JacobianNode* _node) const
1699 {
1700   return variadicGetJacobian(this, _node);
1701 }
1702 
1703 //==============================================================================
getJacobian(const JacobianNode * _node,const Frame * _inCoordinatesOf) const1704 math::Jacobian Skeleton::getJacobian(
1705     const JacobianNode* _node, const Frame* _inCoordinatesOf) const
1706 {
1707   return variadicGetJacobian(this, _node, _inCoordinatesOf);
1708 }
1709 
1710 //==============================================================================
getJacobian(const JacobianNode * _node,const Eigen::Vector3d & _localOffset) const1711 math::Jacobian Skeleton::getJacobian(
1712     const JacobianNode* _node, const Eigen::Vector3d& _localOffset) const
1713 {
1714   return variadicGetJacobian(this, _node, _localOffset);
1715 }
1716 
1717 //==============================================================================
getJacobian(const JacobianNode * _node,const Eigen::Vector3d & _localOffset,const Frame * _inCoordinatesOf) const1718 math::Jacobian Skeleton::getJacobian(
1719     const JacobianNode* _node,
1720     const Eigen::Vector3d& _localOffset,
1721     const Frame* _inCoordinatesOf) const
1722 {
1723   return variadicGetJacobian(this, _node, _localOffset, _inCoordinatesOf);
1724 }
1725 
1726 //==============================================================================
1727 template <typename... Args>
variadicGetWorldJacobian(const Skeleton * _skel,const JacobianNode * _node,Args...args)1728 math::Jacobian variadicGetWorldJacobian(
1729     const Skeleton* _skel, const JacobianNode* _node, Args... args)
1730 {
1731   math::Jacobian J = math::Jacobian::Zero(6, _skel->getNumDofs());
1732 
1733   if (!isValidBodyNode(_skel, _node, "getWorldJacobian"))
1734     return J;
1735 
1736   const math::Jacobian JBodyNode = _node->getWorldJacobian(args...);
1737 
1738   assignJacobian<math::Jacobian>(J, _node, JBodyNode);
1739 
1740   return J;
1741 }
1742 
1743 //==============================================================================
getWorldJacobian(const JacobianNode * _node) const1744 math::Jacobian Skeleton::getWorldJacobian(const JacobianNode* _node) const
1745 {
1746   return variadicGetWorldJacobian(this, _node);
1747 }
1748 
1749 //==============================================================================
getWorldJacobian(const JacobianNode * _node,const Eigen::Vector3d & _localOffset) const1750 math::Jacobian Skeleton::getWorldJacobian(
1751     const JacobianNode* _node, const Eigen::Vector3d& _localOffset) const
1752 {
1753   return variadicGetWorldJacobian(this, _node, _localOffset);
1754 }
1755 
1756 //==============================================================================
1757 template <typename... Args>
variadicGetLinearJacobian(const Skeleton * _skel,const JacobianNode * _node,Args...args)1758 math::LinearJacobian variadicGetLinearJacobian(
1759     const Skeleton* _skel, const JacobianNode* _node, Args... args)
1760 {
1761   math::LinearJacobian J = math::LinearJacobian::Zero(3, _skel->getNumDofs());
1762 
1763   if (!isValidBodyNode(_skel, _node, "getLinearJacobian"))
1764     return J;
1765 
1766   const math::LinearJacobian JBodyNode = _node->getLinearJacobian(args...);
1767 
1768   assignJacobian<math::LinearJacobian>(J, _node, JBodyNode);
1769 
1770   return J;
1771 }
1772 
1773 //==============================================================================
getLinearJacobian(const JacobianNode * _node,const Frame * _inCoordinatesOf) const1774 math::LinearJacobian Skeleton::getLinearJacobian(
1775     const JacobianNode* _node, const Frame* _inCoordinatesOf) const
1776 {
1777   return variadicGetLinearJacobian(this, _node, _inCoordinatesOf);
1778 }
1779 
1780 //==============================================================================
getLinearJacobian(const JacobianNode * _node,const Eigen::Vector3d & _localOffset,const Frame * _inCoordinatesOf) const1781 math::LinearJacobian Skeleton::getLinearJacobian(
1782     const JacobianNode* _node,
1783     const Eigen::Vector3d& _localOffset,
1784     const Frame* _inCoordinatesOf) const
1785 {
1786   return variadicGetLinearJacobian(this, _node, _localOffset, _inCoordinatesOf);
1787 }
1788 
1789 //==============================================================================
1790 template <typename... Args>
variadicGetAngularJacobian(const Skeleton * _skel,const JacobianNode * _node,Args...args)1791 math::AngularJacobian variadicGetAngularJacobian(
1792     const Skeleton* _skel, const JacobianNode* _node, Args... args)
1793 {
1794   math::AngularJacobian J = math::AngularJacobian::Zero(3, _skel->getNumDofs());
1795 
1796   if (!isValidBodyNode(_skel, _node, "getAngularJacobian"))
1797     return J;
1798 
1799   const math::AngularJacobian JBodyNode = _node->getAngularJacobian(args...);
1800 
1801   assignJacobian<math::AngularJacobian>(J, _node, JBodyNode);
1802 
1803   return J;
1804 }
1805 
1806 //==============================================================================
getAngularJacobian(const JacobianNode * _node,const Frame * _inCoordinatesOf) const1807 math::AngularJacobian Skeleton::getAngularJacobian(
1808     const JacobianNode* _node, const Frame* _inCoordinatesOf) const
1809 {
1810   return variadicGetAngularJacobian(this, _node, _inCoordinatesOf);
1811 }
1812 
1813 //==============================================================================
1814 template <typename... Args>
variadicGetJacobianSpatialDeriv(const Skeleton * _skel,const JacobianNode * _node,Args...args)1815 math::Jacobian variadicGetJacobianSpatialDeriv(
1816     const Skeleton* _skel, const JacobianNode* _node, Args... args)
1817 {
1818   math::Jacobian dJ = math::Jacobian::Zero(6, _skel->getNumDofs());
1819 
1820   if (!isValidBodyNode(_skel, _node, "getJacobianSpatialDeriv"))
1821     return dJ;
1822 
1823   const math::Jacobian dJBodyNode = _node->getJacobianSpatialDeriv(args...);
1824 
1825   assignJacobian<math::Jacobian>(dJ, _node, dJBodyNode);
1826 
1827   return dJ;
1828 }
1829 
1830 //==============================================================================
getJacobianSpatialDeriv(const JacobianNode * _node) const1831 math::Jacobian Skeleton::getJacobianSpatialDeriv(
1832     const JacobianNode* _node) const
1833 {
1834   return variadicGetJacobianSpatialDeriv(this, _node);
1835 }
1836 
1837 //==============================================================================
getJacobianSpatialDeriv(const JacobianNode * _node,const Frame * _inCoordinatesOf) const1838 math::Jacobian Skeleton::getJacobianSpatialDeriv(
1839     const JacobianNode* _node, const Frame* _inCoordinatesOf) const
1840 {
1841   return variadicGetJacobianSpatialDeriv(this, _node, _inCoordinatesOf);
1842 }
1843 
1844 //==============================================================================
getJacobianSpatialDeriv(const JacobianNode * _node,const Eigen::Vector3d & _localOffset) const1845 math::Jacobian Skeleton::getJacobianSpatialDeriv(
1846     const JacobianNode* _node, const Eigen::Vector3d& _localOffset) const
1847 {
1848   return variadicGetJacobianSpatialDeriv(this, _node, _localOffset);
1849 }
1850 
1851 //==============================================================================
getJacobianSpatialDeriv(const JacobianNode * _node,const Eigen::Vector3d & _localOffset,const Frame * _inCoordinatesOf) const1852 math::Jacobian Skeleton::getJacobianSpatialDeriv(
1853     const JacobianNode* _node,
1854     const Eigen::Vector3d& _localOffset,
1855     const Frame* _inCoordinatesOf) const
1856 {
1857   return variadicGetJacobianSpatialDeriv(
1858       this, _node, _localOffset, _inCoordinatesOf);
1859 }
1860 
1861 //==============================================================================
1862 template <typename... Args>
variadicGetJacobianClassicDeriv(const Skeleton * _skel,const JacobianNode * _node,Args...args)1863 math::Jacobian variadicGetJacobianClassicDeriv(
1864     const Skeleton* _skel, const JacobianNode* _node, Args... args)
1865 {
1866   math::Jacobian dJ = math::Jacobian::Zero(6, _skel->getNumDofs());
1867 
1868   if (!isValidBodyNode(_skel, _node, "getJacobianClassicDeriv"))
1869     return dJ;
1870 
1871   const math::Jacobian dJBodyNode = _node->getJacobianClassicDeriv(args...);
1872 
1873   assignJacobian<math::Jacobian>(dJ, _node, dJBodyNode);
1874 
1875   return dJ;
1876 }
1877 
1878 //==============================================================================
getJacobianClassicDeriv(const JacobianNode * _node) const1879 math::Jacobian Skeleton::getJacobianClassicDeriv(
1880     const JacobianNode* _node) const
1881 {
1882   return variadicGetJacobianClassicDeriv(this, _node);
1883 }
1884 
1885 //==============================================================================
getJacobianClassicDeriv(const JacobianNode * _node,const Frame * _inCoordinatesOf) const1886 math::Jacobian Skeleton::getJacobianClassicDeriv(
1887     const JacobianNode* _node, const Frame* _inCoordinatesOf) const
1888 {
1889   return variadicGetJacobianClassicDeriv(this, _node, _inCoordinatesOf);
1890 }
1891 
1892 //==============================================================================
getJacobianClassicDeriv(const JacobianNode * _node,const Eigen::Vector3d & _localOffset,const Frame * _inCoordinatesOf) const1893 math::Jacobian Skeleton::getJacobianClassicDeriv(
1894     const JacobianNode* _node,
1895     const Eigen::Vector3d& _localOffset,
1896     const Frame* _inCoordinatesOf) const
1897 {
1898   return variadicGetJacobianClassicDeriv(
1899       this, _node, _localOffset, _inCoordinatesOf);
1900 }
1901 
1902 //==============================================================================
1903 template <typename... Args>
variadicGetLinearJacobianDeriv(const Skeleton * _skel,const JacobianNode * _node,Args...args)1904 math::LinearJacobian variadicGetLinearJacobianDeriv(
1905     const Skeleton* _skel, const JacobianNode* _node, Args... args)
1906 {
1907   math::LinearJacobian dJv = math::LinearJacobian::Zero(3, _skel->getNumDofs());
1908 
1909   if (!isValidBodyNode(_skel, _node, "getLinearJacobianDeriv"))
1910     return dJv;
1911 
1912   const math::LinearJacobian dJvBodyNode
1913       = _node->getLinearJacobianDeriv(args...);
1914 
1915   assignJacobian<math::LinearJacobian>(dJv, _node, dJvBodyNode);
1916 
1917   return dJv;
1918 }
1919 
1920 //==============================================================================
getLinearJacobianDeriv(const JacobianNode * _node,const Frame * _inCoordinatesOf) const1921 math::LinearJacobian Skeleton::getLinearJacobianDeriv(
1922     const JacobianNode* _node, const Frame* _inCoordinatesOf) const
1923 {
1924   return variadicGetLinearJacobianDeriv(this, _node, _inCoordinatesOf);
1925 }
1926 
1927 //==============================================================================
getLinearJacobianDeriv(const JacobianNode * _node,const Eigen::Vector3d & _localOffset,const Frame * _inCoordinatesOf) const1928 math::LinearJacobian Skeleton::getLinearJacobianDeriv(
1929     const JacobianNode* _node,
1930     const Eigen::Vector3d& _localOffset,
1931     const Frame* _inCoordinatesOf) const
1932 {
1933   return variadicGetLinearJacobianDeriv(
1934       this, _node, _localOffset, _inCoordinatesOf);
1935 }
1936 
1937 //==============================================================================
1938 template <typename... Args>
variadicGetAngularJacobianDeriv(const Skeleton * _skel,const JacobianNode * _node,Args...args)1939 math::AngularJacobian variadicGetAngularJacobianDeriv(
1940     const Skeleton* _skel, const JacobianNode* _node, Args... args)
1941 {
1942   math::AngularJacobian dJw
1943       = math::AngularJacobian::Zero(3, _skel->getNumDofs());
1944 
1945   if (!isValidBodyNode(_skel, _node, "getAngularJacobianDeriv"))
1946     return dJw;
1947 
1948   const math::AngularJacobian dJwBodyNode
1949       = _node->getAngularJacobianDeriv(args...);
1950 
1951   assignJacobian<math::AngularJacobian>(dJw, _node, dJwBodyNode);
1952 
1953   return dJw;
1954 }
1955 
1956 //==============================================================================
getAngularJacobianDeriv(const JacobianNode * _node,const Frame * _inCoordinatesOf) const1957 math::AngularJacobian Skeleton::getAngularJacobianDeriv(
1958     const JacobianNode* _node, const Frame* _inCoordinatesOf) const
1959 {
1960   return variadicGetAngularJacobianDeriv(this, _node, _inCoordinatesOf);
1961 }
1962 
1963 //==============================================================================
getMass() const1964 double Skeleton::getMass() const
1965 {
1966   return mTotalMass;
1967 }
1968 
1969 //==============================================================================
getMassMatrix(std::size_t _treeIdx) const1970 const Eigen::MatrixXd& Skeleton::getMassMatrix(std::size_t _treeIdx) const
1971 {
1972   if (mTreeCache[_treeIdx].mDirty.mMassMatrix)
1973     updateMassMatrix(_treeIdx);
1974   return mTreeCache[_treeIdx].mM;
1975 }
1976 
1977 //==============================================================================
getMassMatrix() const1978 const Eigen::MatrixXd& Skeleton::getMassMatrix() const
1979 {
1980   if (mSkelCache.mDirty.mMassMatrix)
1981     updateMassMatrix();
1982   return mSkelCache.mM;
1983 }
1984 
1985 //==============================================================================
getAugMassMatrix(std::size_t _treeIdx) const1986 const Eigen::MatrixXd& Skeleton::getAugMassMatrix(std::size_t _treeIdx) const
1987 {
1988   if (mTreeCache[_treeIdx].mDirty.mAugMassMatrix)
1989     updateAugMassMatrix(_treeIdx);
1990 
1991   return mTreeCache[_treeIdx].mAugM;
1992 }
1993 
1994 //==============================================================================
getAugMassMatrix() const1995 const Eigen::MatrixXd& Skeleton::getAugMassMatrix() const
1996 {
1997   if (mSkelCache.mDirty.mAugMassMatrix)
1998     updateAugMassMatrix();
1999 
2000   return mSkelCache.mAugM;
2001 }
2002 
2003 //==============================================================================
getInvMassMatrix(std::size_t _treeIdx) const2004 const Eigen::MatrixXd& Skeleton::getInvMassMatrix(std::size_t _treeIdx) const
2005 {
2006   if (mTreeCache[_treeIdx].mDirty.mInvMassMatrix)
2007     updateInvMassMatrix(_treeIdx);
2008 
2009   return mTreeCache[_treeIdx].mInvM;
2010 }
2011 
2012 //==============================================================================
getInvMassMatrix() const2013 const Eigen::MatrixXd& Skeleton::getInvMassMatrix() const
2014 {
2015   if (mSkelCache.mDirty.mInvMassMatrix)
2016     updateInvMassMatrix();
2017 
2018   return mSkelCache.mInvM;
2019 }
2020 
2021 //==============================================================================
getInvAugMassMatrix(std::size_t _treeIdx) const2022 const Eigen::MatrixXd& Skeleton::getInvAugMassMatrix(std::size_t _treeIdx) const
2023 {
2024   if (mTreeCache[_treeIdx].mDirty.mInvAugMassMatrix)
2025     updateInvAugMassMatrix(_treeIdx);
2026 
2027   return mTreeCache[_treeIdx].mInvAugM;
2028 }
2029 
2030 //==============================================================================
getInvAugMassMatrix() const2031 const Eigen::MatrixXd& Skeleton::getInvAugMassMatrix() const
2032 {
2033   if (mSkelCache.mDirty.mInvAugMassMatrix)
2034     updateInvAugMassMatrix();
2035 
2036   return mSkelCache.mInvAugM;
2037 }
2038 
2039 //==============================================================================
getCoriolisForces(std::size_t _treeIdx) const2040 const Eigen::VectorXd& Skeleton::getCoriolisForces(std::size_t _treeIdx) const
2041 {
2042   if (mTreeCache[_treeIdx].mDirty.mCoriolisForces)
2043     updateCoriolisForces(_treeIdx);
2044 
2045   return mTreeCache[_treeIdx].mCvec;
2046 }
2047 
2048 //==============================================================================
getCoriolisForces() const2049 const Eigen::VectorXd& Skeleton::getCoriolisForces() const
2050 {
2051   if (mSkelCache.mDirty.mCoriolisForces)
2052     updateCoriolisForces();
2053 
2054   return mSkelCache.mCvec;
2055 }
2056 
2057 //==============================================================================
getGravityForces(std::size_t _treeIdx) const2058 const Eigen::VectorXd& Skeleton::getGravityForces(std::size_t _treeIdx) const
2059 {
2060   if (mTreeCache[_treeIdx].mDirty.mGravityForces)
2061     updateGravityForces(_treeIdx);
2062 
2063   return mTreeCache[_treeIdx].mG;
2064 }
2065 
2066 //==============================================================================
getGravityForces() const2067 const Eigen::VectorXd& Skeleton::getGravityForces() const
2068 {
2069   if (mSkelCache.mDirty.mGravityForces)
2070     updateGravityForces();
2071 
2072   return mSkelCache.mG;
2073 }
2074 
2075 //==============================================================================
getCoriolisAndGravityForces(std::size_t _treeIdx) const2076 const Eigen::VectorXd& Skeleton::getCoriolisAndGravityForces(
2077     std::size_t _treeIdx) const
2078 {
2079   if (mTreeCache[_treeIdx].mDirty.mCoriolisAndGravityForces)
2080     updateCoriolisAndGravityForces(_treeIdx);
2081 
2082   return mTreeCache[_treeIdx].mCg;
2083 }
2084 
2085 //==============================================================================
getCoriolisAndGravityForces() const2086 const Eigen::VectorXd& Skeleton::getCoriolisAndGravityForces() const
2087 {
2088   if (mSkelCache.mDirty.mCoriolisAndGravityForces)
2089     updateCoriolisAndGravityForces();
2090 
2091   return mSkelCache.mCg;
2092 }
2093 
2094 //==============================================================================
getExternalForces(std::size_t _treeIdx) const2095 const Eigen::VectorXd& Skeleton::getExternalForces(std::size_t _treeIdx) const
2096 {
2097   if (mTreeCache[_treeIdx].mDirty.mExternalForces)
2098     updateExternalForces(_treeIdx);
2099 
2100   return mTreeCache[_treeIdx].mFext;
2101 }
2102 
2103 //==============================================================================
getExternalForces() const2104 const Eigen::VectorXd& Skeleton::getExternalForces() const
2105 {
2106   if (mSkelCache.mDirty.mExternalForces)
2107     updateExternalForces();
2108 
2109   return mSkelCache.mFext;
2110 }
2111 
2112 //==============================================================================
getConstraintForces(std::size_t _treeIdx) const2113 const Eigen::VectorXd& Skeleton::getConstraintForces(std::size_t _treeIdx) const
2114 {
2115   return computeConstraintForces(mTreeCache[_treeIdx]);
2116 }
2117 
2118 //==============================================================================
getConstraintForces() const2119 const Eigen::VectorXd& Skeleton::getConstraintForces() const
2120 {
2121   return computeConstraintForces(mSkelCache);
2122 }
2123 
2124 //==============================================================================
2125 // const Eigen::VectorXd& Skeleton::getDampingForceVector() {
2126 //  if (mIsDampingForceVectorDirty)
2127 //    updateDampingForceVector();
2128 //  return mFd;
2129 //}
2130 
2131 //==============================================================================
Skeleton(const AspectPropertiesData & properties)2132 Skeleton::Skeleton(const AspectPropertiesData& properties)
2133   : mTotalMass(0.0), mIsImpulseApplied(false), mUnionSize(1)
2134 {
2135   createAspect<Aspect>(properties);
2136   createAspect<detail::BodyNodeVectorProxyAspect>();
2137   createAspect<detail::JointVectorProxyAspect>();
2138 
2139   updateNameManagerNames();
2140 }
2141 
2142 //==============================================================================
setPtr(const SkeletonPtr & _ptr)2143 void Skeleton::setPtr(const SkeletonPtr& _ptr)
2144 {
2145   mPtr = _ptr;
2146   resetUnion();
2147 }
2148 
2149 //==============================================================================
constructNewTree()2150 void Skeleton::constructNewTree()
2151 {
2152   mTreeCache.push_back(DataCache());
2153 
2154   mTreeNodeMaps.push_back(NodeMap());
2155   NodeMap& nodeMap = mTreeNodeMaps.back();
2156 
2157   // Create the machinery needed to directly call on specialized node types
2158   for (auto& nodeType : mSpecializedTreeNodes)
2159   {
2160     const std::type_index& index = nodeType.first;
2161     nodeMap[index] = std::vector<Node*>();
2162 
2163     std::vector<NodeMap::iterator>* nodeVec = nodeType.second;
2164     nodeVec->push_back(nodeMap.find(index));
2165 
2166     assert(nodeVec->size() == mTreeCache.size());
2167   }
2168 }
2169 
2170 //==============================================================================
registerBodyNode(BodyNode * _newBodyNode)2171 void Skeleton::registerBodyNode(BodyNode* _newBodyNode)
2172 {
2173 #ifndef NDEBUG // Debug mode
2174   std::vector<BodyNode*>::iterator repeat = std::find(
2175       mSkelCache.mBodyNodes.begin(), mSkelCache.mBodyNodes.end(), _newBodyNode);
2176   if (repeat != mSkelCache.mBodyNodes.end())
2177   {
2178     dterr << "[Skeleton::registerBodyNode] Attempting to double-register the "
2179           << "BodyNode named [" << _newBodyNode->getName() << "] in the "
2180           << "Skeleton named [" << getName() << "]. Please report this as a "
2181           << "bug!\n";
2182     assert(false);
2183     return;
2184   }
2185 #endif // -------- Debug mode
2186 
2187   mSkelCache.mBodyNodes.push_back(_newBodyNode);
2188   if (nullptr == _newBodyNode->getParentBodyNode())
2189   {
2190     // Create a new tree and add the new BodyNode to it
2191     _newBodyNode->mIndexInTree = 0;
2192     constructNewTree();
2193     mTreeCache.back().mBodyNodes.push_back(_newBodyNode);
2194     _newBodyNode->mTreeIndex = mTreeCache.size() - 1;
2195   }
2196   else
2197   {
2198     std::size_t tree = _newBodyNode->getParentBodyNode()->getTreeIndex();
2199     _newBodyNode->mTreeIndex = tree;
2200     DataCache& cache = mTreeCache[tree];
2201     cache.mBodyNodes.push_back(_newBodyNode);
2202     _newBodyNode->mIndexInTree = cache.mBodyNodes.size() - 1;
2203   }
2204 
2205   _newBodyNode->mSkeleton = getPtr();
2206   _newBodyNode->mIndexInSkeleton = mSkelCache.mBodyNodes.size() - 1;
2207   addEntryToBodyNodeNameMgr(_newBodyNode);
2208   registerJoint(_newBodyNode->getParentJoint());
2209 
2210   SoftBodyNode* softBodyNode = dynamic_cast<SoftBodyNode*>(_newBodyNode);
2211   if (softBodyNode)
2212   {
2213     mSoftBodyNodes.push_back(softBodyNode);
2214     addEntryToSoftBodyNodeNameMgr(softBodyNode);
2215   }
2216 
2217   _newBodyNode->init(getPtr());
2218 
2219   BodyNode::NodeMap& nodeMap = _newBodyNode->mNodeMap;
2220   for (auto& nodeType : nodeMap)
2221     for (auto& node : nodeType.second)
2222       registerNode(node);
2223 
2224   updateTotalMass();
2225   updateCacheDimensions(_newBodyNode->mTreeIndex);
2226 
2227 #ifndef NDEBUG // Debug mode
2228   for (std::size_t i = 0; i < mSkelCache.mBodyNodes.size(); ++i)
2229   {
2230     if (mSkelCache.mBodyNodes[i]->mIndexInSkeleton != i)
2231     {
2232       dterr << "[Skeleton::registerBodyNode] BodyNode named ["
2233             << mSkelCache.mBodyNodes[i]->getName() << "] in Skeleton ["
2234             << getName() << "] is mistaken about its index in the Skeleton ( "
2235             << i << " : " << mSkelCache.mBodyNodes[i]->mIndexInSkeleton
2236             << "). Please report this as a bug!\n";
2237       assert(false);
2238     }
2239   }
2240 
2241   for (std::size_t i = 0; i < mTreeCache.size(); ++i)
2242   {
2243     const DataCache& cache = mTreeCache[i];
2244     for (std::size_t j = 0; j < cache.mBodyNodes.size(); ++j)
2245     {
2246       BodyNode* bn = cache.mBodyNodes[j];
2247       if (bn->mTreeIndex != i)
2248       {
2249         dterr << "[Skeleton::registerBodyNode] BodyNode named ["
2250               << bn->getName() << "] in Skeleton [" << getName() << "] is "
2251               << "mistaken about its tree's index (" << i << " : "
2252               << bn->mTreeIndex << "). Please report this as a bug!\n";
2253         assert(false);
2254       }
2255 
2256       if (bn->mIndexInTree != j)
2257       {
2258         dterr << "[Skeleton::registerBodyNode] BodyNode named ["
2259               << bn->getName() << "] in Skeleton [" << getName() << "] is "
2260               << "mistaken about its index in the tree (" << j << " : "
2261               << bn->mIndexInTree << "). Please report this as a bug!\n";
2262         assert(false);
2263       }
2264     }
2265   }
2266 #endif // ------- Debug mode
2267 
2268   _newBodyNode->incrementVersion();
2269   _newBodyNode->mStructuralChangeSignal.raise(_newBodyNode);
2270   // We don't need to explicitly increment the version of this Skeleton here
2271   // because the BodyNode will increment the version of its dependent, which is
2272   // this Skeleton.
2273 }
2274 
2275 //==============================================================================
registerJoint(Joint * _newJoint)2276 void Skeleton::registerJoint(Joint* _newJoint)
2277 {
2278   if (nullptr == _newJoint)
2279   {
2280     dterr << "[Skeleton::registerJoint] Error: Attempting to add a nullptr "
2281              "Joint to the Skeleton named ["
2282           << mAspectProperties.mName
2283           << "]. Report "
2284              "this as a bug!\n";
2285     assert(false);
2286     return;
2287   }
2288 
2289   addEntryToJointNameMgr(_newJoint);
2290   _newJoint->registerDofs();
2291 
2292   std::size_t tree = _newJoint->getChildBodyNode()->getTreeIndex();
2293   std::vector<DegreeOfFreedom*>& treeDofs = mTreeCache[tree].mDofs;
2294   for (std::size_t i = 0; i < _newJoint->getNumDofs(); ++i)
2295   {
2296     mSkelCache.mDofs.push_back(_newJoint->getDof(i));
2297     _newJoint->getDof(i)->mIndexInSkeleton = mSkelCache.mDofs.size() - 1;
2298 
2299     treeDofs.push_back(_newJoint->getDof(i));
2300     _newJoint->getDof(i)->mIndexInTree = treeDofs.size() - 1;
2301   }
2302 }
2303 
2304 //==============================================================================
registerNode(NodeMap & nodeMap,Node * _newNode,std::size_t & _index)2305 void Skeleton::registerNode(
2306     NodeMap& nodeMap, Node* _newNode, std::size_t& _index)
2307 {
2308   NodeMap::iterator it = nodeMap.find(typeid(*_newNode));
2309 
2310   if (nodeMap.end() == it)
2311   {
2312     nodeMap[typeid(*_newNode)] = std::vector<Node*>();
2313     it = nodeMap.find(typeid(*_newNode));
2314   }
2315 
2316   std::vector<Node*>& nodes = it->second;
2317 
2318   if (INVALID_INDEX == _index)
2319   {
2320     // If this Node believes its index is invalid, then it should not exist
2321     // anywhere in the vector
2322     assert(std::find(nodes.begin(), nodes.end(), _newNode) == nodes.end());
2323 
2324     nodes.push_back(_newNode);
2325     _index = nodes.size() - 1;
2326   }
2327 
2328   assert(std::find(nodes.begin(), nodes.end(), _newNode) != nodes.end());
2329 }
2330 
2331 //==============================================================================
registerNode(Node * _newNode)2332 void Skeleton::registerNode(Node* _newNode)
2333 {
2334   registerNode(mNodeMap, _newNode, _newNode->mIndexInSkeleton);
2335 
2336   registerNode(
2337       mTreeNodeMaps[_newNode->getBodyNodePtr()->getTreeIndex()],
2338       _newNode,
2339       _newNode->mIndexInTree);
2340 
2341   const std::type_info& info = typeid(*_newNode);
2342   NodeNameMgrMap::iterator it = mNodeNameMgrMap.find(info);
2343   if (mNodeNameMgrMap.end() == it)
2344   {
2345     mNodeNameMgrMap[info] = common::NameManager<Node*>(
2346         std::string("Skeleton::") + info.name() + " | "
2347             + mAspectProperties.mName,
2348         info.name());
2349 
2350     it = mNodeNameMgrMap.find(info);
2351   }
2352 
2353   common::NameManager<Node*>& mgr = it->second;
2354   _newNode->setName(mgr.issueNewNameAndAdd(_newNode->getName(), _newNode));
2355 }
2356 
2357 //==============================================================================
destructOldTree(std::size_t tree)2358 void Skeleton::destructOldTree(std::size_t tree)
2359 {
2360   mTreeCache.erase(mTreeCache.begin() + tree);
2361   mTreeNodeMaps.erase(mTreeNodeMaps.begin() + tree);
2362 
2363   // Decrease the tree index of every BodyNode whose tree index is higher than
2364   // the one which is being removed. None of the BodyNodes that predate the
2365   // current one can have a higher tree index, so they can be ignored.
2366   for (std::size_t i = tree; i < mTreeCache.size(); ++i)
2367   {
2368     DataCache& loweredTree = mTreeCache[i];
2369     for (std::size_t j = 0; j < loweredTree.mBodyNodes.size(); ++j)
2370       loweredTree.mBodyNodes[j]->mTreeIndex = i;
2371   }
2372 
2373   for (auto& nodeType : mSpecializedTreeNodes)
2374   {
2375     std::vector<NodeMap::iterator>* nodeRepo = nodeType.second;
2376     nodeRepo->erase(nodeRepo->begin() + tree);
2377   }
2378 }
2379 
2380 //==============================================================================
unregisterBodyNode(BodyNode * _oldBodyNode)2381 void Skeleton::unregisterBodyNode(BodyNode* _oldBodyNode)
2382 {
2383   unregisterJoint(_oldBodyNode->getParentJoint());
2384 
2385   BodyNode::NodeMap& nodeMap = _oldBodyNode->mNodeMap;
2386   for (auto& nodeType : nodeMap)
2387     for (auto& node : nodeType.second)
2388       unregisterNode(node);
2389 
2390   mNameMgrForBodyNodes.removeName(_oldBodyNode->getName());
2391 
2392   std::size_t index = _oldBodyNode->getIndexInSkeleton();
2393   assert(mSkelCache.mBodyNodes[index] == _oldBodyNode);
2394   mSkelCache.mBodyNodes.erase(mSkelCache.mBodyNodes.begin() + index);
2395   for (std::size_t i = index; i < mSkelCache.mBodyNodes.size(); ++i)
2396   {
2397     BodyNode* bn = mSkelCache.mBodyNodes[i];
2398     bn->mIndexInSkeleton = i;
2399   }
2400 
2401   if (nullptr == _oldBodyNode->getParentBodyNode())
2402   {
2403     // If the parent of this BodyNode is a nullptr, then this is the root of its
2404     // tree. If the root of the tree is being removed, then the tree itself
2405     // should be destroyed.
2406 
2407     // There is no way that any child BodyNodes of this root BodyNode are still
2408     // registered, because the BodyNodes always get unregistered from leaf to
2409     // root.
2410 
2411     std::size_t tree = _oldBodyNode->getTreeIndex();
2412     assert(mTreeCache[tree].mBodyNodes.size() == 1);
2413     assert(mTreeCache[tree].mBodyNodes[0] == _oldBodyNode);
2414 
2415     destructOldTree(tree);
2416     updateCacheDimensions(mSkelCache);
2417   }
2418   else
2419   {
2420     std::size_t tree = _oldBodyNode->getTreeIndex();
2421     std::size_t indexInTree = _oldBodyNode->getIndexInTree();
2422     assert(mTreeCache[tree].mBodyNodes[indexInTree] == _oldBodyNode);
2423     mTreeCache[tree].mBodyNodes.erase(
2424         mTreeCache[tree].mBodyNodes.begin() + indexInTree);
2425 
2426     for (std::size_t i = indexInTree; i < mTreeCache[tree].mBodyNodes.size();
2427          ++i)
2428       mTreeCache[tree].mBodyNodes[i]->mIndexInTree = i;
2429 
2430     updateCacheDimensions(tree);
2431   }
2432 
2433   SoftBodyNode* soft = dynamic_cast<SoftBodyNode*>(_oldBodyNode);
2434   if (soft)
2435   {
2436     mNameMgrForSoftBodyNodes.removeName(soft->getName());
2437 
2438     mSoftBodyNodes.erase(
2439         std::remove(mSoftBodyNodes.begin(), mSoftBodyNodes.end(), soft),
2440         mSoftBodyNodes.end());
2441   }
2442 
2443   updateTotalMass();
2444 
2445   _oldBodyNode->incrementVersion();
2446   _oldBodyNode->mStructuralChangeSignal.raise(_oldBodyNode);
2447   // We don't need to explicitly increment the version of this Skeleton here
2448   // because the BodyNode will increment the version of its dependent, which is
2449   // this Skeleton.
2450 }
2451 
2452 //==============================================================================
unregisterJoint(Joint * _oldJoint)2453 void Skeleton::unregisterJoint(Joint* _oldJoint)
2454 {
2455   if (nullptr == _oldJoint)
2456   {
2457     dterr << "[Skeleton::unregisterJoint] Attempting to unregister nullptr "
2458           << "Joint from Skeleton named [" << getName() << "]. Report this as "
2459           << "a bug!\n";
2460     assert(false);
2461     return;
2462   }
2463 
2464   mNameMgrForJoints.removeName(_oldJoint->getName());
2465 
2466   std::size_t tree = _oldJoint->getChildBodyNode()->getTreeIndex();
2467   std::vector<DegreeOfFreedom*>& treeDofs = mTreeCache[tree].mDofs;
2468   std::vector<DegreeOfFreedom*>& skelDofs = mSkelCache.mDofs;
2469 
2470   std::size_t firstSkelIndex = INVALID_INDEX;
2471   std::size_t firstTreeIndex = INVALID_INDEX;
2472   for (std::size_t i = 0; i < _oldJoint->getNumDofs(); ++i)
2473   {
2474     DegreeOfFreedom* dof = _oldJoint->getDof(i);
2475     mNameMgrForDofs.removeObject(dof);
2476 
2477     firstSkelIndex = std::min(firstSkelIndex, dof->getIndexInSkeleton());
2478     skelDofs.erase(
2479         std::remove(skelDofs.begin(), skelDofs.end(), dof), skelDofs.end());
2480 
2481     firstTreeIndex = std::min(firstTreeIndex, dof->getIndexInTree());
2482     treeDofs.erase(
2483         std::remove(treeDofs.begin(), treeDofs.end(), dof), treeDofs.end());
2484   }
2485 
2486   for (std::size_t i = firstSkelIndex; i < skelDofs.size(); ++i)
2487   {
2488     DegreeOfFreedom* dof = skelDofs[i];
2489     dof->mIndexInSkeleton = i;
2490   }
2491 
2492   for (std::size_t i = firstTreeIndex; i < treeDofs.size(); ++i)
2493   {
2494     DegreeOfFreedom* dof = treeDofs[i];
2495     dof->mIndexInTree = i;
2496   }
2497 }
2498 
2499 //==============================================================================
unregisterNode(NodeMap & nodeMap,Node * _oldNode,std::size_t & _index)2500 void Skeleton::unregisterNode(
2501     NodeMap& nodeMap, Node* _oldNode, std::size_t& _index)
2502 {
2503   NodeMap::iterator it = nodeMap.find(typeid(*_oldNode));
2504 
2505   if (nodeMap.end() == it)
2506   {
2507     // If the Node was not in the map, then its index should be invalid
2508     assert(INVALID_INDEX == _index);
2509     return;
2510   }
2511 
2512   std::vector<Node*>& nodes = it->second;
2513 
2514   // This Node's index in the vector should be referring to this Node
2515   assert(nodes[_index] == _oldNode);
2516   nodes.erase(nodes.begin() + _index);
2517 
2518   _index = INVALID_INDEX;
2519 }
2520 
2521 //==============================================================================
unregisterNode(Node * _oldNode)2522 void Skeleton::unregisterNode(Node* _oldNode)
2523 {
2524   const std::size_t indexInSkel = _oldNode->mIndexInSkeleton;
2525   unregisterNode(mNodeMap, _oldNode, _oldNode->mIndexInSkeleton);
2526 
2527   NodeMap::iterator node_it = mNodeMap.find(typeid(*_oldNode));
2528   assert(mNodeMap.end() != node_it);
2529 
2530   const std::vector<Node*>& skelNodes = node_it->second;
2531   for (std::size_t i = indexInSkel; i < skelNodes.size(); ++i)
2532     skelNodes[i]->mIndexInSkeleton = i;
2533 
2534   const std::size_t indexInTree = _oldNode->mIndexInTree;
2535   const std::size_t treeIndex = _oldNode->getBodyNodePtr()->getTreeIndex();
2536   NodeMap& treeNodeMap = mTreeNodeMaps[treeIndex];
2537   unregisterNode(treeNodeMap, _oldNode, _oldNode->mIndexInTree);
2538 
2539   node_it = treeNodeMap.find(typeid(*_oldNode));
2540   assert(treeNodeMap.end() != node_it);
2541 
2542   const std::vector<Node*>& treeNodes = node_it->second;
2543   for (std::size_t i = indexInTree; i < treeNodes.size(); ++i)
2544     treeNodes[i]->mIndexInTree = i;
2545 
2546   // Remove it from the NameManager, if a NameManager is being used for this
2547   // type.
2548   NodeNameMgrMap::iterator name_it = mNodeNameMgrMap.find(typeid(*_oldNode));
2549   if (mNodeNameMgrMap.end() != name_it)
2550   {
2551     common::NameManager<Node*>& mgr = name_it->second;
2552     mgr.removeObject(_oldNode);
2553   }
2554 }
2555 
2556 //==============================================================================
moveBodyNodeTree(Joint * _parentJoint,BodyNode * _bodyNode,SkeletonPtr _newSkeleton,BodyNode * _parentNode)2557 bool Skeleton::moveBodyNodeTree(
2558     Joint* _parentJoint,
2559     BodyNode* _bodyNode,
2560     SkeletonPtr _newSkeleton,
2561     BodyNode* _parentNode)
2562 {
2563   if (nullptr == _bodyNode)
2564   {
2565     dterr << "[Skeleton::moveBodyNodeTree] Skeleton named [" << getName()
2566           << "] (" << this << ") is attempting to move a nullptr BodyNode. "
2567           << "Please report this as a bug!\n";
2568     assert(false);
2569     return false;
2570   }
2571 
2572   if (this != _bodyNode->getSkeleton().get())
2573   {
2574     dterr << "[Skeleton::moveBodyNodeTree] Skeleton named [" << getName()
2575           << "] (" << this << ") is attempting to move a BodyNode named ["
2576           << _bodyNode->getName() << "] even though it belongs to another "
2577           << "Skeleton [" << _bodyNode->getSkeleton()->getName() << "] ("
2578           << _bodyNode->getSkeleton() << "). Please report this as a bug!\n";
2579     assert(false);
2580     return false;
2581   }
2582 
2583   if ((nullptr == _parentJoint)
2584       && (_bodyNode->getParentBodyNode() == _parentNode)
2585       && (this == _newSkeleton.get()))
2586   {
2587     // Short-circuit if the BodyNode is already in the requested place, and its
2588     // Joint does not need to be changed
2589     return false;
2590   }
2591 
2592   if (_bodyNode == _parentNode)
2593   {
2594     dterr << "[Skeleton::moveBodyNodeTree] Attempting to move BodyNode named ["
2595           << _bodyNode->getName() << "] (" << _bodyNode << ") to be its own "
2596           << "parent. This is not permitted!\n";
2597     return false;
2598   }
2599 
2600   if (_parentNode && _parentNode->descendsFrom(_bodyNode))
2601   {
2602     dterr << "[Skeleton::moveBodyNodeTree] Attempting to move BodyNode named ["
2603           << _bodyNode->getName() << "] of Skeleton [" << getName() << "] ("
2604           << this << ") to be a child of BodyNode [" << _parentNode->getName()
2605           << "] in Skeleton [" << _newSkeleton->getName() << "] ("
2606           << _newSkeleton << "), but that would create a closed kinematic "
2607           << "chain, which is not permitted! Nothing will be moved.\n";
2608     return false;
2609   }
2610 
2611   if (nullptr == _newSkeleton)
2612   {
2613     if (nullptr == _parentNode)
2614     {
2615       dterr << "[Skeleton::moveBodyNodeTree] Attempting to move a BodyNode "
2616             << "tree starting from [" << _bodyNode->getName() << "] in "
2617             << "Skeleton [" << getName() << "] into a nullptr Skeleton. This "
2618             << "is not permitted!\n";
2619       return false;
2620     }
2621 
2622     _newSkeleton = _parentNode->getSkeleton();
2623   }
2624 
2625   if (_parentNode && _newSkeleton != _parentNode->getSkeleton())
2626   {
2627     dterr << "[Skeleton::moveBodyNodeTree] Mismatch between the specified "
2628           << "Skeleton [" << _newSkeleton->getName() << "] (" << _newSkeleton
2629           << ") and the specified new parent BodyNode ["
2630           << _parentNode->getName() << "] whose actual Skeleton is named ["
2631           << _parentNode->getSkeleton()->getName() << "] ("
2632           << _parentNode->getSkeleton() << ") while attempting to move a "
2633           << "BodyNode tree starting from [" << _bodyNode->getName() << "] in "
2634           << "Skeleton [" << getName() << "] (" << this << ")\n";
2635     return false;
2636   }
2637 
2638   std::vector<BodyNode*> tree = extractBodyNodeTree(_bodyNode);
2639 
2640   Joint* originalParent = _bodyNode->getParentJoint();
2641   if (originalParent != _parentJoint)
2642   {
2643     _bodyNode->mParentJoint = _parentJoint;
2644     _parentJoint->mChildBodyNode = _bodyNode;
2645     delete originalParent;
2646   }
2647 
2648   if (_parentNode != _bodyNode->getParentBodyNode())
2649   {
2650     _bodyNode->mParentBodyNode = _parentNode;
2651     if (_parentNode)
2652     {
2653       _parentNode->mChildBodyNodes.push_back(_bodyNode);
2654       _bodyNode->changeParentFrame(_parentNode);
2655     }
2656     else
2657     {
2658       _bodyNode->changeParentFrame(Frame::World());
2659     }
2660   }
2661   _newSkeleton->receiveBodyNodeTree(tree);
2662 
2663   return true;
2664 }
2665 
2666 //==============================================================================
cloneBodyNodeTree(Joint * _parentJoint,const BodyNode * _bodyNode,const SkeletonPtr & _newSkeleton,BodyNode * _parentNode,bool _recursive) const2667 std::pair<Joint*, BodyNode*> Skeleton::cloneBodyNodeTree(
2668     Joint* _parentJoint,
2669     const BodyNode* _bodyNode,
2670     const SkeletonPtr& _newSkeleton,
2671     BodyNode* _parentNode,
2672     bool _recursive) const
2673 {
2674   std::pair<Joint*, BodyNode*> root(nullptr, nullptr);
2675   std::vector<const BodyNode*> tree;
2676   if (_recursive)
2677     tree = constructBodyNodeTree(_bodyNode);
2678   else
2679     tree.push_back(_bodyNode);
2680 
2681   std::map<std::string, BodyNode*> nameMap;
2682   std::vector<BodyNode*> clones;
2683   clones.reserve(tree.size());
2684 
2685   for (std::size_t i = 0; i < tree.size(); ++i)
2686   {
2687     const BodyNode* original = tree[i];
2688     // If this is the root of the tree, and the user has requested a change in
2689     // its parent Joint, use the specified parent Joint instead of created a
2690     // clone
2691     Joint* joint = (i == 0 && _parentJoint != nullptr)
2692                        ? _parentJoint
2693                        : original->getParentJoint()->clone();
2694 
2695     BodyNode* newParent
2696         = i == 0 ? _parentNode
2697                  : nameMap[original->getParentBodyNode()->getName()];
2698 
2699     BodyNode* clone = original->clone(newParent, joint, true);
2700     clones.push_back(clone);
2701     nameMap[clone->getName()] = clone;
2702 
2703     if (0 == i)
2704     {
2705       root.first = joint;
2706       root.second = clone;
2707     }
2708   }
2709 
2710   _newSkeleton->receiveBodyNodeTree(clones);
2711   return root;
2712 }
2713 
2714 //==============================================================================
2715 template <typename BodyNodeT>
recursiveConstructBodyNodeTree(std::vector<BodyNodeT * > & tree,BodyNodeT * _currentBodyNode)2716 static void recursiveConstructBodyNodeTree(
2717     std::vector<BodyNodeT*>& tree, BodyNodeT* _currentBodyNode)
2718 {
2719   tree.push_back(_currentBodyNode);
2720   for (std::size_t i = 0; i < _currentBodyNode->getNumChildBodyNodes(); ++i)
2721     recursiveConstructBodyNodeTree(tree, _currentBodyNode->getChildBodyNode(i));
2722 }
2723 
2724 //==============================================================================
constructBodyNodeTree(const BodyNode * _bodyNode) const2725 std::vector<const BodyNode*> Skeleton::constructBodyNodeTree(
2726     const BodyNode* _bodyNode) const
2727 {
2728   std::vector<const BodyNode*> tree;
2729   recursiveConstructBodyNodeTree<const BodyNode>(tree, _bodyNode);
2730 
2731   return tree;
2732 }
2733 
2734 //==============================================================================
constructBodyNodeTree(BodyNode * _bodyNode)2735 std::vector<BodyNode*> Skeleton::constructBodyNodeTree(BodyNode* _bodyNode)
2736 {
2737   std::vector<BodyNode*> tree;
2738   recursiveConstructBodyNodeTree<BodyNode>(tree, _bodyNode);
2739 
2740   return tree;
2741 }
2742 
2743 //==============================================================================
extractBodyNodeTree(BodyNode * _bodyNode)2744 std::vector<BodyNode*> Skeleton::extractBodyNodeTree(BodyNode* _bodyNode)
2745 {
2746   std::vector<BodyNode*> tree = constructBodyNodeTree(_bodyNode);
2747 
2748   // Go backwards to minimize the number of shifts needed
2749   std::vector<BodyNode*>::reverse_iterator rit;
2750   // Go backwards to minimize the amount of element shifting in the vectors
2751   for (rit = tree.rbegin(); rit != tree.rend(); ++rit)
2752     unregisterBodyNode(*rit);
2753 
2754   for (std::size_t i = 0; i < mSkelCache.mBodyNodes.size(); ++i)
2755     mSkelCache.mBodyNodes[i]->init(getPtr());
2756 
2757   return tree;
2758 }
2759 
2760 //==============================================================================
receiveBodyNodeTree(const std::vector<BodyNode * > & _tree)2761 void Skeleton::receiveBodyNodeTree(const std::vector<BodyNode*>& _tree)
2762 {
2763   for (BodyNode* bn : _tree)
2764     registerBodyNode(bn);
2765 }
2766 
2767 //==============================================================================
updateTotalMass()2768 void Skeleton::updateTotalMass()
2769 {
2770   mTotalMass = 0.0;
2771   for (std::size_t i = 0; i < getNumBodyNodes(); ++i)
2772     mTotalMass += getBodyNode(i)->getMass();
2773 }
2774 
2775 //==============================================================================
updateCacheDimensions(Skeleton::DataCache & _cache)2776 void Skeleton::updateCacheDimensions(Skeleton::DataCache& _cache)
2777 {
2778   std::size_t dof = _cache.mDofs.size();
2779   _cache.mM = Eigen::MatrixXd::Zero(dof, dof);
2780   _cache.mAugM = Eigen::MatrixXd::Zero(dof, dof);
2781   _cache.mInvM = Eigen::MatrixXd::Zero(dof, dof);
2782   _cache.mInvAugM = Eigen::MatrixXd::Zero(dof, dof);
2783   _cache.mCvec = Eigen::VectorXd::Zero(dof);
2784   _cache.mG = Eigen::VectorXd::Zero(dof);
2785   _cache.mCg = Eigen::VectorXd::Zero(dof);
2786   _cache.mFext = Eigen::VectorXd::Zero(dof);
2787   _cache.mFc = Eigen::VectorXd::Zero(dof);
2788 }
2789 
2790 //==============================================================================
updateCacheDimensions(std::size_t _treeIdx)2791 void Skeleton::updateCacheDimensions(std::size_t _treeIdx)
2792 {
2793   updateCacheDimensions(mTreeCache[_treeIdx]);
2794   updateCacheDimensions(mSkelCache);
2795 
2796   dirtyArticulatedInertia(_treeIdx);
2797 }
2798 
2799 //==============================================================================
updateArticulatedInertia(std::size_t _tree) const2800 void Skeleton::updateArticulatedInertia(std::size_t _tree) const
2801 {
2802   DataCache& cache = mTreeCache[_tree];
2803   for (std::vector<BodyNode*>::const_reverse_iterator it
2804        = cache.mBodyNodes.rbegin();
2805        it != cache.mBodyNodes.rend();
2806        ++it)
2807   {
2808     (*it)->updateArtInertia(mAspectProperties.mTimeStep);
2809   }
2810 
2811   cache.mDirty.mArticulatedInertia = false;
2812 }
2813 
2814 //==============================================================================
updateArticulatedInertia() const2815 void Skeleton::updateArticulatedInertia() const
2816 {
2817   for (std::size_t i = 0; i < mTreeCache.size(); ++i)
2818   {
2819     DataCache& cache = mTreeCache[i];
2820     if (cache.mDirty.mArticulatedInertia)
2821       updateArticulatedInertia(i);
2822   }
2823 
2824   mSkelCache.mDirty.mArticulatedInertia = false;
2825 }
2826 
2827 //==============================================================================
updateMassMatrix(std::size_t _treeIdx) const2828 void Skeleton::updateMassMatrix(std::size_t _treeIdx) const
2829 {
2830   DataCache& cache = mTreeCache[_treeIdx];
2831   std::size_t dof = cache.mDofs.size();
2832   assert(
2833       static_cast<std::size_t>(cache.mM.cols()) == dof
2834       && static_cast<std::size_t>(cache.mM.rows()) == dof);
2835   if (dof == 0)
2836   {
2837     cache.mDirty.mMassMatrix = false;
2838     return;
2839   }
2840 
2841   cache.mM.setZero();
2842 
2843   // Backup the original internal force
2844   Eigen::VectorXd originalGenAcceleration = getAccelerations();
2845 
2846   // Clear out the accelerations of the dofs in this tree so that we can set
2847   // them to 1.0 one at a time to build up the mass matrix
2848   for (std::size_t i = 0; i < dof; ++i)
2849     cache.mDofs[i]->setAcceleration(0.0);
2850 
2851   for (std::size_t j = 0; j < dof; ++j)
2852   {
2853     // Set the acceleration of this DOF to 1.0 while all the rest are 0.0
2854     cache.mDofs[j]->setAcceleration(1.0);
2855 
2856     // Prepare cache data
2857     for (std::vector<BodyNode*>::const_iterator it = cache.mBodyNodes.begin();
2858          it != cache.mBodyNodes.end();
2859          ++it)
2860     {
2861       (*it)->updateMassMatrix();
2862     }
2863 
2864     // Mass matrix
2865     for (std::vector<BodyNode*>::const_reverse_iterator it
2866          = cache.mBodyNodes.rbegin();
2867          it != cache.mBodyNodes.rend();
2868          ++it)
2869     {
2870       (*it)->aggregateMassMatrix(cache.mM, j);
2871       std::size_t localDof = (*it)->mParentJoint->getNumDofs();
2872       if (localDof > 0)
2873       {
2874         std::size_t iStart = (*it)->mParentJoint->getIndexInTree(0);
2875 
2876         if (iStart + localDof < j)
2877           break;
2878       }
2879     }
2880 
2881     // Set the acceleration of this DOF back to 0.0
2882     cache.mDofs[j]->setAcceleration(0.0);
2883   }
2884   cache.mM.triangularView<Eigen::StrictlyUpper>() = cache.mM.transpose();
2885 
2886   // Restore the original generalized accelerations
2887   const_cast<Skeleton*>(this)->setAccelerations(originalGenAcceleration);
2888 
2889   cache.mDirty.mMassMatrix = false;
2890 }
2891 
2892 //==============================================================================
updateMassMatrix() const2893 void Skeleton::updateMassMatrix() const
2894 {
2895   std::size_t dof = mSkelCache.mDofs.size();
2896   assert(
2897       static_cast<std::size_t>(mSkelCache.mM.cols()) == dof
2898       && static_cast<std::size_t>(mSkelCache.mM.rows()) == dof);
2899   if (dof == 0)
2900   {
2901     mSkelCache.mDirty.mMassMatrix = false;
2902     return;
2903   }
2904 
2905   mSkelCache.mM.setZero();
2906 
2907   for (std::size_t tree = 0; tree < mTreeCache.size(); ++tree)
2908   {
2909     const Eigen::MatrixXd& treeM = getMassMatrix(tree);
2910     const std::vector<DegreeOfFreedom*>& treeDofs = mTreeCache[tree].mDofs;
2911     std::size_t nTreeDofs = treeDofs.size();
2912     for (std::size_t i = 0; i < nTreeDofs; ++i)
2913     {
2914       for (std::size_t j = 0; j < nTreeDofs; ++j)
2915       {
2916         std::size_t ki = treeDofs[i]->getIndexInSkeleton();
2917         std::size_t kj = treeDofs[j]->getIndexInSkeleton();
2918 
2919         mSkelCache.mM(ki, kj) = treeM(i, j);
2920       }
2921     }
2922   }
2923 
2924   mSkelCache.mDirty.mMassMatrix = false;
2925 }
2926 
2927 //==============================================================================
updateAugMassMatrix(std::size_t _treeIdx) const2928 void Skeleton::updateAugMassMatrix(std::size_t _treeIdx) const
2929 {
2930   DataCache& cache = mTreeCache[_treeIdx];
2931   std::size_t dof = cache.mDofs.size();
2932   assert(
2933       static_cast<std::size_t>(cache.mAugM.cols()) == dof
2934       && static_cast<std::size_t>(cache.mAugM.rows()) == dof);
2935   if (dof == 0)
2936   {
2937     cache.mDirty.mAugMassMatrix = false;
2938     return;
2939   }
2940 
2941   cache.mAugM.setZero();
2942 
2943   // Backup the origianl internal force
2944   Eigen::VectorXd originalGenAcceleration = getAccelerations();
2945 
2946   // Clear out the accelerations of the DOFs in this tree so that we can set
2947   // them to 1.0 one at a time to build up the augmented mass matrix
2948   for (std::size_t i = 0; i < dof; ++i)
2949     cache.mDofs[i]->setAcceleration(0.0);
2950 
2951   for (std::size_t j = 0; j < dof; ++j)
2952   {
2953     // Set the acceleration of this DOF to 1.0 while all the rest are 0.0
2954     cache.mDofs[j]->setAcceleration(1.0);
2955 
2956     // Prepare cache data
2957     for (std::vector<BodyNode*>::const_iterator it = cache.mBodyNodes.begin();
2958          it != cache.mBodyNodes.end();
2959          ++it)
2960     {
2961       (*it)->updateMassMatrix();
2962     }
2963 
2964     // Augmented Mass matrix
2965     for (std::vector<BodyNode*>::const_reverse_iterator it
2966          = cache.mBodyNodes.rbegin();
2967          it != cache.mBodyNodes.rend();
2968          ++it)
2969     {
2970       (*it)->aggregateAugMassMatrix(
2971           cache.mAugM, j, mAspectProperties.mTimeStep);
2972       std::size_t localDof = (*it)->mParentJoint->getNumDofs();
2973       if (localDof > 0)
2974       {
2975         std::size_t iStart = (*it)->mParentJoint->getIndexInTree(0);
2976 
2977         if (iStart + localDof < j)
2978           break;
2979       }
2980     }
2981 
2982     // Set the acceleration of this DOF back to 0.0
2983     cache.mDofs[j]->setAcceleration(0.0);
2984   }
2985   cache.mAugM.triangularView<Eigen::StrictlyUpper>() = cache.mAugM.transpose();
2986 
2987   // Restore the origianl internal force
2988   const_cast<Skeleton*>(this)->setAccelerations(originalGenAcceleration);
2989 
2990   cache.mDirty.mAugMassMatrix = false;
2991 }
2992 
2993 //==============================================================================
updateAugMassMatrix() const2994 void Skeleton::updateAugMassMatrix() const
2995 {
2996   std::size_t dof = mSkelCache.mDofs.size();
2997   assert(
2998       static_cast<std::size_t>(mSkelCache.mAugM.cols()) == dof
2999       && static_cast<std::size_t>(mSkelCache.mAugM.rows()) == dof);
3000   if (dof == 0)
3001   {
3002     mSkelCache.mDirty.mMassMatrix = false;
3003     return;
3004   }
3005 
3006   mSkelCache.mAugM.setZero();
3007 
3008   for (std::size_t tree = 0; tree < mTreeCache.size(); ++tree)
3009   {
3010     const Eigen::MatrixXd& treeAugM = getAugMassMatrix(tree);
3011     const std::vector<DegreeOfFreedom*>& treeDofs = mTreeCache[tree].mDofs;
3012     std::size_t nTreeDofs = treeDofs.size();
3013     for (std::size_t i = 0; i < nTreeDofs; ++i)
3014     {
3015       for (std::size_t j = 0; j < nTreeDofs; ++j)
3016       {
3017         std::size_t ki = treeDofs[i]->getIndexInSkeleton();
3018         std::size_t kj = treeDofs[j]->getIndexInSkeleton();
3019 
3020         mSkelCache.mAugM(ki, kj) = treeAugM(i, j);
3021       }
3022     }
3023   }
3024 
3025   mSkelCache.mDirty.mAugMassMatrix = false;
3026 }
3027 
3028 //==============================================================================
updateInvMassMatrix(std::size_t _treeIdx) const3029 void Skeleton::updateInvMassMatrix(std::size_t _treeIdx) const
3030 {
3031   DataCache& cache = mTreeCache[_treeIdx];
3032   std::size_t dof = cache.mDofs.size();
3033   assert(
3034       static_cast<std::size_t>(cache.mInvM.cols()) == dof
3035       && static_cast<std::size_t>(cache.mInvM.rows()) == dof);
3036   if (dof == 0)
3037   {
3038     cache.mDirty.mInvMassMatrix = false;
3039     return;
3040   }
3041 
3042   // We don't need to set mInvM as zero matrix as long as the below is correct
3043   // cache.mInvM.setZero();
3044 
3045   // Backup the origianl internal force
3046   Eigen::VectorXd originalInternalForce = getForces();
3047 
3048   // Clear out the forces of the dofs in this tree so that we can set them to
3049   // 1.0 one at a time to build up the inverse mass matrix
3050   for (std::size_t i = 0; i < dof; ++i)
3051     cache.mDofs[i]->setForce(0.0);
3052 
3053   for (std::size_t j = 0; j < dof; ++j)
3054   {
3055     // Set the force of this DOF to 1.0 while all the rest are 0.0
3056     cache.mDofs[j]->setForce(1.0);
3057 
3058     // Prepare cache data
3059     for (std::vector<BodyNode*>::const_reverse_iterator it
3060          = cache.mBodyNodes.rbegin();
3061          it != cache.mBodyNodes.rend();
3062          ++it)
3063     {
3064       (*it)->updateInvMassMatrix();
3065     }
3066 
3067     // Inverse of mass matrix
3068     for (std::vector<BodyNode*>::const_iterator it = cache.mBodyNodes.begin();
3069          it != cache.mBodyNodes.end();
3070          ++it)
3071     {
3072       (*it)->aggregateInvMassMatrix(cache.mInvM, j);
3073       std::size_t localDof = (*it)->mParentJoint->getNumDofs();
3074       if (localDof > 0)
3075       {
3076         std::size_t iStart = (*it)->mParentJoint->getIndexInTree(0);
3077 
3078         if (iStart + localDof > j)
3079           break;
3080       }
3081     }
3082 
3083     // Set the force of this DOF back to 0.0
3084     cache.mDofs[j]->setForce(0.0);
3085   }
3086   cache.mInvM.triangularView<Eigen::StrictlyLower>() = cache.mInvM.transpose();
3087 
3088   // Restore the original internal force
3089   const_cast<Skeleton*>(this)->setForces(originalInternalForce);
3090 
3091   cache.mDirty.mInvMassMatrix = false;
3092 }
3093 
3094 //==============================================================================
updateInvMassMatrix() const3095 void Skeleton::updateInvMassMatrix() const
3096 {
3097   std::size_t dof = mSkelCache.mDofs.size();
3098   assert(
3099       static_cast<std::size_t>(mSkelCache.mInvM.cols()) == dof
3100       && static_cast<std::size_t>(mSkelCache.mInvM.rows()) == dof);
3101   if (dof == 0)
3102   {
3103     mSkelCache.mDirty.mInvMassMatrix = false;
3104     return;
3105   }
3106 
3107   mSkelCache.mInvM.setZero();
3108 
3109   for (std::size_t tree = 0; tree < mTreeCache.size(); ++tree)
3110   {
3111     const Eigen::MatrixXd& treeInvM = getInvMassMatrix(tree);
3112     const std::vector<DegreeOfFreedom*>& treeDofs = mTreeCache[tree].mDofs;
3113     std::size_t nTreeDofs = treeDofs.size();
3114     for (std::size_t i = 0; i < nTreeDofs; ++i)
3115     {
3116       for (std::size_t j = 0; j < nTreeDofs; ++j)
3117       {
3118         std::size_t ki = treeDofs[i]->getIndexInSkeleton();
3119         std::size_t kj = treeDofs[j]->getIndexInSkeleton();
3120 
3121         mSkelCache.mInvM(ki, kj) = treeInvM(i, j);
3122       }
3123     }
3124   }
3125 
3126   mSkelCache.mDirty.mInvMassMatrix = false;
3127 }
3128 
3129 //==============================================================================
updateInvAugMassMatrix(std::size_t _treeIdx) const3130 void Skeleton::updateInvAugMassMatrix(std::size_t _treeIdx) const
3131 {
3132   DataCache& cache = mTreeCache[_treeIdx];
3133   std::size_t dof = cache.mDofs.size();
3134   assert(
3135       static_cast<std::size_t>(cache.mInvAugM.cols()) == dof
3136       && static_cast<std::size_t>(cache.mInvAugM.rows()) == dof);
3137   if (dof == 0)
3138   {
3139     cache.mDirty.mInvAugMassMatrix = false;
3140     return;
3141   }
3142 
3143   // We don't need to set mInvM as zero matrix as long as the below is correct
3144   // mInvM.setZero();
3145 
3146   // Backup the origianl internal force
3147   Eigen::VectorXd originalInternalForce = getForces();
3148 
3149   // Clear out the forces of the dofs in this tree so that we can set them to
3150   // 1.0 one at a time to build up the inverse augmented mass matrix
3151   for (std::size_t i = 0; i < dof; ++i)
3152     cache.mDofs[i]->setForce(0.0);
3153 
3154   for (std::size_t j = 0; j < dof; ++j)
3155   {
3156     // Set the force of this DOF to 1.0 while all the rest are 0.0
3157     cache.mDofs[j]->setForce(1.0);
3158 
3159     // Prepare cache data
3160     for (std::vector<BodyNode*>::const_reverse_iterator it
3161          = cache.mBodyNodes.rbegin();
3162          it != cache.mBodyNodes.rend();
3163          ++it)
3164     {
3165       (*it)->updateInvAugMassMatrix();
3166     }
3167 
3168     // Inverse of augmented mass matrix
3169     for (std::vector<BodyNode*>::const_iterator it = cache.mBodyNodes.begin();
3170          it != cache.mBodyNodes.end();
3171          ++it)
3172     {
3173       (*it)->aggregateInvAugMassMatrix(
3174           cache.mInvAugM, j, mAspectProperties.mTimeStep);
3175       std::size_t localDof = (*it)->mParentJoint->getNumDofs();
3176       if (localDof > 0)
3177       {
3178         std::size_t iStart = (*it)->mParentJoint->getIndexInTree(0);
3179 
3180         if (iStart + localDof > j)
3181           break;
3182       }
3183     }
3184 
3185     // Set the force of this DOF back to 0.0
3186     cache.mDofs[j]->setForce(0.0);
3187   }
3188   cache.mInvAugM.triangularView<Eigen::StrictlyLower>()
3189       = cache.mInvAugM.transpose();
3190 
3191   // Restore the original internal force
3192   const_cast<Skeleton*>(this)->setForces(originalInternalForce);
3193 
3194   cache.mDirty.mInvAugMassMatrix = false;
3195 }
3196 
3197 //==============================================================================
updateInvAugMassMatrix() const3198 void Skeleton::updateInvAugMassMatrix() const
3199 {
3200   std::size_t dof = mSkelCache.mDofs.size();
3201   assert(
3202       static_cast<std::size_t>(mSkelCache.mInvAugM.cols()) == dof
3203       && static_cast<std::size_t>(mSkelCache.mInvAugM.rows()) == dof);
3204   if (dof == 0)
3205   {
3206     mSkelCache.mDirty.mInvAugMassMatrix = false;
3207     return;
3208   }
3209 
3210   mSkelCache.mInvAugM.setZero();
3211 
3212   for (std::size_t tree = 0; tree < mTreeCache.size(); ++tree)
3213   {
3214     const Eigen::MatrixXd& treeInvAugM = getInvAugMassMatrix(tree);
3215     const std::vector<DegreeOfFreedom*>& treeDofs = mTreeCache[tree].mDofs;
3216     std::size_t nTreeDofs = treeDofs.size();
3217     for (std::size_t i = 0; i < nTreeDofs; ++i)
3218     {
3219       for (std::size_t j = 0; j < nTreeDofs; ++j)
3220       {
3221         std::size_t ki = treeDofs[i]->getIndexInSkeleton();
3222         std::size_t kj = treeDofs[j]->getIndexInSkeleton();
3223 
3224         mSkelCache.mInvAugM(ki, kj) = treeInvAugM(i, j);
3225       }
3226     }
3227   }
3228 
3229   mSkelCache.mDirty.mInvAugMassMatrix = false;
3230 }
3231 
3232 //==============================================================================
updateCoriolisForces(std::size_t _treeIdx) const3233 void Skeleton::updateCoriolisForces(std::size_t _treeIdx) const
3234 {
3235   DataCache& cache = mTreeCache[_treeIdx];
3236   std::size_t dof = cache.mDofs.size();
3237   assert(static_cast<std::size_t>(cache.mCvec.size()) == dof);
3238   if (dof == 0)
3239   {
3240     cache.mDirty.mCoriolisForces = false;
3241     return;
3242   }
3243 
3244   cache.mCvec.setZero();
3245 
3246   for (std::vector<BodyNode*>::const_iterator it = cache.mBodyNodes.begin();
3247        it != cache.mBodyNodes.end();
3248        ++it)
3249   {
3250     (*it)->updateCombinedVector();
3251   }
3252 
3253   for (std::vector<BodyNode*>::const_reverse_iterator it
3254        = cache.mBodyNodes.rbegin();
3255        it != cache.mBodyNodes.rend();
3256        ++it)
3257   {
3258     (*it)->aggregateCoriolisForceVector(cache.mCvec);
3259   }
3260 
3261   cache.mDirty.mCoriolisForces = false;
3262 }
3263 
3264 //==============================================================================
updateCoriolisForces() const3265 void Skeleton::updateCoriolisForces() const
3266 {
3267   std::size_t dof = mSkelCache.mDofs.size();
3268   assert(static_cast<std::size_t>(mSkelCache.mCvec.size()) == dof);
3269   if (dof == 0)
3270   {
3271     mSkelCache.mDirty.mCoriolisForces = false;
3272     return;
3273   }
3274 
3275   mSkelCache.mCvec.setZero();
3276 
3277   for (std::size_t tree = 0; tree < mTreeCache.size(); ++tree)
3278   {
3279     const Eigen::VectorXd& treeCvec = getCoriolisForces(tree);
3280     const std::vector<DegreeOfFreedom*>& treeDofs = mTreeCache[tree].mDofs;
3281     std::size_t nTreeDofs = treeDofs.size();
3282     for (std::size_t i = 0; i < nTreeDofs; ++i)
3283     {
3284       std::size_t k = treeDofs[i]->getIndexInSkeleton();
3285       mSkelCache.mCvec[k] = treeCvec[i];
3286     }
3287   }
3288 
3289   mSkelCache.mDirty.mCoriolisForces = false;
3290 }
3291 
3292 //==============================================================================
updateGravityForces(std::size_t _treeIdx) const3293 void Skeleton::updateGravityForces(std::size_t _treeIdx) const
3294 {
3295   DataCache& cache = mTreeCache[_treeIdx];
3296   std::size_t dof = cache.mDofs.size();
3297   assert(static_cast<std::size_t>(cache.mG.size()) == dof);
3298   if (dof == 0)
3299   {
3300     cache.mDirty.mGravityForces = false;
3301     return;
3302   }
3303 
3304   cache.mG.setZero();
3305 
3306   for (std::vector<BodyNode*>::const_reverse_iterator it
3307        = cache.mBodyNodes.rbegin();
3308        it != cache.mBodyNodes.rend();
3309        ++it)
3310   {
3311     (*it)->aggregateGravityForceVector(cache.mG, mAspectProperties.mGravity);
3312   }
3313 
3314   cache.mDirty.mGravityForces = false;
3315 }
3316 
3317 //==============================================================================
updateGravityForces() const3318 void Skeleton::updateGravityForces() const
3319 {
3320   std::size_t dof = mSkelCache.mDofs.size();
3321   assert(static_cast<std::size_t>(mSkelCache.mG.size()) == dof);
3322   if (dof == 0)
3323   {
3324     mSkelCache.mDirty.mGravityForces = false;
3325     return;
3326   }
3327 
3328   mSkelCache.mG.setZero();
3329 
3330   for (std::size_t tree = 0; tree < mTreeCache.size(); ++tree)
3331   {
3332     const Eigen::VectorXd& treeG = getGravityForces(tree);
3333     std::vector<DegreeOfFreedom*>& treeDofs = mTreeCache[tree].mDofs;
3334     std::size_t nTreeDofs = treeDofs.size();
3335     for (std::size_t i = 0; i < nTreeDofs; ++i)
3336     {
3337       std::size_t k = treeDofs[i]->getIndexInSkeleton();
3338       mSkelCache.mG[k] = treeG[i];
3339     }
3340   }
3341 
3342   mSkelCache.mDirty.mGravityForces = false;
3343 }
3344 
3345 //==============================================================================
updateCoriolisAndGravityForces(std::size_t _treeIdx) const3346 void Skeleton::updateCoriolisAndGravityForces(std::size_t _treeIdx) const
3347 {
3348   DataCache& cache = mTreeCache[_treeIdx];
3349   std::size_t dof = cache.mDofs.size();
3350   assert(static_cast<std::size_t>(cache.mCg.size()) == dof);
3351   if (dof == 0)
3352   {
3353     cache.mDirty.mCoriolisAndGravityForces = false;
3354     return;
3355   }
3356 
3357   cache.mCg.setZero();
3358 
3359   for (std::vector<BodyNode*>::const_iterator it = cache.mBodyNodes.begin();
3360        it != cache.mBodyNodes.end();
3361        ++it)
3362   {
3363     (*it)->updateCombinedVector();
3364   }
3365 
3366   for (std::vector<BodyNode*>::const_reverse_iterator it
3367        = cache.mBodyNodes.rbegin();
3368        it != cache.mBodyNodes.rend();
3369        ++it)
3370   {
3371     (*it)->aggregateCombinedVector(cache.mCg, mAspectProperties.mGravity);
3372   }
3373 
3374   cache.mDirty.mCoriolisAndGravityForces = false;
3375 }
3376 
3377 //==============================================================================
updateCoriolisAndGravityForces() const3378 void Skeleton::updateCoriolisAndGravityForces() const
3379 {
3380   std::size_t dof = mSkelCache.mDofs.size();
3381   assert(static_cast<std::size_t>(mSkelCache.mCg.size()) == dof);
3382   if (dof == 0)
3383   {
3384     mSkelCache.mDirty.mCoriolisAndGravityForces = false;
3385     return;
3386   }
3387 
3388   mSkelCache.mCg.setZero();
3389 
3390   for (std::size_t tree = 0; tree < mTreeCache.size(); ++tree)
3391   {
3392     const Eigen::VectorXd& treeCg = getCoriolisAndGravityForces(tree);
3393     const std::vector<DegreeOfFreedom*>& treeDofs = mTreeCache[tree].mDofs;
3394     std::size_t nTreeDofs = treeDofs.size();
3395     for (std::size_t i = 0; i < nTreeDofs; ++i)
3396     {
3397       std::size_t k = treeDofs[i]->getIndexInSkeleton();
3398       mSkelCache.mCg[k] = treeCg[i];
3399     }
3400   }
3401 
3402   mSkelCache.mDirty.mCoriolisAndGravityForces = false;
3403 }
3404 
3405 //==============================================================================
updateExternalForces(std::size_t _treeIdx) const3406 void Skeleton::updateExternalForces(std::size_t _treeIdx) const
3407 {
3408   DataCache& cache = mTreeCache[_treeIdx];
3409   std::size_t dof = cache.mDofs.size();
3410   assert(static_cast<std::size_t>(cache.mFext.size()) == dof);
3411   if (dof == 0)
3412   {
3413     cache.mDirty.mExternalForces = false;
3414     return;
3415   }
3416 
3417   // Clear external force.
3418   cache.mFext.setZero();
3419 
3420   for (std::vector<BodyNode*>::const_reverse_iterator itr
3421        = cache.mBodyNodes.rbegin();
3422        itr != cache.mBodyNodes.rend();
3423        ++itr)
3424   {
3425     (*itr)->aggregateExternalForces(cache.mFext);
3426   }
3427 
3428   // TODO(JS): Not implemented yet
3429   //  for (std::vector<SoftBodyNode*>::iterator it = mSoftBodyNodes.begin();
3430   //       it != mSoftBodyNodes.end(); ++it)
3431   //  {
3432   //    double kv = (*it)->getVertexSpringStiffness();
3433   //    double ke = (*it)->getEdgeSpringStiffness();
3434 
3435   //    for (int i = 0; i < (*it)->getNumPointMasses(); ++i)
3436   //    {
3437   //      PointMass* pm = (*it)->getPointMass(i);
3438   //      int nN = pm->getNumConnectedPointMasses();
3439 
3440   //      // Vertex restoring force
3441   //      Eigen::Vector3d Fext = -(kv + nN * ke) * pm->getPositions()
3442   //                             - (mTimeStep * (kv + nN*ke)) *
3443   //                             pm->getVelocities();
3444 
3445   //      // Edge restoring force
3446   //      for (int j = 0; j < nN; ++j)
3447   //      {
3448   //        Fext += ke * (pm->getConnectedPointMass(j)->getPositions()
3449   //                      + mTimeStep
3450   //                        * pm->getConnectedPointMass(j)->getVelocities());
3451   //      }
3452 
3453   //      // Assign
3454   //      int iStart = pm->getIndexInSkeleton(0);
3455   //      mFext.segment<3>(iStart) = Fext;
3456   //    }
3457   //  }
3458 
3459   cache.mDirty.mExternalForces = false;
3460 }
3461 
3462 //==============================================================================
updateExternalForces() const3463 void Skeleton::updateExternalForces() const
3464 {
3465   std::size_t dof = mSkelCache.mDofs.size();
3466   assert(static_cast<std::size_t>(mSkelCache.mFext.size()) == dof);
3467   if (dof == 0)
3468   {
3469     mSkelCache.mDirty.mExternalForces = false;
3470     return;
3471   }
3472 
3473   mSkelCache.mFext.setZero();
3474 
3475   for (std::size_t tree = 0; tree < mTreeCache.size(); ++tree)
3476   {
3477     const Eigen::VectorXd& treeFext = getExternalForces(tree);
3478     const std::vector<DegreeOfFreedom*>& treeDofs = mTreeCache[tree].mDofs;
3479     std::size_t nTreeDofs = treeDofs.size();
3480     for (std::size_t i = 0; i < nTreeDofs; ++i)
3481     {
3482       std::size_t k = treeDofs[i]->getIndexInSkeleton();
3483       mSkelCache.mFext[k] = treeFext[i];
3484     }
3485   }
3486 
3487   mSkelCache.mDirty.mExternalForces = false;
3488 }
3489 
3490 //==============================================================================
computeConstraintForces(DataCache & cache) const3491 const Eigen::VectorXd& Skeleton::computeConstraintForces(DataCache& cache) const
3492 {
3493   const std::size_t dof = cache.mDofs.size();
3494   assert(static_cast<std::size_t>(cache.mFc.size()) == dof);
3495 
3496   // Body constraint impulses
3497   for (std::vector<BodyNode*>::reverse_iterator it = cache.mBodyNodes.rbegin();
3498        it != cache.mBodyNodes.rend();
3499        ++it)
3500   {
3501     (*it)->aggregateSpatialToGeneralized(
3502         cache.mFc, (*it)->getConstraintImpulse());
3503   }
3504 
3505   // Joint constraint impulses
3506   for (std::size_t i = 0; i < dof; ++i)
3507     cache.mFc[i] += cache.mDofs[i]->getConstraintImpulse();
3508 
3509   // Get force by dividing the impulse by the time step
3510   cache.mFc = cache.mFc / mAspectProperties.mTimeStep;
3511 
3512   return cache.mFc;
3513 }
3514 
3515 //==============================================================================
computeSupportPolygon(const Skeleton * skel,math::SupportPolygon & polygon,math::SupportGeometry & geometry,std::vector<std::size_t> & ee_indices,Eigen::Vector3d & axis1,Eigen::Vector3d & axis2,Eigen::Vector2d & centroid,std::size_t treeIndex)3516 static void computeSupportPolygon(
3517     const Skeleton* skel,
3518     math::SupportPolygon& polygon,
3519     math::SupportGeometry& geometry,
3520     std::vector<std::size_t>& ee_indices,
3521     Eigen::Vector3d& axis1,
3522     Eigen::Vector3d& axis2,
3523     Eigen::Vector2d& centroid,
3524     std::size_t treeIndex)
3525 {
3526   polygon.clear();
3527   geometry.clear();
3528   ee_indices.clear();
3529 
3530   const Eigen::Vector3d& up = -skel->getGravity();
3531   if (up.norm() == 0.0)
3532   {
3533     dtwarn << "[computeSupportPolygon] Requesting support polygon of a "
3534            << "Skeleton with no gravity. The result will only be an empty "
3535            << "set!\n";
3536     axis1.setZero();
3537     axis2.setZero();
3538     centroid = Eigen::Vector2d::Constant(std::nan(""));
3539     return;
3540   }
3541 
3542   std::vector<std::size_t> originalEE_map;
3543   originalEE_map.reserve(skel->getNumEndEffectors());
3544   for (std::size_t i = 0; i < skel->getNumEndEffectors(); ++i)
3545   {
3546     const EndEffector* ee = skel->getEndEffector(i);
3547     if (ee->getSupport() && ee->getSupport()->isActive()
3548         && (INVALID_INDEX == treeIndex || ee->getTreeIndex() == treeIndex))
3549     {
3550       const math::SupportGeometry& eeGeom = ee->getSupport()->getGeometry();
3551       for (const Eigen::Vector3d& v : eeGeom)
3552       {
3553         geometry.push_back(ee->getWorldTransform() * v);
3554         originalEE_map.push_back(ee->getIndexInSkeleton());
3555       }
3556     }
3557   }
3558 
3559   axis1 = (up - Eigen::Vector3d::UnitX()).norm() > 1e-6
3560               ? Eigen::Vector3d::UnitX()
3561               : Eigen::Vector3d::UnitY();
3562 
3563   axis1 = axis1 - up.dot(axis1) * up / up.dot(up);
3564   axis1.normalize();
3565 
3566   axis2 = up.normalized().cross(axis1);
3567 
3568   std::vector<std::size_t> vertex_indices;
3569   polygon = math::computeSupportPolgyon(vertex_indices, geometry, axis1, axis2);
3570 
3571   ee_indices.reserve(vertex_indices.size());
3572   for (std::size_t i = 0; i < vertex_indices.size(); ++i)
3573     ee_indices[i] = originalEE_map[vertex_indices[i]];
3574 
3575   if (polygon.size() > 0)
3576     centroid = math::computeCentroidOfHull(polygon);
3577   else
3578     centroid = Eigen::Vector2d::Constant(std::nan(""));
3579 }
3580 
3581 //==============================================================================
getSupportPolygon() const3582 const math::SupportPolygon& Skeleton::getSupportPolygon() const
3583 {
3584   math::SupportPolygon& polygon = mSkelCache.mSupportPolygon;
3585 
3586   if (!mSkelCache.mDirty.mSupport)
3587     return polygon;
3588 
3589   computeSupportPolygon(
3590       this,
3591       polygon,
3592       mSkelCache.mSupportGeometry,
3593       mSkelCache.mSupportIndices,
3594       mSkelCache.mSupportAxes.first,
3595       mSkelCache.mSupportAxes.second,
3596       mSkelCache.mSupportCentroid,
3597       INVALID_INDEX);
3598 
3599   mSkelCache.mDirty.mSupport = false;
3600   ++mSkelCache.mDirty.mSupportVersion;
3601   return polygon;
3602 }
3603 
3604 //==============================================================================
getSupportPolygon(std::size_t _treeIdx) const3605 const math::SupportPolygon& Skeleton::getSupportPolygon(
3606     std::size_t _treeIdx) const
3607 {
3608   math::SupportPolygon& polygon = mTreeCache[_treeIdx].mSupportPolygon;
3609 
3610   if (!mTreeCache[_treeIdx].mDirty.mSupport)
3611     return polygon;
3612 
3613   computeSupportPolygon(
3614       this,
3615       polygon,
3616       mTreeCache[_treeIdx].mSupportGeometry,
3617       mTreeCache[_treeIdx].mSupportIndices,
3618       mTreeCache[_treeIdx].mSupportAxes.first,
3619       mTreeCache[_treeIdx].mSupportAxes.second,
3620       mTreeCache[_treeIdx].mSupportCentroid,
3621       _treeIdx);
3622 
3623   mTreeCache[_treeIdx].mDirty.mSupport = false;
3624   ++mTreeCache[_treeIdx].mDirty.mSupportVersion;
3625   return polygon;
3626 }
3627 
3628 //==============================================================================
getSupportIndices() const3629 const std::vector<std::size_t>& Skeleton::getSupportIndices() const
3630 {
3631   getSupportPolygon();
3632   return mSkelCache.mSupportIndices;
3633 }
3634 
3635 //==============================================================================
getSupportIndices(std::size_t _treeIdx) const3636 const std::vector<std::size_t>& Skeleton::getSupportIndices(
3637     std::size_t _treeIdx) const
3638 {
3639   getSupportPolygon(_treeIdx);
3640   return mTreeCache[_treeIdx].mSupportIndices;
3641 }
3642 
3643 //==============================================================================
getSupportAxes() const3644 const std::pair<Eigen::Vector3d, Eigen::Vector3d>& Skeleton::getSupportAxes()
3645     const
3646 {
3647   getSupportPolygon();
3648   return mSkelCache.mSupportAxes;
3649 }
3650 
3651 //==============================================================================
getSupportAxes(std::size_t _treeIdx) const3652 const std::pair<Eigen::Vector3d, Eigen::Vector3d>& Skeleton::getSupportAxes(
3653     std::size_t _treeIdx) const
3654 {
3655   getSupportPolygon(_treeIdx);
3656   return mTreeCache[_treeIdx].mSupportAxes;
3657 }
3658 
3659 //==============================================================================
getSupportCentroid() const3660 const Eigen::Vector2d& Skeleton::getSupportCentroid() const
3661 {
3662   getSupportPolygon();
3663   return mSkelCache.mSupportCentroid;
3664 }
3665 
3666 //==============================================================================
getSupportCentroid(std::size_t _treeIdx) const3667 const Eigen::Vector2d& Skeleton::getSupportCentroid(std::size_t _treeIdx) const
3668 {
3669   getSupportPolygon(_treeIdx);
3670   return mTreeCache[_treeIdx].mSupportCentroid;
3671 }
3672 
3673 //==============================================================================
getSupportVersion() const3674 std::size_t Skeleton::getSupportVersion() const
3675 {
3676   if (mSkelCache.mDirty.mSupport)
3677     return mSkelCache.mDirty.mSupportVersion + 1;
3678 
3679   return mSkelCache.mDirty.mSupportVersion;
3680 }
3681 
3682 //==============================================================================
getSupportVersion(std::size_t _treeIdx) const3683 std::size_t Skeleton::getSupportVersion(std::size_t _treeIdx) const
3684 {
3685   if (mTreeCache[_treeIdx].mDirty.mSupport)
3686     return mTreeCache[_treeIdx].mDirty.mSupportVersion + 1;
3687 
3688   return mTreeCache[_treeIdx].mDirty.mSupportVersion;
3689 }
3690 
3691 //==============================================================================
computeForwardKinematics(bool _updateTransforms,bool _updateVels,bool _updateAccs)3692 void Skeleton::computeForwardKinematics(
3693     bool _updateTransforms, bool _updateVels, bool _updateAccs)
3694 {
3695   if (_updateTransforms)
3696   {
3697     for (std::vector<BodyNode*>::iterator it = mSkelCache.mBodyNodes.begin();
3698          it != mSkelCache.mBodyNodes.end();
3699          ++it)
3700     {
3701       (*it)->updateTransform();
3702     }
3703   }
3704 
3705   if (_updateVels)
3706   {
3707     for (std::vector<BodyNode*>::iterator it = mSkelCache.mBodyNodes.begin();
3708          it != mSkelCache.mBodyNodes.end();
3709          ++it)
3710     {
3711       (*it)->updateVelocity();
3712       (*it)->updatePartialAcceleration();
3713     }
3714   }
3715 
3716   if (_updateAccs)
3717   {
3718     for (std::vector<BodyNode*>::iterator it = mSkelCache.mBodyNodes.begin();
3719          it != mSkelCache.mBodyNodes.end();
3720          ++it)
3721     {
3722       (*it)->updateAccelerationID();
3723     }
3724   }
3725 }
3726 
3727 //==============================================================================
computeForwardDynamics()3728 void Skeleton::computeForwardDynamics()
3729 {
3730   // Note: Articulated Inertias will be updated automatically when
3731   // getArtInertiaImplicit() is called in BodyNode::updateBiasForce()
3732 
3733   for (auto it = mSkelCache.mBodyNodes.rbegin();
3734        it != mSkelCache.mBodyNodes.rend();
3735        ++it)
3736     (*it)->updateBiasForce(
3737         mAspectProperties.mGravity, mAspectProperties.mTimeStep);
3738 
3739   // Forward recursion
3740   for (auto& bodyNode : mSkelCache.mBodyNodes)
3741   {
3742     bodyNode->updateAccelerationFD();
3743     bodyNode->updateTransmittedForceFD();
3744     bodyNode->updateJointForceFD(mAspectProperties.mTimeStep, true, true);
3745   }
3746 }
3747 
3748 //==============================================================================
computeInverseDynamics(bool _withExternalForces,bool _withDampingForces,bool _withSpringForces)3749 void Skeleton::computeInverseDynamics(
3750     bool _withExternalForces, bool _withDampingForces, bool _withSpringForces)
3751 {
3752   // Skip immobile or 0-dof skeleton
3753   if (getNumDofs() == 0)
3754     return;
3755 
3756   // Backward recursion
3757   for (auto it = mSkelCache.mBodyNodes.rbegin();
3758        it != mSkelCache.mBodyNodes.rend();
3759        ++it)
3760   {
3761     (*it)->updateTransmittedForceID(
3762         mAspectProperties.mGravity, _withExternalForces);
3763     (*it)->updateJointForceID(
3764         mAspectProperties.mTimeStep, _withDampingForces, _withSpringForces);
3765   }
3766 }
3767 
3768 //==============================================================================
clearExternalForces()3769 void Skeleton::clearExternalForces()
3770 {
3771   for (auto& bodyNode : mSkelCache.mBodyNodes)
3772     bodyNode->clearExternalForces();
3773 }
3774 
3775 //==============================================================================
clearInternalForces()3776 void Skeleton::clearInternalForces()
3777 {
3778   for (auto& bodyNode : mSkelCache.mBodyNodes)
3779     bodyNode->clearInternalForces();
3780 }
3781 
3782 //==============================================================================
notifyArticulatedInertiaUpdate(std::size_t _treeIdx)3783 void Skeleton::notifyArticulatedInertiaUpdate(std::size_t _treeIdx)
3784 {
3785   dirtyArticulatedInertia(_treeIdx);
3786 }
3787 
3788 //==============================================================================
dirtyArticulatedInertia(std::size_t _treeIdx)3789 void Skeleton::dirtyArticulatedInertia(std::size_t _treeIdx)
3790 {
3791   SET_FLAG(_treeIdx, mArticulatedInertia);
3792   SET_FLAG(_treeIdx, mMassMatrix);
3793   SET_FLAG(_treeIdx, mAugMassMatrix);
3794   SET_FLAG(_treeIdx, mInvMassMatrix);
3795   SET_FLAG(_treeIdx, mInvAugMassMatrix);
3796   SET_FLAG(_treeIdx, mCoriolisForces);
3797   SET_FLAG(_treeIdx, mGravityForces);
3798   SET_FLAG(_treeIdx, mCoriolisAndGravityForces);
3799 }
3800 
3801 //==============================================================================
notifySupportUpdate(std::size_t _treeIdx)3802 void Skeleton::notifySupportUpdate(std::size_t _treeIdx)
3803 {
3804   dirtySupportPolygon(_treeIdx);
3805 }
3806 
3807 //==============================================================================
dirtySupportPolygon(std::size_t _treeIdx)3808 void Skeleton::dirtySupportPolygon(std::size_t _treeIdx)
3809 {
3810   SET_FLAG(_treeIdx, mSupport);
3811 }
3812 
3813 //==============================================================================
clearConstraintImpulses()3814 void Skeleton::clearConstraintImpulses()
3815 {
3816   for (auto& bodyNode : mSkelCache.mBodyNodes)
3817     bodyNode->clearConstraintImpulse();
3818 }
3819 
3820 //==============================================================================
updateBiasImpulse(BodyNode * _bodyNode)3821 void Skeleton::updateBiasImpulse(BodyNode* _bodyNode)
3822 {
3823   if (nullptr == _bodyNode)
3824   {
3825     dterr << "[Skeleton::updateBiasImpulse] Passed in a nullptr!\n";
3826     assert(false);
3827     return;
3828   }
3829 
3830   assert(getNumDofs() > 0);
3831 
3832   // This skeleton should contain _bodyNode
3833   assert(_bodyNode->getSkeleton().get() == this);
3834 
3835 #ifndef NDEBUG
3836   // All the constraint impulse should be zero
3837   for (std::size_t i = 0; i < mSkelCache.mBodyNodes.size(); ++i)
3838     assert(
3839         mSkelCache.mBodyNodes[i]->mConstraintImpulse
3840         == Eigen::Vector6d::Zero());
3841 #endif
3842 
3843   // Prepare cache data
3844   BodyNode* it = _bodyNode;
3845   while (it != nullptr)
3846   {
3847     it->updateBiasImpulse();
3848     it = it->getParentBodyNode();
3849   }
3850 }
3851 
3852 //==============================================================================
updateBiasImpulse(BodyNode * _bodyNode,const Eigen::Vector6d & _imp)3853 void Skeleton::updateBiasImpulse(
3854     BodyNode* _bodyNode, const Eigen::Vector6d& _imp)
3855 {
3856   if (nullptr == _bodyNode)
3857   {
3858     dterr << "[Skeleton::updateBiasImpulse] Passed in a nullptr!\n";
3859     assert(false);
3860     return;
3861   }
3862 
3863   assert(getNumDofs() > 0);
3864 
3865   // This skeleton should contain _bodyNode
3866   assert(_bodyNode->getSkeleton().get() == this);
3867 
3868 #ifndef NDEBUG
3869   // All the constraint impulse should be zero
3870   for (std::size_t i = 0; i < mSkelCache.mBodyNodes.size(); ++i)
3871     assert(
3872         mSkelCache.mBodyNodes[i]->mConstraintImpulse
3873         == Eigen::Vector6d::Zero());
3874 #endif
3875 
3876   // Set impulse of _bodyNode
3877   _bodyNode->mConstraintImpulse = _imp;
3878 
3879   // Prepare cache data
3880   BodyNode* it = _bodyNode;
3881   while (it != nullptr)
3882   {
3883     it->updateBiasImpulse();
3884     it = it->getParentBodyNode();
3885   }
3886 
3887   _bodyNode->mConstraintImpulse.setZero();
3888 }
3889 
3890 //==============================================================================
updateBiasImpulse(BodyNode * _bodyNode1,const Eigen::Vector6d & _imp1,BodyNode * _bodyNode2,const Eigen::Vector6d & _imp2)3891 void Skeleton::updateBiasImpulse(
3892     BodyNode* _bodyNode1,
3893     const Eigen::Vector6d& _imp1,
3894     BodyNode* _bodyNode2,
3895     const Eigen::Vector6d& _imp2)
3896 {
3897   // Assertions
3898   if (nullptr == _bodyNode1)
3899   {
3900     dterr << "[Skeleton::updateBiasImpulse] Passed in nullptr for BodyNode1!\n";
3901     assert(false);
3902     return;
3903   }
3904 
3905   if (nullptr == _bodyNode2)
3906   {
3907     dterr << "[Skeleton::updateBiasImpulse] Passed in nullptr for BodyNode2!\n";
3908     assert(false);
3909     return;
3910   }
3911 
3912   assert(getNumDofs() > 0);
3913 
3914   // This skeleton should contain _bodyNode
3915   assert(_bodyNode1->getSkeleton().get() == this);
3916   assert(_bodyNode2->getSkeleton().get() == this);
3917 
3918 #ifndef NDEBUG
3919   // All the constraint impulse should be zero
3920   for (std::size_t i = 0; i < mSkelCache.mBodyNodes.size(); ++i)
3921     assert(
3922         mSkelCache.mBodyNodes[i]->mConstraintImpulse
3923         == Eigen::Vector6d::Zero());
3924 #endif
3925 
3926   // Set impulse to _bodyNode
3927   _bodyNode1->mConstraintImpulse = _imp1;
3928   _bodyNode2->mConstraintImpulse = _imp2;
3929 
3930   // Find which body is placed later in the list of body nodes in this skeleton
3931   std::size_t index1 = _bodyNode1->getIndexInSkeleton();
3932   std::size_t index2 = _bodyNode2->getIndexInSkeleton();
3933 
3934   std::size_t index = std::max(index1, index2);
3935 
3936   // Prepare cache data
3937   for (int i = index; 0 <= i; --i)
3938     mSkelCache.mBodyNodes[i]->updateBiasImpulse();
3939 
3940   _bodyNode1->mConstraintImpulse.setZero();
3941   _bodyNode2->mConstraintImpulse.setZero();
3942 }
3943 
3944 //==============================================================================
updateBiasImpulse(SoftBodyNode * _softBodyNode,PointMass * _pointMass,const Eigen::Vector3d & _imp)3945 void Skeleton::updateBiasImpulse(
3946     SoftBodyNode* _softBodyNode,
3947     PointMass* _pointMass,
3948     const Eigen::Vector3d& _imp)
3949 {
3950   // Assertions
3951   assert(_softBodyNode != nullptr);
3952   assert(getNumDofs() > 0);
3953 
3954   // This skeleton should contain _bodyNode
3955   assert(
3956       std::find(mSoftBodyNodes.begin(), mSoftBodyNodes.end(), _softBodyNode)
3957       != mSoftBodyNodes.end());
3958 
3959 #ifndef NDEBUG
3960   // All the constraint impulse should be zero
3961   for (std::size_t i = 0; i < mSkelCache.mBodyNodes.size(); ++i)
3962     assert(
3963         mSkelCache.mBodyNodes[i]->mConstraintImpulse
3964         == Eigen::Vector6d::Zero());
3965 #endif
3966 
3967   // Set impulse to _bodyNode
3968   Eigen::Vector3d oldConstraintImpulse = _pointMass->getConstraintImpulses();
3969   _pointMass->setConstraintImpulse(_imp, true);
3970 
3971   // Prepare cache data
3972   BodyNode* it = _softBodyNode;
3973   while (it != nullptr)
3974   {
3975     it->updateBiasImpulse();
3976     it = it->getParentBodyNode();
3977   }
3978 
3979   // TODO(JS): Do we need to backup and restore the original value?
3980   _pointMass->setConstraintImpulse(oldConstraintImpulse);
3981 }
3982 
3983 //==============================================================================
updateVelocityChange()3984 void Skeleton::updateVelocityChange()
3985 {
3986   for (auto& bodyNode : mSkelCache.mBodyNodes)
3987     bodyNode->updateVelocityChangeFD();
3988 }
3989 
3990 //==============================================================================
setImpulseApplied(bool _val)3991 void Skeleton::setImpulseApplied(bool _val)
3992 {
3993   mIsImpulseApplied = _val;
3994 }
3995 
3996 //==============================================================================
isImpulseApplied() const3997 bool Skeleton::isImpulseApplied() const
3998 {
3999   return mIsImpulseApplied;
4000 }
4001 
4002 //==============================================================================
computeImpulseForwardDynamics()4003 void Skeleton::computeImpulseForwardDynamics()
4004 {
4005   // Skip immobile or 0-dof skeleton
4006   if (!isMobile() || getNumDofs() == 0)
4007     return;
4008 
4009   // Note: we do not need to update articulated inertias here, because they will
4010   // be updated when BodyNode::updateBiasImpulse() calls
4011   // BodyNode::getArticulatedInertia()
4012 
4013   // Backward recursion
4014   for (auto it = mSkelCache.mBodyNodes.rbegin();
4015        it != mSkelCache.mBodyNodes.rend();
4016        ++it)
4017     (*it)->updateBiasImpulse();
4018 
4019   // Forward recursion
4020   for (auto& bodyNode : mSkelCache.mBodyNodes)
4021   {
4022     bodyNode->updateVelocityChangeFD();
4023     bodyNode->updateTransmittedImpulse();
4024     bodyNode->updateJointImpulseFD();
4025     bodyNode->updateConstrainedTerms(mAspectProperties.mTimeStep);
4026   }
4027 }
4028 
4029 //==============================================================================
computeKineticEnergy() const4030 double Skeleton::computeKineticEnergy() const
4031 {
4032   double KE = 0.0;
4033 
4034   for (auto* bodyNode : mSkelCache.mBodyNodes)
4035     KE += bodyNode->computeKineticEnergy();
4036 
4037   assert(KE >= 0.0 && "Kinetic energy should be positive value.");
4038   return KE;
4039 }
4040 
4041 //==============================================================================
computePotentialEnergy() const4042 double Skeleton::computePotentialEnergy() const
4043 {
4044   double PE = 0.0;
4045 
4046   for (auto* bodyNode : mSkelCache.mBodyNodes)
4047   {
4048     PE += bodyNode->computePotentialEnergy(mAspectProperties.mGravity);
4049     PE += bodyNode->getParentJoint()->computePotentialEnergy();
4050   }
4051 
4052   return PE;
4053 }
4054 
4055 //==============================================================================
clearCollidingBodies()4056 void Skeleton::clearCollidingBodies()
4057 {
4058   for (auto i = 0u; i < getNumBodyNodes(); ++i)
4059   {
4060     auto bodyNode = getBodyNode(i);
4061     DART_SUPPRESS_DEPRECATED_BEGIN
4062     bodyNode->setColliding(false);
4063     DART_SUPPRESS_DEPRECATED_END
4064 
4065     auto softBodyNode = bodyNode->asSoftBodyNode();
4066     if (softBodyNode)
4067     {
4068       auto& pointMasses = softBodyNode->getPointMasses();
4069 
4070       for (auto pointMass : pointMasses)
4071         pointMass->setColliding(false);
4072     }
4073   }
4074 }
4075 
4076 //==============================================================================
getCOM(const Frame * _withRespectTo) const4077 Eigen::Vector3d Skeleton::getCOM(const Frame* _withRespectTo) const
4078 {
4079   Eigen::Vector3d com = Eigen::Vector3d::Zero();
4080 
4081   const std::size_t numBodies = getNumBodyNodes();
4082   for (std::size_t i = 0; i < numBodies; ++i)
4083   {
4084     const BodyNode* bodyNode = getBodyNode(i);
4085     com += bodyNode->getMass() * bodyNode->getCOM(_withRespectTo);
4086   }
4087 
4088   assert(mTotalMass != 0.0);
4089   return com / mTotalMass;
4090 }
4091 
4092 //==============================================================================
4093 // Templated function for computing different kinds of COM properties, like
4094 // velocities and accelerations
4095 template <
4096     typename PropertyType,
4097     PropertyType (BodyNode::*getPropertyFn)(const Frame*, const Frame*) const>
4098 PropertyType getCOMPropertyTemplate(
4099     const Skeleton* _skel,
4100     const Frame* _relativeTo,
4101     const Frame* _inCoordinatesOf)
4102 {
4103   PropertyType result(PropertyType::Zero());
4104 
4105   const std::size_t numBodies = _skel->getNumBodyNodes();
4106   for (std::size_t i = 0; i < numBodies; ++i)
4107   {
4108     const BodyNode* bodyNode = _skel->getBodyNode(i);
4109     result += bodyNode->getMass()
4110               * (bodyNode->*getPropertyFn)(_relativeTo, _inCoordinatesOf);
4111   }
4112 
4113   assert(_skel->getMass() != 0.0);
4114   return result / _skel->getMass();
4115 }
4116 
4117 //==============================================================================
getCOMSpatialVelocity(const Frame * _relativeTo,const Frame * _inCoordinatesOf) const4118 Eigen::Vector6d Skeleton::getCOMSpatialVelocity(
4119     const Frame* _relativeTo, const Frame* _inCoordinatesOf) const
4120 {
4121   return getCOMPropertyTemplate<
4122       Eigen::Vector6d,
4123       &BodyNode::getCOMSpatialVelocity>(this, _relativeTo, _inCoordinatesOf);
4124 }
4125 
4126 //==============================================================================
getCOMLinearVelocity(const Frame * _relativeTo,const Frame * _inCoordinatesOf) const4127 Eigen::Vector3d Skeleton::getCOMLinearVelocity(
4128     const Frame* _relativeTo, const Frame* _inCoordinatesOf) const
4129 {
4130   return getCOMPropertyTemplate<
4131       Eigen::Vector3d,
4132       &BodyNode::getCOMLinearVelocity>(this, _relativeTo, _inCoordinatesOf);
4133 }
4134 
4135 //==============================================================================
getCOMSpatialAcceleration(const Frame * _relativeTo,const Frame * _inCoordinatesOf) const4136 Eigen::Vector6d Skeleton::getCOMSpatialAcceleration(
4137     const Frame* _relativeTo, const Frame* _inCoordinatesOf) const
4138 {
4139   return getCOMPropertyTemplate<
4140       Eigen::Vector6d,
4141       &BodyNode::getCOMSpatialAcceleration>(
4142       this, _relativeTo, _inCoordinatesOf);
4143 }
4144 
4145 //==============================================================================
getCOMLinearAcceleration(const Frame * _relativeTo,const Frame * _inCoordinatesOf) const4146 Eigen::Vector3d Skeleton::getCOMLinearAcceleration(
4147     const Frame* _relativeTo, const Frame* _inCoordinatesOf) const
4148 {
4149   return getCOMPropertyTemplate<
4150       Eigen::Vector3d,
4151       &BodyNode::getCOMLinearAcceleration>(this, _relativeTo, _inCoordinatesOf);
4152 }
4153 
4154 //==============================================================================
4155 // Templated function for computing different kinds of COM Jacobians and their
4156 // derivatives
4157 template <
4158     typename JacType, // JacType is the type of Jacobian we're computing
4159     JacType (TemplatedJacobianNode<BodyNode>::*getJacFn)(
4160         const Eigen::Vector3d&, const Frame*) const>
4161 JacType getCOMJacobianTemplate(
4162     const Skeleton* _skel, const Frame* _inCoordinatesOf)
4163 {
4164   // Initialize the Jacobian to zero
4165   JacType J = JacType::Zero(JacType::RowsAtCompileTime, _skel->getNumDofs());
4166 
4167   // Iterate through each of the Skeleton's BodyNodes
4168   const std::size_t numBodies = _skel->getNumBodyNodes();
4169   for (std::size_t i = 0; i < numBodies; ++i)
4170   {
4171     const BodyNode* bn = _skel->getBodyNode(i);
4172 
4173     // (bn->*getJacFn) is a function pointer to the function that gives us the
4174     // kind of Jacobian we want from the BodyNodes. Calling it will give us the
4175     // relevant Jacobian for this BodyNode
4176     JacType bnJ
4177         = bn->getMass() * (bn->*getJacFn)(bn->getLocalCOM(), _inCoordinatesOf);
4178 
4179     // For each column in the Jacobian of this BodyNode, we add it to the
4180     // appropriate column of the overall BodyNode
4181     for (std::size_t j = 0, end = bn->getNumDependentGenCoords(); j < end; ++j)
4182     {
4183       std::size_t idx = bn->getDependentGenCoordIndex(j);
4184       J.col(idx) += bnJ.col(j);
4185     }
4186   }
4187 
4188   assert(_skel->getMass() != 0.0);
4189   return J / _skel->getMass();
4190 }
4191 
4192 //==============================================================================
getCOMJacobian(const Frame * _inCoordinatesOf) const4193 math::Jacobian Skeleton::getCOMJacobian(const Frame* _inCoordinatesOf) const
4194 {
4195   return getCOMJacobianTemplate<
4196       math::Jacobian,
4197       &TemplatedJacobianNode<BodyNode>::getJacobian>(this, _inCoordinatesOf);
4198 }
4199 
4200 //==============================================================================
getCOMLinearJacobian(const Frame * _inCoordinatesOf) const4201 math::LinearJacobian Skeleton::getCOMLinearJacobian(
4202     const Frame* _inCoordinatesOf) const
4203 {
4204   return getCOMJacobianTemplate<
4205       math::LinearJacobian,
4206       &TemplatedJacobianNode<BodyNode>::getLinearJacobian>(
4207       this, _inCoordinatesOf);
4208 }
4209 
4210 //==============================================================================
getCOMJacobianSpatialDeriv(const Frame * _inCoordinatesOf) const4211 math::Jacobian Skeleton::getCOMJacobianSpatialDeriv(
4212     const Frame* _inCoordinatesOf) const
4213 {
4214   return getCOMJacobianTemplate<
4215       math::Jacobian,
4216       &TemplatedJacobianNode<BodyNode>::getJacobianSpatialDeriv>(
4217       this, _inCoordinatesOf);
4218 }
4219 
4220 //==============================================================================
getCOMLinearJacobianDeriv(const Frame * _inCoordinatesOf) const4221 math::LinearJacobian Skeleton::getCOMLinearJacobianDeriv(
4222     const Frame* _inCoordinatesOf) const
4223 {
4224   return getCOMJacobianTemplate<
4225       math::LinearJacobian,
4226       &TemplatedJacobianNode<BodyNode>::getLinearJacobianDeriv>(
4227       this, _inCoordinatesOf);
4228 }
4229 
4230 //==============================================================================
DirtyFlags()4231 Skeleton::DirtyFlags::DirtyFlags()
4232   : mArticulatedInertia(true),
4233     mMassMatrix(true),
4234     mAugMassMatrix(true),
4235     mInvMassMatrix(true),
4236     mInvAugMassMatrix(true),
4237     mGravityForces(true),
4238     mCoriolisForces(true),
4239     mCoriolisAndGravityForces(true),
4240     mExternalForces(true),
4241     mDampingForces(true),
4242     mSupport(true),
4243     mSupportVersion(0)
4244 {
4245   // Do nothing
4246 }
4247 
4248 } // namespace dynamics
4249 } // namespace dart
4250