use bevy::{color::palettes::tailwind::BLUE_400, prelude::*};
use bevy_rapier3d::{
plugin::{NoUserData, RapierPhysicsPlugin},
render::RapierDebugRenderPlugin,
};
use robocomp_rapier3d::{
RobocompRapierControllerPlugin, RobocompRapierPlugin,
rc::{
RcCollider, RcDisableSleep, RcJoint, RcJointKind, RcJointLocalAnchor1, RcJointLocalAnchor2,
RcJointMotorControlConfig, RcLink, RcLinkRoot, RcPrismaticJointLimits,
RcPrismaticJointMotor, RcRevoluteJointMotor, RcRigidBody, RcRobotRoot, RcSceneRoot,
},
rd::{RdJointLimits, RdMotorModel, RdMotorPosition, RdMotorVelocity, RdName},
};
use crate::scene_setup::SceneSetupPlugin;
#[path = "helpers/scene_setup.rs"]
mod scene_setup;
const CUBE_SIZE: f32 = 1.0;
const HALF: f32 = CUBE_SIZE / 2.0;
const REVOLUTE_LINK_OFFSET: f32 = 0.5;
const LINKS: [&str; 5] = ["Link 1", "Link 2", "Link 3", "Link 4", "Link 5"];
const JOINTS: [&str; 4] = [
"Revolute Joint 1",
"Prismatic Joint 1",
"Revolute Joint 2",
"Prismatic Joint 2",
];
const MOTOR_CONTROL_NORMAL_VEL: f32 = 10.;
const MOTOR_CONTROL_DAMPING: f32 = 125.;
const MOTOR_CONTROL_BOOST_VEL: f32 = 20.;
const PRISMATIC_MOTOR_CONTROL_NORM_ANG_VEL: f32 = 4.;
const PRISMATIC_MOTOR_CONTROL_BOOST_ANG_VEL: f32 = 8.;
const PRISMATIC_MOTOR_STIFFNESS: f32 = 1000.;
const PRISMATIC_MOTOR_DAMPING: f32 = 130.;
fn main() {
let mut app = App::new();
app.add_plugins((DefaultPlugins, SceneSetupPlugin));
app.add_plugins((
RapierPhysicsPlugin::<NoUserData>::default(),
RapierDebugRenderPlugin::default(),
RobocompRapierPlugin,
RobocompRapierControllerPlugin,
));
app.add_systems(Startup, setup_scene);
app.add_systems(Startup, || {
info!("Robocomp multi joints control example running!")
});
app.run();
}
fn setup_scene(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
) {
commands
.spawn((
Name::new("Multi Joints Control Example Scene"),
Transform::default(),
Visibility::default(),
RcSceneRoot, ))
.with_child(multi_joint_robot(&mut meshes, &mut materials));
}
fn multi_joint_robot(
meshes: &mut Assets<Mesh>,
materials: &mut Assets<StandardMaterial>,
) -> impl Bundle {
let cube_mesh_hdl = meshes.add(Mesh::from(Cuboid::from_size(Vec3::splat(CUBE_SIZE))));
let cube_mat_hdl = materials.add(StandardMaterial {
base_color: Color::from(BLUE_400),
perceptual_roughness: 0.,
..Default::default()
});
(
Name::new("Multi Joint Robot"),
RcRobotRoot,
Transform::default(),
Visibility::default(),
children![
(
link(
LINKS[0],
RcRigidBody::Fixed,
cube_mesh_hdl.clone(),
cube_mat_hdl.clone()
),
RcLinkRoot, Transform::from_translation(Vec3::new(0., HALF, 0.)),
),
(
joint(JOINTS[0], Vec3::ZERO, Vec3::ZERO),
RcJointKind::Revolute {
parent: RdName::new(LINKS[0]),
child: RdName::new(LINKS[1]),
axis: Vec3::Y,
},
RcRevoluteJointMotor {
model: RdMotorModel::AccelerationBased {
stiffness: 0.,
damping: MOTOR_CONTROL_DAMPING,
},
velocity: Some(RdMotorVelocity { target: 0. }),
position: None,
max_force: None,
},
RcJointMotorControlConfig::Velocity {
normal_vel: MOTOR_CONTROL_NORMAL_VEL,
boost_vel: MOTOR_CONTROL_BOOST_VEL,
},
Transform::from_translation(Vec3::new(0., CUBE_SIZE, 0.)),
),
(
link(
LINKS[1],
RcRigidBody::Dynamic,
cube_mesh_hdl.clone(),
cube_mat_hdl.clone()
),
Transform::from_translation(Vec3::new(
0.,
CUBE_SIZE + HALF + REVOLUTE_LINK_OFFSET,
0.
)),
RcDisableSleep, ),
(
joint(JOINTS[1], Vec3::ZERO, Vec3::ZERO),
RcJointKind::Prismatic {
parent: RdName::new(LINKS[1]),
child: RdName::new(LINKS[2]),
axis: Vec3::X,
},
RcPrismaticJointMotor {
model: RdMotorModel::AccelerationBased {
stiffness: PRISMATIC_MOTOR_STIFFNESS,
damping: PRISMATIC_MOTOR_DAMPING,
},
velocity: None,
position: Some(RdMotorPosition { target: 0. }),
max_force: None,
},
RcPrismaticJointLimits(RdJointLimits {
min: 0.,
max: CUBE_SIZE,
}), RcJointMotorControlConfig::Position {
norm_ang_vel: PRISMATIC_MOTOR_CONTROL_NORM_ANG_VEL,
boost_ang_vel: PRISMATIC_MOTOR_CONTROL_BOOST_ANG_VEL,
},
Transform::from_translation(Vec3::new(
HALF,
CUBE_SIZE + HALF + REVOLUTE_LINK_OFFSET,
0.
)),
),
(
link(
LINKS[2],
RcRigidBody::Dynamic,
cube_mesh_hdl.clone(),
cube_mat_hdl.clone()
),
Transform::from_translation(Vec3::new(
CUBE_SIZE + HALF,
CUBE_SIZE + HALF + REVOLUTE_LINK_OFFSET,
0.
)),
RcDisableSleep, ),
(
joint(JOINTS[2], Vec3::ZERO, Vec3::ZERO),
RcJointKind::Revolute {
parent: RdName::new(LINKS[2]),
child: RdName::new(LINKS[3]),
axis: Vec3::Y,
},
RcRevoluteJointMotor {
model: RdMotorModel::AccelerationBased {
stiffness: 0.,
damping: MOTOR_CONTROL_DAMPING,
},
velocity: Some(RdMotorVelocity { target: 0. }),
position: None,
max_force: None,
},
RcJointMotorControlConfig::Velocity {
normal_vel: MOTOR_CONTROL_NORMAL_VEL,
boost_vel: MOTOR_CONTROL_BOOST_VEL,
},
Transform::from_translation(Vec3::new(
CUBE_SIZE + HALF,
CUBE_SIZE + HALF + REVOLUTE_LINK_OFFSET + HALF,
0.,
)),
),
(
link(
LINKS[3],
RcRigidBody::Dynamic,
cube_mesh_hdl.clone(),
cube_mat_hdl.clone()
),
Transform::from_translation(Vec3::new(
CUBE_SIZE + HALF,
CUBE_SIZE + HALF + REVOLUTE_LINK_OFFSET + HALF + HALF + REVOLUTE_LINK_OFFSET,
0.,
)),
RcDisableSleep, ),
(
joint(JOINTS[3], Vec3::ZERO, Vec3::ZERO),
RcJointKind::Prismatic {
parent: RdName::new(LINKS[3]),
child: RdName::new(LINKS[4]),
axis: Vec3::X,
},
RcPrismaticJointMotor {
model: RdMotorModel::AccelerationBased {
stiffness: PRISMATIC_MOTOR_STIFFNESS,
damping: PRISMATIC_MOTOR_DAMPING,
},
velocity: None,
position: Some(RdMotorPosition { target: 0. }),
max_force: None,
},
RcPrismaticJointLimits(RdJointLimits {
min: 0.,
max: CUBE_SIZE * 2.,
}), RcJointMotorControlConfig::Position {
norm_ang_vel: PRISMATIC_MOTOR_CONTROL_NORM_ANG_VEL,
boost_ang_vel: PRISMATIC_MOTOR_CONTROL_BOOST_ANG_VEL,
},
Transform::from_translation(Vec3::new(
CUBE_SIZE * 2. + HALF,
CUBE_SIZE + HALF + REVOLUTE_LINK_OFFSET + HALF + HALF + REVOLUTE_LINK_OFFSET,
0.,
)),
),
(
link(
LINKS[4],
RcRigidBody::Dynamic,
cube_mesh_hdl.clone(),
cube_mat_hdl.clone()
),
Transform::from_translation(Vec3::new(
CUBE_SIZE + HALF + CUBE_SIZE,
CUBE_SIZE + HALF + REVOLUTE_LINK_OFFSET + HALF + HALF + REVOLUTE_LINK_OFFSET,
0.,
)),
RcDisableSleep, ),
],
)
}
fn link(
name: &'static str,
rigid_body: RcRigidBody,
mesh_hdl: Handle<Mesh>,
material_hdl: Handle<StandardMaterial>,
) -> impl Bundle {
(
Name::new(name),
RcLink {
name: RdName::new(name),
rigid_body,
},
Visibility::default(),
RcCollider {
keep_mesh: true,
..Default::default()
},
children![(
Name::new(format!("{} Mesh", name)),
Transform::default(),
Visibility::default(),
Mesh3d(mesh_hdl),
MeshMaterial3d(material_hdl),
)],
)
}
fn joint(name: &'static str, local_anchor1: Vec3, local_anchor2: Vec3) -> impl Bundle {
(
Name::new(format!("{} Joint", name)),
Visibility::default(),
RcJoint {
name: RdName::new(name),
..Default::default()
},
children![
(
Name::new(format!("{} local anchor 1", name)),
Transform::from_translation(local_anchor1),
Visibility::default(),
RcJointLocalAnchor1,
),
(
Name::new(format!("{} local anchor 2", name)),
Transform::from_translation(local_anchor2),
Visibility::default(),
RcJointLocalAnchor2,
),
],
)
}