#![deny(missing_docs)]
use nalgebra::{Isometry3, UnitQuaternion, Vector3};
pub struct PoseGenerator(Box<dyn FnMut(&Isometry3<f64>, f64) -> Isometry3<f64>>);
pub struct PositionGenerator(Box<dyn FnMut(&Vector3<f64>, f64) -> Vector3<f64>>);
pub struct OrientationGenerator(Box<dyn FnMut(&UnitQuaternion<f64>, f64) -> UnitQuaternion<f64>>);
impl PositionGenerator {
pub fn new(
position_generator_function: Box<dyn FnMut(&Vector3<f64>, f64) -> Vector3<f64>>,
) -> Self {
PositionGenerator(position_generator_function)
}
pub fn get_position(&mut self, start_position: &Vector3<f64>, progress: f64) -> Vector3<f64> {
(self.0)(start_position, progress)
}
pub fn constant_position_generator() -> Self {
let position_generator = move |start_position: &Vector3<f64>,
_progress: f64|
-> Vector3<f64> { start_position.clone_owned() };
PositionGenerator(Box::new(position_generator))
}
}
impl OrientationGenerator {
pub fn new(
orientation_generator_function: Box<
dyn FnMut(&UnitQuaternion<f64>, f64) -> UnitQuaternion<f64>,
>,
) -> Self {
OrientationGenerator(orientation_generator_function)
}
pub fn get_orientation(
&mut self,
start_orientation: &UnitQuaternion<f64>,
progress: f64,
) -> UnitQuaternion<f64> {
(self.0)(start_orientation, progress)
}
pub fn constant_orientation_generator() -> Self {
let orientation_generator = move |start_orientation: &UnitQuaternion<f64>,
_progress: f64|
-> UnitQuaternion<f64> { *start_orientation };
OrientationGenerator(Box::new(orientation_generator))
}
}
impl PoseGenerator {
pub fn new(
pose_generator_function: Box<dyn FnMut(&Isometry3<f64>, f64) -> Isometry3<f64>>,
) -> Self {
PoseGenerator(pose_generator_function)
}
pub fn from_parts(
mut position_generator: PositionGenerator,
mut orientation_generator: OrientationGenerator,
) -> Self {
let pose_generator =
move |initial_pose: &Isometry3<f64>, progress: f64| -> Isometry3<f64> {
let position =
position_generator.get_position(&initial_pose.translation.vector, progress);
let orientation =
orientation_generator.get_orientation(&initial_pose.rotation, progress);
Isometry3::from_parts(position.into(), orientation)
};
PoseGenerator(Box::new(pose_generator))
}
pub fn get_pose(&mut self, start: &Isometry3<f64>, progress: f64) -> Isometry3<f64> {
(self.0)(start, progress)
}
pub fn get_approximate_length(
&mut self,
start_pose: &Isometry3<f64>,
sample_size: usize,
) -> f64 {
(0..sample_size)
.map(|x| {
(
x as f64 / sample_size as f64,
(x as f64 + 1.) / sample_size as f64,
)
})
.map(|(t1, t2)| {
(self.get_pose(&start_pose, t1).translation.inverse()
* self.get_pose(&start_pose, t2).translation)
.vector
.norm()
})
.sum()
}
pub fn append(
mut self,
start_pose: &Isometry3<f64>,
mut other_generator: PoseGenerator,
) -> PoseGenerator {
let length_self = self.get_approximate_length(start_pose, 10000);
let end_pose_self = self.get_pose(start_pose, 1.);
let length_other = other_generator.get_approximate_length(&end_pose_self, 10000);
let length_split = length_self / (length_self + length_other);
let pose_generator =
move |initial_pose: &Isometry3<f64>, progress: f64| -> Isometry3<f64> {
if progress < length_split {
self.get_pose(initial_pose, progress / length_split)
} else {
other_generator.get_pose(
&end_pose_self,
(progress - length_split) / (1. - length_split),
)
}
};
PoseGenerator(Box::new(pose_generator))
}
}
impl std::ops::Mul for PoseGenerator {
type Output = PoseGenerator;
fn mul(mut self, mut rhs: Self) -> Self::Output {
let pose_generator =
move |initial_pose: &Isometry3<f64>, progress: f64| -> Isometry3<f64> {
(self.0)(initial_pose, progress) * (rhs.0)(initial_pose, progress)
};
PoseGenerator(Box::new(pose_generator))
}
}
mod cartesian_trajectory;
pub mod pose_generators;
mod velocity_profile;
pub use crate::cartesian_trajectory::{
CartesianTrajectory, CartesianTrajectoryOutput, VelocityProfile,
};
pub use crate::pose_generators::{
generate_absolute_motion, generate_circle_motion, generate_relative_motion, RelativeMotionFrame,
};
pub use crate::velocity_profile::{
generate_cosine_velocity_profile, generate_linear_velocity_profile, generate_s_curve_profile,
VelocityProfileMapping, VelocityProfileOutput,
};
pub use s_curve;