feat: more urdf loader improvements
This commit is contained in:
committed by
Sébastien Crozet
parent
98e32b7f3c
commit
cfddaa3c46
@@ -9,6 +9,7 @@ stl = ["rapier-stl"]
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
anyhow = "1"
|
anyhow = "1"
|
||||||
|
bitflags = "2"
|
||||||
# NOTE: we are not using the (more recent) urdf-rs crate because of https://github.com/openrr/urdf-rs/issues/94
|
# NOTE: we are not using the (more recent) urdf-rs crate because of https://github.com/openrr/urdf-rs/issues/94
|
||||||
xurdf = "0.2"
|
xurdf = "0.2"
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ use rapier3d::{
|
|||||||
},
|
},
|
||||||
geometry::{
|
geometry::{
|
||||||
Collider, ColliderBuilder, ColliderHandle, ColliderSet, MeshConverter, SharedShape,
|
Collider, ColliderBuilder, ColliderHandle, ColliderSet, MeshConverter, SharedShape,
|
||||||
|
TriMeshFlags,
|
||||||
},
|
},
|
||||||
math::{Isometry, Point, Real, Vector},
|
math::{Isometry, Point, Real, Vector},
|
||||||
na,
|
na,
|
||||||
@@ -15,6 +16,15 @@ use std::collections::HashMap;
|
|||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use xurdf::{Collision, Geometry, Inertial, Joint, Pose, Robot};
|
use xurdf::{Collision, Geometry, Inertial, Joint, Pose, Robot};
|
||||||
|
|
||||||
|
bitflags::bitflags! {
|
||||||
|
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
|
||||||
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, Default)]
|
||||||
|
pub struct UrdfMultibodyOptions: u8 {
|
||||||
|
const JOINTS_ARE_KINEMATIC = 0b0001;
|
||||||
|
const DISABLE_SELF_CONTACTS = 0b0010;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub type LinkId = usize;
|
pub type LinkId = usize;
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
@@ -24,6 +34,7 @@ pub struct UrdfLoaderOptions {
|
|||||||
pub apply_imported_mass_props: bool,
|
pub apply_imported_mass_props: bool,
|
||||||
pub enable_joint_collisions: bool,
|
pub enable_joint_collisions: bool,
|
||||||
pub make_roots_fixed: bool,
|
pub make_roots_fixed: bool,
|
||||||
|
pub trimesh_flags: TriMeshFlags,
|
||||||
pub shift: Isometry<Real>,
|
pub shift: Isometry<Real>,
|
||||||
pub collider_blueprint: ColliderBuilder,
|
pub collider_blueprint: ColliderBuilder,
|
||||||
pub rigid_body_blueprint: RigidBodyBuilder,
|
pub rigid_body_blueprint: RigidBodyBuilder,
|
||||||
@@ -37,6 +48,7 @@ impl Default for UrdfLoaderOptions {
|
|||||||
apply_imported_mass_props: true,
|
apply_imported_mass_props: true,
|
||||||
enable_joint_collisions: false,
|
enable_joint_collisions: false,
|
||||||
make_roots_fixed: false,
|
make_roots_fixed: false,
|
||||||
|
trimesh_flags: TriMeshFlags::all(),
|
||||||
shift: Isometry::identity(),
|
shift: Isometry::identity(),
|
||||||
collider_blueprint: ColliderBuilder::ball(0.0).density(0.0),
|
collider_blueprint: ColliderBuilder::ball(0.0).density(0.0),
|
||||||
rigid_body_blueprint: RigidBodyBuilder::dynamic(),
|
rigid_body_blueprint: RigidBodyBuilder::dynamic(),
|
||||||
@@ -77,6 +89,15 @@ pub struct UrdfRobot {
|
|||||||
pub joints: Vec<UrdfJoint>,
|
pub joints: Vec<UrdfJoint>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl UrdfRobot {
|
||||||
|
pub fn append_transform(&mut self, transform: &Isometry<Real>) {
|
||||||
|
for link in &mut self.links {
|
||||||
|
link.body
|
||||||
|
.set_position(transform * link.body.position(), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct UrdfJointHandle<JointHandle> {
|
pub struct UrdfJointHandle<JointHandle> {
|
||||||
pub joint: JointHandle,
|
pub joint: JointHandle,
|
||||||
pub link1: RigidBodyHandle,
|
pub link1: RigidBodyHandle,
|
||||||
@@ -237,6 +258,7 @@ impl UrdfRobot {
|
|||||||
rigid_body_set: &mut RigidBodySet,
|
rigid_body_set: &mut RigidBodySet,
|
||||||
collider_set: &mut ColliderSet,
|
collider_set: &mut ColliderSet,
|
||||||
joint_set: &mut MultibodyJointSet,
|
joint_set: &mut MultibodyJointSet,
|
||||||
|
multibody_options: UrdfMultibodyOptions,
|
||||||
) -> UrdfRobotHandles<Option<MultibodyJointHandle>> {
|
) -> UrdfRobotHandles<Option<MultibodyJointHandle>> {
|
||||||
let links: Vec<_> = self
|
let links: Vec<_> = self
|
||||||
.links
|
.links
|
||||||
@@ -257,7 +279,20 @@ impl UrdfRobot {
|
|||||||
.map(|joint| {
|
.map(|joint| {
|
||||||
let link1 = links[joint.link1].body;
|
let link1 = links[joint.link1].body;
|
||||||
let link2 = links[joint.link2].body;
|
let link2 = links[joint.link2].body;
|
||||||
let joint = joint_set.insert(link1, link2, joint.joint, false);
|
let joint =
|
||||||
|
if multibody_options.contains(UrdfMultibodyOptions::JOINTS_ARE_KINEMATIC) {
|
||||||
|
joint_set.insert_kinematic(link1, link2, joint.joint, false)
|
||||||
|
} else {
|
||||||
|
joint_set.insert(link1, link2, joint.joint, false)
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(joint) = joint {
|
||||||
|
let (multibody, _) = joint_set.get_mut(joint).unwrap_or_else(|| unreachable!());
|
||||||
|
multibody.set_self_contacts_enabled(
|
||||||
|
!multibody_options.contains(UrdfMultibodyOptions::DISABLE_SELF_CONTACTS),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
UrdfJointHandle {
|
UrdfJointHandle {
|
||||||
joint,
|
joint,
|
||||||
link1,
|
link1,
|
||||||
@@ -304,7 +339,7 @@ fn urdf_to_collider(
|
|||||||
) -> Option<Collider> {
|
) -> Option<Collider> {
|
||||||
let mut builder = options.collider_blueprint.clone();
|
let mut builder = options.collider_blueprint.clone();
|
||||||
let mut shape_transform = Isometry::identity();
|
let mut shape_transform = Isometry::identity();
|
||||||
let shape = match &geometry {
|
let mut shape = match &geometry {
|
||||||
Geometry::Box { size } => SharedShape::cuboid(
|
Geometry::Box { size } => SharedShape::cuboid(
|
||||||
size[0] as Real / 2.0,
|
size[0] as Real / 2.0,
|
||||||
size[1] as Real / 2.0,
|
size[1] as Real / 2.0,
|
||||||
@@ -326,7 +361,11 @@ fn urdf_to_collider(
|
|||||||
#[cfg(feature = "stl")]
|
#[cfg(feature = "stl")]
|
||||||
Some("stl") | Some("STL") => {
|
Some("stl") | Some("STL") => {
|
||||||
let full_path = mesh_dir.map(|dir| dir.join(filename)).unwrap_or_default();
|
let full_path = mesh_dir.map(|dir| dir.join(filename)).unwrap_or_default();
|
||||||
match rapier_stl::load_from_path(&full_path, MeshConverter::TriMesh, scale) {
|
match rapier_stl::load_from_path(
|
||||||
|
&full_path,
|
||||||
|
MeshConverter::TriMeshWithFlags(options.trimesh_flags),
|
||||||
|
scale,
|
||||||
|
) {
|
||||||
Ok(stl_shape) => {
|
Ok(stl_shape) => {
|
||||||
shape_transform = stl_shape.pose;
|
shape_transform = stl_shape.pose;
|
||||||
stl_shape.shape
|
stl_shape.shape
|
||||||
|
|||||||
@@ -89,6 +89,7 @@ pub fn init_world(testbed: &mut Testbed) {
|
|||||||
link_id,
|
link_id,
|
||||||
&options,
|
&options,
|
||||||
&Isometry::from(target_point),
|
&Isometry::from(target_point),
|
||||||
|
|_| true,
|
||||||
&mut displacements,
|
&mut displacements,
|
||||||
);
|
);
|
||||||
multibody.apply_displacements(displacements.as_slice());
|
multibody.apply_displacements(displacements.as_slice());
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
use rapier3d::prelude::*;
|
use rapier3d::prelude::*;
|
||||||
use rapier_testbed3d::Testbed;
|
use rapier_testbed3d::Testbed;
|
||||||
use rapier_urdf::{UrdfLoaderOptions, UrdfRobot};
|
use rapier_urdf::{UrdfLoaderOptions, UrdfMultibodyOptions, UrdfRobot};
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
pub fn init_world(testbed: &mut Testbed) {
|
pub fn init_world(testbed: &mut Testbed) {
|
||||||
/*
|
/*
|
||||||
@@ -17,28 +18,28 @@ pub fn init_world(testbed: &mut Testbed) {
|
|||||||
let options = UrdfLoaderOptions {
|
let options = UrdfLoaderOptions {
|
||||||
create_colliders_from_visual_shapes: true,
|
create_colliders_from_visual_shapes: true,
|
||||||
create_colliders_from_collision_shapes: false,
|
create_colliders_from_collision_shapes: false,
|
||||||
apply_imported_mass_props: false,
|
|
||||||
make_roots_fixed: true,
|
make_roots_fixed: true,
|
||||||
// Z-up to Y-up.
|
// Z-up to Y-up.
|
||||||
shift: Isometry::rotation(Vector::x() * std::f32::consts::FRAC_PI_2),
|
shift: Isometry::rotation(Vector::x() * std::f32::consts::FRAC_PI_2),
|
||||||
rigid_body_blueprint: RigidBodyBuilder::default().gravity_scale(1.0),
|
|
||||||
collider_blueprint: ColliderBuilder::default()
|
|
||||||
.density(1.0)
|
|
||||||
.active_collision_types(ActiveCollisionTypes::empty()),
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
let (mut robot, _) =
|
let (mut robot, _) =
|
||||||
UrdfRobot::from_file("assets/3d/T12/urdf/T12.URDF", options, None).unwrap();
|
UrdfRobot::from_file("assets/3d/T12/urdf/T12.URDF", options, None).unwrap();
|
||||||
// let (mut robot, _) = UrdfRobot::from_file("assets/3d/sample.urdf", options).unwrap();
|
|
||||||
|
|
||||||
// robot.insert_using_impulse_joints(&mut bodies, &mut colliders, &mut impulse_joints);
|
// The robot can be inserted using impulse joints.
|
||||||
robot.insert_using_multibody_joints(&mut bodies, &mut colliders, &mut multibody_joints);
|
// (We clone because we want to insert the same robot once more afterward.)
|
||||||
|
robot
|
||||||
testbed.add_callback(move |mut graphics, physics, _, state| {
|
.clone()
|
||||||
for (_, body) in physics.bodies.iter() {
|
.insert_using_impulse_joints(&mut bodies, &mut colliders, &mut impulse_joints);
|
||||||
println!("pose: {:?}", body.position());
|
// Insert the robot a second time, but using multibody joints this time.
|
||||||
}
|
robot.append_transform(&Isometry::translation(10.0, 0.0, 0.0));
|
||||||
});
|
robot.insert_using_multibody_joints(
|
||||||
|
&mut bodies,
|
||||||
|
&mut colliders,
|
||||||
|
&mut multibody_joints,
|
||||||
|
UrdfMultibodyOptions::DISABLE_SELF_CONTACTS,
|
||||||
|
);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set up the testbed.
|
* Set up the testbed.
|
||||||
|
|||||||
Reference in New Issue
Block a user