use crate::inverse_kinematics::{
auxiliary::{Kinematics, Matrix3x7}, hardcoded::*, setups::calculate_ik_error,
gen_six_dof as gen_six_dof_solver,
spherical as spherical_solver,
spherical_two_intersecting as spherical_two_intersecting_solver,
spherical_two_parallel as spherical_two_parallel_solver,
three_parallel as three_parallel_solver,
three_parallel_two_intersecting as three_parallel_two_intersecting_solver,
two_intersecting as two_intersecting_solver,
two_parallel as two_parallel_solver,
};
use nalgebra::{Matrix3, Matrix3x6, Vector3, Vector6};
use setups::{Irb6640, SphericalBot, ThreeParallelBot, TwoParallelBot, Ur5};
pub type IKFunction =
fn(&Matrix3<f64>, &Vector3<f64>, &Kinematics<6, 7>) -> (Vec<Vector6<f64>>, Vec<bool>);
pub struct Robot {
sub_problem_solver: IKFunction,
kinematics: Kinematics<6, 7>,
}
pub trait IKSolver {
fn ik(&self, rot: Matrix3<f64>, translation: Vector3<f64>) -> Vec<(Vector6<f64>, bool)>;
}
impl Robot {
pub fn spherical_two_parallel(kinematics: Kinematics<6, 7>) -> Self {
Robot {
sub_problem_solver: spherical_two_parallel_solver,
kinematics
}
}
pub fn spherical_two_intersecting(kinematics: Kinematics<6, 7>) -> Self {
Robot {
sub_problem_solver: spherical_two_intersecting_solver,
kinematics
}
}
pub fn spherical(kinematics: Kinematics<6, 7>) -> Self {
Robot {
sub_problem_solver: spherical_solver,
kinematics
}
}
pub fn three_parallel_two_intersecting(kinematics: Kinematics<6, 7>) -> Self {
Robot {
sub_problem_solver: three_parallel_two_intersecting_solver,
kinematics
}
}
pub fn three_parallel(kinematics: Kinematics<6, 7>) -> Self {
Robot {
sub_problem_solver: three_parallel_solver,
kinematics
}
}
pub fn two_parallel(kinematics: Kinematics<6, 7>) -> Self {
Robot {
sub_problem_solver: two_parallel_solver,
kinematics
}
}
pub fn two_intersecting(kinematics: Kinematics<6, 7>) -> Self {
Robot {
sub_problem_solver: two_intersecting_solver,
kinematics
}
}
pub fn gen_six_dof(kinematics: Kinematics<6, 7>) -> Self {
Robot {
sub_problem_solver: gen_six_dof_solver,
kinematics
}
}
pub fn get_ik_sorted(
&mut self,
rot: Matrix3<f64>,
translation: Vector3<f64>,
) -> Vec<([f64; 6], f64, bool)> {
let solutions = self.ik(rot, translation);
let mut solutions_with_errors: Vec<([f64; 6], f64, bool)> =
Vec::<([f64; 6], f64, bool)>::new();
for (q, is_ls) in solutions {
let mut error: f64 = 0.0;
if is_ls {
error = calculate_ik_error(&self.kinematics, &rot, &translation, &q);
}
let mut q_vals = [0.0; 6];
for j in 0..6 {
q_vals[j] = q[j];
}
solutions_with_errors.push((q_vals, error, is_ls));
}
solutions_with_errors.sort_by(|a, b| a.1.partial_cmp(&b.1).unwrap());
solutions_with_errors
}
pub fn fk(&self, q: &[f64; 6]) -> (Matrix3<f64>, Vector3<f64>) {
self.kinematics
.forward_kinematics(&Vector6::from_row_slice(q))
}
}
impl IKSolver for Robot {
fn ik(&self, rot: Matrix3<f64>, translation: Vector3<f64>) -> Vec<(Vector6<f64>, bool)> {
let (solutions, lest_square_ness) =
(self.sub_problem_solver)(&rot, &translation, &self.kinematics);
solutions
.into_iter()
.zip(lest_square_ness.into_iter())
.collect()
}
}
fn create_kinematics(h: Matrix3x6<f64>, p: Matrix3x7<f64>) -> Kinematics<6, 7> {
Kinematics {
h,
p,
}
}
pub fn spherical_two_parallel(h: Matrix3x6<f64>, p: Matrix3x7<f64>) -> Robot {
Robot::spherical_two_parallel(create_kinematics(h, p))
}
pub fn spherical_two_intersecting(h: Matrix3x6<f64>, p: Matrix3x7<f64>) -> Robot {
Robot::spherical_two_intersecting(create_kinematics(h, p))
}
pub fn spherical(h: Matrix3x6<f64>, p: Matrix3x7<f64>) -> Robot {
Robot::spherical(create_kinematics(h, p))
}
pub fn three_parallel_two_intersecting(h: Matrix3x6<f64>, p: Matrix3x7<f64>) -> Robot {
Robot::three_parallel_two_intersecting(create_kinematics(h, p))
}
pub fn three_parallel(h: Matrix3x6<f64>, p: Matrix3x7<f64>) -> Robot {
Robot::three_parallel(create_kinematics(h, p))
}
pub fn two_parallel(h: Matrix3x6<f64>, p: Matrix3x7<f64>) -> Robot {
Robot::two_parallel(create_kinematics(h, p))
}
pub fn two_intersecting(h: Matrix3x6<f64>, p: Matrix3x7<f64>) -> Robot {
Robot::two_intersecting(create_kinematics(h, p))
}
pub fn gen_six_dof(h: Matrix3x6<f64>, p: Matrix3x7<f64>) -> Robot {
Robot::gen_six_dof(create_kinematics(h, p))
}
pub fn irb6640() -> Robot {
Robot::spherical_two_parallel(Irb6640::get_kin())
}
pub fn ur5() -> Robot {
Robot::three_parallel_two_intersecting(Ur5::get_kin())
}
pub fn three_parallel_bot() -> Robot {
Robot::three_parallel(ThreeParallelBot::get_kin())
}
pub fn two_parallel_bot() -> Robot {
Robot::two_parallel(TwoParallelBot::get_kin())
}
pub fn spherical_bot() -> Robot {
Robot::spherical(SphericalBot::get_kin())
}
pub struct KukaR800FixedQ3 {
robot: Robot,
r_6t: Matrix3<f64>,
}
impl KukaR800FixedQ3 {
pub fn new() -> Self {
let (kinematics, r_6t) = setups::KukaR800FixedQ3::get_kin_partial();
KukaR800FixedQ3 {
robot: Robot::spherical_two_intersecting(kinematics),
r_6t: r_6t,
}
}
}
impl IKSolver for KukaR800FixedQ3 {
fn ik(&self, rot: Matrix3<f64>, translation: Vector3<f64>) -> Vec<(Vector6<f64>, bool)> {
self.robot.ik(rot * self.r_6t.transpose(), translation)
}
}
pub struct RrcFixedQ6 {
robot: Robot,
r_6t: Matrix3<f64>,
}
impl RrcFixedQ6 {
pub fn new() -> Self {
let (kinematics, r_6t) = setups::RrcFixedQ6::get_kin_partial();
RrcFixedQ6 {
robot: Robot::spherical_two_intersecting(kinematics),
r_6t: r_6t,
}
}
}
impl IKSolver for RrcFixedQ6 {
fn ik(&self, rot: Matrix3<f64>, translation: Vector3<f64>) -> Vec<(Vector6<f64>, bool)> {
self.robot.ik(rot * self.r_6t.transpose(), translation)
}
}
pub struct YumiFixedQ3 {
robot: Robot,
r_6t: Matrix3<f64>,
}
impl YumiFixedQ3 {
pub fn new() -> Self {
let (kinematics, r_6t) = setups::YumiFixedQ3::get_kin_partial();
YumiFixedQ3 {
robot: Robot::spherical_two_intersecting(kinematics),
r_6t: r_6t,
}
}
}
impl IKSolver for YumiFixedQ3 {
fn ik(&self, rot: Matrix3<f64>, translation: Vector3<f64>) -> Vec<(Vector6<f64>, bool)> {
self.robot.ik(rot * self.r_6t.transpose(), translation)
}
}