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/PointMass.hpp"
34
35 #include "dart/common/Console.hpp"
36 #include "dart/dynamics/EllipsoidShape.hpp"
37 #include "dart/dynamics/SoftBodyNode.hpp"
38 #include "dart/math/Geometry.hpp"
39 #include "dart/math/Helpers.hpp"
40
41 using namespace Eigen;
42
43 namespace dart {
44 namespace dynamics {
45
46 #define RETURN_FALSE_IF_OTHER_IS_EQUAL(X) \
47 if (other.X != X) \
48 return false;
49
50 //==============================================================================
State(const Vector3d & positions,const Vector3d & velocities,const Vector3d & accelerations,const Vector3d & forces)51 PointMass::State::State(
52 const Vector3d& positions,
53 const Vector3d& velocities,
54 const Vector3d& accelerations,
55 const Vector3d& forces)
56 : mPositions(positions),
57 mVelocities(velocities),
58 mAccelerations(accelerations),
59 mForces(forces)
60 {
61 // Do nothing
62 }
63
64 //==============================================================================
operator ==(const PointMass::State & other) const65 bool PointMass::State::operator==(const PointMass::State& other) const
66 {
67 RETURN_FALSE_IF_OTHER_IS_EQUAL(mPositions);
68 RETURN_FALSE_IF_OTHER_IS_EQUAL(mVelocities);
69 RETURN_FALSE_IF_OTHER_IS_EQUAL(mAccelerations);
70 RETURN_FALSE_IF_OTHER_IS_EQUAL(mForces);
71
72 return true;
73 }
74
75 //==============================================================================
Properties(const Vector3d & _X0,double _mass,const std::vector<std::size_t> & _connections,const Vector3d & _positionLowerLimits,const Vector3d & _positionUpperLimits,const Vector3d & _velocityLowerLimits,const Vector3d & _velocityUpperLimits,const Vector3d & _accelerationLowerLimits,const Vector3d & _accelerationUpperLimits,const Vector3d & _forceLowerLimits,const Vector3d & _forceUpperLimits)76 PointMass::Properties::Properties(
77 const Vector3d& _X0,
78 double _mass,
79 const std::vector<std::size_t>& _connections,
80 const Vector3d& _positionLowerLimits,
81 const Vector3d& _positionUpperLimits,
82 const Vector3d& _velocityLowerLimits,
83 const Vector3d& _velocityUpperLimits,
84 const Vector3d& _accelerationLowerLimits,
85 const Vector3d& _accelerationUpperLimits,
86 const Vector3d& _forceLowerLimits,
87 const Vector3d& _forceUpperLimits)
88 : mX0(_X0),
89 mMass(_mass),
90 mConnectedPointMassIndices(_connections),
91 mPositionLowerLimits(_positionLowerLimits),
92 mPositionUpperLimits(_positionUpperLimits),
93 mVelocityLowerLimits(_velocityLowerLimits),
94 mVelocityUpperLimits(_velocityUpperLimits),
95 mAccelerationLowerLimits(_accelerationLowerLimits),
96 mAccelerationUpperLimits(_accelerationUpperLimits),
97 mForceLowerLimits(_forceLowerLimits),
98 mForceUpperLimits(_forceUpperLimits)
99 {
100 // Do nothing
101 }
102
103 //==============================================================================
setRestingPosition(const Vector3d & _x)104 void PointMass::Properties::setRestingPosition(const Vector3d& _x)
105 {
106 mX0 = _x;
107 }
108
109 //==============================================================================
setMass(double _mass)110 void PointMass::Properties::setMass(double _mass)
111 {
112 mMass = _mass;
113 }
114
115 //==============================================================================
operator ==(const PointMass::Properties & other) const116 bool PointMass::Properties::operator==(const PointMass::Properties& other) const
117 {
118 RETURN_FALSE_IF_OTHER_IS_EQUAL(mX0);
119 RETURN_FALSE_IF_OTHER_IS_EQUAL(mMass);
120 RETURN_FALSE_IF_OTHER_IS_EQUAL(mConnectedPointMassIndices);
121 RETURN_FALSE_IF_OTHER_IS_EQUAL(mPositionLowerLimits);
122 RETURN_FALSE_IF_OTHER_IS_EQUAL(mPositionUpperLimits);
123 RETURN_FALSE_IF_OTHER_IS_EQUAL(mVelocityLowerLimits);
124 RETURN_FALSE_IF_OTHER_IS_EQUAL(mVelocityUpperLimits);
125 RETURN_FALSE_IF_OTHER_IS_EQUAL(mAccelerationLowerLimits);
126 RETURN_FALSE_IF_OTHER_IS_EQUAL(mAccelerationUpperLimits);
127 RETURN_FALSE_IF_OTHER_IS_EQUAL(mForceLowerLimits);
128 RETURN_FALSE_IF_OTHER_IS_EQUAL(mForceUpperLimits);
129
130 // Nothing was inequal, so we return true
131 return true;
132 }
133
134 //==============================================================================
operator !=(const PointMass::Properties & other) const135 bool PointMass::Properties::operator!=(const PointMass::Properties& other) const
136 {
137 return !(other == *this);
138 }
139
140 //==============================================================================
PointMass(SoftBodyNode * _softBodyNode)141 PointMass::PointMass(SoftBodyNode* _softBodyNode)
142 : // mIndexInSkeleton(Eigen::Matrix<std::size_t, 3, 1>::Zero()),
143 mParentSoftBodyNode(_softBodyNode),
144 mPositionDeriv(Eigen::Vector3d::Zero()),
145 mVelocitiesDeriv(Eigen::Vector3d::Zero()),
146 mAccelerationsDeriv(Eigen::Vector3d::Zero()),
147 mForcesDeriv(Eigen::Vector3d::Zero()),
148 mVelocityChanges(Eigen::Vector3d::Zero()),
149 // mImpulse(Eigen::Vector3d::Zero()),
150 mConstraintImpulses(Eigen::Vector3d::Zero()),
151 mW(Eigen::Vector3d::Zero()),
152 mX(Eigen::Vector3d::Zero()),
153 mV(Eigen::Vector3d::Zero()),
154 mEta(Eigen::Vector3d::Zero()),
155 mAlpha(Eigen::Vector3d::Zero()),
156 mBeta(Eigen::Vector3d::Zero()),
157 mA(Eigen::Vector3d::Zero()),
158 mF(Eigen::Vector3d::Zero()),
159 mPsi(0.0),
160 mImplicitPsi(0.0),
161 mPi(0.0),
162 mImplicitPi(0.0),
163 mB(Eigen::Vector3d::Zero()),
164 mFext(Eigen::Vector3d::Zero()),
165 mIsColliding(false),
166 mDelV(Eigen::Vector3d::Zero()),
167 mImpB(Eigen::Vector3d::Zero()),
168 mImpAlpha(Eigen::Vector3d::Zero()),
169 mImpBeta(Eigen::Vector3d::Zero()),
170 mImpF(Eigen::Vector3d::Zero()),
171 mNotifier(_softBodyNode->mNotifier)
172 {
173 assert(mParentSoftBodyNode != nullptr);
174 mNotifier->dirtyTransform();
175 }
176
177 //==============================================================================
~PointMass()178 PointMass::~PointMass()
179 {
180 // Do nothing
181 }
182
183 //==============================================================================
getState()184 PointMass::State& PointMass::getState()
185 {
186 return mParentSoftBodyNode->mAspectState.mPointStates[mIndex];
187 }
188
189 //==============================================================================
getState() const190 const PointMass::State& PointMass::getState() const
191 {
192 return mParentSoftBodyNode->mAspectState.mPointStates[mIndex];
193 }
194
195 //==============================================================================
getIndexInSoftBodyNode() const196 std::size_t PointMass::getIndexInSoftBodyNode() const
197 {
198 return mIndex;
199 }
200
201 //==============================================================================
setMass(double _mass)202 void PointMass::setMass(double _mass)
203 {
204 assert(0.0 < _mass);
205 double& mMass
206 = mParentSoftBodyNode->mAspectProperties.mPointProps[mIndex].mMass;
207 if (_mass == mMass)
208 return;
209
210 mMass = _mass;
211 mParentSoftBodyNode->incrementVersion();
212 }
213
214 //==============================================================================
getMass() const215 double PointMass::getMass() const
216 {
217 return mParentSoftBodyNode->mAspectProperties.mPointProps[mIndex].mMass;
218 }
219
220 //==============================================================================
getPsi() const221 double PointMass::getPsi() const
222 {
223 mParentSoftBodyNode->checkArticulatedInertiaUpdate();
224 return mPsi;
225 }
226
227 //==============================================================================
getImplicitPsi() const228 double PointMass::getImplicitPsi() const
229 {
230 mParentSoftBodyNode->checkArticulatedInertiaUpdate();
231 return mImplicitPsi;
232 }
233
234 //==============================================================================
getPi() const235 double PointMass::getPi() const
236 {
237 mParentSoftBodyNode->checkArticulatedInertiaUpdate();
238 return mPi;
239 }
240
241 //==============================================================================
getImplicitPi() const242 double PointMass::getImplicitPi() const
243 {
244 mParentSoftBodyNode->checkArticulatedInertiaUpdate();
245 return mImplicitPi;
246 }
247
248 //==============================================================================
addConnectedPointMass(PointMass * _pointMass)249 void PointMass::addConnectedPointMass(PointMass* _pointMass)
250 {
251 assert(_pointMass != nullptr);
252
253 mParentSoftBodyNode->mAspectProperties.mPointProps[mIndex]
254 .mConnectedPointMassIndices.push_back(_pointMass->mIndex);
255 mParentSoftBodyNode->incrementVersion();
256 }
257
258 //==============================================================================
getNumConnectedPointMasses() const259 std::size_t PointMass::getNumConnectedPointMasses() const
260 {
261 return mParentSoftBodyNode->mAspectProperties.mPointProps[mIndex]
262 .mConnectedPointMassIndices.size();
263 }
264
265 //==============================================================================
getConnectedPointMass(std::size_t _idx)266 PointMass* PointMass::getConnectedPointMass(std::size_t _idx)
267 {
268 assert(_idx < getNumConnectedPointMasses());
269
270 return mParentSoftBodyNode
271 ->mPointMasses[mParentSoftBodyNode->mAspectProperties.mPointProps[mIndex]
272 .mConnectedPointMassIndices[_idx]];
273 }
274
275 //==============================================================================
getConnectedPointMass(std::size_t _idx) const276 const PointMass* PointMass::getConnectedPointMass(std::size_t _idx) const
277 {
278 return const_cast<PointMass*>(this)->getConnectedPointMass(_idx);
279 }
280
281 //==============================================================================
setColliding(bool _isColliding)282 void PointMass::setColliding(bool _isColliding)
283 {
284 mIsColliding = _isColliding;
285 }
286
287 //==============================================================================
isColliding()288 bool PointMass::isColliding()
289 {
290 return mIsColliding;
291 }
292
293 //==============================================================================
getNumDofs() const294 std::size_t PointMass::getNumDofs() const
295 {
296 return 3;
297 }
298
299 ////==============================================================================
300 // void PointMass::setIndexInSkeleton(std::size_t _index, std::size_t
301 // _indexInSkeleton)
302 //{
303 // assert(_index < 3);
304
305 // mIndexInSkeleton[_index] = _indexInSkeleton;
306 //}
307
308 ////==============================================================================
309 // std::size_t PointMass::getIndexInSkeleton(std::size_t _index) const
310 //{
311 // assert(_index < 3);
312
313 // return mIndexInSkeleton[_index];
314 //}
315
316 //==============================================================================
setPosition(std::size_t _index,double _position)317 void PointMass::setPosition(std::size_t _index, double _position)
318 {
319 assert(_index < 3);
320
321 getState().mPositions[_index] = _position;
322 mNotifier->dirtyTransform();
323 }
324
325 //==============================================================================
getPosition(std::size_t _index) const326 double PointMass::getPosition(std::size_t _index) const
327 {
328 assert(_index < 3);
329
330 return getState().mPositions[_index];
331 }
332
333 //==============================================================================
setPositions(const Vector3d & _positions)334 void PointMass::setPositions(const Vector3d& _positions)
335 {
336 getState().mPositions = _positions;
337 mNotifier->dirtyTransform();
338 }
339
340 //==============================================================================
getPositions() const341 const Vector3d& PointMass::getPositions() const
342 {
343 return getState().mPositions;
344 }
345
346 //==============================================================================
resetPositions()347 void PointMass::resetPositions()
348 {
349 getState().mPositions.setZero();
350 mNotifier->dirtyTransform();
351 }
352
353 //==============================================================================
setVelocity(std::size_t _index,double _velocity)354 void PointMass::setVelocity(std::size_t _index, double _velocity)
355 {
356 assert(_index < 3);
357
358 getState().mVelocities[_index] = _velocity;
359 mNotifier->dirtyVelocity();
360 }
361
362 //==============================================================================
getVelocity(std::size_t _index) const363 double PointMass::getVelocity(std::size_t _index) const
364 {
365 assert(_index < 3);
366
367 return getState().mVelocities[_index];
368 }
369
370 //==============================================================================
setVelocities(const Vector3d & _velocities)371 void PointMass::setVelocities(const Vector3d& _velocities)
372 {
373 getState().mVelocities = _velocities;
374 mNotifier->dirtyVelocity();
375 }
376
377 //==============================================================================
getVelocities() const378 const Vector3d& PointMass::getVelocities() const
379 {
380 return getState().mVelocities;
381 }
382
383 //==============================================================================
resetVelocities()384 void PointMass::resetVelocities()
385 {
386 getState().mVelocities.setZero();
387 mNotifier->dirtyVelocity();
388 }
389
390 //==============================================================================
setAcceleration(std::size_t _index,double _acceleration)391 void PointMass::setAcceleration(std::size_t _index, double _acceleration)
392 {
393 assert(_index < 3);
394
395 getState().mAccelerations[_index] = _acceleration;
396 mNotifier->dirtyAcceleration();
397 }
398
399 //==============================================================================
getAcceleration(std::size_t _index) const400 double PointMass::getAcceleration(std::size_t _index) const
401 {
402 assert(_index < 3);
403
404 return getState().mAccelerations[_index];
405 }
406
407 //==============================================================================
setAccelerations(const Eigen::Vector3d & _accelerations)408 void PointMass::setAccelerations(const Eigen::Vector3d& _accelerations)
409 {
410 getState().mAccelerations = _accelerations;
411 mNotifier->dirtyAcceleration();
412 }
413
414 //==============================================================================
getAccelerations() const415 const Vector3d& PointMass::getAccelerations() const
416 {
417 return getState().mAccelerations;
418 }
419
420 //==============================================================================
getPartialAccelerations() const421 const Vector3d& PointMass::getPartialAccelerations() const
422 {
423 if (mNotifier->needsPartialAccelerationUpdate())
424 mParentSoftBodyNode->updatePartialAcceleration();
425 return mEta;
426 }
427
428 //==============================================================================
resetAccelerations()429 void PointMass::resetAccelerations()
430 {
431 getState().mAccelerations.setZero();
432 mNotifier->dirtyAcceleration();
433 }
434
435 //==============================================================================
setForce(std::size_t _index,double _force)436 void PointMass::setForce(std::size_t _index, double _force)
437 {
438 assert(_index < 3);
439
440 getState().mForces[_index] = _force;
441 }
442
443 //==============================================================================
getForce(std::size_t _index)444 double PointMass::getForce(std::size_t _index)
445 {
446 assert(_index < 3);
447
448 return getState().mForces[_index];
449 }
450
451 //==============================================================================
setForces(const Vector3d & _forces)452 void PointMass::setForces(const Vector3d& _forces)
453 {
454 getState().mForces = _forces;
455 }
456
457 //==============================================================================
getForces() const458 const Vector3d& PointMass::getForces() const
459 {
460 return getState().mForces;
461 }
462
463 //==============================================================================
resetForces()464 void PointMass::resetForces()
465 {
466 getState().mForces.setZero();
467 }
468
469 //==============================================================================
setVelocityChange(std::size_t _index,double _velocityChange)470 void PointMass::setVelocityChange(std::size_t _index, double _velocityChange)
471 {
472 assert(_index < 3);
473
474 mVelocityChanges[_index] = _velocityChange;
475 }
476
477 //==============================================================================
getVelocityChange(std::size_t _index)478 double PointMass::getVelocityChange(std::size_t _index)
479 {
480 assert(_index < 3);
481
482 return mVelocityChanges[_index];
483 }
484
485 //==============================================================================
resetVelocityChanges()486 void PointMass::resetVelocityChanges()
487 {
488 mVelocityChanges.setZero();
489 }
490
491 //==============================================================================
setConstraintImpulse(std::size_t _index,double _impulse)492 void PointMass::setConstraintImpulse(std::size_t _index, double _impulse)
493 {
494 assert(_index < 3);
495
496 mConstraintImpulses[_index] = _impulse;
497 }
498
499 //==============================================================================
getConstraintImpulse(std::size_t _index)500 double PointMass::getConstraintImpulse(std::size_t _index)
501 {
502 assert(_index < 3);
503
504 return mConstraintImpulses[_index];
505 }
506
507 //==============================================================================
resetConstraintImpulses()508 void PointMass::resetConstraintImpulses()
509 {
510 mConstraintImpulses.setZero();
511 }
512
513 //==============================================================================
integratePositions(double _dt)514 void PointMass::integratePositions(double _dt)
515 {
516 setPositions(getPositions() + getVelocities() * _dt);
517 }
518
519 //==============================================================================
integrateVelocities(double _dt)520 void PointMass::integrateVelocities(double _dt)
521 {
522 setVelocities(getVelocities() + getAccelerations() * _dt);
523 }
524
525 //==============================================================================
addExtForce(const Eigen::Vector3d & _force,bool _isForceLocal)526 void PointMass::addExtForce(const Eigen::Vector3d& _force, bool _isForceLocal)
527 {
528 if (_isForceLocal)
529 {
530 mFext += _force;
531 }
532 else
533 {
534 mFext += mParentSoftBodyNode->getWorldTransform().linear().transpose()
535 * _force;
536 }
537 }
538
539 //==============================================================================
clearExtForce()540 void PointMass::clearExtForce()
541 {
542 mFext.setZero();
543 }
544
545 //==============================================================================
setConstraintImpulse(const Eigen::Vector3d & _constImp,bool _isLocal)546 void PointMass::setConstraintImpulse(
547 const Eigen::Vector3d& _constImp, bool _isLocal)
548 {
549 if (_isLocal)
550 {
551 mConstraintImpulses = _constImp;
552 }
553 else
554 {
555 const Matrix3d Rt
556 = mParentSoftBodyNode->getWorldTransform().linear().transpose();
557 mConstraintImpulses = Rt * _constImp;
558 }
559 }
560
561 //==============================================================================
addConstraintImpulse(const Eigen::Vector3d & _constImp,bool _isLocal)562 void PointMass::addConstraintImpulse(
563 const Eigen::Vector3d& _constImp, bool _isLocal)
564 {
565 if (_isLocal)
566 {
567 mConstraintImpulses += _constImp;
568 }
569 else
570 {
571 const Matrix3d Rt
572 = mParentSoftBodyNode->getWorldTransform().linear().transpose();
573 mConstraintImpulses.noalias() += Rt * _constImp;
574 }
575 }
576
577 //==============================================================================
getConstraintImpulses() const578 Eigen::Vector3d PointMass::getConstraintImpulses() const
579 {
580 return mConstraintImpulses;
581 }
582
583 //==============================================================================
clearConstraintImpulse()584 void PointMass::clearConstraintImpulse()
585 {
586 assert(getNumDofs() == 3);
587 mConstraintImpulses.setZero();
588 mDelV.setZero();
589 mImpB.setZero();
590 mImpAlpha.setZero();
591 mImpBeta.setZero();
592 mImpF.setZero();
593 }
594
595 //==============================================================================
setRestingPosition(const Eigen::Vector3d & _p)596 void PointMass::setRestingPosition(const Eigen::Vector3d& _p)
597 {
598
599 Eigen::Vector3d& mRest
600 = mParentSoftBodyNode->mAspectProperties.mPointProps[mIndex].mX0;
601 if (_p == mRest)
602 return;
603
604 mRest = _p;
605 mParentSoftBodyNode->incrementVersion();
606 mNotifier->dirtyTransform();
607 }
608
609 //==============================================================================
getRestingPosition() const610 const Eigen::Vector3d& PointMass::getRestingPosition() const
611 {
612 return mParentSoftBodyNode->mAspectProperties.mPointProps[mIndex].mX0;
613 }
614
615 //==============================================================================
getLocalPosition() const616 const Eigen::Vector3d& PointMass::getLocalPosition() const
617 {
618 if (mNotifier->needsTransformUpdate())
619 mParentSoftBodyNode->updateTransform();
620 return mX;
621 }
622
623 //==============================================================================
getWorldPosition() const624 const Eigen::Vector3d& PointMass::getWorldPosition() const
625 {
626 if (mNotifier && mNotifier->needsTransformUpdate())
627 mParentSoftBodyNode->updateTransform();
628 return mW;
629 }
630
631 //==============================================================================
getBodyJacobian()632 Eigen::Matrix<double, 3, Eigen::Dynamic> PointMass::getBodyJacobian()
633 {
634 assert(mParentSoftBodyNode != nullptr);
635
636 int dof = mParentSoftBodyNode->getNumDependentGenCoords();
637 int totalDof = mParentSoftBodyNode->getNumDependentGenCoords() + 3;
638
639 Eigen::Matrix<double, 3, Eigen::Dynamic> J
640 = Eigen::MatrixXd::Zero(3, totalDof);
641
642 Eigen::Isometry3d T = Eigen::Isometry3d::Identity();
643 T.translation() = getLocalPosition();
644
645 J.leftCols(dof)
646 = math::AdInvTJac(T, mParentSoftBodyNode->getJacobian()).bottomRows<3>();
647 J.rightCols<3>() = Eigen::Matrix3d::Identity();
648
649 return J;
650 }
651
652 //==============================================================================
getWorldJacobian()653 Eigen::Matrix<double, 3, Eigen::Dynamic> PointMass::getWorldJacobian()
654 {
655 return mParentSoftBodyNode->getWorldTransform().linear() * getBodyJacobian();
656 }
657
658 //==============================================================================
getBodyVelocityChange() const659 const Eigen::Vector3d& PointMass::getBodyVelocityChange() const
660 {
661 return mDelV;
662 }
663
664 //==============================================================================
getParentSoftBodyNode()665 SoftBodyNode* PointMass::getParentSoftBodyNode()
666 {
667 return mParentSoftBodyNode;
668 }
669
670 //==============================================================================
getParentSoftBodyNode() const671 const SoftBodyNode* PointMass::getParentSoftBodyNode() const
672 {
673 return mParentSoftBodyNode;
674 }
675
676 //==============================================================================
677 // int PointMass::getNumDependentGenCoords() const
678 //{
679 // return mDependentGenCoordIndices.size();
680 //}
681
682 //==============================================================================
683 // int PointMass::getDependentGenCoord(int _arrayIndex) const
684 //{
685 // assert(0 <= _arrayIndex && _arrayIndex < mDependentGenCoordIndices.size());
686 // return mDependentGenCoordIndices[_arrayIndex];
687 //}
688
689 //==============================================================================
getBodyVelocity() const690 const Eigen::Vector3d& PointMass::getBodyVelocity() const
691 {
692 if (mNotifier->needsVelocityUpdate())
693 mParentSoftBodyNode->updateVelocity();
694 return mV;
695 }
696
697 //==============================================================================
getWorldVelocity() const698 Eigen::Vector3d PointMass::getWorldVelocity() const
699 {
700 return mParentSoftBodyNode->getWorldTransform().linear() * getBodyVelocity();
701 }
702
703 //==============================================================================
getBodyAcceleration() const704 const Eigen::Vector3d& PointMass::getBodyAcceleration() const
705 {
706 if (mNotifier->needsAccelerationUpdate())
707 mParentSoftBodyNode->updateAccelerationID();
708 return mA;
709 }
710
711 //==============================================================================
getWorldAcceleration() const712 Eigen::Vector3d PointMass::getWorldAcceleration() const
713 {
714 return mParentSoftBodyNode->getWorldTransform().linear()
715 * getBodyAcceleration();
716 }
717
718 //==============================================================================
init()719 void PointMass::init()
720 {
721 mDependentGenCoordIndices
722 = mParentSoftBodyNode->getDependentGenCoordIndices();
723 }
724
725 //==============================================================================
updateTransform() const726 void PointMass::updateTransform() const
727 {
728 // Local translation
729 mX = getPositions() + getRestingPosition();
730 assert(!math::isNan(mX));
731
732 // World translation
733 const Eigen::Isometry3d& parentW = mParentSoftBodyNode->getWorldTransform();
734 mW = parentW.translation() + parentW.linear() * mX;
735 assert(!math::isNan(mW));
736 }
737
738 //==============================================================================
updateVelocity() const739 void PointMass::updateVelocity() const
740 {
741 // v = w(parent) x mX + v(parent) + dq
742 const Eigen::Vector6d& v_parent = mParentSoftBodyNode->getSpatialVelocity();
743 mV = v_parent.head<3>().cross(getLocalPosition()) + v_parent.tail<3>()
744 + getVelocities();
745 assert(!math::isNan(mV));
746 }
747
748 //==============================================================================
updatePartialAcceleration() const749 void PointMass::updatePartialAcceleration() const
750 {
751 // eta = w(parent) x dq
752 const Eigen::Vector3d& dq = getVelocities();
753 mEta = mParentSoftBodyNode->getSpatialVelocity().head<3>().cross(dq);
754 assert(!math::isNan(mEta));
755 }
756
757 //==============================================================================
updateAccelerationID() const758 void PointMass::updateAccelerationID() const
759 {
760 // dv = dw(parent) x mX + dv(parent) + eata + ddq
761 const Eigen::Vector6d& a_parent
762 = mParentSoftBodyNode->getSpatialAcceleration();
763 mA = a_parent.head<3>().cross(getLocalPosition()) + a_parent.tail<3>()
764 + getPartialAccelerations() + getAccelerations();
765 assert(!math::isNan(mA));
766 }
767
768 //==============================================================================
updateTransmittedForceID(const Eigen::Vector3d & _gravity,bool)769 void PointMass::updateTransmittedForceID(
770 const Eigen::Vector3d& _gravity, bool /*_withExternalForces*/)
771 {
772 // f = m*dv + w(parent) x m*v - fext
773 mF.noalias() = getMass() * getBodyAcceleration();
774 mF += mParentSoftBodyNode->getSpatialVelocity().head<3>().cross(
775 getMass() * getBodyVelocity())
776 - mFext;
777 if (mParentSoftBodyNode->getGravityMode() == true)
778 {
779 mF -= getMass()
780 * (mParentSoftBodyNode->getWorldTransform().linear().transpose()
781 * _gravity);
782 }
783 assert(!math::isNan(mF));
784 }
785
786 //==============================================================================
updateArtInertiaFD(double _timeStep) const787 void PointMass::updateArtInertiaFD(double _timeStep) const
788 {
789 // Articulated inertia
790 // - Do nothing
791
792 // Cache data: PsiK and Psi
793 mPsi = 1.0 / getMass();
794 mImplicitPsi
795 = 1.0
796 / (getMass() + _timeStep * mParentSoftBodyNode->getDampingCoefficient()
797 + _timeStep * _timeStep
798 * mParentSoftBodyNode->getVertexSpringStiffness());
799 assert(!math::isNan(mImplicitPsi));
800
801 // Cache data: AI_S_Psi
802 // - Do nothing
803
804 // Cache data: Pi
805 mPi = getMass() - getMass() * getMass() * mPsi;
806 mImplicitPi = getMass() - getMass() * getMass() * mImplicitPsi;
807 assert(!math::isNan(mPi));
808 assert(!math::isNan(mImplicitPi));
809 }
810
811 //==============================================================================
updateJointForceID(double,double,double)812 void PointMass::updateJointForceID(
813 double /*_timeStep*/,
814 double /*_withDampingForces*/,
815 double /*_withSpringForces*/)
816 {
817 // tau = f
818 getState().mForces = mF;
819 // TODO: need to add spring and damping forces
820 }
821
822 //==============================================================================
updateBiasForceFD(double _dt,const Eigen::Vector3d & _gravity)823 void PointMass::updateBiasForceFD(double _dt, const Eigen::Vector3d& _gravity)
824 {
825 // B = w(parent) x m*v - fext - fgravity
826 // - w(parent) x m*v - fext
827 mB = mParentSoftBodyNode->getSpatialVelocity().head<3>().cross(
828 getMass() * getBodyVelocity())
829 - mFext;
830 // - fgravity
831 if (mParentSoftBodyNode->getGravityMode() == true)
832 {
833 mB -= getMass()
834 * (mParentSoftBodyNode->getWorldTransform().linear().transpose()
835 * _gravity);
836 }
837 assert(!math::isNan(mB));
838
839 const State& state = getState();
840
841 // Cache data: alpha
842 double kv = mParentSoftBodyNode->getVertexSpringStiffness();
843 double ke = mParentSoftBodyNode->getEdgeSpringStiffness();
844 double kd = mParentSoftBodyNode->getDampingCoefficient();
845 std::size_t nN = getNumConnectedPointMasses();
846 mAlpha = state.mForces - (kv + nN * ke) * getPositions()
847 - (_dt * (kv + nN * ke) + kd) * getVelocities()
848 - getMass() * getPartialAccelerations() - mB;
849 for (std::size_t i = 0; i < getNumConnectedPointMasses(); ++i)
850 {
851 const State& i_state = getConnectedPointMass(i)->getState();
852 mAlpha += ke * (i_state.mPositions + _dt * i_state.mVelocities);
853 }
854 assert(!math::isNan(mAlpha));
855
856 // Cache data: beta
857 mBeta = mB;
858 mBeta.noalias()
859 += getMass() * (getPartialAccelerations() + getImplicitPsi() * mAlpha);
860 assert(!math::isNan(mBeta));
861 }
862
863 //==============================================================================
updateAccelerationFD()864 void PointMass::updateAccelerationFD()
865 {
866 // ddq = imp_psi*(alpha - m*(dw(parent) x mX + dv(parent))
867 const Eigen::Vector3d& X = getLocalPosition();
868 const Eigen::Vector6d& a_parent
869 = mParentSoftBodyNode->getSpatialAcceleration();
870 Eigen::Vector3d ddq
871 = getImplicitPsi()
872 * (mAlpha
873 - getMass() * (a_parent.head<3>().cross(X) + a_parent.tail<3>()));
874 setAccelerations(ddq);
875 assert(!math::isNan(ddq));
876
877 // dv = dw(parent) x mX + dv(parent) + eata + ddq
878 mA = a_parent.head<3>().cross(X) + a_parent.tail<3>()
879 + getPartialAccelerations() + getAccelerations();
880 assert(!math::isNan(mA));
881 }
882
883 //==============================================================================
updateTransmittedForce()884 void PointMass::updateTransmittedForce()
885 {
886 // f = m*dv + B
887 mF = mB;
888 mF.noalias() += getMass() * getBodyAcceleration();
889 assert(!math::isNan(mF));
890 }
891
892 //==============================================================================
updateMassMatrix()893 void PointMass::updateMassMatrix()
894 {
895 mM_dV = getAccelerations()
896 + mParentSoftBodyNode->mM_dV.head<3>().cross(getLocalPosition())
897 + mParentSoftBodyNode->mM_dV.tail<3>();
898 assert(!math::isNan(mM_dV));
899 }
900
901 //==============================================================================
updateBiasImpulseFD()902 void PointMass::updateBiasImpulseFD()
903 {
904 mImpB = -mConstraintImpulses;
905 assert(!math::isNan(mImpB));
906
907 // Cache data: alpha
908 mImpAlpha = -mImpB;
909 assert(!math::isNan(mImpAlpha));
910
911 // Cache data: beta
912 mImpBeta.setZero();
913 assert(!math::isNan(mImpBeta));
914 }
915
916 //==============================================================================
updateVelocityChangeFD()917 void PointMass::updateVelocityChangeFD()
918 {
919 // Eigen::Vector3d del_dq
920 // = mPsi
921 // * (mImpAlpha - mMass
922 // *
923 // (mParentSoftBodyNode->getBodyVelocityChange().head<3>().cross(mX)
924 // + mParentSoftBodyNode->getBodyVelocityChange().tail<3>()));
925
926 const Eigen::Vector3d& X = getLocalPosition();
927 Eigen::Vector3d del_dq
928 = getPsi() * mImpAlpha
929 - mParentSoftBodyNode->getBodyVelocityChange().head<3>().cross(X)
930 - mParentSoftBodyNode->getBodyVelocityChange().tail<3>();
931
932 // del_dq = Eigen::Vector3d::Zero();
933
934 mVelocityChanges = del_dq;
935 assert(!math::isNan(del_dq));
936
937 mDelV = mParentSoftBodyNode->getBodyVelocityChange().head<3>().cross(X)
938 + mParentSoftBodyNode->getBodyVelocityChange().tail<3>()
939 + mVelocityChanges;
940 assert(!math::isNan(mDelV));
941 }
942
943 //==============================================================================
updateTransmittedImpulse()944 void PointMass::updateTransmittedImpulse()
945 {
946 mImpF = mImpB;
947 mImpF.noalias() += getMass() * mDelV;
948 assert(!math::isNan(mImpF));
949 }
950
951 //==============================================================================
updateConstrainedTermsFD(double _timeStep)952 void PointMass::updateConstrainedTermsFD(double _timeStep)
953 {
954 // 1. dq = dq + del_dq
955 setVelocities(getVelocities() + mVelocityChanges);
956
957 // 2. ddq = ddq + del_dq / dt
958 setAccelerations(getAccelerations() + mVelocityChanges / _timeStep);
959
960 // 3. tau = tau + imp / dt
961 getState().mForces.noalias() += mConstraintImpulses / _timeStep;
962
963 ///
964 // mA += mDelV / _timeStep;
965 setAccelerations(getAccelerations() + mDelV / _timeStep);
966
967 ///
968 mF += _timeStep * mImpF;
969 }
970
971 //==============================================================================
aggregateMassMatrix(MatrixXd &,int)972 void PointMass::aggregateMassMatrix(MatrixXd& /*_MCol*/, int /*_col*/)
973 {
974 // TODO(JS): Not implemented
975 // // Assign
976 // // We assume that the three generalized coordinates are in a row.
977 // int iStart = mIndexInSkeleton[0];
978 // mM_F.noalias() = mMass * mM_dV;
979 // _MCol->block<3, 1>(iStart, _col).noalias() = mM_F;
980 }
981
982 //==============================================================================
aggregateAugMassMatrix(Eigen::MatrixXd &,int,double)983 void PointMass::aggregateAugMassMatrix(
984 Eigen::MatrixXd& /*_MCol*/, int /*_col*/, double /*_timeStep*/)
985 {
986 // TODO(JS): Not implemented
987 // // Assign
988 // // We assume that the three generalized coordinates are in a row.
989 // int iStart = mIndexInSkeleton[0];
990 // mM_F.noalias() = mMass * mM_dV;
991
992 // double d = mParentSoftBodyNode->getDampingCoefficient();
993 // double kv = mParentSoftBodyNode->getVertexSpringStiffness();
994 // _MCol->block<3, 1>(iStart, _col).noalias()
995 // = mM_F + (_timeStep * _timeStep * kv + _timeStep * d) *
996 // mAccelerations;
997 }
998
999 //==============================================================================
updateInvMassMatrix()1000 void PointMass::updateInvMassMatrix()
1001 {
1002 mBiasForceForInvMeta = getState().mForces;
1003 }
1004
1005 //==============================================================================
updateInvAugMassMatrix()1006 void PointMass::updateInvAugMassMatrix()
1007 {
1008 // mBiasForceForInvMeta = mMass * mImplicitPsi * mForces;
1009 }
1010
1011 //==============================================================================
aggregateInvMassMatrix(Eigen::MatrixXd &,int)1012 void PointMass::aggregateInvMassMatrix(
1013 Eigen::MatrixXd& /*_MInvCol*/, int /*_col*/)
1014 {
1015 // TODO(JS): Not implemented
1016 // // Assign
1017 // // We assume that the three generalized coordinates are in a row.
1018 // int iStart = mIndexInSkeleton[0];
1019 // _MInvCol->block<3, 1>(iStart, _col)
1020 // = mPsi * mForces
1021 // - mParentSoftBodyNode->mInvM_U.head<3>().cross(mX)
1022 // - mParentSoftBodyNode->mInvM_U.tail<3>();
1023 }
1024
1025 //==============================================================================
aggregateInvAugMassMatrix(Eigen::MatrixXd &,int,double)1026 void PointMass::aggregateInvAugMassMatrix(
1027 Eigen::MatrixXd& /*_MInvCol*/, int /*_col*/, double /*_timeStep*/)
1028 {
1029 // TODO(JS): Not implemented
1030 // // Assign
1031 // // We assume that the three generalized coordinates are in a row.
1032 // int iStart = mIndexInSkeleton[0];
1033 // _MInvCol->block<3, 1>(iStart, _col)
1034 // = mImplicitPsi
1035 // * (mForces
1036 // - mMass * (mParentSoftBodyNode->mInvM_U.head<3>().cross(mX)
1037 // + mParentSoftBodyNode->mInvM_U.tail<3>()));
1038 }
1039
1040 //==============================================================================
aggregateGravityForceVector(VectorXd &,const Eigen::Vector3d &)1041 void PointMass::aggregateGravityForceVector(
1042 VectorXd& /*_g*/, const Eigen::Vector3d& /*_gravity*/)
1043 {
1044 // TODO(JS): Not implemented
1045 // mG_F = mMass *
1046 // (mParentSoftBodyNode->getWorldTransform().linear().transpose()
1047 // * _gravity);
1048
1049 // // Assign
1050 // // We assume that the three generalized coordinates are in a row.
1051 // int iStart = mIndexInSkeleton[0];
1052 // _g->segment<3>(iStart) = mG_F;
1053 }
1054
1055 //==============================================================================
updateCombinedVector()1056 void PointMass::updateCombinedVector()
1057 {
1058 mCg_dV = getPartialAccelerations()
1059 + mParentSoftBodyNode->mCg_dV.head<3>().cross(getLocalPosition())
1060 + mParentSoftBodyNode->mCg_dV.tail<3>();
1061 }
1062
1063 //==============================================================================
aggregateCombinedVector(Eigen::VectorXd &,const Eigen::Vector3d &)1064 void PointMass::aggregateCombinedVector(
1065 Eigen::VectorXd& /*_Cg*/, const Eigen::Vector3d& /*_gravity*/)
1066 {
1067 // TODO(JS): Not implemented
1068 // mCg_F.noalias() = mMass * mCg_dV;
1069 // mCg_F -= mMass
1070 // * (mParentSoftBodyNode->getWorldTransform().linear().transpose()
1071 // * _gravity);
1072 // mCg_F += mParentSoftBodyNode->getBodyVelocity().head<3>().cross(mMass *
1073 // mV);
1074
1075 // // Assign
1076 // // We assume that the three generalized coordinates are in a row.
1077 // int iStart = mIndexInSkeleton[0];
1078 // _Cg->segment<3>(iStart) = mCg_F;
1079 }
1080
1081 //==============================================================================
aggregateExternalForces(VectorXd &)1082 void PointMass::aggregateExternalForces(VectorXd& /*_Fext*/)
1083 {
1084 // TODO(JS): Not implemented
1085 // int iStart = mIndexInSkeleton[0];
1086 // _Fext->segment<3>(iStart) = mFext;
1087 }
1088
1089 //==============================================================================
PointMassNotifier(SoftBodyNode * _parentSoftBody,const std::string & _name)1090 PointMassNotifier::PointMassNotifier(
1091 SoftBodyNode* _parentSoftBody, const std::string& _name)
1092 : Entity(_parentSoftBody, false),
1093 mNeedPartialAccelerationUpdate(true),
1094 mParentSoftBodyNode(_parentSoftBody)
1095 {
1096 setName(_name);
1097 }
1098
1099 //==============================================================================
needsPartialAccelerationUpdate() const1100 bool PointMassNotifier::needsPartialAccelerationUpdate() const
1101 {
1102 return mNeedPartialAccelerationUpdate;
1103 }
1104
1105 //==============================================================================
clearTransformNotice()1106 void PointMassNotifier::clearTransformNotice()
1107 {
1108 mNeedTransformUpdate = false;
1109 }
1110
1111 //==============================================================================
clearVelocityNotice()1112 void PointMassNotifier::clearVelocityNotice()
1113 {
1114 mNeedVelocityUpdate = false;
1115 }
1116
1117 //==============================================================================
clearPartialAccelerationNotice()1118 void PointMassNotifier::clearPartialAccelerationNotice()
1119 {
1120 mNeedPartialAccelerationUpdate = false;
1121 }
1122
1123 //==============================================================================
clearAccelerationNotice()1124 void PointMassNotifier::clearAccelerationNotice()
1125 {
1126 mNeedAccelerationUpdate = false;
1127 }
1128
1129 //==============================================================================
dirtyTransform()1130 void PointMassNotifier::dirtyTransform()
1131 {
1132 mNeedTransformUpdate = true;
1133 mNeedVelocityUpdate = true;
1134 mNeedPartialAccelerationUpdate = true;
1135 mNeedAccelerationUpdate = true;
1136
1137 mParentSoftBodyNode->dirtyArticulatedInertia();
1138 mParentSoftBodyNode->dirtyExternalForces();
1139 }
1140
1141 //==============================================================================
dirtyVelocity()1142 void PointMassNotifier::dirtyVelocity()
1143 {
1144 mNeedVelocityUpdate = true;
1145 mNeedPartialAccelerationUpdate = true;
1146 mNeedAccelerationUpdate = true;
1147
1148 mParentSoftBodyNode->dirtyCoriolisForces();
1149 }
1150
1151 //==============================================================================
dirtyAcceleration()1152 void PointMassNotifier::dirtyAcceleration()
1153 {
1154 mNeedAccelerationUpdate = true;
1155 }
1156
1157 //==============================================================================
setName(const std::string & _name)1158 const std::string& PointMassNotifier::setName(const std::string& _name)
1159 {
1160 if (_name == mName)
1161 return mName;
1162
1163 const std::string oldName = mName;
1164
1165 mName = _name;
1166
1167 Entity::mNameChangedSignal.raise(this, oldName, mName);
1168
1169 return mName;
1170 }
1171
1172 //==============================================================================
getName() const1173 const std::string& PointMassNotifier::getName() const
1174 {
1175 return mName;
1176 }
1177
1178 } // namespace dynamics
1179 } // namespace dart
1180