feat: continue urdf impl

This commit is contained in:
Sébastien Crozet
2024-05-25 20:52:16 +02:00
committed by Sébastien Crozet
parent d6a76833d9
commit 0446d4457f

View File

@@ -1,11 +1,16 @@
use rapier3d::{ use rapier3d::{
dynamics::{GenericJoint, RigidBody}, dynamics::{
geometry::{Collider, ColliderBuilder, SharedShape}, GenericJoint, GenericJointBuilder, ImpulseJointHandle, ImpulseJointSet, JointAxesMask,
JointAxis, MassProperties, MultibodyJointHandle, MultibodyJointSet, RigidBody,
RigidBodyBuilder, RigidBodyHandle, RigidBodySet,
},
geometry::{Collider, ColliderBuilder, ColliderHandle, ColliderSet},
math::{Isometry, Point, Vector}, math::{Isometry, Point, Vector},
na, na,
}; };
use std::collections::HashMap;
use std::path::Path; use std::path::Path;
use urdf_rs::{Collision, Geometry, Inertial, Pose, Robot, UrdfError}; use urdf_rs::{Collision, Geometry, Inertial, Joint, JointType, Pose, Robot, UrdfError};
pub type LinkId = usize; pub type LinkId = usize;
@@ -34,21 +39,33 @@ pub struct RapierJoint {
pub struct RapierRobot { pub struct RapierRobot {
/// The bodies and colliders loaded from the urdf file. /// The bodies and colliders loaded from the urdf file.
/// ///
/// This vector matches the order of the loaded [`Robot::links`]. /// This vector matches the order of [`Robot::links`].
pub links: Vec<RapierLink>, pub links: Vec<RapierLink>,
/// The joints loaded from the urdf file. /// The joints loaded from the urdf file.
/// ///
/// This vector matches the order of the loaded [`Robot::joints`]. /// This vector matches the order of [`Robot::joints`].
pub joints: Vec<RapierLink>, pub joints: Vec<RapierJoint>,
}
pub struct RapierJointHandle<JointHandle> {
pub joint: JointHandle,
pub link1: RigidBodyHandle,
pub link2: RigidBodyHandle,
}
pub struct RapierLinkHandle {
pub body: RigidBodyHandle,
pub colliders: Vec<ColliderHandle>,
}
pub struct RapierRobotHandles<JointHandle> {
pub links: Vec<RapierLinkHandle>,
pub joints: Vec<RapierJointHandle<JointHandle>>,
} }
impl RapierRobot { impl RapierRobot {
pub fn from_file(path: impl AsRef<Path>) -> urdf_rs::Result<(Self, Robot)> { pub fn from_file(path: impl AsRef<Path>) -> urdf_rs::Result<(Self, Robot)> {
let robot = urdf_rs::read_from_string( let robot = urdf_rs::read_file(path)?;
path.as_ref()
.to_str()
.ok_or_else(|| UrdfError::from("file path contains unsupported characters"))?,
)?;
Ok((Self::from_robot(&robot), robot)) Ok((Self::from_robot(&robot), robot))
} }
@@ -58,10 +75,14 @@ impl RapierRobot {
} }
pub fn from_robot(robot: &Robot) -> Self { pub fn from_robot(robot: &Robot) -> Self {
let mut name_to_link_id = HashMap::new();
let links: Vec<_> = robot let links: Vec<_> = robot
.links .links
.iter() .iter()
.map(|link| { .enumerate()
.map(|(id, link)| {
name_to_link_id.insert(&link.name, id);
let colliders: Vec<_> = link let colliders: Vec<_> = link
.collision .collision
.iter() .iter()
@@ -71,16 +92,121 @@ impl RapierRobot {
RapierLink { body, colliders } RapierLink { body, colliders }
}) })
.collect(); .collect();
todo!() let joints: Vec<_> = robot
.joints
.iter()
.map(|joint| {
let link1 = name_to_link_id[&joint.parent.link];
let link2 = name_to_link_id[&joint.child.link];
let joint = urdf_to_joint(joint);
RapierJoint {
joint,
link1,
link2,
}
})
.collect();
Self { links, joints }
}
pub fn insert_using_impulse_joints(
self,
rigid_body_set: &mut RigidBodySet,
collider_set: &mut ColliderSet,
joint_set: &mut ImpulseJointSet,
) -> RapierRobotHandles<ImpulseJointHandle> {
let links: Vec<_> = self
.links
.into_iter()
.map(|link| {
let body = rigid_body_set.insert(link.body);
let colliders = link
.colliders
.into_iter()
.map(|co| collider_set.insert_with_parent(co, body, rigid_body_set))
.collect();
RapierLinkHandle { body, colliders }
})
.collect();
let joints: Vec<_> = self
.joints
.into_iter()
.map(|joint| {
let link1 = links[joint.link1].body;
let link2 = links[joint.link2].body;
let joint = joint_set.insert(link1, link2, joint.joint, true);
RapierJointHandle {
joint,
link1,
link2,
}
})
.collect();
RapierRobotHandles { links, joints }
}
pub fn insert_using_multibody_joints(
self,
rigid_body_set: &mut RigidBodySet,
collider_set: &mut ColliderSet,
joint_set: &mut MultibodyJointSet,
) -> RapierRobotHandles<Option<MultibodyJointHandle>> {
let links: Vec<_> = self
.links
.into_iter()
.map(|link| {
let body = rigid_body_set.insert(link.body);
let colliders = link
.colliders
.into_iter()
.map(|co| collider_set.insert_with_parent(co, body, rigid_body_set))
.collect();
RapierLinkHandle { body, colliders }
})
.collect();
let joints: Vec<_> = self
.joints
.into_iter()
.map(|joint| {
let link1 = links[joint.link1].body;
let link2 = links[joint.link2].body;
let joint = joint_set.insert(link1, link2, joint.joint, true);
RapierJointHandle {
joint,
link1,
link2,
}
})
.collect();
RapierRobotHandles { links, joints }
} }
} }
fn urdf_to_rigid_body(inertial: &Inertial) -> RigidBody { fn urdf_to_rigid_body(inertial: &Inertial) -> RigidBody {
RigidBodyBuilder::dynamic().mass_props(); RigidBodyBuilder::dynamic()
.position(urdf_to_isometry(&inertial.origin))
.additional_mass_properties(MassProperties::with_inertia_matrix(
Point::origin(),
inertial.mass.value as f32,
na::Matrix3::new(
inertial.inertia.ixx as f32,
inertial.inertia.ixy as f32,
inertial.inertia.ixz as f32,
inertial.inertia.ixy as f32,
inertial.inertia.iyy as f32,
inertial.inertia.iyz as f32,
inertial.inertia.ixz as f32,
inertial.inertia.iyz as f32,
inertial.inertia.izz as f32,
),
))
.build()
} }
fn urdf_to_collider(co: &Collision) -> Collider { fn urdf_to_collider(co: &Collision) -> Collider {
let mut builder = match &co.geometry { let builder = match &co.geometry {
Geometry::Box { size } => ColliderBuilder::cuboid( Geometry::Box { size } => ColliderBuilder::cuboid(
size[0] as f32 / 2.0, size[0] as f32 / 2.0,
size[1] as f32 / 2.0, size[1] as f32 / 2.0,
@@ -97,12 +223,12 @@ fn urdf_to_collider(co: &Collision) -> Collider {
}; };
builder builder
.position(pose_to_isometry(&co.origin)) .position(urdf_to_isometry(&co.origin))
.density(0.0) .density(0.0)
.build() .build()
} }
fn pose_to_isometry(pose: &Pose) -> Isometry<f32> { fn urdf_to_isometry(pose: &Pose) -> Isometry<f32> {
Isometry::from_parts( Isometry::from_parts(
Point::new(pose.xyz[0] as f32, pose.xyz[1] as f32, pose.xyz[2] as f32).into(), Point::new(pose.xyz[0] as f32, pose.xyz[1] as f32, pose.xyz[2] as f32).into(),
na::UnitQuaternion::from_euler_angles( na::UnitQuaternion::from_euler_angles(
@@ -112,3 +238,42 @@ fn pose_to_isometry(pose: &Pose) -> Isometry<f32> {
), ),
) )
} }
fn urdf_to_joint(joint: &Joint) -> GenericJoint {
let locked_axes = match joint.joint_type {
JointType::Fixed => JointAxesMask::LOCKED_FIXED_AXES,
JointType::Continuous | JointType::Revolute => JointAxesMask::LOCKED_REVOLUTE_AXES,
JointType::Floating => JointAxesMask::empty(),
JointType::Planar => JointAxesMask::ANG_AXES | JointAxesMask::X,
JointType::Prismatic => JointAxesMask::LOCKED_PRISMATIC_AXES,
JointType::Spherical => JointAxesMask::LOCKED_SPHERICAL_AXES,
};
let joint_to_parent = urdf_to_isometry(&joint.origin);
let joint_axis = na::Unit::new_normalize(Vector::new(
joint.axis.xyz[0] as f32,
joint.axis.xyz[1] as f32,
joint.axis.xyz[2] as f32,
));
let mut builder = GenericJointBuilder::new(locked_axes)
.local_axis1(joint_to_parent * joint_axis)
.local_axis2(joint_axis)
.local_anchor1(joint_to_parent.translation.vector.into());
match joint.joint_type {
JointType::Revolute | JointType::Prismatic => {
builder = builder.limits(
JointAxis::X,
[joint.limit.lower as f32, joint.limit.upper as f32],
)
}
_ => {}
}
// TODO: the following fields are currently ignored:
// - Joint::dynamics
// - Joint::limit.effort / limit.velocity
// - Joint::mimic
// - Joint::safety_controller
builder.build()
}