use nalgebra::{Matrix3, Vector3};
use featherstone::prelude::*;
use featherstone::contact::ground_plane_contacts;
use featherstone::contact_jacobian::ContactConstraints;
fn main() {
let mut body = ArticulatedBody::new();
body.set_gravity(Vector3::new(0.0, -9.81, 0.0));
let mass = 1.0;
let inertia = SpatialInertia::from_mass_inertia_at_com(
mass,
Matrix3::from_diagonal(&Vector3::new(0.067, 0.067, 0.067)),
);
body.add_body("box", -1, GenJoint::Floating, inertia, SpatialTransform::identity());
body.set_joint_q(0, &[0.0, 2.0, 0.0, 1.0, 0.0, 0.0, 0.0]);
let dt = 0.001;
let integrator_config = IntegratorConfig {
dt,
method: IntegrationMethod::SemiImplicitEuler,
normalize_quaternions: true,
..Default::default()
};
let lcp_config = LcpSolverConfig {
max_iterations: 20,
tolerance: 1e-6,
baumgarte: 0.2,
..Default::default()
};
let total_steps = 3000; let print_every = 500;
println!("Dropping box from 2.0 m onto ground plane...\n");
println!("{:>6} {:>8} {:>8} {:>10}", "time", "height", "vel_y", "contacts");
println!("{:-<6} {:-<8} {:-<8} {:-<10}", "", "", "", "");
for i in 0..total_steps {
featherstone::integrator::compute_accelerations(&mut body, &integrator_config);
featherstone::integrator::update_velocities(&mut body, &integrator_config);
let manifold = ground_plane_contacts(&body, 0.0, Vector3::y(), 0.5, 0.0);
let nc = manifold.contacts.len();
if nc > 0 {
let constraints = ContactConstraints::from_manifold(&body, &manifold);
let result = solve_contact_lcp(&body, &constraints, dt, &lcp_config);
let m = featherstone::crba::crba_mass_matrix(&body);
if let Some(m_inv) = m.try_inverse() {
let dqd = m_inv * &result.tau_contact;
body.qd += dqd;
}
}
featherstone::integrator::update_positions(&mut body, &integrator_config);
if i % print_every == 0 || i == total_steps - 1 {
let height = body.q[1]; let vel_y = body.qd[1]; let time = (i as f32 + 1.0) * dt;
println!("{time:6.3} {height:8.4} {vel_y:8.4} {nc:>10}");
}
}
println!("\nFinal position: ({:.4}, {:.4}, {:.4})", body.q[0], body.q[1], body.q[2]);
}