nphysics2d/object/
multibody_link.rs

1use std::ops::{Deref, DerefMut};
2
3use na::RealField;
4
5use crate::joint::Joint;
6use crate::math::{Inertia, Isometry, Point, Vector, Velocity};
7use crate::object::BodyPart;
8
9/// One link of a multibody.
10pub struct MultibodyLink<N: RealField + Copy> {
11    pub(crate) name: String,
12    // FIXME: make all those private.
13    pub(crate) internal_id: usize,
14    pub(crate) assembly_id: usize,
15    pub(crate) impulse_id: usize,
16    pub(crate) is_leaf: bool,
17
18    // XXX: rename to "joint".
19    // (And rename the full-coordinates joint constraints JointConstraint).
20    pub(crate) parent_internal_id: usize,
21    pub(crate) dof: Box<dyn Joint<N>>,
22    pub(crate) parent_shift: Vector<N>,
23    pub(crate) body_shift: Vector<N>,
24
25    // Change at each time step.
26    pub(crate) parent_to_world: Isometry<N>,
27    pub(crate) local_to_world: Isometry<N>,
28    pub(crate) local_to_parent: Isometry<N>,
29    // FIXME: put this on a workspace buffer instead ?
30    pub(crate) velocity_dot_wrt_joint: Velocity<N>,
31    // J' q' in world space. FIXME: what could be a better name ?
32    pub(crate) velocity_wrt_joint: Velocity<N>,
33    // J  q' in world space.
34    pub(crate) velocity: Velocity<N>,
35    pub(crate) inertia: Inertia<N>,
36    pub(crate) com: Point<N>,
37
38    pub(crate) local_inertia: Inertia<N>,
39    pub(crate) local_com: Point<N>,
40    // TODO: User-defined data
41    // user_data:       T
42}
43
44impl<N: RealField + Copy> MultibodyLink<N> {
45    /// Creates a new multibody link.
46    pub fn new(
47        internal_id: usize,
48        assembly_id: usize,
49        impulse_id: usize,
50        parent_internal_id: usize,
51        dof: Box<dyn Joint<N>>,
52        parent_shift: Vector<N>,
53        body_shift: Vector<N>,
54        parent_to_world: Isometry<N>,
55        local_to_world: Isometry<N>,
56        local_to_parent: Isometry<N>,
57        local_inertia: Inertia<N>,
58        local_com: Point<N>,
59    ) -> Self {
60        let is_leaf = true;
61        let velocity = Velocity::zero();
62        let velocity_dot_wrt_joint = Velocity::zero();
63        let velocity_wrt_joint = Velocity::zero();
64        let inertia = local_inertia.transformed(&local_to_world);
65        let com = local_to_world * local_com;
66
67        MultibodyLink {
68            name: String::new(),
69            internal_id,
70            assembly_id,
71            impulse_id,
72            is_leaf,
73            parent_internal_id,
74            dof,
75            parent_shift,
76            body_shift,
77            parent_to_world,
78            local_to_world,
79            local_to_parent,
80            velocity_dot_wrt_joint,
81            velocity_wrt_joint,
82            velocity,
83            local_inertia,
84            local_com,
85            inertia,
86            com,
87        }
88    }
89
90    /// Checks if this link is the root of the multibody.
91    #[inline]
92    pub fn is_root(&self) -> bool {
93        self.internal_id == 0
94    }
95
96    /// Reference to the joint attaching this link to its parent.
97    #[inline]
98    pub fn joint(&self) -> &dyn Joint<N> {
99        &*self.dof
100    }
101
102    /// Mutable reference to the joint attaching this link to its parent.
103    #[inline]
104    pub fn joint_mut(&mut self) -> &mut dyn Joint<N> {
105        &mut *self.dof
106    }
107
108    /// The shift between this link's parent and this link joint origin.
109    #[inline]
110    pub fn parent_shift(&self) -> &Vector<N> {
111        &self.parent_shift
112    }
113
114    /// The shift between this link's joint origin and this link origin.
115    #[inline]
116    pub fn body_shift(&self) -> &Vector<N> {
117        &self.body_shift
118    }
119
120    /// This link's name.
121    #[inline]
122    pub fn name(&self) -> &str {
123        &self.name
124    }
125
126    /// Sets this link's name.
127    #[inline]
128    pub fn set_name(&mut self, name: String) {
129        self.name = name
130    }
131
132    /// The handle of this multibody link.
133    #[inline]
134    pub fn link_id(&self) -> usize {
135        self.internal_id
136    }
137
138    /// The handle of the parent link.
139    #[inline]
140    pub fn parent_id(&self) -> Option<usize> {
141        if self.internal_id != 0 {
142            Some(self.parent_internal_id)
143        } else {
144            None
145        }
146    }
147}
148
149impl<N: RealField + Copy> BodyPart<N> for MultibodyLink<N> {
150    #[inline]
151    fn is_ground(&self) -> bool {
152        false
153    }
154
155    #[inline]
156    fn center_of_mass(&self) -> Point<N> {
157        self.com
158    }
159
160    #[inline]
161    fn local_center_of_mass(&self) -> Point<N> {
162        self.local_com
163    }
164
165    #[inline]
166    fn velocity(&self) -> Velocity<N> {
167        self.velocity
168    }
169
170    #[inline]
171    fn position(&self) -> Isometry<N> {
172        self.local_to_world
173    }
174
175    #[inline]
176    fn local_inertia(&self) -> Inertia<N> {
177        self.local_inertia
178    }
179
180    #[inline]
181    fn inertia(&self) -> Inertia<N> {
182        self.inertia
183    }
184}
185
186// FIXME: keep this even if we already have the Index2 traits?
187pub(crate) struct MultibodyLinkVec<N: RealField + Copy>(pub Vec<MultibodyLink<N>>);
188
189impl<N: RealField + Copy> MultibodyLinkVec<N> {
190    // #[inline]
191    // pub fn get_with_parent(&self, i: usize) -> (&MultibodyLink<N>, &MultibodyLink<N>) {
192    //     assert!(
193    //         i != 0,
194    //         "The parent of this body is not part of the same multibody."
195    //     );
196    //     let rb = &self[i];
197    //     let parent_rb = &self[rb.parent.internal_id];
198
199    //     (rb, parent_rb)
200    // }
201    #[inline]
202    pub fn get_mut_with_parent(&mut self, i: usize) -> (&mut MultibodyLink<N>, &MultibodyLink<N>) {
203        let parent_id = self[i].parent_internal_id;
204
205        assert!(
206            parent_id != i,
207            "Internal error: circular rigid body dependency."
208        );
209        assert!(parent_id < self.len(), "Invalid parent index.");
210
211        unsafe {
212            let rb = &mut *(self.get_unchecked_mut(i) as *mut _);
213            let parent_rb = &*(self.get_unchecked(parent_id) as *const _);
214            (rb, parent_rb)
215        }
216    }
217}
218
219impl<N: RealField + Copy> Deref for MultibodyLinkVec<N> {
220    type Target = Vec<MultibodyLink<N>>;
221
222    #[inline]
223    fn deref(&self) -> &Vec<MultibodyLink<N>> {
224        let MultibodyLinkVec(ref me) = *self;
225        me
226    }
227}
228
229impl<N: RealField + Copy> DerefMut for MultibodyLinkVec<N> {
230    #[inline]
231    fn deref_mut(&mut self) -> &mut Vec<MultibodyLink<N>> {
232        let MultibodyLinkVec(ref mut me) = *self;
233        me
234    }
235}