265 lines
7.4 KiB
Rust
265 lines
7.4 KiB
Rust
|
|
use crate::dynamics::RawRigidBodySet;
|
||
|
|
use crate::math::RawVector;
|
||
|
|
use crate::utils::{self, FlatHandle};
|
||
|
|
use rapier::control::PidController;
|
||
|
|
use rapier::dynamics::AxesMask;
|
||
|
|
use rapier::math::Vector;
|
||
|
|
use wasm_bindgen::prelude::*;
|
||
|
|
|
||
|
|
#[cfg(feature = "dim3")]
|
||
|
|
use crate::math::RawRotation;
|
||
|
|
#[cfg(feature = "dim2")]
|
||
|
|
use rapier::math::Rotation;
|
||
|
|
|
||
|
|
#[wasm_bindgen]
|
||
|
|
pub struct RawPidController {
|
||
|
|
controller: PidController,
|
||
|
|
}
|
||
|
|
|
||
|
|
#[wasm_bindgen]
|
||
|
|
impl RawPidController {
|
||
|
|
#[wasm_bindgen(constructor)]
|
||
|
|
pub fn new(kp: f32, ki: f32, kd: f32, axes_mask: u8) -> Self {
|
||
|
|
let controller = PidController::new(
|
||
|
|
kp,
|
||
|
|
ki,
|
||
|
|
kd,
|
||
|
|
AxesMask::from_bits(axes_mask).unwrap_or(AxesMask::all()),
|
||
|
|
);
|
||
|
|
Self { controller }
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn set_kp(&mut self, kp: f32, axes: u8) {
|
||
|
|
let axes = AxesMask::from_bits(axes).unwrap_or(AxesMask::all());
|
||
|
|
if axes.contains(AxesMask::LIN_X) {
|
||
|
|
self.controller.pd.lin_kp.x = kp;
|
||
|
|
}
|
||
|
|
if axes.contains(AxesMask::LIN_Y) {
|
||
|
|
self.controller.pd.lin_kp.y = kp;
|
||
|
|
}
|
||
|
|
#[cfg(feature = "dim3")]
|
||
|
|
if axes.contains(AxesMask::LIN_Z) {
|
||
|
|
self.controller.pd.lin_kp.z = kp;
|
||
|
|
}
|
||
|
|
#[cfg(feature = "dim3")]
|
||
|
|
if axes.contains(AxesMask::ANG_X) {
|
||
|
|
self.controller.pd.ang_kp.x = kp;
|
||
|
|
}
|
||
|
|
#[cfg(feature = "dim3")]
|
||
|
|
if axes.contains(AxesMask::ANG_Y) {
|
||
|
|
self.controller.pd.ang_kp.y = kp;
|
||
|
|
}
|
||
|
|
if axes.contains(AxesMask::ANG_Z) {
|
||
|
|
#[cfg(feature = "dim2")]
|
||
|
|
{
|
||
|
|
self.controller.pd.ang_kp = kp;
|
||
|
|
}
|
||
|
|
#[cfg(feature = "dim3")]
|
||
|
|
{
|
||
|
|
self.controller.pd.ang_kp.z = kp;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn set_ki(&mut self, ki: f32, axes: u8) {
|
||
|
|
let axes = AxesMask::from_bits(axes).unwrap_or(AxesMask::all());
|
||
|
|
if axes.contains(AxesMask::LIN_X) {
|
||
|
|
self.controller.lin_ki.x = ki;
|
||
|
|
}
|
||
|
|
if axes.contains(AxesMask::LIN_Y) {
|
||
|
|
self.controller.lin_ki.y = ki;
|
||
|
|
}
|
||
|
|
#[cfg(feature = "dim3")]
|
||
|
|
if axes.contains(AxesMask::LIN_Z) {
|
||
|
|
self.controller.lin_ki.z = ki;
|
||
|
|
}
|
||
|
|
#[cfg(feature = "dim3")]
|
||
|
|
if axes.contains(AxesMask::ANG_X) {
|
||
|
|
self.controller.ang_ki.x = ki;
|
||
|
|
}
|
||
|
|
#[cfg(feature = "dim3")]
|
||
|
|
if axes.contains(AxesMask::ANG_Y) {
|
||
|
|
self.controller.ang_ki.y = ki;
|
||
|
|
}
|
||
|
|
if axes.contains(AxesMask::ANG_Z) {
|
||
|
|
#[cfg(feature = "dim2")]
|
||
|
|
{
|
||
|
|
self.controller.ang_ki = ki;
|
||
|
|
}
|
||
|
|
#[cfg(feature = "dim3")]
|
||
|
|
{
|
||
|
|
self.controller.ang_ki.z = ki;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn set_kd(&mut self, kd: f32, axes: u8) {
|
||
|
|
let axes = AxesMask::from_bits(axes).unwrap_or(AxesMask::all());
|
||
|
|
if axes.contains(AxesMask::LIN_X) {
|
||
|
|
self.controller.pd.lin_kd.x = kd;
|
||
|
|
}
|
||
|
|
if axes.contains(AxesMask::LIN_Y) {
|
||
|
|
self.controller.pd.lin_kd.x = kd;
|
||
|
|
}
|
||
|
|
#[cfg(feature = "dim3")]
|
||
|
|
if axes.contains(AxesMask::LIN_Z) {
|
||
|
|
self.controller.pd.lin_kd.x = kd;
|
||
|
|
}
|
||
|
|
#[cfg(feature = "dim3")]
|
||
|
|
if axes.contains(AxesMask::ANG_X) {
|
||
|
|
self.controller.pd.ang_kd.x = kd;
|
||
|
|
}
|
||
|
|
#[cfg(feature = "dim3")]
|
||
|
|
if axes.contains(AxesMask::ANG_Y) {
|
||
|
|
self.controller.pd.ang_kd.y = kd;
|
||
|
|
}
|
||
|
|
if axes.contains(AxesMask::ANG_Z) {
|
||
|
|
#[cfg(feature = "dim2")]
|
||
|
|
{
|
||
|
|
self.controller.pd.ang_kd = kd;
|
||
|
|
}
|
||
|
|
#[cfg(feature = "dim3")]
|
||
|
|
{
|
||
|
|
self.controller.pd.ang_kd.z = kd;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn set_axes_mask(&mut self, axes_mask: u8) {
|
||
|
|
if let Some(mask) = AxesMask::from_bits(axes_mask) {
|
||
|
|
self.controller.pd.axes = mask;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn reset_integrals(&mut self) {
|
||
|
|
self.controller.reset_integrals();
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn apply_linear_correction(
|
||
|
|
&mut self,
|
||
|
|
dt: f32,
|
||
|
|
bodies: &mut RawRigidBodySet,
|
||
|
|
rb_handle: FlatHandle,
|
||
|
|
target_translation: &RawVector,
|
||
|
|
target_linvel: &RawVector,
|
||
|
|
) {
|
||
|
|
let rb_handle = utils::body_handle(rb_handle);
|
||
|
|
let Some(rb) = bodies.0.get_mut(rb_handle) else {
|
||
|
|
return;
|
||
|
|
};
|
||
|
|
|
||
|
|
let correction = self.controller.linear_rigid_body_correction(
|
||
|
|
dt,
|
||
|
|
rb,
|
||
|
|
target_translation.0.into(),
|
||
|
|
target_linvel.0,
|
||
|
|
);
|
||
|
|
rb.set_linvel(*rb.linvel() + correction, true);
|
||
|
|
}
|
||
|
|
|
||
|
|
#[cfg(feature = "dim2")]
|
||
|
|
pub fn apply_angular_correction(
|
||
|
|
&mut self,
|
||
|
|
dt: f32,
|
||
|
|
bodies: &mut RawRigidBodySet,
|
||
|
|
rb_handle: FlatHandle,
|
||
|
|
target_rotation: f32,
|
||
|
|
target_angvel: f32,
|
||
|
|
) {
|
||
|
|
let rb_handle = crate::utils::body_handle(rb_handle);
|
||
|
|
let Some(rb) = bodies.0.get_mut(rb_handle) else {
|
||
|
|
return;
|
||
|
|
};
|
||
|
|
|
||
|
|
let correction = self.controller.angular_rigid_body_correction(
|
||
|
|
dt,
|
||
|
|
rb,
|
||
|
|
Rotation::new(target_rotation),
|
||
|
|
target_angvel,
|
||
|
|
);
|
||
|
|
rb.set_angvel(rb.angvel() + correction, true);
|
||
|
|
}
|
||
|
|
|
||
|
|
#[cfg(feature = "dim3")]
|
||
|
|
pub fn apply_angular_correction(
|
||
|
|
&mut self,
|
||
|
|
dt: f32,
|
||
|
|
bodies: &mut RawRigidBodySet,
|
||
|
|
rb_handle: FlatHandle,
|
||
|
|
target_rotation: &RawRotation,
|
||
|
|
target_angvel: &RawVector,
|
||
|
|
) {
|
||
|
|
let rb_handle = crate::utils::body_handle(rb_handle);
|
||
|
|
let Some(rb) = bodies.0.get_mut(rb_handle) else {
|
||
|
|
return;
|
||
|
|
};
|
||
|
|
|
||
|
|
let correction = self.controller.angular_rigid_body_correction(
|
||
|
|
dt,
|
||
|
|
rb,
|
||
|
|
target_rotation.0,
|
||
|
|
target_angvel.0,
|
||
|
|
);
|
||
|
|
rb.set_angvel(rb.angvel() + correction, true);
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn linear_correction(
|
||
|
|
&mut self,
|
||
|
|
dt: f32,
|
||
|
|
bodies: &RawRigidBodySet,
|
||
|
|
rb_handle: FlatHandle,
|
||
|
|
target_translation: &RawVector,
|
||
|
|
target_linvel: &RawVector,
|
||
|
|
) -> RawVector {
|
||
|
|
let rb_handle = crate::utils::body_handle(rb_handle);
|
||
|
|
let Some(rb) = bodies.0.get(rb_handle) else {
|
||
|
|
return RawVector(Vector::zeros());
|
||
|
|
};
|
||
|
|
|
||
|
|
self.controller
|
||
|
|
.linear_rigid_body_correction(dt, rb, target_translation.0.into(), target_linvel.0)
|
||
|
|
.into()
|
||
|
|
}
|
||
|
|
|
||
|
|
#[cfg(feature = "dim2")]
|
||
|
|
pub fn angular_correction(
|
||
|
|
&mut self,
|
||
|
|
dt: f32,
|
||
|
|
bodies: &RawRigidBodySet,
|
||
|
|
rb_handle: FlatHandle,
|
||
|
|
target_rotation: f32,
|
||
|
|
target_angvel: f32,
|
||
|
|
) -> f32 {
|
||
|
|
let rb_handle = crate::utils::body_handle(rb_handle);
|
||
|
|
let Some(rb) = bodies.0.get(rb_handle) else {
|
||
|
|
return 0.0;
|
||
|
|
};
|
||
|
|
|
||
|
|
self.controller.angular_rigid_body_correction(
|
||
|
|
dt,
|
||
|
|
rb,
|
||
|
|
Rotation::new(target_rotation),
|
||
|
|
target_angvel,
|
||
|
|
)
|
||
|
|
}
|
||
|
|
|
||
|
|
#[cfg(feature = "dim3")]
|
||
|
|
pub fn angular_correction(
|
||
|
|
&mut self,
|
||
|
|
dt: f32,
|
||
|
|
bodies: &RawRigidBodySet,
|
||
|
|
rb_handle: FlatHandle,
|
||
|
|
target_rotation: &RawRotation,
|
||
|
|
target_angvel: &RawVector,
|
||
|
|
) -> RawVector {
|
||
|
|
let rb_handle = crate::utils::body_handle(rb_handle);
|
||
|
|
let Some(rb) = bodies.0.get(rb_handle) else {
|
||
|
|
return RawVector(Vector::zeros());
|
||
|
|
};
|
||
|
|
|
||
|
|
self.controller
|
||
|
|
.angular_rigid_body_correction(dt, rb, target_rotation.0, target_angvel.0)
|
||
|
|
.into()
|
||
|
|
}
|
||
|
|
}
|