@@ -314,8 +314,9 @@ QuaternionFloatingMobilizer<T>::QuaternionRateToAngularVelocityMatrix(
314
314
const Eigen::Matrix<T, 3 , 4 > NrPlus_q_unit = CalcTwoTimesQMatrixTranspose (
315
315
{q_unit[0 ], q_unit[1 ], q_unit[2 ], q_unit[3 ]});
316
316
317
- // Returns the matrix that when multiplied by q̇_FM produces
318
- // w_FM_F (M's angular velocity in F, expressed in F).
317
+ // Returns the matrix that when multiplied by q̇_FM produces w_FM_F
318
+ // (M's angular velocity in F, expressed in F). Note: When q_FM is a unit
319
+ // quaternion (so q_norm = 1), the returned value is denoted Nᵣ⁺(q̂_FM).
319
320
return NrPlus_q_unit * dqnorm_dq;
320
321
}
321
322
@@ -324,13 +325,11 @@ void QuaternionFloatingMobilizer<T>::DoCalcNMatrix(
324
325
const systems::Context<T>& context, EigenPtr<MatrixX<T>> N) const {
325
326
// Upper-left block (rotational part of the N matrix) is Nᵣ ≜ 0.5 Q_FM.
326
327
// See QuaternionFloatingMobilizer::CalcQMatrix() for details.
328
+ // The lower-right block (translational part of the N matrix) is [I₃₃].
327
329
N->template block <4 , 3 >(0 , 0 ) = CalcQMatrixOverTwo (get_quaternion (context));
328
- // Upper-right block
329
- N->template block <4 , 3 >(0 , 3 ).setZero ();
330
- // Lower-left block
331
- N->template block <3 , 3 >(4 , 0 ).setZero ();
332
- // Lower-right block (translational part of the N matrix).
333
- N->template block <3 , 3 >(4 , 3 ).setIdentity ();
330
+ N->template block <4 , 3 >(0 , 3 ).setZero (); // Upper-right block.
331
+ N->template block <3 , 3 >(4 , 0 ).setZero (); // Lower-left block.
332
+ N->template block <3 , 3 >(4 , 3 ).setIdentity (); // Lower-right block.
334
333
}
335
334
336
335
template <typename T>
@@ -343,13 +342,10 @@ void QuaternionFloatingMobilizer<T>::DoCalcNplusMatrix(
343
342
// in frame F, expressed in F. Hence, this accounts for a non-unit q_FM.
344
343
const Quaternion<T> q_FM = get_quaternion (context);
345
344
Nplus->template block <3 , 4 >(0 , 0 ) =
346
- QuaternionRateToAngularVelocityMatrix (q_FM);
347
- // Upper-right block
348
- Nplus->template block <3 , 3 >(0 , 4 ).setZero ();
349
- // Lower-left block
350
- Nplus->template block <3 , 4 >(3 , 0 ).setZero ();
351
- // Lower-right block
352
- Nplus->template block <3 , 3 >(3 , 4 ).setIdentity ();
345
+ QuaternionRateToAngularVelocityMatrix (q_FM); // Upper-left block.
346
+ Nplus->template block <3 , 3 >(0 , 4 ).setZero (); // Upper-right block.
347
+ Nplus->template block <3 , 4 >(3 , 0 ).setZero (); // Lower-left block.
348
+ Nplus->template block <3 , 3 >(3 , 4 ).setIdentity (); // Lower-right block.
353
349
}
354
350
355
351
template <typename T>
@@ -366,11 +362,6 @@ void QuaternionFloatingMobilizer<T>::DoCalcNDotMatrix(
366
362
// | q̇y | | -qz qw qx | ⌊ ωz ⌋
367
363
// ⌊ q̇z ⌋ ⌊ qy -qx qw ⌋
368
364
//
369
- // For the translational part of this mobilizer, the time-derivative of the
370
- // generalized positions q̇ₜ = [ẋ, ẏ, ż]ᵀ are related to the translational
371
- // generalized velocities v_FM_F = vₜ = [vx, vy, vz]ᵀ as q̇ₜ = Nₜ(q)⋅vₜ, where
372
- // Nₜ(q) = [I₃₃] (3x3 identity matrix). Hence, Ṅₜ(q,q̇ᵣ) = [0₃₃] (zero matrix).
373
-
374
365
// Calculate the time-derivative of the quaternion, i.e., q̇ᵣ = Nᵣ(q)⋅vᵣ.
375
366
const Quaternion<T> q_FM = get_quaternion (context);
376
367
const Vector3<T> w_FM_F = get_angular_velocity (context);
@@ -381,6 +372,11 @@ void QuaternionFloatingMobilizer<T>::DoCalcNDotMatrix(
381
372
// q_FM = [qw, qx, qy, qz]ᵀ, so Ṅᵣ(qᵣ,q̇ᵣ) = 0.5 * Q(q̇_FM).
382
373
const Eigen::Matrix<T, 4 , 3 > NrDotMatrix = CalcQMatrixOverTwo (qdot_FM);
383
374
375
+ // For the translational part of this mobilizer, the time-derivative of the
376
+ // generalized positions q̇ₜ = [ẋ, ẏ, ż]ᵀ are related to the translational
377
+ // generalized velocities v_FM_F = vₜ = [vx, vy, vz]ᵀ as q̇ₜ = Nₜ(q)⋅vₜ, where
378
+ // Nₜ(q) = [I₃₃] (3x3 identity matrix). Hence, Ṅₜ(q,q̇ᵣ) = [0₃₃] (zero matrix).
379
+
384
380
// Form the Ṅ(q,q̇) matrix associated with q̈ = Ṅ(q,q̇)⋅v + N(q)⋅v̇.
385
381
Ndot->template block <4 , 3 >(0 , 0 ) = NrDotMatrix; // Upper-left block.
386
382
Ndot->template block <4 , 3 >(0 , 3 ).setZero (); // Upper-right block.
@@ -402,11 +398,6 @@ void QuaternionFloatingMobilizer<T>::DoCalcNplusDotMatrix(
402
398
// ⌊ ωz ⌋ | -qz -qy qx qw | | q̇y |
403
399
// ⌊ q̇z ⌋
404
400
//
405
- // For the translational part of this mobilizer, the translational generalized
406
- // velocities v_FM_F = vₜ = [vx, vy, vz]ᵀ are related to the time-derivatives
407
- // of the generalized positions q̇ₜ = [ẋ, ẏ, ż]ᵀ as vₜ = N⁺ₜ(q)⋅q̇ₜ, where
408
- // Nₜ(q) = [I₃₃] (3x3 identity matrix). Thus, Ṅ⁺ₜ(q,q̇ₜ) = [0₃₃] (zero matrix).
409
-
410
401
// Calculate the time-derivative of the quaternion, i.e., q̇ᵣ = Nᵣ(q)⋅vᵣ.
411
402
const Quaternion<T> q_FM = get_quaternion (context);
412
403
const Vector3<T> w_FM_F = get_angular_velocity (context);
@@ -416,11 +407,16 @@ void QuaternionFloatingMobilizer<T>::DoCalcNplusDotMatrix(
416
407
// In view of the documentation in CalcQMatrix(), since
417
408
// N⁺ᵣ(q_FM) = 2 * (Q_FM)ᵀ, where Q_FM is linear in the elements of
418
409
// q_FM = [qw, qx, qy, qz]ᵀ, hence Ṅ⁺ᵣ(q̇_FM) = 2 * (Q̇_FM)ᵀ.
419
- // TODO(Mitiguy) Ensure this calculation is consistent with the precise
420
- // definition of this function (the definition is also a TODO ).
410
+ // TODO(Mitiguy) Ensure this calculation provides the time derivative of the
411
+ // calculation in DoCalcNplusMatrix( ).
421
412
const Eigen::Matrix<T, 3 , 4 > NrPlusDot =
422
413
CalcTwoTimesQMatrixTranspose (qdot_FM);
423
414
415
+ // For the translational part of this mobilizer, the translational generalized
416
+ // velocities v_FM_F = vₜ = [vx, vy, vz]ᵀ are related to the time-derivatives
417
+ // of the generalized positions q̇ₜ = [ẋ, ẏ, ż]ᵀ as vₜ = N⁺ₜ(q)⋅q̇ₜ, where
418
+ // Nₜ(q) = [I₃₃] (3x3 identity matrix). Thus, Ṅ⁺ₜ(q,q̇ₜ) = [0₃₃] (zero matrix).
419
+
424
420
// Form the Ṅ⁺(q,q̇) matrix associated with v̇ = Ṅ⁺(q,q̇)⋅q̇ + N⁺(q)⋅q̈.
425
421
NplusDot->template block <3 , 4 >(0 , 0 ) = NrPlusDot; // Upper-left block.
426
422
NplusDot->template block <3 , 3 >(0 , 4 ).setZero (); // Upper-right block.
0 commit comments