use na::{Isometry3, RealField, Translation3, UnitQuaternion};
use nalgebra as na;
use parking_lot::{Mutex, MutexGuard};
use simba::scalar::SubsetOf;
use std::fmt::{self, Display};
use std::ops::Deref;
use std::sync::{Arc, Weak};
use super::errors::*;
use super::iterator::*;
use super::joint::*;
use super::link::*;
type WeakNode<T> = Weak<Mutex<NodeImpl<T>>>;
#[derive(Debug)]
pub struct NodeImpl<T>
where
T: RealField,
{
pub parent: Option<WeakNode<T>>,
pub children: Vec<Node<T>>,
pub joint: Joint<T>,
pub mimic_parent: Option<WeakNode<T>>,
pub mimic_children: Vec<Node<T>>,
pub mimic: Option<Mimic<T>>,
pub link: Option<Link<T>>,
}
#[derive(Debug)]
pub struct Node<T: RealField>(pub(crate) Arc<Mutex<NodeImpl<T>>>);
impl<T> Node<T>
where
T: RealField + SubsetOf<f64>,
{
pub(crate) fn from_arc(arc_mutex_node: Arc<Mutex<NodeImpl<T>>>) -> Self {
Node(arc_mutex_node)
}
pub fn new(joint: Joint<T>) -> Self {
Node::<T>(Arc::new(Mutex::new(NodeImpl {
parent: None,
children: Vec::new(),
joint,
mimic_parent: None,
mimic_children: Vec::new(),
mimic: None,
link: None,
})))
}
pub(crate) fn lock(&self) -> MutexGuard<'_, NodeImpl<T>> {
self.0.lock()
}
pub fn joint(&self) -> JointRefGuard<'_, T> {
JointRefGuard { guard: self.lock() }
}
pub fn joint_position(&self) -> Option<T> {
self.lock().joint.joint_position()
}
pub fn parent(&self) -> Option<Node<T>> {
match self.lock().parent {
Some(ref weak) => weak.upgrade().map(Node::from_arc),
None => None,
}
}
pub fn children(&self) -> ChildrenRefGuard<'_, T> {
ChildrenRefGuard { guard: self.lock() }
}
#[inline]
pub fn iter_ancestors(&self) -> Ancestors<T> {
Ancestors::new(Some(self.clone()))
}
#[inline]
pub fn iter_descendants(&self) -> Descendants<T> {
Descendants::new(vec![self.clone()])
}
pub fn set_parent(&self, parent: &Node<T>) {
self.lock().parent = Some(Arc::downgrade(&parent.0));
parent.0.lock().children.push(self.clone());
}
pub fn remove_parent(&self, parent: &Node<T>) {
self.lock().parent = None;
parent.0.lock().children.retain(|x| *x != *self);
}
pub fn is_root(&self) -> bool {
self.lock().parent.is_none()
}
pub fn is_end(&self) -> bool {
self.0.lock().children.is_empty()
}
#[inline]
pub fn set_origin(&self, trans: Isometry3<T>) {
self.lock().joint.set_origin(trans);
}
#[inline]
pub fn origin(&self) -> Isometry3<T> {
self.joint().origin().clone()
}
pub fn set_joint_position(&self, position: T) -> Result<(), Error> {
let mut node = self.lock();
if node.mimic_parent.is_some() {
return Ok(());
}
node.joint.set_joint_position(position.clone())?;
for child in &node.mimic_children {
let mut child_node = child.lock();
let mimic = child_node.mimic.clone();
match mimic {
Some(m) => child_node
.joint
.set_joint_position(m.mimic_position(position.clone()))?,
None => {
let from = self.joint().name.to_owned();
let to = child.joint().name.to_owned();
return Err(Error::MimicError { from, to });
}
};
}
Ok(())
}
pub fn set_joint_position_clamped(&self, position: T) {
self.0.lock().joint.set_joint_position_clamped(position);
}
#[inline]
pub fn set_joint_position_unchecked(&self, position: T) {
self.0.lock().joint.set_joint_position_unchecked(position);
}
pub(crate) fn parent_world_transform(&self) -> Option<Isometry3<T>> {
match self.parent() {
Some(ref parent) => parent.world_transform(),
None => Some(Isometry3::identity()),
}
}
pub(crate) fn parent_world_velocity(&self) -> Option<Velocity<T>> {
match self.parent() {
Some(ref parent) => parent.world_velocity(),
None => Some(Velocity::zero()),
}
}
#[inline]
pub fn world_transform(&self) -> Option<Isometry3<T>> {
self.joint().world_transform()
}
#[inline]
pub fn world_velocity(&self) -> Option<Velocity<T>> {
self.joint().world_velocity()
}
pub fn mimic_parent(&self) -> Option<Node<T>> {
match self.lock().mimic_parent {
Some(ref weak) => weak.upgrade().map(Node::from_arc),
None => None,
}
}
pub fn set_mimic_parent(&self, parent: &Node<T>, mimic: Mimic<T>) {
self.lock().mimic_parent = Some(Arc::downgrade(&parent.0));
parent.lock().mimic_children.push(self.clone());
self.lock().mimic = Some(mimic);
}
pub fn set_link(&self, link: Option<Link<T>>) {
self.lock().link = link;
}
pub fn link(&self) -> OptionLinkRefGuard<'_, T> {
OptionLinkRefGuard { guard: self.lock() }
}
}
impl<T> ::std::clone::Clone for Node<T>
where
T: RealField,
{
fn clone(&self) -> Self {
Node::<T>(self.0.clone())
}
}
impl<T> PartialEq for Node<T>
where
T: RealField,
{
fn eq(&self, other: &Node<T>) -> bool {
std::ptr::eq(&*self.0, &*other.0)
}
}
impl<T: RealField + SubsetOf<f64>> Display for Node<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let inner = self.lock();
inner.joint.fmt(f)?;
if let Some(l) = &inner.link {
write!(f, " => /{}/", l.name)?;
}
Ok(())
}
}
impl<T> From<Joint<T>> for Node<T>
where
T: RealField + SubsetOf<f64>,
{
fn from(joint: Joint<T>) -> Self {
Self::new(joint)
}
}
macro_rules! def_ref_guard {
($guard_struct:ident, $target:ty, $member:ident) => {
#[derive(Debug)]
pub struct $guard_struct<'a, T>
where
T: RealField,
{
guard: MutexGuard<'a, NodeImpl<T>>,
}
impl<'a, T> Deref for $guard_struct<'a, T>
where
T: RealField,
{
type Target = $target;
fn deref(&self) -> &Self::Target {
&self.guard.$member
}
}
};
}
def_ref_guard!(JointRefGuard, Joint<T>, joint);
def_ref_guard!(OptionLinkRefGuard, Option<Link<T>>, link);
def_ref_guard!(ChildrenRefGuard, Vec<Node<T>>, children);
#[derive(Debug)]
pub struct LinkRefGuard<'a, T>
where
T: RealField,
{
pub(crate) guard: MutexGuard<'a, NodeImpl<T>>,
}
impl<'a, T> Deref for LinkRefGuard<'a, T>
where
T: RealField,
{
type Target = Link<T>;
fn deref(&self) -> &Self::Target {
self.guard.link.as_ref().unwrap()
}
}
#[derive(Debug, Clone)]
pub struct NodeBuilder<T: RealField> {
name: String,
joint_type: JointType<T>,
limits: Option<Range<T>>,
origin: Isometry3<T>,
}
impl<T> Default for NodeBuilder<T>
where
T: RealField + SubsetOf<f64>,
{
fn default() -> Self {
Self::new()
}
}
impl<T> NodeBuilder<T>
where
T: RealField + SubsetOf<f64>,
{
pub fn new() -> NodeBuilder<T> {
NodeBuilder {
name: "".to_string(),
joint_type: JointType::Fixed,
limits: None,
origin: Isometry3::identity(),
}
}
pub fn name(mut self, name: &str) -> NodeBuilder<T> {
self.name = name.to_string();
self
}
pub fn joint_type(mut self, joint_type: JointType<T>) -> NodeBuilder<T> {
self.joint_type = joint_type;
self
}
pub fn limits(mut self, limits: Option<Range<T>>) -> NodeBuilder<T> {
self.limits = limits;
self
}
pub fn origin(mut self, origin: Isometry3<T>) -> NodeBuilder<T> {
self.origin = origin;
self
}
pub fn translation(mut self, translation: Translation3<T>) -> NodeBuilder<T> {
self.origin.translation = translation;
self
}
pub fn rotation(mut self, rotation: UnitQuaternion<T>) -> NodeBuilder<T> {
self.origin.rotation = rotation;
self
}
pub fn finalize(self) -> Joint<T> {
let mut joint = Joint::new(&self.name, self.joint_type);
joint.set_origin(self.origin);
joint.limits = self.limits;
joint
}
pub fn into_node(self) -> Node<T> {
self.finalize().into()
}
}
#[macro_export]
macro_rules! connect {
($x:expr => $y:expr) => {
$y.set_parent(&$x);
};
($x:expr => $y:expr => $($rest:tt)+) => {
$y.set_parent(&$x);
$crate::connect!($y => $($rest)*);
};
}