@@ -368,6 +368,66 @@ void RpyBallMobilizer<T>::MapQDotToVelocity(
368
368
-sp * rdot /* + 0 * pdot */ + ydot);
369
369
}
370
370
371
+ template <typename T>
372
+ void RpyBallMobilizer<T>::MapQDDotToAcceleration(
373
+ const systems::Context<T>& context,
374
+ const Eigen::Ref<const VectorX<T>>& qddot,
375
+ EigenPtr<VectorX<T>> vdot) const {
376
+ DRAKE_ASSERT (qddot.size () == kNq );
377
+ DRAKE_ASSERT (vdot != nullptr );
378
+ DRAKE_ASSERT (vdot->size () == kNv );
379
+
380
+ // Shown in MapQDotToVelocity(), the generalized velocities v = [ωx, ωy, ωz]ᵀ
381
+ // are linearly related to q̇ = [ṙ, ṗ, ẏ]ᵀ (the time-derivatives of generalized
382
+ // positions) as
383
+ //
384
+ // ⌈ ωx ⌉ ⌈cos(y) cos(p) -sin(y) 0⌉ ⌈ ṙ ⌉
385
+ // | ωy | = |sin(y) cos(p) cos(y) 0| | ṗ |
386
+ // ⌊ ωz ⌋ ⌊ -sin(p) 0 1⌋ ⌊ ẏ ⌋
387
+ //
388
+ // where, for this mobilizer, the angular velocity of the "fixed frame" F in
389
+ // the "mobilized frame" M, expressed in frame F is w_FM_F = [ωx, ωy, ωz]ᵀ
390
+ // and r, p, y denote roll, pitch, yaw angles.
391
+ //
392
+ // There are various ways to calculate v̇ = [ω̇x, ω̇y, ω̇z]ᵀ (the time-derivatives
393
+ // of the generalized velocities). One efficient calculation uses
394
+ //
395
+ // ⌈ ω̇x ⌉ ⌈ cos(y) cos(p) -sin(y) 0 ⌉ ⌈ r̈ ⌉ ⌈-ωy ẏ - sin(p) cos(y) ṙ ṗ ⌉
396
+ // | ω̇y | = | sin(y) cos(p) cos(y) 0 | | p̈ | + | wx ẏ - sin(p) sin(y) ṙ ṗ |
397
+ // ⌊ ω̇z ⌋ ⌊ -sin(p) 0 1 ⌋ ⌊ ÿ ⌋ ⌊ -cos(p) ṙ ṗ ⌋
398
+
399
+ const T& rddot = qddot[0 ];
400
+ const T& pddot = qddot[1 ];
401
+ const T& yddot = qddot[2 ];
402
+
403
+ using std::cos;
404
+ using std::sin;
405
+ const Vector3<T> angles = get_angles (context);
406
+ const T sp = sin (angles[1 ]);
407
+ const T cp = cos (angles[1 ]);
408
+ const T sy = sin (angles[2 ]);
409
+ const T cy = cos (angles[2 ]);
410
+ const T cp_x_rddot = cp * rddot;
411
+
412
+ // Compute the product w_FM = E_W * q̇ directly since it's cheaper than
413
+ // explicitly forming E_F and then multiplying with q̇.
414
+ *vdot = Vector3<T>(cy * cp_x_rddot - sy * pddot, /* + 0 * yddot */
415
+ sy * cp_x_rddot + cy * pddot, /* + 0 * yddot */
416
+ -sp * rddot /* + 0 * pddot */ + yddot);
417
+
418
+ const Vector3<T> v = get_angular_velocity (context);
419
+ const T& wx = v[0 ];
420
+ const T& wy = v[1 ];
421
+ const T& wz = v[2 ];
422
+ // const T rdot = (wx*cy + wy*sy) / cp;
423
+ const T pdot = wy * cy - wx * sy;
424
+ const T ydot = wz + sp / cp * (wx * cy + wy * sy);
425
+ const T pdot_ydot = pdot * ydot;
426
+ Vector3<T> alfExtra (-wy * ydot - sp * cy * pdot_ydot,
427
+ wx * ydot - sp * sy * pdot_ydot, -cp * pdot_ydot);
428
+ *vdot += alfExtra;
429
+ }
430
+
371
431
template <typename T>
372
432
template <typename ToScalar>
373
433
std::unique_ptr<Mobilizer<ToScalar>>
0 commit comments