robot_description_builder/chained/
mod.rs1mod chained_jointbuilder;
2mod chained_linkbuilder;
3
4use std::{
5 fmt::Debug,
6 ops::{Deref, DerefMut},
7};
8
9use crate::identifiers::GroupIDChanger;
10
11#[derive(Debug, PartialEq, Clone)]
15#[repr(transparent)]
16pub struct Chained<Builder: ChainableBuilder>(pub(crate) Builder);
17
18impl<Builder> Deref for Chained<Builder>
28where
29 Builder: ChainableBuilder,
30{
31 type Target = Builder;
32
33 fn deref(&self) -> &Self::Target {
34 &self.0
35 }
36}
37
38impl<Builder> DerefMut for Chained<Builder>
41where
42 Builder: ChainableBuilder,
43{
44 fn deref_mut(&mut self) -> &mut Self::Target {
45 &mut self.0
46 }
47}
48
49#[cfg(feature = "wrapper")]
50impl<Builder> Chained<Builder>
51where
52 Builder: ChainableBuilder,
53{
54 pub unsafe fn new(builder: Builder) -> Self {
56 Chained(builder)
57 }
58}
59
60pub trait ChainableBuilder: Debug + PartialEq + Clone + GroupIDChanger {
61 fn has_chain(&self) -> bool;
63}
64
65#[cfg(test)]
66mod tests {
67 use super::Chained;
68 use crate::{
69 joint::{JointBuilder, SmartJointBuilder},
70 link::{builder::LinkBuilder, Link},
71 prelude::*,
72 };
73 use test_log::test;
74
75 #[test]
77 fn deref_mut_test() {
78 let leg_tree = Link::builder("leg_[[L01]]_l1").build_tree();
79 leg_tree
80 .get_root_link()
81 .try_write()
82 .unwrap()
83 .try_attach_child(
84 SmartJointBuilder::new_fixed("leg_[[L01]]_j1"),
85 Link::builder("leg_[[L01]]_l2"),
86 )
87 .unwrap();
88
89 let tree = Link::builder("root").build_tree();
90 tree.get_root_link()
91 .try_write()
92 .unwrap()
93 .try_attach_child(SmartJointBuilder::new_fixed("leg_[[L01]]_j0"), leg_tree)
94 .unwrap();
95
96 let builder_chain = tree.yank_joint("leg_[[L01]]_j0").unwrap();
97
98 assert_eq!(
99 builder_chain,
100 Chained(JointBuilder {
101 name: "leg_[[L01]]_j0".into(),
102 child: Some(LinkBuilder {
103 name: "leg_[[L01]]_l1".into(),
104 joints: vec![JointBuilder {
105 name: "leg_[[L01]]_j1".into(),
106 child: Some(LinkBuilder {
107 name: "leg_[[L01]]_l2".into(),
108 ..Default::default()
109 }),
110 ..Default::default()
111 }],
112 ..Default::default()
113 }),
114 ..Default::default()
115 })
116 );
117
118 let mut mirrored_chain = builder_chain
119 .clone()
120 .mirror(crate::transform::MirrorAxis::X);
121 mirrored_chain.change_group_id("R01").unwrap();
123
124 let tree = Link::builder("root").build_tree();
125 tree.get_root_link()
126 .try_write()
127 .unwrap()
128 .attach_joint_chain(builder_chain)
129 .unwrap();
130 tree.get_root_link()
131 .try_write()
132 .unwrap()
133 .attach_joint_chain(mirrored_chain)
134 .unwrap();
135
136 assert_eq!(
137 tree.yank_link("root").unwrap(),
138 Chained(LinkBuilder {
139 name: "root".into(),
140 joints: vec![
141 JointBuilder {
142 name: "leg_[[L01]]_j0".into(),
143 child: Some(LinkBuilder {
144 name: "leg_[[L01]]_l1".into(),
145 joints: vec![JointBuilder {
146 name: "leg_[[L01]]_j1".into(),
147 child: Some(LinkBuilder {
148 name: "leg_[[L01]]_l2".into(),
149 ..Default::default()
150 }),
151 ..Default::default()
152 }],
153 ..Default::default()
154 }),
155 ..Default::default()
156 },
157 JointBuilder {
158 name: "leg_[[R01]]_j0".into(),
159 child: Some(LinkBuilder {
160 name: "leg_[[R01]]_l1".into(),
161 joints: vec![JointBuilder {
162 name: "leg_[[R01]]_j1".into(),
163 child: Some(LinkBuilder {
164 name: "leg_[[R01]]_l2".into(),
165 ..Default::default()
166 }),
167 ..Default::default()
168 }],
169 ..Default::default()
170 }),
171 ..Default::default()
172 }
173 ],
174 ..Default::default()
175 })
176 )
177 }
178}