use carla::{
client::{ActorBase, Client, Walker},
geom::{Location, Rotation, Transform},
rpc::{BoneTransformDataIn, WalkerBoneControlIn},
};
fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("Connecting to CARLA server at 127.0.0.1:2000");
let client = Client::connect("127.0.0.1", 2000, None)?;
let mut world = client.world()?;
let bp_lib = world.blueprint_library()?;
let walker_bp = match bp_lib.filter("walker.pedestrian.*")?.get(0)? {
Some(bp) => bp,
None => {
eprintln!("No walker blueprints found");
std::process::exit(1);
}
};
let spawn_points = world.map()?.recommended_spawn_points()?;
let spawn_point = match spawn_points.get(0) {
Some(point) => point,
None => {
eprintln!("No spawn points available");
std::process::exit(1);
}
};
println!("Spawning walker at {:?}", spawn_point.location);
let actor = match world.spawn_actor(&walker_bp, spawn_point) {
Ok(actor) => actor,
Err(e) => {
eprintln!("Failed to spawn walker: {}", e);
std::process::exit(1);
}
};
let walker: Walker = match actor.try_into() {
Ok(w) => w,
Err(_) => {
eprintln!("Failed to convert actor to walker");
std::process::exit(1);
}
};
println!("Walker spawned with ID: {}", walker.id());
println!("\n=== Getting current bone transforms ===");
let bone_transforms = walker.get_bones_transform()?;
println!("Found {} bones", bone_transforms.bone_transforms.len());
for (i, bone) in bone_transforms.bone_transforms.iter().take(5).enumerate() {
println!("\nBone {}: {}", i, bone.bone_name);
println!(
" World: loc({:.2}, {:.2}, {:.2}), rot({:.2}, {:.2}, {:.2})",
bone.world.location.x,
bone.world.location.y,
bone.world.location.z,
bone.world.rotation.pitch,
bone.world.rotation.yaw,
bone.world.rotation.roll
);
println!(
" Component: loc({:.2}, {:.2}, {:.2}), rot({:.2}, {:.2}, {:.2})",
bone.component.location.x,
bone.component.location.y,
bone.component.location.z,
bone.component.rotation.pitch,
bone.component.rotation.yaw,
bone.component.rotation.roll
);
}
println!("\n=== Setting custom bone transforms ===");
let custom_bones = WalkerBoneControlIn {
bone_transforms: vec![
BoneTransformDataIn {
bone_name: "crl_arm__L".to_string(),
transform: Transform {
location: Location::new(0.0, 0.0, 0.0),
rotation: Rotation {
pitch: 0.0,
yaw: 45.0,
roll: 0.0,
},
},
},
BoneTransformDataIn {
bone_name: "crl_arm__R".to_string(),
transform: Transform {
location: Location::new(0.0, 0.0, 0.0),
rotation: Rotation {
pitch: 0.0,
yaw: -45.0,
roll: 0.0,
},
},
},
],
};
walker.set_bones(&custom_bones)?;
println!(
"Applied custom transforms to {} bones",
custom_bones.bone_transforms.len()
);
println!("\n=== Showing custom pose ===");
walker.show_pose()?;
println!("Custom pose is now visible (blend factor: 1.0)");
std::thread::sleep(std::time::Duration::from_secs(2));
println!("\n=== Blending pose (50% animation, 50% custom) ===");
walker.blend_pose(0.5)?;
println!("Pose blended at 50%");
std::thread::sleep(std::time::Duration::from_secs(2));
println!("\n=== Hiding custom pose ===");
walker.hide_pose()?;
println!("Returned to animation pose (blend factor: 0.0)");
std::thread::sleep(std::time::Duration::from_secs(1));
println!("\n=== Verifying bone transforms after modifications ===");
let final_transforms = walker.get_bones_transform()?;
println!(
"Retrieved {} bones in final state",
final_transforms.bone_transforms.len()
);
for bone_name in &["crl_arm__L", "crl_arm__R"] {
if let Some(bone) = final_transforms
.bone_transforms
.iter()
.find(|b| b.bone_name == *bone_name)
{
println!(
"\n{}: rot({:.2}, {:.2}, {:.2})",
bone_name,
bone.world.rotation.pitch,
bone.world.rotation.yaw,
bone.world.rotation.roll
);
}
}
println!("\n=== Walker bone control demo complete ===");
Ok(())
}