feat: implement new "small-steps" solver + joint improvements

This commit is contained in:
Sébastien Crozet
2024-01-21 21:02:23 +01:00
parent 9ac3503b87
commit 9b87f06a85
76 changed files with 6672 additions and 4305 deletions

View File

@@ -53,13 +53,24 @@ impl IndexedData for MultibodyJointHandle {
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct MultibodyJointLink {
pub graph_id: RigidBodyGraphIndex,
/// Indexes usable to get a multibody link from a `MultibodyJointSet`.
///
/// ```rust
/// // With:
/// // multibody_joint_set: MultibodyJointSet
/// // multibody_link_id: MultibodyLinkId
/// let multibody = &multibody_joint_set[multibody_link_id.multibody];
/// let link = multibody.link(multibody_link_id.id).expect("Link not found.");
pub struct MultibodyLinkId {
pub(crate) graph_id: RigidBodyGraphIndex,
/// The multibody index to be used as `&multibody_joint_set[multibody]` to
/// retrieve the multibody reference.
pub multibody: MultibodyIndex,
/// The multibody link index to be given to [`Multibody::link`].
pub id: usize,
}
impl Default for MultibodyJointLink {
impl Default for MultibodyLinkId {
fn default() -> Self {
Self {
graph_id: RigidBodyGraphIndex::new(crate::INVALID_U32),
@@ -78,7 +89,7 @@ impl Default for MultibodyJointLink {
#[derive(Clone)]
pub struct MultibodyJointSet {
pub(crate) multibodies: Arena<Multibody>, // NOTE: a Slab would be sufficient.
pub(crate) rb2mb: Coarena<MultibodyJointLink>,
pub(crate) rb2mb: Coarena<MultibodyLinkId>,
// NOTE: this is mostly for the island extraction. So perhaps we wont need
// that any more in the future when we improve our island builder.
pub(crate) connectivity_graph: InteractionGraph<RigidBodyHandle, ()>,
@@ -97,13 +108,22 @@ impl MultibodyJointSet {
}
/// Iterates through all the multibody joints from this set.
pub fn iter(&self) -> impl Iterator<Item = (MultibodyJointHandle, &Multibody, &MultibodyLink)> {
pub fn iter(
&self,
) -> impl Iterator<
Item = (
MultibodyJointHandle,
&MultibodyLinkId,
&Multibody,
&MultibodyLink,
),
> {
self.rb2mb
.iter()
.filter(|(_, link)| link.id > 0) // The first link of a rigid-body hasnt been added by the user.
.map(|(h, link)| {
let mb = &self.multibodies[link.multibody.0];
(MultibodyJointHandle(h), mb, mb.link(link.id).unwrap())
(MultibodyJointHandle(h), link, mb, mb.link(link.id).unwrap())
})
}
@@ -118,7 +138,7 @@ impl MultibodyJointSet {
let data = data.into();
let link1 = self.rb2mb.get(body1.0).copied().unwrap_or_else(|| {
let mb_handle = self.multibodies.insert(Multibody::with_root(body1));
MultibodyJointLink {
MultibodyLinkId {
graph_id: self.connectivity_graph.graph.add_node(body1),
multibody: MultibodyIndex(mb_handle),
id: 0,
@@ -127,7 +147,7 @@ impl MultibodyJointSet {
let link2 = self.rb2mb.get(body2.0).copied().unwrap_or_else(|| {
let mb_handle = self.multibodies.insert(Multibody::with_root(body2));
MultibodyJointLink {
MultibodyLinkId {
graph_id: self.connectivity_graph.graph.add_node(body2),
multibody: MultibodyIndex(mb_handle),
id: 0,
@@ -257,7 +277,7 @@ impl MultibodyJointSet {
/// Returns the link of this multibody attached to the given rigid-body.
///
/// Returns `None` if `rb` isnt part of any rigid-body.
pub fn rigid_body_link(&self, rb: RigidBodyHandle) -> Option<&MultibodyJointLink> {
pub fn rigid_body_link(&self, rb: RigidBodyHandle) -> Option<&MultibodyLinkId> {
self.rb2mb.get(rb.0)
}
@@ -340,15 +360,15 @@ impl MultibodyJointSet {
// NOTE: if there is a joint between these two bodies, then
// one of the bodies must be the parent of the other.
let link1 = mb.link(id1.id)?;
let parent1 = link1.parent_id()?;
let parent1 = link1.parent_id();
if parent1 == id2.id {
if parent1 == Some(id2.id) {
Some((MultibodyJointHandle(rb1.0), mb, &link1))
} else {
let link2 = mb.link(id2.id)?;
let parent2 = link2.parent_id()?;
let parent2 = link2.parent_id();
if parent2 == id1.id {
if parent2 == Some(id1.id) {
Some((MultibodyJointHandle(rb2.0), mb, &link2))
} else {
None