aboutsummaryrefslogtreecommitdiff
path: root/src/dynamics/joint/multibody_joint/multibody_link.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/dynamics/joint/multibody_joint/multibody_link.rs')
-rw-r--r--src/dynamics/joint/multibody_joint/multibody_link.rs173
1 files changed, 173 insertions, 0 deletions
diff --git a/src/dynamics/joint/multibody_joint/multibody_link.rs b/src/dynamics/joint/multibody_joint/multibody_link.rs
new file mode 100644
index 0000000..94bd3de
--- /dev/null
+++ b/src/dynamics/joint/multibody_joint/multibody_link.rs
@@ -0,0 +1,173 @@
+use std::ops::{Deref, DerefMut};
+
+use crate::dynamics::{MultibodyJoint, RigidBodyHandle};
+use crate::math::{Isometry, Real};
+use crate::prelude::RigidBodyVelocity;
+
+pub(crate) struct KinematicState {
+ pub joint: MultibodyJoint,
+ pub parent_to_world: Isometry<Real>,
+ // TODO: should this be removed in favor of the rigid-body position?
+ pub local_to_world: Isometry<Real>,
+ pub local_to_parent: Isometry<Real>,
+}
+
+impl Clone for KinematicState {
+ fn clone(&self) -> Self {
+ Self {
+ joint: self.joint.clone(),
+ parent_to_world: self.parent_to_world.clone(),
+ local_to_world: self.local_to_world.clone(),
+ local_to_parent: self.local_to_parent.clone(),
+ }
+ }
+}
+
+/// One link of a multibody.
+pub struct MultibodyLink {
+ pub(crate) name: String,
+ // FIXME: make all those private.
+ pub(crate) internal_id: usize,
+ pub(crate) assembly_id: usize,
+ pub(crate) is_leaf: bool,
+
+ pub(crate) parent_internal_id: usize,
+ pub(crate) rigid_body: RigidBodyHandle,
+
+ /*
+ * Change at each time step.
+ */
+ pub(crate) state: KinematicState,
+
+ // FIXME: put this on a workspace buffer instead ?
+ pub(crate) velocity_dot_wrt_joint: RigidBodyVelocity,
+ pub(crate) velocity_wrt_joint: RigidBodyVelocity,
+}
+
+impl MultibodyLink {
+ /// Creates a new multibody link.
+ pub fn new(
+ rigid_body: RigidBodyHandle,
+ internal_id: usize,
+ assembly_id: usize,
+ parent_internal_id: usize,
+ joint: MultibodyJoint,
+ parent_to_world: Isometry<Real>,
+ local_to_world: Isometry<Real>,
+ local_to_parent: Isometry<Real>,
+ ) -> Self {
+ let is_leaf = true;
+ let velocity_dot_wrt_joint = RigidBodyVelocity::zero();
+ let velocity_wrt_joint = RigidBodyVelocity::zero();
+ let kinematic_state = KinematicState {
+ joint,
+ parent_to_world,
+ local_to_world,
+ local_to_parent,
+ };
+
+ MultibodyLink {
+ name: String::new(),
+ internal_id,
+ assembly_id,
+ is_leaf,
+ parent_internal_id,
+ state: kinematic_state,
+ velocity_dot_wrt_joint,
+ velocity_wrt_joint,
+ rigid_body,
+ }
+ }
+
+ pub fn joint(&self) -> &MultibodyJoint {
+ &self.state.joint
+ }
+
+ pub fn rigid_body_handle(&self) -> RigidBodyHandle {
+ self.rigid_body
+ }
+
+ /// Checks if this link is the root of the multibody.
+ #[inline]
+ pub fn is_root(&self) -> bool {
+ self.internal_id == 0
+ }
+
+ /// This link's name.
+ #[inline]
+ pub fn name(&self) -> &str {
+ &self.name
+ }
+
+ /// Sets this link's name.
+ #[inline]
+ pub fn set_name(&mut self, name: String) {
+ self.name = name
+ }
+
+ /// The handle of this multibody link.
+ #[inline]
+ pub fn link_id(&self) -> usize {
+ self.internal_id
+ }
+
+ /// The handle of the parent link.
+ #[inline]
+ pub fn parent_id(&self) -> Option<usize> {
+ if self.internal_id != 0 {
+ Some(self.parent_internal_id)
+ } else {
+ None
+ }
+ }
+
+ #[inline]
+ pub fn local_to_world(&self) -> &Isometry<Real> {
+ &self.state.local_to_world
+ }
+
+ #[inline]
+ pub fn local_to_parent(&self) -> &Isometry<Real> {
+ &self.state.local_to_parent
+ }
+}
+
+// FIXME: keep this even if we already have the Index2 traits?
+pub(crate) struct MultibodyLinkVec(pub Vec<MultibodyLink>);
+
+impl MultibodyLinkVec {
+ #[inline]
+ pub fn get_mut_with_parent(&mut self, i: usize) -> (&mut MultibodyLink, &MultibodyLink) {
+ let parent_id = self[i].parent_internal_id;
+
+ assert!(
+ parent_id != i,
+ "Internal error: circular rigid body dependency."
+ );
+ assert!(parent_id < self.len(), "Invalid parent index.");
+
+ unsafe {
+ let rb = &mut *(self.get_unchecked_mut(i) as *mut _);
+ let parent_rb = &*(self.get_unchecked(parent_id) as *const _);
+ (rb, parent_rb)
+ }
+ }
+}
+
+impl Deref for MultibodyLinkVec {
+ type Target = Vec<MultibodyLink>;
+
+ #[inline]
+ fn deref(&self) -> &Vec<MultibodyLink> {
+ let MultibodyLinkVec(ref me) = *self;
+ me
+ }
+}
+
+impl DerefMut for MultibodyLinkVec {
+ #[inline]
+ fn deref_mut(&mut self) -> &mut Vec<MultibodyLink> {
+ let MultibodyLinkVec(ref mut me) = *self;
+ me
+ }
+}