/usr/include/simbody/SimTKcommon/internal/SpatialAlgebra.h is in libsimbody-dev 3.5.4+dfsg-1ubuntu2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 | #ifndef SimTK_SIMMATRIX_SPATIAL_ALGEBRA_H_
#define SimTK_SIMMATRIX_SPATIAL_ALGEBRA_H_
/* -------------------------------------------------------------------------- *
* Simbody(tm): SimTKcommon *
* -------------------------------------------------------------------------- *
* This is part of the SimTK biosimulation toolkit originating from *
* Simbios, the NIH National Center for Physics-Based Simulation of *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org/home/simbody. *
* *
* Portions copyright (c) 2005-12 Stanford University and the Authors. *
* Authors: Michael Sherman *
* Contributors: *
* *
* Licensed under the Apache License, Version 2.0 (the "License"); you may *
* not use this file except in compliance with the License. You may obtain a *
* copy of the License at http://www.apache.org/licenses/LICENSE-2.0. *
* *
* Unless required by applicable law or agreed to in writing, software *
* distributed under the License is distributed on an "AS IS" BASIS, *
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
* See the License for the specific language governing permissions and *
* limitations under the License. *
* -------------------------------------------------------------------------- */
/** @file
These are declarations for special matrices and vectors of use in implementing
Rodriguez and Jain's Spatial Operator Algebra. **/
#include "SimTKcommon/SmallMatrix.h"
#include <iostream>
namespace SimTK {
/**@defgroup SpatialAlgebraUtilities Spatial Algebra Utilities
@ingroup GlobalFunctions
These utility functions are used for manipulation of spatial quantities that
are contained in SpatialVec or SpatialMat objects. These are intended for
expert use and are mostly used in the implemention of friendlier methods such
as those in MobilizedBody that are used to obtain various spatial quantities.
@note Although we use SpatialVec for both, there are two different spatial
vector bases: one for motion quantities like velocities, accelerations, and
momentum and another for forces and impulses; be sure to use the appropriate
functions. Also, we use a pair of ordinary vectors, following Abhi Jain,
rather than the similar but subtly different Plucker basis vectors used by
Roy Featherstone.
Spatial vectors are used for combined (rotational,translational) quantities.
These include
@verbatim
spatial velocity = (angularVelocity,linearVelocity)
spatial acceleration = (angularAcceleration,linearAcceleration)
spatial force = (moment,force)
@endverbatim
Spatial configuration (pose) has to be handled differently though since
orientation is not a vector quantity. We use the Transform class for this
concept, which includes an orientation matrix and a translation vector.
@see Transform **/
/**@{**/
/** SpatialVec[0] is the rotational component; [1] is translational. **/
typedef Vec<2, Vec3> SpatialVec;
/** This is the type of a transposed SpatialVec. **/
typedef Row<2, Row3> SpatialRow;
/** This is used for primarily for spatial mass properties. **/
typedef Mat<2,2, Mat33> SpatialMat;
// Pre-declare methods here so that we can list them in whatever order we'd
// like them to appear in Doxygen.
inline SpatialVec findRelativeVelocity( const Transform& X_FA,
const SpatialVec& V_FA,
const Transform& X_FB,
const SpatialVec& V_FB);
inline SpatialVec findRelativeVelocityInF( const Vec3& p_AB_F,
const SpatialVec& V_FA,
const SpatialVec& V_FB);
inline SpatialVec findRelativeAcceleration( const Transform& X_FA,
const SpatialVec& V_FA,
const SpatialVec& A_FA,
const Transform& X_FB,
const SpatialVec& V_FB,
const SpatialVec& A_FB);
inline SpatialVec findRelativeAccelerationInF( const Vec3& p_AB_F,
const SpatialVec& V_FA,
const SpatialVec& A_FA,
const SpatialVec& V_FB,
const SpatialVec& A_FB);
inline SpatialVec reverseRelativeVelocity(const Transform& X_AB,
const SpatialVec& V_AB);
inline SpatialVec reverseRelativeVelocityInA(const Transform& X_AB,
const SpatialVec& V_AB);
inline SpatialVec shiftVelocityBy(const SpatialVec& V_AB, const Vec3& r_A);
inline SpatialVec shiftVelocityFromTo(const SpatialVec& V_A_BP,
const Vec3& fromP_A,
const Vec3& toQ_A);
inline SpatialVec shiftForceBy(const SpatialVec& F_AP, const Vec3& r_A);
inline SpatialVec shiftForceFromTo(const SpatialVec& F_AP,
const Vec3& fromP_A,
const Vec3& toQ_A);
//==============================================================================
// FIND RELATIVE VELOCITY
//==============================================================================
/** @brief Find the relative spatial velocity between two frames A and B whose
individual spatial velocities are known with respect to a third frame F, with
the result returned in A.
@param[in] X_FA
The pose of frame A measured and expressed in frame F.
@param[in] V_FA
The spatial velocity of frame A measured and expressed in frame F.
@param[in] X_FB
The pose of frame B measured and expressed in frame F.
@param[in] V_FB
The spatial velocity of frame B measured and expressed in frame F.
@return V_AB, the relative spatial velocity of frame B in frame A, expressed
in A.
Given the spatial velocity V_FA of frame A in a reference frame F, and
the spatial velocity V_FB of frame B in F, and transforms giving the poses of
frames A and B in F, calculate the relative velocity V_AB of frame B in
frame A, measured and expressed in A. Typical usage:
@code
Transform X_GA, X_GB; // assume these are known from somewhere
SpatialVec V_GA, V_GB;
SpatialVec V_AB = findRelativeVelocity(X_GA, V_GA,
X_GB, V_GB);
@endcode
@note This returns the result expressed in A which is almost always what you
want; however, if you don't want it in that frame you can save 30 flops by
calling findRelativeVelocityInF() instead.
Cost is 51 flops. @see findRelativeVelocityInF() **/
inline SpatialVec findRelativeVelocity(const Transform& X_FA,
const SpatialVec& V_FA,
const Transform& X_FB,
const SpatialVec& V_FB)
{
const Vec3 p_AB_F = X_FB.p() - X_FA.p(); // 3 flops
return ~X_FA.R()*findRelativeVelocityInF(p_AB_F,V_FA,V_FB); // 48 flops
}
//==============================================================================
// FIND RELATIVE VELOCITY IN F
//==============================================================================
/** @brief Find the relative spatial velocity between two frames A and B whose
individual spatial velocities are known in a third frame F, but leave the
result in F.
@param[in] p_AB_F
The vector from the A frame origin OA to the B frame origin OB, but
expressed in frame F.
@param[in] V_FA
The spatial velocity of frame A measured and expressed in frame F.
@param[in] V_FB
The spatial velocity of frame B measured and expressed in frame F.
@return V_AB_F, the relative spatial velocity of frame B in frame A, but still
expressed in F.
Typically the relative velocity of B in A would be returned in A; most
users will want to use findRelativeVelocity() instead which returns the result
in A. Use of this method saves the substantial cost of reexpressing the result,
so is useful in the rare case that you don't want the final result in A.
Example:
@code
Transform X_GA, X_GB; // assume these are known from somewhere
SpatialVec V_GA, V_GB;
const Vec3 p_AB_G = X_GB.p() - X_GA.p();
SpatialVec V_AB_G = findRelativeVelocityInF(p_AB_G, V_GA, V_GB);
@endcode
Cost is 18 flops. @see findRelativeVelocity() **/
inline SpatialVec findRelativeVelocityInF(const Vec3& p_AB_F,
const SpatialVec& V_FA,
const SpatialVec& V_FB)
{
// Relative angular velocity of B in A, expressed in F.
const Vec3 w_AB_F = V_FB[0] - V_FA[0]; // 3 flops
// Relative linear velocity of B in A, taken and expressed in F.
const Vec3 p_AB_F_dot = V_FB[1] - V_FA[1]; // 3 flops
// Get linear velocity taken in A by removing the component due
// to A's rotation in F (still expressed in F).
const Vec3 v_AB_F = p_AB_F_dot - V_FA[0] % p_AB_F; // 12 flops
return SpatialVec(w_AB_F, v_AB_F);
}
//==============================================================================
// FIND RELATIVE ACCELERATION
//==============================================================================
/** @brief Find the relative spatial acceleration between two frames A and B
whose individual spatial accelerations are known with respect to a third
frame F, with the result returned in A.
@param[in] X_FA
The pose of frame A measured and expressed in frame F.
@param[in] V_FA
The spatial velocity of frame A measured and expressed in frame F.
@param[in] A_FA
The spatial acceleration of frame A measured and expressed in frame F.
@param[in] X_FB
The pose of frame B measured and expressed in frame F.
@param[in] V_FB
The spatial velocity of frame B measured and expressed in frame F.
@param[in] A_FB
The spatial acceleration of frame B measured and expressed in frame F.
@return A_AB, the relative spatial acceleration of frame B in frame A,
expressed in A.
Given the spatial acceleration A_FA of frame A in a reference frame F, and
the spatial acceleration A_FB of frame B in F, and corresonding pose and
velocity information, calculate the relative acceleration A_AB of frame B in
frame A, measured and expressed in A. Typical usage:
@code
Transform X_GA, X_GB; // assume these are known from somewhere
SpatialVec V_GA, V_GB;
SpatialVec A_GA, A_GB;
SpatialVec A_AB = findRelativeAcceleration(X_GA, V_GA, A_GA,
X_GB, V_GB, A_GB);
@endcode
@note This returns the result expressed in A which is almost always what you
want; however, if you don't want it in that frame you can save 30 flops by
calling findRelativeAccelerationInF() instead.
Cost is 105 flops. @see findRelativeAccelerationInF() **/
inline SpatialVec findRelativeAcceleration( const Transform& X_FA,
const SpatialVec& V_FA,
const SpatialVec& A_FA,
const Transform& X_FB,
const SpatialVec& V_FB,
const SpatialVec& A_FB)
{
const Vec3 p_AB_F = X_FB.p() - X_FA.p(); // 3 flops
return ~X_FA.R() * // 30 flops
findRelativeAccelerationInF(p_AB_F,V_FA,A_FA,V_FB,A_FB); // 72 flops
}
//==============================================================================
// FIND RELATIVE ACCELERATION IN F
//==============================================================================
/** @brief Find the relative spatial acceleration between two frames A and B
whose individual spatial acceleration are known in a third frame F, but leave
the result in F.
@param[in] p_AB_F
The vector from the A frame origin OA to the B frame origin OB, but
expressed in frame F.
@param[in] V_FA
The spatial velocity of frame A measured and expressed in frame F.
@param[in] A_FA
The spatial acceleration of frame A measured and expressed in frame F.
@param[in] V_FB
The spatial velocity of frame B measured and expressed in frame F.
@param[in] A_FB
The spatial acceleration of frame B measured and expressed in frame F.
@return A_AB_F, the relative spatial acceleration of frame B in frame A, but
still expressed in F.
Typically the relative acceleration of B in A would be returned in A; most
users will want to use findRelativeAcceleration() instead which returns the
result in A. Use of this method saves the substantial cost of reexpressing the
result, so is useful in the rare case that you don't want the final result in A.
Example:
@code
Transform X_GA, X_GB; // assume these are known from somewhere
SpatialVec V_GA, V_GB;
SpatialVec A_GA, A_GB;
const Vec3 p_AB_G = X_GB.p() - X_GA.p();
SpatialVec A_AB_G = findRelativeAccelerationInF(p_AB_G, V_GA, A_GA,
V_GB, A_GB);
@endcode
Cost is 72 flops. @see findRelativeAcceleration() **/
inline SpatialVec findRelativeAccelerationInF( const Vec3& p_AB_F,
const SpatialVec& V_FA,
const SpatialVec& A_FA,
const SpatialVec& V_FB,
const SpatialVec& A_FB)
{
const Vec3& w_FA = V_FA[0]; // aliases for convenience
const Vec3& w_FB = V_FB[0];
const Vec3& b_FA = A_FA[0];
const Vec3& b_FB = A_FB[0];
const Vec3 p_AB_F_dot = V_FB[1] - V_FA[1]; // d/dt p taken in F (3 flops)
const Vec3 p_AB_F_dotdot = A_FB[1] - A_FA[1]; // d^2/dt^2 taken in F (3 flops)
const Vec3 w_AB_F = // relative angvel of B in A, exp. in F
w_FB - w_FA; // (3 flops)
const Vec3 v_AB_F = // d/dt p taken in A, exp in F
p_AB_F_dot - w_FA % p_AB_F; // (12 flops)
const Vec3 w_AB_F_dot = b_FB - b_FA; // d/dt of w_AB_F taken in F (3 flops)
const Vec3 v_AB_F_dot = // d/dt v_AB_F taken in F
p_AB_F_dotdot - (b_FA % p_AB_F + w_FA % p_AB_F_dot); // (24 flops)
// We have the derivative in F; change it to derivative in A by adding in
// contribution caused by motion of F in A, that is w_AF X w_AB_F. (Note
// that w_AF=-w_FA.)
const Vec3 b_AB_F = // ang. accel. of B in A, exp. in F
w_AB_F_dot - w_FA % w_AB_F; // (12 flops)
const Vec3 a_AB_F = // taken in A, exp. in F
v_AB_F_dot - w_FA % v_AB_F; // (12 flops)
return SpatialVec(b_AB_F, a_AB_F); // taken in A, expressed in F
}
//==============================================================================
// REVERSE RELATIVE VELOCITY
//==============================================================================
/** @brief Given the relative velocity of frame B in frame A, reverse that to
give the relative velocity of frame A in B.
@param[in] X_AB
The pose of frame B in frame A, measured and expressed in A.
@param[in] V_AB
The relative spatial velocity of frame B in frame A, measured and
expressed in frame A.
@return V_BA, the relative spatial velocity of frame A in frame B, measured
and expressed in B.
The input is expressed in the A frame; the result will be expressed in the B
frame instead. If you prefer that the result remain in the A frame you should
call reverseRelativeVelocityInA() instead to avoid the extra cost of changing
frames. Example:
@code
Transform X_AB; // assume these are known from somewhere
SpatialVec V_AB;
SpatialVec V_BA = reverseRelativeVelocity(X_AB, V_AB);
@endcode
@note If the frame origins were in the same spatial location, then the result
would just be the negative of the supplied velocity. However, since the linear
component of spatial velocity has to be measured at a point, and we're
switching from measuring at a point coincident with B's origin OB to one
coincident with A's origin OA, there is going to be a change in the linear
part of the result. The angular velocity will just be negated, though, and
then reexpressed in B.
Cost is 51 flops. @see reverseRelativeVelocityInA() **/
inline SpatialVec reverseRelativeVelocity(const Transform& X_AB,
const SpatialVec& V_AB)
{
// Reverse the velocity but with the result still expressed in A.
const SpatialVec V_BA_A = reverseRelativeVelocityInA(X_AB,V_AB);
// 21 flops
// Then reexpress in B.
return ~X_AB.R()*V_BA_A; // 30 flops
}
//==============================================================================
// REVERSE RELATIVE VELOCITY IN A
//==============================================================================
/** @brief Given the relative velocity of frame B in frame A, reverse that to
give the relative velocity of frame A in B, but leave the result expressed
in frame A.
@param[in] X_AB
The pose of frame B in frame A, measured and expressed in A.
@param[in] V_AB
The relative spatial velocity of frame B in frame A, measured and
expressed in frame A.
@return V_BA_A, the relative velocity of frame A in frame B, but still
expressed in A.
The input V_AB is expressed in the A frame; you will almost always want the
output V_BA expressed in the B frame which is what the function
reverseRelativeVelocity() does. However, if you're going to want it in
some other frame ultimately you may prefer to avoid the substantial cost of
reexpressing it in B now, in which case this routine is useful.
See reverseRelativeVelocity() for more information about what this does.
Example:
@code
Transform X_AB; // assume these are known from somewhere
SpatialVec V_AB; // (expressed in A)
// result is still expressed in A
SpatialVec V_BA_A = reverseRelativeVelocityInA(X_AB, V_AB);
@endcode
Cost is 21 flops. @see reverseRelativeVelocity() **/
inline SpatialVec reverseRelativeVelocityInA(const Transform& X_AB,
const SpatialVec& V_AB)
{
// Change the measurement point from a point coincident with OB
// to a point coincident with OA, and negate since we want A's velocity
// in B rather than the other way around.
const SpatialVec V_BA_A = -shiftVelocityBy(V_AB, -X_AB.p()); // 21 flops
return V_BA_A;
}
//==============================================================================
// SHIFT VELOCITY BY
//==============================================================================
/** @brief Shift a relative spatial velocity measured at some point to that
same relative spatial quantity but measured at a new point given by an offset
from the old one.
@param[in] V_AB
The relative spatial velocity of frame B in frame A, measured and
expressed in frame A.
@param[in] r_A
The vector offset, expressed in frame A, by which to change the point at
which the translational component of the relative spatial velocity is
measured.
@return V_A_BQ, the relative velocity of frame B in frame A, but measured at
the point Q=Bo+r rather than at B's origin Bo.
Given the spatial velocity V_AB of frame B in A, measured at a point
coincident with B's origin Bo, change it to the spatial velocity V_A_BQ
representing the same relationship but with the velocity measured at a new
point Q=Bo+r for some position vector r. All vectors are measured and expressed
in frame A, including the vector r. Example:
@code
SpatialVec V_AB; // assume these are known from somewhere
Vec3 offset_A; // Q = Bo + offset
SpatialVec V_A_BQ = shiftVelocityBy(V_AB, offset_A);
@endcode
@note The shift in location leaves the relative angular velocity w the same but
results in the linear velocity changing by w X r.
Cost is 12 flops. @see shiftVelocityFromTo() **/
inline SpatialVec shiftVelocityBy(const SpatialVec& V_AB, const Vec3& r_A)
{ return SpatialVec( V_AB[0], V_AB[1] + V_AB[0] % r_A ); } // vp=v + wXr
//==============================================================================
// SHIFT VELOCITY FROM TO
//==============================================================================
/** @brief Shift a relative spatial velocity measured at some point P to that
same relative spatial quantity but measured at a new point Q given the points
P and Q.
@param[in] V_A_BP
The relative spatial velocity of frame B in frame A, measured and
expressed in frame A, with the linear component measured at a point P.
@param[in] fromP_A
The "from" point P at which the input linear velocity was measured, given
as a vector from A's origin OA to the point P, expressed in A.
@param[in] toQ_A
The "to" point Q at which we want to re-measure the linear velocity, given
as a vector from A's origin OA to the point Q, expressed in A.
@return V_A_BQ, the relative velocity of frame B in frame A, but measured at
the point Q rather than at point P.
Given the spatial velocity V_A_BP of frame B in A, measured at a point P,
change it to the spatial velocity V_A_BQ representing the same relationship but
with the velocity measured at a new point Q. Example:
@code
// assume these are known from somewhere
Transform X_AB; // contains the vector from OA to OB
SpatialVec V_AB; // linear velocity is measured at origin OB of B
Vec3 p_AQ; // vector from OA to some other point Q, in A
SpatialVec V_A_BQ = shiftVelocityFromTo(V_AB, X_AB.p(), p_AQ);
@endcode
@note There is no way to know whether the supplied velocity was actually
measured at P; this method really just shifts the relative velocity by
the vector r=(to-from). Use it carefully.
Cost is 15 flops. @see shiftVelocityBy() **/
inline SpatialVec shiftVelocityFromTo(const SpatialVec& V_A_BP,
const Vec3& fromP_A,
const Vec3& toQ_A)
{ return shiftVelocityBy(V_A_BP, toQ_A - fromP_A); }
//==============================================================================
// SHIFT ACCELERATION BY
//==============================================================================
/** @brief Shift a relative spatial acceleration measured at some point to that
same relative spatial quantity but measured at a new point given by an offset
from the old one.
@param[in] A_AB
The relative spatial acceleration of frame B in frame A, measured and
expressed in frame A.
@param[in] w_AB
The relative angular velocity of frame B in frame A, expressed in frame A.
@param[in] r_A
The vector offset, expressed in frame A, by which to change the point at
which the translational component of the relative spatial acceleration is
measured.
@return A_A_BQ, the relative acceleration of frame B in frame A, but measured at
the point Q=Bo+r rather than at B's origin Bo.
Given the spatial acceleration A_AB and angular velocity w_AB of frame B in A,
measured at a point coincident with B's origin Bo, change it to the spatial
acceleration A_A_BQ representing the same relationship but with the acceleration
measured at a new point Q=Bo+r for some position vector r. All vectors are
measured and expressed in frame A, including the vector r. Example:
@code
SpatialVec A_AB; // assume these are known from somewhere
Vec3 w_AB;
Vec3 offset_A; // Q = Bo + offset
SpatialVec A_A_BQ = shiftAccelerationBy(A_AB, w_AB, offset_A);
@endcode
@note The shift in location leaves the relative angular acceleration b the same
but results in the linear acceleration changing by b X r + w X (w X r).
Cost is 33 flops. @see shiftAccelerationFromTo() **/
inline SpatialVec shiftAccelerationBy(const SpatialVec& A_AB,
const Vec3& w_AB,
const Vec3& r_A)
{ return SpatialVec( A_AB[0],
A_AB[1] + A_AB[0] % r_A + w_AB % (w_AB % r_A) ); }
//==============================================================================
// SHIFT ACCELERATION FROM TO
//==============================================================================
/** @brief Shift a relative spatial acceleration measured at some point P to
that same relative spatial quantity but measured at a new point Q given the
points P and Q.
@param[in] A_A_BP
The relative spatial acceleration of frame B in frame A, measured and
expressed in frame A, with the linear component measured at a point P.
@param[in] w_AB
The relative angular velocity of frame B in frame A, expressed in frame A.
@param[in] fromP_A
The "from" point P at which the input linear acceleration was
measured, given as a vector from A's origin Ao to the point P,
expressed in A.
@param[in] toQ_A
The "to" point Q at which we want to re-measure the linear acceleration,
given as a vector from A's origin Ao to the point Q, expressed
in A.
@return A_A_BQ, the relative acceleration of frame B in frame A, but measured at
the point Q rather than at point P.
Given the spatial acceleration A_A_BP of frame B in A, measured at a point P,
change it to the spatial acceleration A_A_BQ representing the same relationship
but with the acceleration measured at a new point Q. Example:
@code
// assume these are known from somewhere
Transform X_AB; // contains the vector from Ao to Bo
SpatialVec A_AB; // linear acceleration is measured at origin Bo of B
Vec3 w_AB;
Vec3 p_AQ; // vector from Ao to some other point Q, in A
SpatialVec A_A_BQ = shiftAccelerationFromTo(A_AB, w_AB, X_AB.p(), p_AQ);
@endcode
@note There is no way to know whether the supplied acceleration was
actually measured at P; this method really just shifts the relative
acceleration by the vector r=(to-from). Use it carefully.
Cost is 36 flops. @see shiftAccelerationBy() **/
inline SpatialVec shiftAccelerationFromTo(const SpatialVec& A_A_BP,
const Vec3& w_AB,
const Vec3& fromP_A,
const Vec3& toQ_A)
{ return shiftAccelerationBy(A_A_BP, w_AB, toQ_A - fromP_A); }
//==============================================================================
// SHIFT FORCE BY
//==============================================================================
/** @brief Shift a spatial force applied at some point of a body to that
same spatial force applied at a new point given by an offset
from the old one.
@param[in] F_AP
A spatial force (moment and linear force), expressed in the A frame,
whose translational component is applied at a point P.
@param[in] r_A
The vector offset, expressed in frame A, by which to change the point at
which the translational component of the input force is to be applied.
@return F_AQ, the same physical effect as the input but with the moment
adjusted to reflect force application at point Q=P+r rather than at the
original point P.
Given the spatial force F_AP including a pure moment m and a force vector f
applied at a point P, return the equivalent force F_AQ representing the same
physical quantity but as though the force were applied at a point Q=P+r
for some position vector r. All vectors are expressed in frame A. Example:
@code
SpatialVec F_AP; // assume these are known from somewhere
Vec3 offset_A; // Q = P + offset
SpatialVec F_AQ = shiftForceBy(F_AP, offset_A);
@endcode
@note The shift in location leaves the force f the same but
results in an adjustment to the moment of -(r X f).
Cost is 12 flops. @see shiftForceFromTo() **/
inline SpatialVec shiftForceBy(const SpatialVec& F_AP, const Vec3& r_A)
{ return SpatialVec(F_AP[0] - r_A % F_AP[1], F_AP[1]); } // mq = mp - r X f
//==============================================================================
// SHIFT FORCE FROM TO
//==============================================================================
/** @brief Shift a spatial force applied at some point P of a body to that
same spatial force applied at a new point Q, given P and Q.
@param[in] F_AP
A spatial force (moment and linear force), expressed in the A frame, whose
translational component is applied at a point P.
@param[in] fromP_A
The "from" point P at which the input force is applied, given as a
vector from A's origin OA to the point P, expressed in A.
@param[in] toQ_A
The "to" point Q to which we want to move the force application point,
given as a vector from A's origin OA to the point Q, expressed in A.
@return F_AQ, the same physical effect as the input but with the moment
adjusted to reflect force application at point Q rather than at the
original point P.
Given the spatial force F_AP including a pure moment m and a force vector f
applied at a point P, return the equivalent force F_AQ representing the same
physical quantity but as though the force were applied at a new point Q. All
vectors are expressed in frame A and points are measured from A's origin OA.
Example:
@code
// assume these are known from somewhere
SpatialVec F_AP; // linear force is applied at point P
Vec3 p_AP; // vector from OA to P, in A
Vec3 p_AQ; // vector from OA to some other point Q, in A
SpatialVec F_AQ = shiftForceFromTo(F_AP, p_AP, p_AQ);
@endcode
@note There is no way to know whether the supplied force was actually
applied at P; this method really just shifts the application point by
the vector r=(to-from). Use it carefully.
Cost is 15 flops. @see shiftForceBy() **/
inline SpatialVec shiftForceFromTo(const SpatialVec& F_AP,
const Vec3& fromP_A,
const Vec3& toQ_A)
{ return shiftForceBy(F_AP, toQ_A - fromP_A); }
/**@}**/
//==============================================================================
// PHI MATRIX
//==============================================================================
// support for efficient matrix multiplication involving the special phi
// matrix
class PhiMatrixTranspose;
class PhiMatrix {
public:
typedef PhiMatrixTranspose TransposeType;
PhiMatrix() { setToNaN(); }
PhiMatrix(const Vec3& l) : l_(l) {}
void setToZero() { l_ = 0; }
void setToNaN() { l_.setToNaN(); }
SpatialMat toSpatialMat() const {
return SpatialMat(Mat33(1), crossMat(l_),
Mat33(0), Mat33(1));
}
const Vec3& l() const { return l_; }
private:
Vec3 l_;
};
class PhiMatrixTranspose {
public:
PhiMatrixTranspose(const PhiMatrix& phi) : phi(phi) {}
SpatialMat toSpatialMat() const {
return SpatialMat( Mat33(1) , Mat33(0),
crossMat(-l()) , Mat33(1));
}
const Vec3& l() const {return phi.l();}
private:
const PhiMatrix& phi;
};
inline PhiMatrixTranspose
transpose(const PhiMatrix& phi)
{
PhiMatrixTranspose ret(phi);
return ret;
}
inline PhiMatrixTranspose
operator~(const PhiMatrix& phi) {return transpose(phi);}
inline SpatialVec
operator*(const PhiMatrix& phi,
const SpatialVec& v)
{
return SpatialVec(v[0] + phi.l() % v[1], // 12 flops
v[1]);
}
inline SpatialMat
operator*(const PhiMatrix& phi,
const SpatialMat& m)
{
const Mat33 x = crossMat(phi.l()); // 3 flops
return SpatialMat( m(0,0) + x*m(1,0), m(0,1) + x*m(1,1), // 108 flops
m(1,0) , m(1,1));
}
inline SpatialVec
operator*(const PhiMatrixTranspose& phiT,
const SpatialVec& v)
{
return SpatialVec(v[0],
v[1] + v[0] % phiT.l()); // 12 flops
}
inline SpatialMat
operator*(const SpatialMat::THerm& m,
const PhiMatrixTranspose& phiT)
{
const Mat33 x = crossMat(phiT.l()); // 3 flops
return SpatialMat( m(0,0) - m(0,1) * x, m(0,1), // 54 flops
m(1,0) - m(1,1) * x, m(1,1) ); // 54 flops
}
inline SpatialMat
operator*(const SpatialMat& m,
const PhiMatrixTranspose& phiT)
{
const Mat33 x = crossMat(phiT.l()); // 3 flops
return SpatialMat( m(0,0) - m(0,1) * x, m(0,1), // 54 flops
m(1,0) - m(1,1) * x, m(1,1) ); // 54 flops
}
inline bool
operator==(const PhiMatrix& p1, const PhiMatrix& p2)
{
return p1.l() == p2.l();
}
inline bool
operator==(const PhiMatrixTranspose& p1, const PhiMatrixTranspose& p2)
{
return p1.l() == p2.l();
}
} // namespace SimTK
#endif // SimTK_SIMMATRIX_SPATIAL_ALGEBRA_H_
|