use super::multibody_link::{MultibodyLink, MultibodyLinkVec};
use super::multibody_workspace::MultibodyWorkspace;
use crate::dynamics::{RigidBodyHandle, RigidBodySet, RigidBodyType, RigidBodyVelocity};
#[cfg(feature = "dim3")]
use crate::math::Matrix;
use crate::math::{
AngDim, AngVector, Dim, Isometry, Jacobian, Point, Real, Vector, ANG_DIM, DIM, SPATIAL_DIM,
};
use crate::prelude::MultibodyJoint;
use crate::utils::{IndexMut2, SimdAngularInertia, SimdCross, SimdCrossMatrix};
use na::{self, DMatrix, DVector, DVectorView, DVectorViewMut, Dyn, OMatrix, SMatrix, SVector, LU};
#[repr(C)]
#[derive(Copy, Clone, Debug, Default)]
struct Force {
linear: Vector<Real>,
angular: AngVector<Real>,
}
impl Force {
fn new(linear: Vector<Real>, angular: AngVector<Real>) -> Self {
Self { linear, angular }
}
fn as_vector(&self) -> &SVector<Real, SPATIAL_DIM> {
unsafe { std::mem::transmute(self) }
}
}
#[cfg(feature = "dim2")]
fn concat_rb_mass_matrix(
mass: Vector<Real>,
inertia: Real,
) -> SMatrix<Real, SPATIAL_DIM, SPATIAL_DIM> {
let mut result = SMatrix::<Real, SPATIAL_DIM, SPATIAL_DIM>::zeros();
result[(0, 0)] = mass.x;
result[(1, 1)] = mass.y;
result[(2, 2)] = inertia;
result
}
#[cfg(feature = "dim3")]
fn concat_rb_mass_matrix(
mass: Vector<Real>,
inertia: Matrix<Real>,
) -> SMatrix<Real, SPATIAL_DIM, SPATIAL_DIM> {
let mut result = SMatrix::<Real, SPATIAL_DIM, SPATIAL_DIM>::zeros();
result[(0, 0)] = mass.x;
result[(1, 1)] = mass.y;
result[(2, 2)] = mass.z;
result
.fixed_view_mut::<ANG_DIM, ANG_DIM>(DIM, DIM)
.copy_from(&inertia);
result
}
/// An articulated body simulated using the reduced-coordinates approach.
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
#[derive(Clone)]
pub struct Multibody {
// TODO: serialization: skip the workspace fields.
links: MultibodyLinkVec,
pub(crate) velocities: DVector<Real>,
pub(crate) damping: DVector<Real>,
pub(crate) accelerations: DVector<Real>,
body_jacobians: Vec<Jacobian<Real>>,
// TODO: use sparse matrices?
augmented_mass: DMatrix<Real>,
inv_augmented_mass: LU<Real, Dyn, Dyn>,
acc_augmented_mass: DMatrix<Real>,
acc_inv_augmented_mass: LU<Real, Dyn, Dyn>,
ndofs: usize,
pub(crate) root_is_dynamic: bool,
pub(crate) solver_id: usize,
/*
* Workspaces.
*/
workspace: MultibodyWorkspace,
coriolis_v: Vec<OMatrix<Real, Dim, Dyn>>,
coriolis_w: Vec<OMatrix<Real, AngDim, Dyn>>,
i_coriolis_dt: Jacobian<Real>,
}
impl Default for Multibody {
fn default() -> Self {
Multibody::new()
}
}
impl Multibody {
/// Creates a new multibody with no link.
pub fn new() -> Self {
Multibody {
links: MultibodyLinkVec(Vec::new()),
velocities: DVector::zeros(0),
damping: DVector::zeros(0),
accelerations: DVector::zeros(0),
body_jacobians: Vec::new(),
augmented_mass: DMatrix::zeros(0, 0),
inv_augmented_mass: LU::new(DMatrix::zeros(0, 0)),
acc_augmented_mass: DMatrix::zeros(0, 0),
acc_inv_augmented_mass: LU::new(DMatrix::zeros(0, 0)),
ndofs: 0,
solver_id: 0,
workspace: MultibodyWorkspace::new(),
coriolis_v: Vec::new(),
coriolis_w