use nalgebra::Vector3;
use featherstone::prelude::*;
fn main() {
let mut body = ArticulatedBody::new();
let link_mass = 1.0;
let half_extents = Vector3::new(0.05, 0.25, 0.05); let link_inertia = SpatialInertia::cuboid(link_mass, half_extents);
let x_tree = SpatialTransform::from_translation(Vector3::new(0.0, -0.5, 0.0));
body.add_body(
"upper_link",
-1,
GenJoint::Revolute { axis: Vector3::z() },
link_inertia.clone(),
x_tree.clone(),
);
body.add_body(
"lower_link",
0,
GenJoint::Revolute { axis: Vector3::z() },
link_inertia,
x_tree,
);
body.q[0] = std::f32::consts::FRAC_PI_2;
body.q[1] = 0.0;
let dt = 0.001; let config = IntegratorConfig {
method: IntegrationMethod::SemiImplicitEuler,
dt,
..Default::default()
};
let steps_per_print = 100; let total_prints = 20;
println!("Double Pendulum Simulation");
println!("==========================");
println!(
"{:>8} {:>10} {:>10} {:>10} {:>10}",
"time(s)", "q1(deg)", "q2(deg)", "qd1", "qd2"
);
println!("{}", "-".repeat(58));
print_state(0.0, &body);
for i in 1..=total_prints {
for _ in 0..steps_per_print {
step(&mut body, &config);
}
let t = i as f32 * steps_per_print as f32 * dt;
print_state(t, &body);
}
println!("{}", "-".repeat(58));
println!(
"Total energy drift is small thanks to the symplectic integrator."
);
}
fn print_state(t: f32, body: &ArticulatedBody) {
let q1_deg = body.q[0].to_degrees();
let q2_deg = body.q[1].to_degrees();
let qd1 = body.qd[0];
let qd2 = body.qd[1];
println!(
"{:>8.3} {:>10.3} {:>10.3} {:>10.4} {:>10.4}",
t, q1_deg, q2_deg, qd1, qd2
);
}