diff --git a/README.md b/README.md
index 15c33176..65483f8c 100644
--- a/README.md
+++ b/README.md
@@ -33,6 +33,8 @@ The default implementations are `openarm_describe_config_component` and `openarm
Interface files declare macros; implementation and third-party model includes belong inside those macros. Each interface is loaded in a local scope, so its definitions do not affect other components. Presets need no implementation selector or product registry.
+Component topology uses stable `link1`, `link2`, ... and `joint1`, `joint2`, ... keys. An optional `name` on each topology entry defines its local URDF name; otherwise the key is used. The instance prefix is added once. Geometry, inertia, joint parameters, parent/child links, mimic targets, references, reflection selections and overrides use the stable keys. Changing `name` preserves these config references. Component descriptors expose resolved `link_name_map` and `joint_name_map` entries for emitters and control generation.
+
## Related links
- 📚 Read the [documentation](https://docs.openarm.dev/software/description)
@@ -49,3 +51,5 @@ Copyright 2025 Enactic, Inc.
All participation in the OpenArm project is governed by our
[Code of Conduct](CODE_OF_CONDUCT.md).
+
+Control partitions are declared under the preset's top-level `systems` mapping. Each system's `joints` maps component instance names to stable local joint keys with an `idx`. Each active joint requires a unique non-negative integer `idx` within its system; gaps are allowed. Joints are emitted in index order, with `idx` included as a joint parameter for runtime adapters. Disabled components are skipped, and final joint names come from the resolved component descriptions. Standard OpenArm hardware defaults are supplied by the model entry. Per-system hardware_plugin and driver parameters can override those defaults, and CAN launch arguments take precedence. `use_fake_hardware:=true` selects `mock_components/GenericSystem`. Optional `command_interfaces` and `state_interfaces` default to `[position, velocity, effort]`.
diff --git a/assets/robot/openarm_v1.0/config/body/inertials.yaml b/assets/body/v1.0/config/inertials/nominal.yaml
similarity index 83%
rename from assets/robot/openarm_v1.0/config/body/inertials.yaml
rename to assets/body/v1.0/config/inertials/nominal.yaml
index a9207078..a5f056fd 100644
--- a/assets/robot/openarm_v1.0/config/body/inertials.yaml
+++ b/assets/body/v1.0/config/inertials/nominal.yaml
@@ -1,4 +1,4 @@
-# Copyright 2025 Enactic, Inc.
+# Copyright 2026 Enactic, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -12,10 +12,14 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-body_link0:
+link1:
origin:
- xyz: -0.016206894902 0 0.244091987626
- rpy: 0.0 0.0 0.0
+ x: -0.016206894902
+ y: 0.0
+ z: 0.244091987626
+ roll: 0.0
+ pitch: 0.0
+ yaw: 0.0
mass: 3.74
inertia:
xx: 0.248946829107
diff --git a/assets/body/v1.0/config/link/collisions.yaml b/assets/body/v1.0/config/link/collisions.yaml
new file mode 100644
index 00000000..b3c0b2d0
--- /dev/null
+++ b/assets/body/v1.0/config/link/collisions.yaml
@@ -0,0 +1,28 @@
+# Copyright 2026 Enactic, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+link1:
+ origin:
+ x: 0
+ y: 0
+ z: 0
+ roll: 0
+ pitch: 0
+ yaw: 0
+ geometry:
+ mesh: package://openarm_description/assets/body/v1.0/meshes/collision/body_link0_symp.stl
+ scale:
+ x: 0.001
+ y: 0.001
+ z: 0.001
diff --git a/assets/body/v1.0/config/link/visuals.yaml b/assets/body/v1.0/config/link/visuals.yaml
new file mode 100644
index 00000000..5a34ffe4
--- /dev/null
+++ b/assets/body/v1.0/config/link/visuals.yaml
@@ -0,0 +1,28 @@
+# Copyright 2026 Enactic, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+link1:
+ origin:
+ x: 0
+ y: 0
+ z: 0
+ roll: 0
+ pitch: 0
+ yaw: 0
+ geometry:
+ mesh: package://openarm_description/assets/body/v1.0/meshes/visual/body_link0.dae
+ scale:
+ x: 0.001
+ y: 0.001
+ z: 0.001
diff --git a/assets/body/v1.0/config/struct/reference_points.yaml b/assets/body/v1.0/config/struct/reference_points.yaml
new file mode 100644
index 00000000..c450202f
--- /dev/null
+++ b/assets/body/v1.0/config/struct/reference_points.yaml
@@ -0,0 +1,34 @@
+# Copyright 2026 Enactic, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+left_arm_mount_point:
+ parent: link1
+ emit: false
+ origin:
+ x: 0
+ y: 0.03
+ z: 0.697
+ roll: -1.5708
+ pitch: 0
+ yaw: 0
+right_arm_mount_point:
+ parent: link1
+ emit: false
+ origin:
+ x: 0
+ y: -0.03
+ z: 0.697
+ roll: 1.5708
+ pitch: 0
+ yaw: 0
diff --git a/assets/robot/openarm_v1.0/config/body/kinematics_link.yaml b/assets/body/v1.0/config/struct/topology.yaml
similarity index 80%
rename from assets/robot/openarm_v1.0/config/body/kinematics_link.yaml
rename to assets/body/v1.0/config/struct/topology.yaml
index bbe02232..97b46d61 100644
--- a/assets/robot/openarm_v1.0/config/body/kinematics_link.yaml
+++ b/assets/body/v1.0/config/struct/topology.yaml
@@ -1,4 +1,4 @@
-# Copyright 2025 Enactic, Inc.
+# Copyright 2026 Enactic, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -12,11 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-body_link0:
- kinematic:
- x: 0.0
- y: 0.0
- z: 0.0
- roll: 0.0
- pitch: 0.0
- yaw: 0.0
+links:
+ link1:
+ name: body_link0
+joints: {}
diff --git a/assets/robot/openarm_v1.0/mesh/body/collision/body_link0_symp.stl b/assets/body/v1.0/meshes/collision/body_link0_symp.stl
similarity index 100%
rename from assets/robot/openarm_v1.0/mesh/body/collision/body_link0_symp.stl
rename to assets/body/v1.0/meshes/collision/body_link0_symp.stl
diff --git a/assets/robot/openarm_v1.0/mesh/body/visual/body_link0.dae b/assets/body/v1.0/meshes/visual/body_link0.dae
similarity index 100%
rename from assets/robot/openarm_v1.0/mesh/body/visual/body_link0.dae
rename to assets/body/v1.0/meshes/visual/body_link0.dae
diff --git a/assets/robot/openarm_v1.0/mesh/body/visual/body_link0.stl b/assets/body/v1.0/meshes/visual/body_link0.stl
similarity index 100%
rename from assets/robot/openarm_v1.0/mesh/body/visual/body_link0.stl
rename to assets/body/v1.0/meshes/visual/body_link0.stl
diff --git a/assets/body/v2.0/config/inertials/nominal.yaml b/assets/body/v2.0/config/inertials/nominal.yaml
index 75949159..52fdec86 100644
--- a/assets/body/v2.0/config/inertials/nominal.yaml
+++ b/assets/body/v2.0/config/inertials/nominal.yaml
@@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-body_link0:
+link1:
origin:
x: -0.01627169562
y: 0.0
diff --git a/assets/body/v2.0/config/link/collisions.yaml b/assets/body/v2.0/config/link/collisions.yaml
index 46fb7013..7e1d776d 100644
--- a/assets/body/v2.0/config/link/collisions.yaml
+++ b/assets/body/v2.0/config/link/collisions.yaml
@@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-body_link0:
+link1:
origin:
x: 0.0
y: 0.0
diff --git a/assets/body/v2.0/config/link/visuals.yaml b/assets/body/v2.0/config/link/visuals.yaml
index f1fa731c..474ec659 100644
--- a/assets/body/v2.0/config/link/visuals.yaml
+++ b/assets/body/v2.0/config/link/visuals.yaml
@@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-body_link0:
+link1:
origin:
x: 0.0
y: 0.0
diff --git a/assets/body/v2.0/config/struct/reference_points.yaml b/assets/body/v2.0/config/struct/reference_points.yaml
index bf695c6c..38e13a41 100644
--- a/assets/body/v2.0/config/struct/reference_points.yaml
+++ b/assets/body/v2.0/config/struct/reference_points.yaml
@@ -13,7 +13,7 @@
# limitations under the License.
left_arm_mount_point:
- parent: body_link0
+ parent: link1
origin:
x: 0.0
y: 0.030
@@ -29,13 +29,13 @@ left_arm_mount_point:
type: fixed
parent_link:
original_name: body_link0
- canonical_name: body_link0
+ canonical_name: link1
child_link:
original_name: body_left_arm_mount_point
canonical_name: null
right_arm_mount_point:
- parent: body_link0
+ parent: link1
origin:
x: 0.0
y: -0.030
@@ -51,13 +51,13 @@ right_arm_mount_point:
type: fixed
parent_link:
original_name: body_link0
- canonical_name: body_link0
+ canonical_name: link1
child_link:
original_name: body_right_arm_mount_point
canonical_name: null
arm_origin:
- parent: body_link0
+ parent: link1
emit: true
origin:
x: 0.0
diff --git a/assets/body/v2.0/config/struct/topology.yaml b/assets/body/v2.0/config/struct/topology.yaml
index 59402442..97b46d61 100644
--- a/assets/body/v2.0/config/struct/topology.yaml
+++ b/assets/body/v2.0/config/struct/topology.yaml
@@ -13,5 +13,6 @@
# limitations under the License.
links:
- - body_link0
+ link1:
+ name: body_link0
joints: {}
diff --git a/assets/common/assembly.xacro b/assets/common/assembly.xacro
index c67a42ac..1398db64 100644
--- a/assets/common/assembly.xacro
+++ b/assets/common/assembly.xacro
@@ -16,23 +16,21 @@ limitations under the License.
-
+
-
-
-
-
+
+
-
+
+ params="component_descriptions component_name components robot_preset config_root root_frame component_cfg component_desc parent_desc:=none emit_grasp_frame:=false out_name">
@@ -96,7 +94,7 @@ limitations under the License.
-
+
@@ -111,9 +109,9 @@ limitations under the License.
-
+
@@ -123,7 +121,7 @@ limitations under the License.
name="attached_children"
value="${[name for name in components if name in robot_preset and robot_preset[name]['enabled'] and 'connection' in robot_preset[name] and 'attach_to' in robot_preset[name]['connection'] and robot_preset[name]['connection']['attach_to'] == component_name]}"
lazy_eval="false" />
-
+
-
+
@@ -169,20 +168,12 @@ limitations under the License.
+ params="component_api component_descriptions component_name components robot_preset config_root root_frame parent_desc:=none emit_grasp_frame:=false">
-
-
+
-
-
-
-
-
-
+ params="component_api component_descriptions index components parent_component_name robot_preset config_root root_frame parent_desc:=none emit_grasp_frame:=false">
@@ -228,22 +217,19 @@ limitations under the License.
-
-
-
-
+ params="component_api config_root robot_preset emit_grasp_frame:=false out_name:=component_descriptions">
@@ -268,9 +252,14 @@ limitations under the License.
components="${components}"
robot_preset="${robot_preset}" />
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+ params="index joint_names topology prefix link_name_map joint_name_map joint_origins joint_axes joint_limits joint_mimics inertials visuals collisions reflect_x reflect_y reflect_z reflect_include_links reflect_include_joints origin_override_joints limit_override_joints tip_collapse_source_link tip_collapse_child_link base_frame_shift">
@@ -26,20 +26,21 @@ limitations under the License.
-
-
+ frame_shift="${base_frame_shift if joint['parent'] == list(topology['links'])[0] else 'none'}" />
+ params="connected_to mount_origin topology prefix link_name_map joint_name_map joint_origins joint_axes joint_limits joint_mimics:=${dict()} inertials visuals collisions reflect_x:=1 reflect_y:=1 reflect_z:=1 reflect_include_links:=${[]} reflect_include_joints:=${[]} origin_override_joints:=${dict()} limit_override_joints:=${dict()} tip_collapse_source_link:=none tip_collapse_child_link:=none skip_mount_joint:=${False} base_frame_shift:=none">
-
+
-
-
+
-
+
-
+
diff --git a/assets/common/ros2_control.xacro b/assets/common/ros2_control.xacro
new file mode 100644
index 00000000..3d56459a
--- /dev/null
+++ b/assets/common/ros2_control.xacro
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+
+
+
+ ${values[keys[index]]}
+
+
+
+
+
+
+
+
+
+ 0.0
+
+
+
+
+
+
+
+
+
+ ${joint_indices[index]}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ${plugin}
+
+
+
+
+
+
+
+
+
diff --git a/assets/common/validation.xacro b/assets/common/validation.xacro
index e772915c..5bcee7d5 100644
--- a/assets/common/validation.xacro
+++ b/assets/common/validation.xacro
@@ -137,7 +137,7 @@ limitations under the License.
-
+
@@ -146,10 +146,16 @@ limitations under the License.
-
+
-
+
+
+
+
+
diff --git a/assets/component_loader.xacro b/assets/component_loader.xacro
index a73afbdc..f4536023 100644
--- a/assets/component_loader.xacro
+++ b/assets/component_loader.xacro
@@ -47,13 +47,12 @@ limitations under the License.
-
+ component_cfg="${component_cfg}" component_desc="${component_desc}" component_descriptions="${dict(component=component_desc)}" out_name="component_runtime" />
diff --git a/assets/end_effector/parallel_link/config/inertials.yaml b/assets/end_effector/parallel_link/config/inertials/nominal.yaml
similarity index 80%
rename from assets/end_effector/parallel_link/config/inertials.yaml
rename to assets/end_effector/parallel_link/config/inertials/nominal.yaml
index 49a29294..ef52c40b 100644
--- a/assets/end_effector/parallel_link/config/inertials.yaml
+++ b/assets/end_effector/parallel_link/config/inertials/nominal.yaml
@@ -12,7 +12,23 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-hand:
+link1:
+ origin:
+ x: -9.897454675528511e-05
+ y: 0.003372444724450437
+ z: 0.06138919729233123
+ roll: 0
+ pitch: 0
+ yaw: 0
+ mass: 0.4054971268153967
+ inertia:
+ xx: 0.0003637830920674498
+ yy: 0.0003351190950225729
+ zz: 0.0001865112723189818
+ xy: 0.0
+ xz: 0.0
+ yz: 7.094884219324384e-05
+link2:
origin:
x: 0
y: 0
@@ -26,10 +42,9 @@ hand:
yy: 5.560627616753029e-05
zz: 0.0002906093338421478
xy: 1.18380219510342e-05
- xz: 0
- yz: 0
-
-left_finger:
+ xz: 0.0
+ yz: 0.0
+link4:
origin:
x: -0.004646697332048465
y: 0.01217890651468325
@@ -45,8 +60,7 @@ left_finger:
xy: -4.813534779503441e-07
xz: -4.110240982958172e-06
yz: 3.504307786795564e-06
-
-right_finger:
+link3:
origin:
x: 0.004646697332048465
y: -0.01217890651468325
diff --git a/assets/robot/openarm_v1.0/config/body/kinematics.yaml b/assets/end_effector/parallel_link/config/joint/joint_axes.yaml
similarity index 80%
rename from assets/robot/openarm_v1.0/config/body/kinematics.yaml
rename to assets/end_effector/parallel_link/config/joint/joint_axes.yaml
index bbe02232..2e58649d 100644
--- a/assets/robot/openarm_v1.0/config/body/kinematics.yaml
+++ b/assets/end_effector/parallel_link/config/joint/joint_axes.yaml
@@ -1,4 +1,4 @@
-# Copyright 2025 Enactic, Inc.
+# Copyright 2026 Enactic, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -12,11 +12,13 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-body_link0:
- kinematic:
- x: 0.0
- y: 0.0
- z: 0.0
- roll: 0.0
- pitch: 0.0
- yaw: 0.0
+joint2:
+ axis:
+ x: 0
+ y: -1
+ z: 0
+joint3:
+ axis:
+ x: 0
+ y: 1
+ z: 0
diff --git a/assets/end_effector/parallel_link/config/joint_limits.yaml b/assets/end_effector/parallel_link/config/joint/joint_limits.yaml
similarity index 87%
rename from assets/end_effector/parallel_link/config/joint_limits.yaml
rename to assets/end_effector/parallel_link/config/joint/joint_limits.yaml
index ee715e39..9f2ba38b 100644
--- a/assets/end_effector/parallel_link/config/joint_limits.yaml
+++ b/assets/end_effector/parallel_link/config/joint/joint_limits.yaml
@@ -12,7 +12,13 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-finger_joint:
+joint2:
+ limit:
+ lower: 0.0
+ upper: 0.044
+ velocity: 0.661
+ effort: 150.75
+joint3:
limit:
lower: 0.0
upper: 0.044
diff --git a/assets/end_effector/parallel_link/config/joint/joint_mimics.yaml b/assets/end_effector/parallel_link/config/joint/joint_mimics.yaml
new file mode 100644
index 00000000..0994fd21
--- /dev/null
+++ b/assets/end_effector/parallel_link/config/joint/joint_mimics.yaml
@@ -0,0 +1,18 @@
+# Copyright 2026 Enactic, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+joint3:
+ joint: joint2
+ multiplier: 1
+ offset: 0
diff --git a/assets/end_effector/parallel_link/config/kinematics.yaml b/assets/end_effector/parallel_link/config/joint/joint_origins.yaml
similarity index 81%
rename from assets/end_effector/parallel_link/config/kinematics.yaml
rename to assets/end_effector/parallel_link/config/joint/joint_origins.yaml
index 0723f094..09b9da8f 100644
--- a/assets/end_effector/parallel_link/config/kinematics.yaml
+++ b/assets/end_effector/parallel_link/config/joint/joint_origins.yaml
@@ -12,20 +12,27 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-hand:
- kinematic:
- x: 0.0
- y: 0.0
+joint1:
+ origin:
+ x: 0
+ y: 0
z: 0.1001
roll: 0
pitch: 0
yaw: 0
-
-finger_joint:
- kinematic:
- x: 0.0
+joint2:
+ origin:
+ x: 0
y: -0.005
z: 0.015
roll: 0
pitch: 0
yaw: 0
+joint3:
+ origin:
+ x: 0
+ y: 0.005
+ z: 0.015
+ roll: 0
+ pitch: 0
+ yaw: 0
diff --git a/assets/end_effector/parallel_link/config/link/collisions.yaml b/assets/end_effector/parallel_link/config/link/collisions.yaml
new file mode 100644
index 00000000..ff1821eb
--- /dev/null
+++ b/assets/end_effector/parallel_link/config/link/collisions.yaml
@@ -0,0 +1,70 @@
+# Copyright 2026 Enactic, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+link1:
+ origin:
+ x: 0.0
+ y: -0.0
+ z: -0.5585
+ roll: 0.0
+ pitch: 0.0
+ yaw: 0.0
+ geometry:
+ mesh: package://openarm_description/assets/end_effector/parallel_link/meshes/collision/link7.stl
+ scale:
+ x: 0.001
+ y: 0.001
+ z: 0.001
+link2:
+ origin:
+ x: 0.0
+ y: 0.0
+ z: -0.6586
+ roll: 0.0
+ pitch: 0.0
+ yaw: 0.0
+ geometry:
+ mesh: package://openarm_description/assets/end_effector/parallel_link/meshes/collision/hand.stl
+ scale:
+ x: 0.001
+ y: 0.001
+ z: 0.001
+link4:
+ origin:
+ x: 0.0
+ y: -0.05
+ z: -0.673001
+ roll: 0.0
+ pitch: 0.0
+ yaw: 0.0
+ geometry:
+ mesh: package://openarm_description/assets/end_effector/parallel_link/meshes/collision/finger.stl
+ scale:
+ x: 0.001
+ y: 0.001
+ z: 0.001
+link3:
+ origin:
+ x: 0.0
+ y: 0.05
+ z: -0.673001
+ roll: 0.0
+ pitch: 0.0
+ yaw: 3.141592653589793
+ geometry:
+ mesh: package://openarm_description/assets/end_effector/parallel_link/meshes/collision/finger.stl
+ scale:
+ x: 0.001
+ y: 0.001
+ z: 0.001
diff --git a/assets/end_effector/parallel_link/config/link/visuals.yaml b/assets/end_effector/parallel_link/config/link/visuals.yaml
new file mode 100644
index 00000000..adfeb92e
--- /dev/null
+++ b/assets/end_effector/parallel_link/config/link/visuals.yaml
@@ -0,0 +1,70 @@
+# Copyright 2026 Enactic, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+link1:
+ origin:
+ x: 0.0
+ y: -0.0
+ z: -0.5585
+ roll: 0.0
+ pitch: 0.0
+ yaw: 0.0
+ geometry:
+ mesh: package://openarm_description/assets/end_effector/parallel_link/meshes/visual/link7.dae
+ scale:
+ x: 0.001
+ y: 0.001
+ z: 0.001
+link2:
+ origin:
+ x: 0.0
+ y: 0.0
+ z: -0.6586
+ roll: 0.0
+ pitch: 0.0
+ yaw: 0.0
+ geometry:
+ mesh: package://openarm_description/assets/end_effector/parallel_link/meshes/visual/hand.dae
+ scale:
+ x: 0.001
+ y: 0.001
+ z: 0.001
+link4:
+ origin:
+ x: 0.0
+ y: -0.05
+ z: -0.673001
+ roll: 0.0
+ pitch: 0.0
+ yaw: 0.0
+ geometry:
+ mesh: package://openarm_description/assets/end_effector/parallel_link/meshes/visual/finger.dae
+ scale:
+ x: 0.001
+ y: 0.001
+ z: 0.001
+link3:
+ origin:
+ x: 0.0
+ y: 0.05
+ z: -0.673001
+ roll: 0.0
+ pitch: 0.0
+ yaw: 3.141592653589793
+ geometry:
+ mesh: package://openarm_description/assets/end_effector/parallel_link/meshes/visual/finger.dae
+ scale:
+ x: 0.001
+ y: 0.001
+ z: 0.001
diff --git a/assets/end_effector/parallel_link/config/struct/reference_points.yaml b/assets/end_effector/parallel_link/config/struct/reference_points.yaml
new file mode 100644
index 00000000..39a77980
--- /dev/null
+++ b/assets/end_effector/parallel_link/config/struct/reference_points.yaml
@@ -0,0 +1,24 @@
+# Copyright 2026 Enactic, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+hand_tcp:
+ parent: link2
+ emit: true
+ origin:
+ x: 0
+ y: 0
+ z: 0.09
+ roll: 0
+ pitch: 0
+ yaw: 0
diff --git a/assets/end_effector/parallel_link/config/struct/topology.yaml b/assets/end_effector/parallel_link/config/struct/topology.yaml
new file mode 100644
index 00000000..c06793d5
--- /dev/null
+++ b/assets/end_effector/parallel_link/config/struct/topology.yaml
@@ -0,0 +1,39 @@
+# Copyright 2026 Enactic, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+links:
+ link1:
+ name: link7
+ link2:
+ name: hand
+ link3:
+ name: right_finger
+ link4:
+ name: left_finger
+joints:
+ joint1:
+ name: hand_joint
+ type: fixed
+ parent: link1
+ child: link2
+ joint2:
+ name: finger_joint1
+ type: prismatic
+ parent: link2
+ child: link3
+ joint3:
+ name: finger_joint2
+ type: prismatic
+ parent: link2
+ child: link4
diff --git a/assets/robot/openarm_v1.0/mesh/arm/collision/link7_symp.stl b/assets/end_effector/parallel_link/meshes/collision/link7.stl
similarity index 100%
rename from assets/robot/openarm_v1.0/mesh/arm/collision/link7_symp.stl
rename to assets/end_effector/parallel_link/meshes/collision/link7.stl
diff --git a/assets/robot/openarm_v1.0/mesh/arm/visual/link7.dae b/assets/end_effector/parallel_link/meshes/visual/link7.dae
similarity index 100%
rename from assets/robot/openarm_v1.0/mesh/arm/visual/link7.dae
rename to assets/end_effector/parallel_link/meshes/visual/link7.dae
diff --git a/assets/robot/openarm_v1.0/mesh/arm/visual/link7.stl b/assets/end_effector/parallel_link/meshes/visual/link7.stl
similarity index 100%
rename from assets/robot/openarm_v1.0/mesh/arm/visual/link7.stl
rename to assets/end_effector/parallel_link/meshes/visual/link7.stl
diff --git a/assets/end_effector/parallel_link/urdf/parallel_link_standalone.urdf.xacro b/assets/end_effector/parallel_link/urdf/parallel_link_standalone.urdf.xacro
index 21416084..21975c29 100644
--- a/assets/end_effector/parallel_link/urdf/parallel_link_standalone.urdf.xacro
+++ b/assets/end_effector/parallel_link/urdf/parallel_link_standalone.urdf.xacro
@@ -13,27 +13,27 @@ limitations under the License.
-->
-
-
-
-
+
-
+
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/assets/end_effector/pinch_gripper/config/inertials/nominal.yaml b/assets/end_effector/pinch_gripper/config/inertials/nominal.yaml
index 6bfd2f4b..05ebfae2 100644
--- a/assets/end_effector/pinch_gripper/config/inertials/nominal.yaml
+++ b/assets/end_effector/pinch_gripper/config/inertials/nominal.yaml
@@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-ee_base_link:
+link1:
origin:
x: -0.0067098
y: 0.008407299999999999
@@ -28,7 +28,7 @@ ee_base_link:
yy: 0.00015627
yz: -1.5124e-06
zz: 0.0001659
-ee_link1:
+link2:
origin:
x: -0.0124990911725494
y: 0.00176592789915655
@@ -44,7 +44,7 @@ ee_link1:
yy: 3.62137424319396e-05
yz: -3.60343788693423e-06
zz: 1.74958961632907e-05
-ee_link2:
+link3:
origin:
x: -0.012796
y: -0.0020183
diff --git a/assets/end_effector/pinch_gripper/config/joint/joint_axes.yaml b/assets/end_effector/pinch_gripper/config/joint/joint_axes.yaml
index 13cc0ae1..c8d738fa 100644
--- a/assets/end_effector/pinch_gripper/config/joint/joint_axes.yaml
+++ b/assets/end_effector/pinch_gripper/config/joint/joint_axes.yaml
@@ -12,12 +12,12 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-finger_joint1:
+joint1:
axis:
x: -1
y: 0
z: 0
-finger_joint2:
+joint2:
axis:
x: 1
y: 0
diff --git a/assets/end_effector/pinch_gripper/config/joint/joint_limits.yaml b/assets/end_effector/pinch_gripper/config/joint/joint_limits.yaml
index 19942211..8dfc86de 100644
--- a/assets/end_effector/pinch_gripper/config/joint/joint_limits.yaml
+++ b/assets/end_effector/pinch_gripper/config/joint/joint_limits.yaml
@@ -12,13 +12,13 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-finger_joint1:
+joint1:
limit:
lower: -0.7854
upper: 0
effort: 7
velocity: 5
-finger_joint2:
+joint2:
limit:
lower: -0.7854
upper: 0
diff --git a/assets/end_effector/pinch_gripper/config/joint/joint_mimics.yaml b/assets/end_effector/pinch_gripper/config/joint/joint_mimics.yaml
index 1c0f9656..48434cde 100644
--- a/assets/end_effector/pinch_gripper/config/joint/joint_mimics.yaml
+++ b/assets/end_effector/pinch_gripper/config/joint/joint_mimics.yaml
@@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-finger_joint2:
- joint: finger_joint1
+joint2:
+ joint: joint1
multiplier: 1
offset: 0
diff --git a/assets/end_effector/pinch_gripper/config/joint/joint_origins.yaml b/assets/end_effector/pinch_gripper/config/joint/joint_origins.yaml
index cc5b65bf..da58c50f 100644
--- a/assets/end_effector/pinch_gripper/config/joint/joint_origins.yaml
+++ b/assets/end_effector/pinch_gripper/config/joint/joint_origins.yaml
@@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-finger_joint1:
+joint1:
origin:
x: -0.0219300000000005
y: 0.0180000000000009
@@ -20,7 +20,7 @@ finger_joint1:
roll: 0
pitch: -0
yaw: 0
-finger_joint2:
+joint2:
origin:
x: -0.0219300000000005
y: -0.0180000000000012
diff --git a/assets/end_effector/pinch_gripper/config/link/collisions.yaml b/assets/end_effector/pinch_gripper/config/link/collisions.yaml
index 2dfa0c8e..1f4d4c1b 100644
--- a/assets/end_effector/pinch_gripper/config/link/collisions.yaml
+++ b/assets/end_effector/pinch_gripper/config/link/collisions.yaml
@@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-ee_base_link:
+link1:
origin:
x: 0
y: 0
@@ -26,7 +26,7 @@ ee_base_link:
x: 1
y: 1
z: 1
-ee_link1:
+link2:
origin:
x: 0
y: 0
@@ -40,7 +40,7 @@ ee_link1:
x: 1
y: 1
z: 1
-ee_link2:
+link3:
origin:
x: 0
y: 0
diff --git a/assets/end_effector/pinch_gripper/config/link/visuals.yaml b/assets/end_effector/pinch_gripper/config/link/visuals.yaml
index d6669034..144aca0d 100644
--- a/assets/end_effector/pinch_gripper/config/link/visuals.yaml
+++ b/assets/end_effector/pinch_gripper/config/link/visuals.yaml
@@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-ee_base_link:
+link1:
origin:
x: 0
y: 0
@@ -26,7 +26,7 @@ ee_base_link:
x: 1
y: 1
z: 1
-ee_link1:
+link2:
origin:
x: 0
y: 0
@@ -40,7 +40,7 @@ ee_link1:
x: 1
y: 1
z: 1
-ee_link2:
+link3:
origin:
x: 0
y: 0
diff --git a/assets/end_effector/pinch_gripper/config/struct/name_mapping.yaml b/assets/end_effector/pinch_gripper/config/struct/name_mapping.yaml
index 84555f5c..b6300337 100644
--- a/assets/end_effector/pinch_gripper/config/struct/name_mapping.yaml
+++ b/assets/end_effector/pinch_gripper/config/struct/name_mapping.yaml
@@ -14,17 +14,17 @@
links:
canonical_to_original:
- ee_base_link: ee_base_link
- ee_link1: finger_inner
- ee_link2: finger_outer
+ link1: ee_base_link
+ link2: finger_inner
+ link3: finger_outer
original_to_canonical:
- ee_base_link: ee_base_link
- finger_inner: ee_link1
- finger_outer: ee_link2
+ ee_base_link: link1
+ finger_inner: link2
+ finger_outer: link3
joints:
canonical_to_original:
- finger_joint1: finger_inner_joint
- finger_joint2: finger_outer_joint
+ joint1: finger_inner_joint
+ joint2: finger_outer_joint
original_to_canonical:
- finger_inner_joint: finger_joint1
- finger_outer_joint: finger_joint2
+ finger_inner_joint: joint1
+ finger_outer_joint: joint2
diff --git a/assets/end_effector/pinch_gripper/config/struct/reference_points.yaml b/assets/end_effector/pinch_gripper/config/struct/reference_points.yaml
index e3cbf358..51344d31 100644
--- a/assets/end_effector/pinch_gripper/config/struct/reference_points.yaml
+++ b/assets/end_effector/pinch_gripper/config/struct/reference_points.yaml
@@ -13,7 +13,7 @@
# limitations under the License.
grasp_frame:
- parent: ee_base_link
+ parent: link1
origin:
x: -0.0219300000000009
y: 0
@@ -29,13 +29,13 @@ grasp_frame:
type: fixed
parent_link:
original_name: ee_base_link
- canonical_name: ee_base_link
+ canonical_name: link1
child_link:
original_name: grasp_frame
canonical_name: null
camera_view_frame:
- parent: ee_base_link
+ parent: link1
emit: true
origin:
x: 0.0013353
diff --git a/assets/end_effector/pinch_gripper/config/struct/topology.yaml b/assets/end_effector/pinch_gripper/config/struct/topology.yaml
index 9b3784e2..ff2863cb 100644
--- a/assets/end_effector/pinch_gripper/config/struct/topology.yaml
+++ b/assets/end_effector/pinch_gripper/config/struct/topology.yaml
@@ -13,15 +13,20 @@
# limitations under the License.
links:
-- ee_base_link
-- ee_link1
-- ee_link2
+ link1:
+ name: ee_base_link
+ link2:
+ name: ee_link1
+ link3:
+ name: ee_link2
joints:
- finger_joint1:
+ joint1:
+ name: finger_joint1
type: revolute
- parent: ee_base_link
- child: ee_link1
- finger_joint2:
+ parent: link1
+ child: link2
+ joint2:
+ name: finger_joint2
type: revolute
- parent: ee_base_link
- child: ee_link2
+ parent: link1
+ child: link3
diff --git a/assets/end_effector/pinch_gripper/urdf/component.xacro b/assets/end_effector/pinch_gripper/urdf/component.xacro
index 4c130677..62f9ea4a 100644
--- a/assets/end_effector/pinch_gripper/urdf/component.xacro
+++ b/assets/end_effector/pinch_gripper/urdf/component.xacro
@@ -28,6 +28,8 @@ limitations under the License.
+ params="prefix connected_to mount_origin:=none topology link_name_map joint_name_map joint_origins joint_axes joint_limits joint_mimics inertials visuals collisions reflect_x:=1 reflect_y:=1 reflect_z:=1 component_reflects:=false reflect_include_links:=^ reflect_include_joints:=^ reflect_include_reference_points:=^ origin_override_joints:=${dict()} limit_override_joints:=^ ee_reference_points:=^ emit_grasp_frame:=false grasp_reference_point:=grasp_frame skip_mount_joint:=false base_frame_shift:=none">
-
+
-
+
-
-
-
-
+
+
+
+
@@ -44,8 +44,8 @@ limitations under the License.
-
-
+
+
-
+
-
-
+
+
@@ -139,15 +139,15 @@ limitations under the License.
-
+
-
-
+
+
@@ -164,6 +164,7 @@ limitations under the License.
reference_points="${ee_reference_points}"
force_emit_reference="${grasp_reference_point if emit_grasp_frame else ''}"
prefix="${prefix}"
+ link_name_map="${link_name_map}"
base_link_name="${base_link_name}"
reflect_x="${reflect_x if component_reflects else 1}"
reflect_y="${reflect_y if component_reflects else 1}"
diff --git a/assets/robot/openarm_v1.0/config/arm/control_gains.yaml b/assets/robot/openarm_v1.0/config/arm/control/control_gains.yaml
similarity index 99%
rename from assets/robot/openarm_v1.0/config/arm/control_gains.yaml
rename to assets/robot/openarm_v1.0/config/arm/control/control_gains.yaml
index 54452fd7..a89644b9 100644
--- a/assets/robot/openarm_v1.0/config/arm/control_gains.yaml
+++ b/assets/robot/openarm_v1.0/config/arm/control/control_gains.yaml
@@ -15,31 +15,24 @@
joint1:
kp: 70.0
kd: 2.75
-
joint2:
kp: 70.0
kd: 2.5
-
joint3:
kp: 70.0
kd: 2.0
-
joint4:
kp: 60.0
kd: 2.0
-
joint5:
kp: 10.0
kd: 0.7
-
joint6:
kp: 10.0
kd: 0.6
-
joint7:
kp: 10.0
kd: 0.5
-
hand:
kp: 5.0
kd: 0.1
diff --git a/assets/robot/openarm_v1.0/config/arm/inertials.yaml b/assets/robot/openarm_v1.0/config/arm/inertials/nominal.yaml
similarity index 84%
rename from assets/robot/openarm_v1.0/config/arm/inertials.yaml
rename to assets/robot/openarm_v1.0/config/arm/inertials/nominal.yaml
index b743b66a..e55e924d 100644
--- a/assets/robot/openarm_v1.0/config/arm/inertials.yaml
+++ b/assets/robot/openarm_v1.0/config/arm/inertials/nominal.yaml
@@ -1,4 +1,4 @@
-# Copyright 2025 Enactic, Inc.
+# Copyright 2026 Enactic, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-link0:
+link1:
origin:
x: -0.0009483362816297526
y: 0.0001580207020448382
@@ -28,8 +28,7 @@ link0:
yy: 0.000962
yz: -7.0e-06
zz: 0.00147
-
-link1:
+link2:
origin:
x: 0.0011467657911800769
y: 3.319987657026362e-05
@@ -43,10 +42,9 @@ link1:
xy: -1.0e-06
xz: -2.9e-05
yy: 0.001273
- yz: 1e-06
+ yz: 1.0e-06
zz: 0.001016
-
-link2:
+link3:
origin:
x: 0.00839629182351943
y: -2.0145102027597523e-08
@@ -57,13 +55,12 @@ link2:
mass: 0.2775092746011571
inertia:
xx: 0.000359
- xy: 1e-06
+ xy: 1.0e-06
xz: -0.000109
yy: 0.000376
- yz: 1e-06
+ yz: 1.0e-06
zz: 0.000232
-
-link3:
+link4:
origin:
x: -0.002104752099628911
y: 0.0005549085042607548
@@ -74,13 +71,12 @@ link3:
mass: 1.073863338202347
inertia:
xx: 0.004372
- xy: 1e-06
+ xy: 1.0e-06
xz: 1.1e-05
yy: 0.004319
yz: -3.6e-05
zz: 0.000661
-
-link4:
+link5:
origin:
x: -0.0029006831074562967
y: -0.03030575826634669
@@ -96,8 +92,7 @@ link4:
yy: 0.000511
yz: 3.8e-05
zz: 0.000334
-
-link5:
+link6:
origin:
x: -0.003049665024221911
y: 0.0008866902457326625
@@ -113,8 +108,7 @@ link5:
yy: 0.000445
yz: -6.0e-06
zz: 0.000324
-
-link6:
+link7:
origin:
x: -0.037136587005447405
y: 0.00033230528343419053
@@ -125,25 +119,8 @@ link6:
mass: 0.475202773187987
inertia:
xx: 0.000143
- xy: 1e-06
- xz: 1e-06
+ xy: 1.0e-06
+ xz: 1.0e-06
yy: 0.000157
- yz: 1e-06
+ yz: 1.0e-06
zz: 0.000159
-
-link7:
- origin:
- x: -9.897454675528511e-05
- y: 0.003372444724450437
- z: 0.06138919729233123
- roll: 0
- pitch: 0
- yaw: 0
- mass: 0.4054971268153967
- inertia:
- xx: 0.0003637830920674498
- yy: 0.0003351190950225729
- zz: 0.0001865112723189818
- xy: 0
- xz: 0
- yz: 7.094884219324384e-05
diff --git a/assets/end_effector/parallel_link/config/kinematics_link.yaml b/assets/robot/openarm_v1.0/config/arm/joint/joint_axes.yaml
similarity index 63%
rename from assets/end_effector/parallel_link/config/kinematics_link.yaml
rename to assets/robot/openarm_v1.0/config/arm/joint/joint_axes.yaml
index d6cee252..8eb1b089 100644
--- a/assets/end_effector/parallel_link/config/kinematics_link.yaml
+++ b/assets/robot/openarm_v1.0/config/arm/joint/joint_axes.yaml
@@ -12,29 +12,38 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-hand:
- kinematic:
- x: 0.0
- y: 0.0
- z: -0.6586
- roll: 0.0
- pitch: 0.0
- yaw: 0.0
-
-left_finger:
- kinematic:
- x: 0.0
- y: -0.05
- z: -0.673001
- roll: 0.0
- pitch: 0.0
- yaw: 0.0
-
-right_finger:
- kinematic:
- x: 0.0
- y: 0.05
- z: -0.673001
- roll: 0.0
- pitch: 0.0
- yaw: 3.141592653589793
+joint1:
+ axis:
+ x: 0
+ y: 0
+ z: 1
+joint2:
+ axis:
+ x: -1
+ y: 0
+ z: 0
+joint3:
+ axis:
+ x: 0
+ y: 0
+ z: 1
+joint4:
+ axis:
+ x: 0
+ y: 1
+ z: 0
+joint5:
+ axis:
+ x: 0
+ y: 0
+ z: 1
+joint6:
+ axis:
+ x: 1
+ y: 0
+ z: 0
+joint7:
+ axis:
+ x: 0
+ y: 1
+ z: 0
diff --git a/assets/robot/openarm_v1.0/config/arm/joint_limits.yaml b/assets/robot/openarm_v1.0/config/arm/joint/joint_limits.yaml
similarity index 83%
rename from assets/robot/openarm_v1.0/config/arm/joint_limits.yaml
rename to assets/robot/openarm_v1.0/config/arm/joint/joint_limits.yaml
index 3b157b1a..ed1cb087 100644
--- a/assets/robot/openarm_v1.0/config/arm/joint_limits.yaml
+++ b/assets/robot/openarm_v1.0/config/arm/joint/joint_limits.yaml
@@ -1,4 +1,4 @@
-# Copyright 2025 Enactic, Inc.
+# Copyright 2026 Enactic, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -18,59 +18,39 @@ joint1:
upper: 3.490659
velocity: 16.754666
effort: 40
-
joint2:
limit:
lower: -1.745329
upper: 1.745329
velocity: 16.754666
effort: 40
-
joint3:
limit:
lower: -1.570796
upper: 1.570796
velocity: 5.445426
effort: 27
-
joint4:
limit:
lower: 0.0
upper: 2.443461
velocity: 5.445426
effort: 27
-
joint5:
limit:
lower: -1.570796
upper: 1.570796
velocity: 20.943946
effort: 7
-
joint6:
limit:
lower: -0.785398
upper: 0.785398
velocity: 20.943946
effort: 7
-
joint7:
limit:
lower: -1.570796
upper: 1.570796
velocity: 20.943946
effort: 7
-
-# joint_gripper1:
-# limit:
-# lower: 0.0
-# upper: 0.043
-# velocity: 100
-# effort: 100
-
-# joint_gripper2:
-# limit:
-# lower: 0.0
-# upper: 0.043
-# velocity: 100
-# effort: 100
diff --git a/assets/robot/openarm_v1.0/config/arm/kinematics.yaml b/assets/robot/openarm_v1.0/config/arm/joint/joint_origins.yaml
similarity index 70%
rename from assets/robot/openarm_v1.0/config/arm/kinematics.yaml
rename to assets/robot/openarm_v1.0/config/arm/joint/joint_origins.yaml
index e6c4df4c..97878685 100644
--- a/assets/robot/openarm_v1.0/config/arm/kinematics.yaml
+++ b/assets/robot/openarm_v1.0/config/arm/joint/joint_origins.yaml
@@ -1,4 +1,4 @@
-# Copyright 2025 Enactic, Inc.
+# Copyright 2026 Enactic, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -13,91 +13,58 @@
# limitations under the License.
joint1:
- kinematic:
+ origin:
x: 0.0
y: 0.0
z: 0.0625
roll: 0
pitch: 0
yaw: 0
-
joint2:
- kinematic:
+ origin:
x: -0.0301
y: 0.0
z: 0.06
roll: 0
pitch: 0
yaw: 0
-
joint3:
- kinematic:
+ origin:
x: 0.0301
y: 0.0
z: 0.06625
roll: 0
pitch: 0
yaw: 0
-
joint4:
- kinematic:
- x: -0.0
+ origin:
+ x: 0.0
y: 0.0315
z: 0.15375
roll: 0
pitch: 0
yaw: 0
-
joint5:
- kinematic:
+ origin:
x: 0.0
y: -0.0315
z: 0.0955
roll: 0
pitch: 0
yaw: 0
-
joint6:
- kinematic:
+ origin:
x: 0.0375
y: 0.0
z: 0.1205
roll: 0
pitch: 0
yaw: 0
-
-# joint7:
-# kinematic:
-# x: -0.0375
-# y: 0.0205
-# z: 0.0
-# roll: 0
-# pitch: 0
-# yaw: 0
-
joint7:
- kinematic:
+ origin:
x: -0.0375
y: 0.0
z: 0.0
roll: 0
pitch: 0
yaw: 0
-
-# joint8:
-# kinematic:
-# x: 1e-06
-# y: -0.098
-# z: 0.114501
-# roll: 0
-# pitch: 0
-# yaw: 0
-
-joint8:
- kinematic:
- x: 1e-06
- y: 0.0205
- z: 0.0
- roll: 0
- pitch: 0
- yaw: 0
diff --git a/assets/robot/openarm_v1.0/config/arm/kinematics_link.yaml b/assets/robot/openarm_v1.0/config/arm/kinematics_link.yaml
deleted file mode 100644
index f31da1b3..00000000
--- a/assets/robot/openarm_v1.0/config/arm/kinematics_link.yaml
+++ /dev/null
@@ -1,94 +0,0 @@
-# Copyright 2025 Enactic, Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-link0:
- kinematic:
- x: 0.0
- y: 0.0
- z: 0.0
- roll: 0.0
- pitch: 0.0
- yaw: 0.0
-
-link1:
- kinematic:
- x: -0.0
- y: 0.0
- z: -0.0625
- roll: 0.0
- pitch: 0.0
- yaw: 0.0
-
-link2:
- kinematic:
- x: 0.0301
- y: 0.0
- z: -0.1225
- roll: 0.0
- pitch: 0.0
- yaw: 0.0
-
-link3:
- kinematic:
- x: -0.0
- y: -0.0
- z: -0.18875
- roll: 0.0
- pitch: 0.0
- yaw: 0.0
-
-link4:
- kinematic:
- x: 0.0
- y: -0.0315
- z: -0.3425
- roll: 0.0
- pitch: 0.0
- yaw: 0.0
-
-link5:
- kinematic:
- x: -0.0
- y: -0.0
- z: -0.438
- roll: 0.0
- pitch: 0.0
- yaw: 0.0
-
-link6:
- kinematic:
- x: -0.0375
- y: -0.0
- z: -0.5585
- roll: 0.0
- pitch: 0.0
- yaw: 0.0
-
-# link7:
-# kinematic:
-# x: 0.0
-# y: -0.0205
-# z: -0.5585
-# roll: 0.0
-# pitch: 0.0
-# yaw: 0.0
-
-link7:
- kinematic:
- x: 0.0
- y: -0.0
- z: -0.5585
- roll: 0.0
- pitch: 0.0
- yaw: 0.0
diff --git a/assets/robot/openarm_v1.0/config/arm/kinematics_offset.yaml b/assets/robot/openarm_v1.0/config/arm/kinematics_offset.yaml
deleted file mode 100644
index 315720bb..00000000
--- a/assets/robot/openarm_v1.0/config/arm/kinematics_offset.yaml
+++ /dev/null
@@ -1,85 +0,0 @@
-# Copyright 2025 Enactic, Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-joint1:
- kinematic_offset:
- x: 0.0
- y: 0.0
- z: 0.0
- roll: 0
- pitch: 0
- yaw: 0
-
-joint2:
- kinematic_offset:
- x: 0.0
- y: 0.0
- z: 0.0
- roll: 1.57079632679
- pitch: 0
- yaw: 0
-
-joint3:
- kinematic_offset:
- x: 0.0
- y: 0.0
- z: 0.0
- roll: 0
- pitch: 0
- yaw: 0
-
-joint4:
- kinematic_offset:
- x: -0.0
- y: 0.0
- z: 0.0
- roll: 0
- pitch: 0
- yaw: 0
-
-joint5:
- kinematic_offset:
- x: 0.0
- y: -0.0
- z: 0.0
- roll: 0
- pitch: 0
- yaw: 0
-
-joint6:
- kinematic_offset:
- x: 0.0
- y: 0.0
- z: 0.0
- roll: 0
- pitch: 0
- yaw: 0
-
-joint7:
- kinematic_offset:
- x: -0.0
- y: 0.0
- z: 0.0
- roll: 0
- pitch: 0
- yaw: 0
-
-joint8:
- kinematic_offset:
- x: 0.0
- y: -0.0
- z: 0.0
- roll: 0
- pitch: 0
- yaw: 0
diff --git a/assets/robot/openarm_v1.0/config/arm/link/collisions.yaml b/assets/robot/openarm_v1.0/config/arm/link/collisions.yaml
new file mode 100644
index 00000000..f2860d07
--- /dev/null
+++ b/assets/robot/openarm_v1.0/config/arm/link/collisions.yaml
@@ -0,0 +1,112 @@
+# Copyright 2026 Enactic, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+link1:
+ origin:
+ x: 0.0
+ y: 0.0
+ z: 0.0
+ roll: 0.0
+ pitch: 0.0
+ yaw: 0.0
+ geometry:
+ mesh: package://openarm_description/assets/robot/openarm_v1.0/mesh/arm/collision/link0_symp.stl
+ scale:
+ x: 0.001
+ y: 0.001
+ z: 0.001
+link2:
+ origin:
+ x: -0.0
+ y: 0.0
+ z: -0.0625
+ roll: 0.0
+ pitch: 0.0
+ yaw: 0.0
+ geometry:
+ mesh: package://openarm_description/assets/robot/openarm_v1.0/mesh/arm/collision/link1_symp.stl
+ scale:
+ x: 0.001
+ y: 0.001
+ z: 0.001
+link3:
+ origin:
+ x: 0.0301
+ y: 0.0
+ z: -0.1225
+ roll: 0.0
+ pitch: 0.0
+ yaw: 0.0
+ geometry:
+ mesh: package://openarm_description/assets/robot/openarm_v1.0/mesh/arm/collision/link2_symp.stl
+ scale:
+ x: 0.001
+ y: 0.001
+ z: 0.001
+link4:
+ origin:
+ x: -0.0
+ y: -0.0
+ z: -0.18875
+ roll: 0.0
+ pitch: 0.0
+ yaw: 0.0
+ geometry:
+ mesh: package://openarm_description/assets/robot/openarm_v1.0/mesh/arm/collision/link3_symp.stl
+ scale:
+ x: 0.001
+ y: 0.001
+ z: 0.001
+link5:
+ origin:
+ x: 0.0
+ y: -0.0315
+ z: -0.3425
+ roll: 0.0
+ pitch: 0.0
+ yaw: 0.0
+ geometry:
+ mesh: package://openarm_description/assets/robot/openarm_v1.0/mesh/arm/collision/link4_symp.stl
+ scale:
+ x: 0.001
+ y: 0.001
+ z: 0.001
+link6:
+ origin:
+ x: -0.0
+ y: -0.0
+ z: -0.438
+ roll: 0.0
+ pitch: 0.0
+ yaw: 0.0
+ geometry:
+ mesh: package://openarm_description/assets/robot/openarm_v1.0/mesh/arm/collision/link5_symp.stl
+ scale:
+ x: 0.001
+ y: 0.001
+ z: 0.001
+link7:
+ origin:
+ x: -0.0375
+ y: 0.0
+ z: -0.5585
+ roll: 0.0
+ pitch: 0.0
+ yaw: 0.0
+ geometry:
+ mesh: package://openarm_description/assets/robot/openarm_v1.0/mesh/arm/collision/link6_symp.stl
+ scale:
+ x: 0.001
+ y: 0.001
+ z: 0.001
diff --git a/assets/robot/openarm_v1.0/config/arm/link/visuals.yaml b/assets/robot/openarm_v1.0/config/arm/link/visuals.yaml
new file mode 100644
index 00000000..2e09913f
--- /dev/null
+++ b/assets/robot/openarm_v1.0/config/arm/link/visuals.yaml
@@ -0,0 +1,112 @@
+# Copyright 2026 Enactic, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+link1:
+ origin:
+ x: 0.0
+ y: 0.0
+ z: 0.0
+ roll: 0.0
+ pitch: 0.0
+ yaw: 0.0
+ geometry:
+ mesh: package://openarm_description/assets/robot/openarm_v1.0/mesh/arm/visual/link0.dae
+ scale:
+ x: 0.001
+ y: 0.001
+ z: 0.001
+link2:
+ origin:
+ x: -0.0
+ y: 0.0
+ z: -0.0625
+ roll: 0.0
+ pitch: 0.0
+ yaw: 0.0
+ geometry:
+ mesh: package://openarm_description/assets/robot/openarm_v1.0/mesh/arm/visual/link1.dae
+ scale:
+ x: 0.001
+ y: 0.001
+ z: 0.001
+link3:
+ origin:
+ x: 0.0301
+ y: 0.0
+ z: -0.1225
+ roll: 0.0
+ pitch: 0.0
+ yaw: 0.0
+ geometry:
+ mesh: package://openarm_description/assets/robot/openarm_v1.0/mesh/arm/visual/link2.dae
+ scale:
+ x: 0.001
+ y: 0.001
+ z: 0.001
+link4:
+ origin:
+ x: -0.0
+ y: -0.0
+ z: -0.18875
+ roll: 0.0
+ pitch: 0.0
+ yaw: 0.0
+ geometry:
+ mesh: package://openarm_description/assets/robot/openarm_v1.0/mesh/arm/visual/link3.dae
+ scale:
+ x: 0.001
+ y: 0.001
+ z: 0.001
+link5:
+ origin:
+ x: 0.0
+ y: -0.0315
+ z: -0.3425
+ roll: 0.0
+ pitch: 0.0
+ yaw: 0.0
+ geometry:
+ mesh: package://openarm_description/assets/robot/openarm_v1.0/mesh/arm/visual/link4.dae
+ scale:
+ x: 0.001
+ y: 0.001
+ z: 0.001
+link6:
+ origin:
+ x: -0.0
+ y: -0.0
+ z: -0.438
+ roll: 0.0
+ pitch: 0.0
+ yaw: 0.0
+ geometry:
+ mesh: package://openarm_description/assets/robot/openarm_v1.0/mesh/arm/visual/link5.dae
+ scale:
+ x: 0.001
+ y: 0.001
+ z: 0.001
+link7:
+ origin:
+ x: -0.0375
+ y: 0.0
+ z: -0.5585
+ roll: 0.0
+ pitch: 0.0
+ yaw: 0.0
+ geometry:
+ mesh: package://openarm_description/assets/robot/openarm_v1.0/mesh/arm/visual/link6.dae
+ scale:
+ x: 0.001
+ y: 0.001
+ z: 0.001
diff --git a/assets/robot/openarm_v1.0/config/arm/struct/name_mapping.yaml b/assets/robot/openarm_v1.0/config/arm/struct/name_mapping.yaml
new file mode 100644
index 00000000..d7f87fa7
--- /dev/null
+++ b/assets/robot/openarm_v1.0/config/arm/struct/name_mapping.yaml
@@ -0,0 +1,33 @@
+# Copyright 2026 Enactic, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+links:
+ canonical_to_original:
+ link1: link0
+ link2: link1
+ link3: link2
+ link4: link3
+ link5: link4
+ link6: link5
+ link7: link6
+ link8: arm_end_link
+joints:
+ canonical_to_original:
+ joint1: joint1
+ joint2: joint2
+ joint3: joint3
+ joint4: joint4
+ joint5: joint5
+ joint6: joint6
+ joint7: joint7
diff --git a/assets/robot/openarm_v1.0/config/arm/struct/reference_points.yaml b/assets/robot/openarm_v1.0/config/arm/struct/reference_points.yaml
new file mode 100644
index 00000000..1f6d008b
--- /dev/null
+++ b/assets/robot/openarm_v1.0/config/arm/struct/reference_points.yaml
@@ -0,0 +1,24 @@
+# Copyright 2026 Enactic, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+ee_mount_point:
+ parent: link8
+ emit: false
+ origin:
+ x: 0
+ y: 0
+ z: 0
+ roll: 0
+ pitch: 0
+ yaw: 0
diff --git a/assets/robot/openarm_v1.0/config/arm/struct/topology.yaml b/assets/robot/openarm_v1.0/config/arm/struct/topology.yaml
new file mode 100644
index 00000000..dd54172a
--- /dev/null
+++ b/assets/robot/openarm_v1.0/config/arm/struct/topology.yaml
@@ -0,0 +1,61 @@
+# Copyright 2026 Enactic, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+collapse_empty_end: true
+links:
+ link1:
+ name: link0
+ link2:
+ name: link1
+ link3:
+ name: link2
+ link4:
+ name: link3
+ link5:
+ name: link4
+ link6:
+ name: link5
+ link7:
+ name: link6
+ link8:
+ name: arm_end_link
+joints:
+ joint1:
+ type: revolute
+ parent: link1
+ child: link2
+ joint2:
+ type: revolute
+ parent: link2
+ child: link3
+ joint3:
+ type: revolute
+ parent: link3
+ child: link4
+ joint4:
+ type: revolute
+ parent: link4
+ child: link5
+ joint5:
+ type: revolute
+ parent: link5
+ child: link6
+ joint6:
+ type: revolute
+ parent: link6
+ child: link7
+ joint7:
+ type: revolute
+ parent: link7
+ child: link8
diff --git a/assets/robot/openarm_v1.0/config/robot_presets/default_bimanual.yaml b/assets/robot/openarm_v1.0/config/robot_presets/default_bimanual.yaml
new file mode 100644
index 00000000..133b9e0f
--- /dev/null
+++ b/assets/robot/openarm_v1.0/config/robot_presets/default_bimanual.yaml
@@ -0,0 +1,174 @@
+# Copyright 2026 Enactic, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+robot:
+ root_frame: world
+ components:
+ - body
+ - primary_arm
+ - secondary_arm
+ - primary_arm_end_effector
+ - secondary_arm_end_effector
+body:
+ type: body
+ prefix: openarm_
+ enabled: true
+ product: v1.0
+ config: null
+ inertials: nominal
+ connection:
+ parent: world
+ origin:
+ x: 0
+ y: 0
+ z: 0
+ roll: 0
+ pitch: 0
+ yaw: 0
+primary_arm:
+ type: robot
+ enabled: true
+ product: openarm_v1.0
+ config: arm
+ inertials: nominal
+ prefix: openarm_left_
+ connection:
+ attach_to: body
+ parent_reference_point: left_arm_mount_point
+ reflect:
+ x: 1
+ y: -1
+ z: 1
+ include:
+ links:
+ - link1
+ - link2
+ - link3
+ - link6
+ - link7
+ - link8
+ joints:
+ - joint1
+ - joint2
+ - joint3
+ - joint6
+ - joint7
+ reference_points:
+ - ee_mount_point
+ origin_override_joints:
+ joint2:
+ x: -0.0301
+ y: 0.0
+ z: 0.06
+ roll: 1.57079632679
+ pitch: 0
+ yaw: 0
+ limit_override_joints:
+ joint2:
+ lower: -0.17453267320510335
+ upper: 3.3161253267948965
+ velocity: 16.754666
+ effort: 40
+primary_arm_end_effector:
+ type: end_effector
+ enabled: true
+ product: parallel_link
+ config: null
+ inertials: nominal
+ prefix: openarm_left_
+ connection:
+ attach_to: primary_arm
+ parent_reference_point: ee_mount_point
+ reflect:
+ x: 1
+ y: -1
+ z: 1
+ include:
+ links:
+ - link1
+ joints: []
+ reference_points: []
+secondary_arm:
+ type: robot
+ enabled: true
+ product: openarm_v1.0
+ config: arm
+ inertials: nominal
+ prefix: openarm_right_
+ connection:
+ attach_to: body
+ parent_reference_point: right_arm_mount_point
+ reflect:
+ x: 1
+ y: 1
+ z: 1
+ origin_override_joints:
+ joint2:
+ x: -0.0301
+ y: 0.0
+ z: 0.06
+ roll: 1.57079632679
+ pitch: 0
+ yaw: 0
+ limit_override_joints:
+ joint2:
+ lower: -0.17453267320510335
+ upper: 3.3161253267948965
+ velocity: 16.754666
+ effort: 40
+secondary_arm_end_effector:
+ type: end_effector
+ enabled: true
+ product: parallel_link
+ config: null
+ inertials: nominal
+ prefix: openarm_right_
+ connection:
+ attach_to: secondary_arm
+ parent_reference_point: ee_mount_point
+ reflect:
+ x: 1
+ y: 1
+ z: 1
+ include:
+ links:
+ - link1
+ joints: []
+ reference_points: []
+
+systems:
+ openarm_left_hardware_interface:
+ joints:
+ primary_arm:
+ joint1: {idx: 1}
+ joint2: {idx: 2}
+ joint3: {idx: 3}
+ joint4: {idx: 4}
+ joint5: {idx: 5}
+ joint6: {idx: 6}
+ joint7: {idx: 7}
+ primary_arm_end_effector:
+ joint2: {idx: 8}
+ openarm_right_hardware_interface:
+ joints:
+ secondary_arm:
+ joint1: {idx: 1}
+ joint2: {idx: 2}
+ joint3: {idx: 3}
+ joint4: {idx: 4}
+ joint5: {idx: 5}
+ joint6: {idx: 6}
+ joint7: {idx: 7}
+ secondary_arm_end_effector:
+ joint2: {idx: 8}
diff --git a/assets/robot/openarm_v1.0/config/robot_presets/default_single.yaml b/assets/robot/openarm_v1.0/config/robot_presets/default_single.yaml
new file mode 100644
index 00000000..64ac1654
--- /dev/null
+++ b/assets/robot/openarm_v1.0/config/robot_presets/default_single.yaml
@@ -0,0 +1,72 @@
+# Copyright 2026 Enactic, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+robot:
+ root_frame: world
+ components:
+ - arm
+ - end_effector
+arm:
+ type: robot
+ enabled: true
+ product: openarm_v1.0
+ config: arm
+ inertials: nominal
+ prefix: openarm_
+ connection:
+ parent: world
+ origin:
+ x: 0
+ y: 0
+ z: 0
+ roll: 0
+ pitch: 0
+ yaw: 0
+ reflect:
+ x: 1
+ y: 1
+ z: 1
+end_effector:
+ type: end_effector
+ enabled: true
+ product: parallel_link
+ config: null
+ inertials: nominal
+ prefix: openarm_
+ connection:
+ attach_to: arm
+ parent_reference_point: ee_mount_point
+ reflect:
+ x: 1
+ y: 1
+ z: 1
+ include:
+ links:
+ - link1
+ joints: []
+ reference_points: []
+
+systems:
+ openarm_hardware_interface:
+ joints:
+ arm:
+ joint1: {idx: 1}
+ joint2: {idx: 2}
+ joint3: {idx: 3}
+ joint4: {idx: 4}
+ joint5: {idx: 5}
+ joint6: {idx: 6}
+ joint7: {idx: 7}
+ end_effector:
+ joint2: {idx: 8}
diff --git a/assets/robot/openarm_v1.0/config/robot_presets/left_arm.yaml b/assets/robot/openarm_v1.0/config/robot_presets/left_arm.yaml
new file mode 100644
index 00000000..3081a852
--- /dev/null
+++ b/assets/robot/openarm_v1.0/config/robot_presets/left_arm.yaml
@@ -0,0 +1,66 @@
+# Copyright 2026 Enactic, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+robot:
+ root_frame: world
+ components:
+ - arm
+arm:
+ type: robot
+ enabled: true
+ product: openarm_v1.0
+ config: arm
+ inertials: nominal
+ prefix: openarm_left_
+ connection:
+ parent: world
+ origin:
+ x: 0
+ y: 0
+ z: 0
+ roll: 0
+ pitch: 0
+ yaw: 0
+ reflect:
+ x: 1
+ y: -1
+ z: 1
+ include:
+ links:
+ - link1
+ - link2
+ - link3
+ - link6
+ - link7
+ - link8
+ joints:
+ - joint1
+ - joint2
+ - joint3
+ - joint6
+ - joint7
+ reference_points:
+ - ee_mount_point
+
+systems:
+ openarm_left_hardware_interface:
+ joints:
+ arm:
+ joint1: {idx: 1}
+ joint2: {idx: 2}
+ joint3: {idx: 3}
+ joint4: {idx: 4}
+ joint5: {idx: 5}
+ joint6: {idx: 6}
+ joint7: {idx: 7}
diff --git a/assets/robot/openarm_v1.0/config/robot_presets/left_arm_with_parallel_link.yaml b/assets/robot/openarm_v1.0/config/robot_presets/left_arm_with_parallel_link.yaml
new file mode 100644
index 00000000..003f55de
--- /dev/null
+++ b/assets/robot/openarm_v1.0/config/robot_presets/left_arm_with_parallel_link.yaml
@@ -0,0 +1,88 @@
+# Copyright 2026 Enactic, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+robot:
+ root_frame: world
+ components:
+ - arm
+ - end_effector
+arm:
+ type: robot
+ enabled: true
+ product: openarm_v1.0
+ config: arm
+ inertials: nominal
+ prefix: openarm_left_
+ connection:
+ parent: world
+ origin:
+ x: 0
+ y: 0
+ z: 0
+ roll: 0
+ pitch: 0
+ yaw: 0
+ reflect:
+ x: 1
+ y: -1
+ z: 1
+ include:
+ links:
+ - link1
+ - link2
+ - link3
+ - link6
+ - link7
+ - link8
+ joints:
+ - joint1
+ - joint2
+ - joint3
+ - joint6
+ - joint7
+ reference_points:
+ - ee_mount_point
+end_effector:
+ type: end_effector
+ enabled: true
+ product: parallel_link
+ config: null
+ inertials: nominal
+ prefix: openarm_left_
+ connection:
+ attach_to: arm
+ parent_reference_point: ee_mount_point
+ reflect:
+ x: 1
+ y: -1
+ z: 1
+ include:
+ links:
+ - link1
+ joints: []
+ reference_points: []
+
+systems:
+ openarm_left_hardware_interface:
+ joints:
+ arm:
+ joint1: {idx: 1}
+ joint2: {idx: 2}
+ joint3: {idx: 3}
+ joint4: {idx: 4}
+ joint5: {idx: 5}
+ joint6: {idx: 6}
+ joint7: {idx: 7}
+ end_effector:
+ joint2: {idx: 8}
diff --git a/assets/robot/openarm_v1.0/config/robot_presets/right_arm.yaml b/assets/robot/openarm_v1.0/config/robot_presets/right_arm.yaml
new file mode 100644
index 00000000..e4f0eddd
--- /dev/null
+++ b/assets/robot/openarm_v1.0/config/robot_presets/right_arm.yaml
@@ -0,0 +1,50 @@
+# Copyright 2026 Enactic, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+robot:
+ root_frame: world
+ components:
+ - arm
+arm:
+ type: robot
+ enabled: true
+ product: openarm_v1.0
+ config: arm
+ inertials: nominal
+ prefix: openarm_right_
+ connection:
+ parent: world
+ origin:
+ x: 0
+ y: 0
+ z: 0
+ roll: 0
+ pitch: 0
+ yaw: 0
+ reflect:
+ x: 1
+ y: 1
+ z: 1
+
+systems:
+ openarm_right_hardware_interface:
+ joints:
+ arm:
+ joint1: {idx: 1}
+ joint2: {idx: 2}
+ joint3: {idx: 3}
+ joint4: {idx: 4}
+ joint5: {idx: 5}
+ joint6: {idx: 6}
+ joint7: {idx: 7}
diff --git a/assets/robot/openarm_v1.0/config/robot_presets/right_arm_with_parallel_link.yaml b/assets/robot/openarm_v1.0/config/robot_presets/right_arm_with_parallel_link.yaml
new file mode 100644
index 00000000..132855e2
--- /dev/null
+++ b/assets/robot/openarm_v1.0/config/robot_presets/right_arm_with_parallel_link.yaml
@@ -0,0 +1,72 @@
+# Copyright 2026 Enactic, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+robot:
+ root_frame: world
+ components:
+ - arm
+ - end_effector
+arm:
+ type: robot
+ enabled: true
+ product: openarm_v1.0
+ config: arm
+ inertials: nominal
+ prefix: openarm_right_
+ connection:
+ parent: world
+ origin:
+ x: 0
+ y: 0
+ z: 0
+ roll: 0
+ pitch: 0
+ yaw: 0
+ reflect:
+ x: 1
+ y: 1
+ z: 1
+end_effector:
+ type: end_effector
+ enabled: true
+ product: parallel_link
+ config: null
+ inertials: nominal
+ prefix: openarm_right_
+ connection:
+ attach_to: arm
+ parent_reference_point: ee_mount_point
+ reflect:
+ x: 1
+ y: 1
+ z: 1
+ include:
+ links:
+ - link1
+ joints: []
+ reference_points: []
+
+systems:
+ openarm_right_hardware_interface:
+ joints:
+ arm:
+ joint1: {idx: 1}
+ joint2: {idx: 2}
+ joint3: {idx: 3}
+ joint4: {idx: 4}
+ joint5: {idx: 5}
+ joint6: {idx: 6}
+ joint7: {idx: 7}
+ end_effector:
+ joint2: {idx: 8}
diff --git a/assets/robot/openarm_v1.0/urdf/arm/openarm_arm.xacro b/assets/robot/openarm_v1.0/urdf/arm/openarm_arm.xacro
deleted file mode 100644
index 3567a9dc..00000000
--- a/assets/robot/openarm_v1.0/urdf/arm/openarm_arm.xacro
+++ /dev/null
@@ -1,123 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/assets/robot/openarm_v1.0/urdf/arm/openarm_macro.xacro b/assets/robot/openarm_v1.0/urdf/arm/openarm_macro.xacro
deleted file mode 100644
index ca530c7b..00000000
--- a/assets/robot/openarm_v1.0/urdf/arm/openarm_macro.xacro
+++ /dev/null
@@ -1,150 +0,0 @@
-
-
-
-
-
-
-
- ${xacro.warning('No inertia properties defined for: ' + name)}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- openarm_hw/openarmStateInterface
- openarm_hw/openarmStateInterface
- openarm_hw/openarmStateInterface
- openarm_hw/openarmStateInterface
- openarm_hw/openarmStateInterface
- openarm_hw/openarmStateInterface
- openarm_hw/openarmStateInterface
- openarm_hw/openarmStateInterface
-
- openarm_hw/openarmStateInterface
- openarm_hw/openarmStateInterface
- openarm_hw/openarmStateInterface
- openarm_hw/openarmStateInterface
- openarm_hw/openarmStateInterface
- openarm_hw/openarmStateInterface
- openarm_hw/openarmStateInterface
-
-
-
-
-
- openarm_hw/openarmModelInterface
-
- root
- openarm_hw/openarmModelInterface
-
-
- tip
- openarm_hw/openarmModelInterface
-
- openarm_hw/openarmModelInterface
- openarm_hw/openarmModelInterface
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/assets/robot/openarm_v1.0/urdf/body/openarm_body.xacro b/assets/robot/openarm_v1.0/urdf/body/openarm_body.xacro
deleted file mode 100644
index d3fada87..00000000
--- a/assets/robot/openarm_v1.0/urdf/body/openarm_body.xacro
+++ /dev/null
@@ -1,49 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/assets/robot/openarm_v1.0/urdf/body/openarm_body_macro.xacro b/assets/robot/openarm_v1.0/urdf/body/openarm_body_macro.xacro
deleted file mode 100644
index 3b200efa..00000000
--- a/assets/robot/openarm_v1.0/urdf/body/openarm_body_macro.xacro
+++ /dev/null
@@ -1,68 +0,0 @@
-
-
-
-
-
-
- ${xacro.warning('No inertia properties defined for: ' + name)}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/assets/robot/openarm_v1.0/urdf/ee/ee_dispatcher.xacro b/assets/robot/openarm_v1.0/urdf/ee/ee_dispatcher.xacro
deleted file mode 100644
index 7f811804..00000000
--- a/assets/robot/openarm_v1.0/urdf/ee/ee_dispatcher.xacro
+++ /dev/null
@@ -1,37 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
- ${xacro.error('assets/robot/openarm_v1.0 only supports ee_type:=parallel_link.')}
-
-
-
diff --git a/assets/robot/openarm_v1.0/urdf/ee/openarm_ee_macro.xacro b/assets/robot/openarm_v1.0/urdf/ee/openarm_ee_macro.xacro
deleted file mode 100644
index 425d08d2..00000000
--- a/assets/robot/openarm_v1.0/urdf/ee/openarm_ee_macro.xacro
+++ /dev/null
@@ -1,94 +0,0 @@
-
-
-
-
-
-
-
- ${xacro.warning('No inertia properties defined for: ' + name)}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/assets/robot/openarm_v1.0/urdf/ee/parallel_link/openarm_parallel_gripper.xacro b/assets/robot/openarm_v1.0/urdf/ee/parallel_link/openarm_parallel_gripper.xacro
deleted file mode 100644
index 6a00c3a2..00000000
--- a/assets/robot/openarm_v1.0/urdf/ee/parallel_link/openarm_parallel_gripper.xacro
+++ /dev/null
@@ -1,106 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/assets/robot/openarm_v1.0/urdf/ee/pinch_gripper/openarm_v20_pinch_gripper.xacro b/assets/robot/openarm_v1.0/urdf/ee/pinch_gripper/openarm_v20_pinch_gripper.xacro
deleted file mode 100644
index 6d366553..00000000
--- a/assets/robot/openarm_v1.0/urdf/ee/pinch_gripper/openarm_v20_pinch_gripper.xacro
+++ /dev/null
@@ -1,102 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/assets/robot/openarm_v1.0/urdf/example/v1.urdf b/assets/robot/openarm_v1.0/urdf/example/v1.urdf
index 7b8865cd..bec33afe 100644
--- a/assets/robot/openarm_v1.0/urdf/example/v1.urdf
+++ b/assets/robot/openarm_v1.0/urdf/example/v1.urdf
@@ -4,7 +4,7 @@
-
-
-
-
-
-
+
+
-
+
-
+
-
-
+
-
+
-
-
-
-
+
+
+
+
-
+
+
-
+
-
-
+
+
+
+
+
+
-
+
+
-
+
-
-
+
-
+
-
+
-
+
+
-
+
-
-
+
-
+
@@ -124,6 +124,7 @@ limitations under the License.
+
@@ -132,7 +133,6 @@ limitations under the License.
-
@@ -142,7 +142,7 @@ limitations under the License.
-
+
@@ -151,6 +151,7 @@ limitations under the License.
+
@@ -159,7 +160,6 @@ limitations under the License.
-
@@ -169,7 +169,7 @@ limitations under the License.
-
+
@@ -177,20 +177,20 @@ limitations under the License.
-
+
+
-
+
-
-
+
@@ -204,66 +204,148 @@ limitations under the License.
-
+
+
-
+
-
-
+
-
+
+
+
+
+
+
+
+
-
+
+
-
+
-
+
-
-
+
-
+
-
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -272,7 +354,6 @@ limitations under the License.
-
@@ -281,9 +362,15 @@ limitations under the License.
+
+
+
+
+
+
@@ -292,7 +379,6 @@ limitations under the License.
-
@@ -311,6 +397,7 @@ limitations under the License.
+
@@ -319,7 +406,6 @@ limitations under the License.
-
@@ -338,6 +424,7 @@ limitations under the License.
+
@@ -346,7 +433,6 @@ limitations under the License.
-
@@ -365,6 +451,7 @@ limitations under the License.
+
@@ -373,7 +460,6 @@ limitations under the License.
-
@@ -383,7 +469,7 @@ limitations under the License.
-
+
@@ -392,6 +478,7 @@ limitations under the License.
+
@@ -400,7 +487,6 @@ limitations under the License.
-
@@ -418,16 +504,16 @@ limitations under the License.
-
+
+
-
+
-
@@ -443,41 +529,42 @@ limitations under the License.
+
+
+
+
+
+
+
-
+
+
-
+
-
+
-
-
+
-
+
-
+
-
-
-
-
-
-
-
-
-
+
+
+
-
+
@@ -486,47 +573,23 @@ limitations under the License.
-
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
-
+
@@ -538,54 +601,17 @@ limitations under the License.
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
@@ -602,38 +628,18 @@ limitations under the License.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
+
+
+
+
+
+
diff --git a/assets/robot/openarm_v1.0/urdf/openarm_v10.urdf.xacro b/assets/robot/openarm_v1.0/urdf/openarm_v10.urdf.xacro
index 4b72af3a..1b711e0d 100644
--- a/assets/robot/openarm_v1.0/urdf/openarm_v10.urdf.xacro
+++ b/assets/robot/openarm_v1.0/urdf/openarm_v10.urdf.xacro
@@ -1,6 +1,6 @@
-
+
-
-
+
+
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
- ${xacro.error('assets/robot/openarm_v1.0 supports arm_type in ' + str(accepted_arm_types) + ' (got: $(arg arm_type)). Use assets/robot/openarm_v2.0 for newer hardware variants.')}
-
-
- ${xacro.error('assets/robot/openarm_v1.0 only supports body_type:=v10.')}
-
-
-
-
-
-
+
+
- ee_inertials="${xacro.load_yaml(parallel_link_cfg_root + '/inertials.yaml')}"
- ee_kinematics="${xacro.load_yaml(parallel_link_cfg_root + '/kinematics.yaml')}"
- ee_kinematics_link="${xacro.load_yaml(parallel_link_cfg_root + '/kinematics_link.yaml')}"
- ee_joints_limits="${xacro.load_yaml(parallel_link_cfg_root + '/joint_limits.yaml')}"
- ee_type="parallel_link"
-
- ros2_control="$(arg ros2_control)"
- can_interface="$(arg can_interface)"
- left_can_interface="$(arg left_can_interface)"
- right_can_interface="$(arg right_can_interface)"
- left_arm_prefix="$(arg left_arm_prefix)"
- right_arm_prefix="$(arg right_arm_prefix)"
- use_fake_hardware="$(arg use_fake_hardware)"
- fake_sensor_commands="$(arg fake_sensor_commands)"
- no_prefix="$(arg no_prefix)"
- arm_prefix=""
- body_prefix=""
- arm_connected_to="base"
- body_connected_to="world"
- bimanual="$(arg bimanual)"
- right_arm_base_xyz="$(arg right_arm_base_xyz)"
- left_arm_base_xyz="$(arg left_arm_base_xyz)"
- right_arm_base_rpy="$(arg right_arm_base_rpy)"
- left_arm_base_rpy="$(arg left_arm_base_rpy)"
- can_fd="$(arg can_fd)"
- />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/assets/robot/openarm_v1.0/urdf/robot/openarm_robot.xacro b/assets/robot/openarm_v1.0/urdf/robot/openarm_robot.xacro
deleted file mode 100644
index 41824fa6..00000000
--- a/assets/robot/openarm_v1.0/urdf/robot/openarm_robot.xacro
+++ /dev/null
@@ -1,202 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/assets/robot/openarm_v1.0/urdf/ros2_control/openarm.bimanual.ros2_control.xacro b/assets/robot/openarm_v1.0/urdf/ros2_control/openarm.bimanual.ros2_control.xacro
deleted file mode 100644
index 999b443a..00000000
--- a/assets/robot/openarm_v1.0/urdf/ros2_control/openarm.bimanual.ros2_control.xacro
+++ /dev/null
@@ -1,152 +0,0 @@
-
-
-
-
-
-
-
-
-
-
- ${arm_type}
-
- mock_components/GenericSystem
- ${fake_sensor_commands}
- 0.0
-
-
- openarm_hardware/OpenArmHW
- ${left_can_interface}
- ${left_arm_prefix}
- ${hand}
- ${can_fd}
- ${ee_type}
- ${control_gains['joint1']['kp']}
- ${control_gains['joint2']['kp']}
- ${control_gains['joint3']['kp']}
- ${control_gains['joint4']['kp']}
- ${control_gains['joint5']['kp']}
- ${control_gains['joint6']['kp']}
- ${control_gains['joint7']['kp']}
- ${control_gains['joint1']['kd']}
- ${control_gains['joint2']['kd']}
- ${control_gains['joint3']['kd']}
- ${control_gains['joint4']['kd']}
- ${control_gains['joint5']['kd']}
- ${control_gains['joint6']['kd']}
- ${control_gains['joint7']['kd']}
-
- ${control_gains['hand']['kp']}
- ${control_gains['hand']['kd']}
-
-
-
-
-
-
-
-
-
-
-
- ${initial_position}
-
-
-
- 0.0
-
-
-
- 0.0
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ${arm_type}
-
- mock_components/GenericSystem
- ${fake_sensor_commands}
- 0.0
-
-
- openarm_hardware/OpenArmHW
- ${right_can_interface}
- ${right_arm_prefix}
- ${hand}
- ${can_fd}
- ${ee_type}
- ${control_gains['joint1']['kp']}
- ${control_gains['joint2']['kp']}
- ${control_gains['joint3']['kp']}
- ${control_gains['joint4']['kp']}
- ${control_gains['joint5']['kp']}
- ${control_gains['joint6']['kp']}
- ${control_gains['joint7']['kp']}
- ${control_gains['joint1']['kd']}
- ${control_gains['joint2']['kd']}
- ${control_gains['joint3']['kd']}
- ${control_gains['joint4']['kd']}
- ${control_gains['joint5']['kd']}
- ${control_gains['joint6']['kd']}
- ${control_gains['joint7']['kd']}
-
- ${control_gains['hand']['kp']}
- ${control_gains['hand']['kd']}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/assets/robot/openarm_v1.0/urdf/ros2_control/openarm.ros2_control.xacro b/assets/robot/openarm_v1.0/urdf/ros2_control/openarm.ros2_control.xacro
deleted file mode 100644
index 97cc630c..00000000
--- a/assets/robot/openarm_v1.0/urdf/ros2_control/openarm.ros2_control.xacro
+++ /dev/null
@@ -1,110 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
- ${arm_type}
- ${arm_prefix}
-
- mock_components/GenericSystem
- ${fake_sensor_commands}
- 0.0
-
-
- openarm_hardware/OpenArmHW
- ${can_interface}
- ${arm_prefix}
- ${hand}
- ${can_fd}
- ${ee_type}
- ${control_gains['joint1']['kp']}
- ${control_gains['joint2']['kp']}
- ${control_gains['joint3']['kp']}
- ${control_gains['joint4']['kp']}
- ${control_gains['joint5']['kp']}
- ${control_gains['joint6']['kp']}
- ${control_gains['joint7']['kp']}
- ${control_gains['joint1']['kd']}
- ${control_gains['joint2']['kd']}
- ${control_gains['joint3']['kd']}
- ${control_gains['joint4']['kd']}
- ${control_gains['joint5']['kd']}
- ${control_gains['joint6']['kd']}
- ${control_gains['joint7']['kd']}
-
-
-
-
-
-
-
-
-
-
-
-
- ${initial_position}
-
-
-
- 0.0
-
-
-
- 0.0
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/assets/robot/openarm_v2.0/config/arm/inertials/nominal.yaml b/assets/robot/openarm_v2.0/config/arm/inertials/nominal.yaml
index a6f5f7ec..6d7df71d 100644
--- a/assets/robot/openarm_v2.0/config/arm/inertials/nominal.yaml
+++ b/assets/robot/openarm_v2.0/config/arm/inertials/nominal.yaml
@@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-base_link:
+link1:
origin:
x: 0.00253123748061566
y: -0.0258185540330169
@@ -28,7 +28,7 @@ base_link:
yy: 0.00159935208714031
yz: 2.7521421737084e-08
zz: 0.000750541980863571
-link1:
+link2:
origin:
x: 0.000900350355624244
y: -0.0444659716892874
@@ -44,7 +44,7 @@ link1:
yy: 0.000759199728161993
yz: 6.66755698859637e-08
zz: 0.000670659201019629
-link2:
+link3:
origin:
x: -0.0247184924346635
y: 7.60578399428002e-08
@@ -60,7 +60,7 @@ link2:
yy: 0.000113062180225725
yz: 3.75816911469744e-10
zz: 8.22999351863579e-05
-link3:
+link4:
origin:
x: -0.00300861804638783
y: -0.000514813312550808
@@ -76,7 +76,7 @@ link3:
yy: 0.00114018992179734
yz: -1.06260802872572e-05
zz: 0.000559765478676303
-link4:
+link5:
origin:
x: -0.00310326243752606
y: -0.00136538979048502
@@ -92,7 +92,7 @@ link4:
yy: 0.000433926270522842
yz: 3.41757797773822e-06
zz: 0.000245211429759716
-link5:
+link6:
origin:
x: -0.000737188580130584
y: -0.000412406544351845
@@ -108,7 +108,7 @@ link5:
yy: 0.000334599623120095
yz: -1.49934409279756e-07
zz: 0.000176662464388138
-link6:
+link7:
origin:
x: 2.27438423593244e-05
y: 0.00068649602098908
diff --git a/assets/robot/openarm_v2.0/config/arm/link/collisions.yaml b/assets/robot/openarm_v2.0/config/arm/link/collisions.yaml
index 288633ba..4980bbc4 100644
--- a/assets/robot/openarm_v2.0/config/arm/link/collisions.yaml
+++ b/assets/robot/openarm_v2.0/config/arm/link/collisions.yaml
@@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-base_link:
+link1:
origin:
x: 0
y: 0
@@ -26,7 +26,7 @@ base_link:
x: 1
y: 1
z: 1
-link1:
+link2:
origin:
x: 0
y: 0
@@ -40,7 +40,7 @@ link1:
x: 1
y: 1
z: 1
-link2:
+link3:
origin:
x: 0
y: 0
@@ -54,7 +54,7 @@ link2:
x: 1
y: 1
z: 1
-link3:
+link4:
origin:
x: 0
y: 0
@@ -68,7 +68,7 @@ link3:
x: 1
y: 1
z: 1
-link4:
+link5:
origin:
x: 0
y: 0
@@ -82,7 +82,7 @@ link4:
x: 1
y: 1
z: 1
-link5:
+link6:
origin:
x: 0
y: 0
@@ -96,7 +96,7 @@ link5:
x: 1
y: 1
z: 1
-link6:
+link7:
origin:
x: 0
y: 0
diff --git a/assets/robot/openarm_v2.0/config/arm/link/visuals.yaml b/assets/robot/openarm_v2.0/config/arm/link/visuals.yaml
index 6fcf1682..9e6a8467 100644
--- a/assets/robot/openarm_v2.0/config/arm/link/visuals.yaml
+++ b/assets/robot/openarm_v2.0/config/arm/link/visuals.yaml
@@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-base_link:
+link1:
origin:
x: 0
y: 0
@@ -26,7 +26,7 @@ base_link:
x: 1
y: 1
z: 1
-link1:
+link2:
origin:
x: 0
y: 0
@@ -40,7 +40,7 @@ link1:
x: 1
y: 1
z: 1
-link2:
+link3:
origin:
x: 0
y: 0
@@ -54,7 +54,7 @@ link2:
x: 1
y: 1
z: 1
-link3:
+link4:
origin:
x: 0
y: 0
@@ -68,7 +68,7 @@ link3:
x: 1
y: 1
z: 1
-link4:
+link5:
origin:
x: 0
y: 0
@@ -82,7 +82,7 @@ link4:
x: 1
y: 1
z: 1
-link5:
+link6:
origin:
x: 0
y: 0
@@ -96,7 +96,7 @@ link5:
x: 1
y: 1
z: 1
-link6:
+link7:
origin:
x: 0
y: 0
diff --git a/assets/robot/openarm_v2.0/config/arm/struct/name_mapping.yaml b/assets/robot/openarm_v2.0/config/arm/struct/name_mapping.yaml
index 98d02fd9..dbabebb3 100644
--- a/assets/robot/openarm_v2.0/config/arm/struct/name_mapping.yaml
+++ b/assets/robot/openarm_v2.0/config/arm/struct/name_mapping.yaml
@@ -14,23 +14,23 @@
links:
canonical_to_original:
- base_link: base_link
- link1: link1
- link2: link2
- link3: link3
- link4: link4
- link5: link5
- link6: link6
- link7: empty_link_for_J7
+ link1: base_link
+ link2: link1
+ link3: link2
+ link4: link3
+ link5: link4
+ link6: link5
+ link7: link6
+ link8: empty_link_for_J7
original_to_canonical:
- base_link: base_link
- link1: link1
- link2: link2
- link3: link3
- link4: link4
- link5: link5
- link6: link6
- empty_link_for_J7: link7
+ base_link: link1
+ link1: link2
+ link2: link3
+ link3: link4
+ link4: link5
+ link5: link6
+ link6: link7
+ empty_link_for_J7: link8
joints:
canonical_to_original:
joint1: joint1
diff --git a/assets/robot/openarm_v2.0/config/arm/struct/reference_points.yaml b/assets/robot/openarm_v2.0/config/arm/struct/reference_points.yaml
index 2f524870..1cd09d60 100644
--- a/assets/robot/openarm_v2.0/config/arm/struct/reference_points.yaml
+++ b/assets/robot/openarm_v2.0/config/arm/struct/reference_points.yaml
@@ -13,7 +13,7 @@
# limitations under the License.
ee_mount_point:
- parent: link7
+ parent: link8
origin:
x: 0.0205
y: 0
@@ -29,7 +29,7 @@ ee_mount_point:
type: fixed
parent_link:
original_name: empty_link_for_J7
- canonical_name: link7
+ canonical_name: link8
child_link:
original_name: empty_link_for_ee_mounting
canonical_name: null
diff --git a/assets/robot/openarm_v2.0/config/arm/struct/topology.yaml b/assets/robot/openarm_v2.0/config/arm/struct/topology.yaml
index acd91f4b..f2f248e3 100644
--- a/assets/robot/openarm_v2.0/config/arm/struct/topology.yaml
+++ b/assets/robot/openarm_v2.0/config/arm/struct/topology.yaml
@@ -13,42 +13,49 @@
# limitations under the License.
collapse_empty_end: true
-
links:
- - base_link
- - link1
- - link2
- - link3
- - link4
- - link5
- - link6
- - link7
+ link1:
+ name: base_link
+ link2:
+ name: link1
+ link3:
+ name: link2
+ link4:
+ name: link3
+ link5:
+ name: link4
+ link6:
+ name: link5
+ link7:
+ name: link6
+ link8:
+ name: link7
joints:
joint1:
- type: revolute
- parent: base_link
- child: link1
- joint2:
type: revolute
parent: link1
child: link2
- joint3:
+ joint2:
type: revolute
parent: link2
child: link3
- joint4:
+ joint3:
type: revolute
parent: link3
child: link4
- joint5:
+ joint4:
type: revolute
parent: link4
child: link5
- joint6:
+ joint5:
type: revolute
parent: link5
child: link6
- joint7:
+ joint6:
type: revolute
parent: link6
child: link7
+ joint7:
+ type: revolute
+ parent: link7
+ child: link8
diff --git a/assets/robot/openarm_v2.0/config/robot_presets/default_bimanual.yaml b/assets/robot/openarm_v2.0/config/robot_presets/default_bimanual.yaml
index 3771f40b..559c7625 100644
--- a/assets/robot/openarm_v2.0/config/robot_presets/default_bimanual.yaml
+++ b/assets/robot/openarm_v2.0/config/robot_presets/default_bimanual.yaml
@@ -60,7 +60,7 @@ primary_arm:
y: -1
z: 1
include:
- links: [base_link, link1, link2, link5, link6, link7]
+ links: [link1, link2, link3, link6, link7, link8]
joints: [joint1, joint2, joint3, joint5, joint6, joint7]
reference_points: [ee_mount_point]
limit_override_joints: {}
@@ -118,3 +118,29 @@ secondary_arm_end_effector:
y: 1
z: 1
limit_override_joints: {}
+
+systems:
+ openarm_left_hardware_interface:
+ joints:
+ primary_arm:
+ joint1: {idx: 1}
+ joint2: {idx: 2}
+ joint3: {idx: 3}
+ joint4: {idx: 4}
+ joint5: {idx: 5}
+ joint6: {idx: 6}
+ joint7: {idx: 7}
+ primary_arm_end_effector:
+ joint1: {idx: 8}
+ openarm_right_hardware_interface:
+ joints:
+ secondary_arm:
+ joint1: {idx: 1}
+ joint2: {idx: 2}
+ joint3: {idx: 3}
+ joint4: {idx: 4}
+ joint5: {idx: 5}
+ joint6: {idx: 6}
+ joint7: {idx: 7}
+ secondary_arm_end_effector:
+ joint1: {idx: 8}
diff --git a/assets/robot/openarm_v2.0/config/robot_presets/left_arm.yaml b/assets/robot/openarm_v2.0/config/robot_presets/left_arm.yaml
index 2b94a8ae..b4debe9d 100644
--- a/assets/robot/openarm_v2.0/config/robot_presets/left_arm.yaml
+++ b/assets/robot/openarm_v2.0/config/robot_presets/left_arm.yaml
@@ -60,7 +60,7 @@ primary_arm:
y: -1
z: 1
include:
- links: [base_link, link1, link2, link5, link6, link7]
+ links: [link1, link2, link3, link6, link7, link8]
joints: [joint1, joint2, joint3, joint5, joint6, joint7]
reference_points: [ee_mount_point]
limit_override_joints: {}
@@ -122,3 +122,15 @@ secondary_arm_end_effector:
y: 1
z: 1
limit_override_joints: {}
+
+systems:
+ openarm_left_hardware_interface:
+ joints:
+ primary_arm:
+ joint1: {idx: 1}
+ joint2: {idx: 2}
+ joint3: {idx: 3}
+ joint4: {idx: 4}
+ joint5: {idx: 5}
+ joint6: {idx: 6}
+ joint7: {idx: 7}
diff --git a/assets/robot/openarm_v2.0/config/robot_presets/left_arm_with_pinch_gripper.yaml b/assets/robot/openarm_v2.0/config/robot_presets/left_arm_with_pinch_gripper.yaml
index fbfa0663..18fb9066 100644
--- a/assets/robot/openarm_v2.0/config/robot_presets/left_arm_with_pinch_gripper.yaml
+++ b/assets/robot/openarm_v2.0/config/robot_presets/left_arm_with_pinch_gripper.yaml
@@ -61,7 +61,7 @@ primary_arm:
y: -1
z: 1
include:
- links: [base_link, link1, link2, link5, link6, link7]
+ links: [link1, link2, link3, link6, link7, link8]
joints: [joint1, joint2, joint3, joint5, joint6, joint7]
reference_points: [ee_mount_point]
limit_override_joints: {}
@@ -123,3 +123,17 @@ secondary_arm_end_effector:
y: 1
z: 1
limit_override_joints: {}
+
+systems:
+ openarm_left_hardware_interface:
+ joints:
+ primary_arm:
+ joint1: {idx: 1}
+ joint2: {idx: 2}
+ joint3: {idx: 3}
+ joint4: {idx: 4}
+ joint5: {idx: 5}
+ joint6: {idx: 6}
+ joint7: {idx: 7}
+ primary_arm_end_effector:
+ joint1: {idx: 8}
diff --git a/assets/robot/openarm_v2.0/config/robot_presets/right_arm.yaml b/assets/robot/openarm_v2.0/config/robot_presets/right_arm.yaml
index fe26dd88..d62cd67c 100644
--- a/assets/robot/openarm_v2.0/config/robot_presets/right_arm.yaml
+++ b/assets/robot/openarm_v2.0/config/robot_presets/right_arm.yaml
@@ -122,3 +122,15 @@ secondary_arm_end_effector:
y: -1
z: 1
limit_override_joints: {}
+
+systems:
+ openarm_right_hardware_interface:
+ joints:
+ primary_arm:
+ joint1: {idx: 1}
+ joint2: {idx: 2}
+ joint3: {idx: 3}
+ joint4: {idx: 4}
+ joint5: {idx: 5}
+ joint6: {idx: 6}
+ joint7: {idx: 7}
diff --git a/assets/robot/openarm_v2.0/config/robot_presets/right_arm_with_pinch_gripper.yaml b/assets/robot/openarm_v2.0/config/robot_presets/right_arm_with_pinch_gripper.yaml
index f5e60d0e..06936a6b 100644
--- a/assets/robot/openarm_v2.0/config/robot_presets/right_arm_with_pinch_gripper.yaml
+++ b/assets/robot/openarm_v2.0/config/robot_presets/right_arm_with_pinch_gripper.yaml
@@ -119,3 +119,17 @@ secondary_arm_end_effector:
y: -1
z: 1
limit_override_joints: {}
+
+systems:
+ openarm_right_hardware_interface:
+ joints:
+ primary_arm:
+ joint1: {idx: 1}
+ joint2: {idx: 2}
+ joint3: {idx: 3}
+ joint4: {idx: 4}
+ joint5: {idx: 5}
+ joint6: {idx: 6}
+ joint7: {idx: 7}
+ primary_arm_end_effector:
+ joint1: {idx: 8}
diff --git a/assets/robot/openarm_v2.0/urdf/example/v2.urdf b/assets/robot/openarm_v2.0/urdf/example/v2.urdf
index 39ad0c70..9ae8fcba 100644
--- a/assets/robot/openarm_v2.0/urdf/example/v2.urdf
+++ b/assets/robot/openarm_v2.0/urdf/example/v2.urdf
@@ -711,14 +711,6 @@ limitations under the License.
0.0
-
@@ -839,13 +831,5 @@ limitations under the License.
0.0
-
diff --git a/assets/robot/openarm_v2.0/urdf/openarm_v20.urdf.xacro b/assets/robot/openarm_v2.0/urdf/openarm_v20.urdf.xacro
index 351b2678..dee35f42 100644
--- a/assets/robot/openarm_v2.0/urdf/openarm_v20.urdf.xacro
+++ b/assets/robot/openarm_v2.0/urdf/openarm_v20.urdf.xacro
@@ -16,42 +16,42 @@ limitations under the License.
-
+
+
+
-
-
-
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
diff --git a/assets/robot/openarm_v2.0/urdf/ros2_control/openarm.bimanual.ros2_control.xacro b/assets/robot/openarm_v2.0/urdf/ros2_control/openarm.bimanual.ros2_control.xacro
deleted file mode 100644
index e7b25ad8..00000000
--- a/assets/robot/openarm_v2.0/urdf/ros2_control/openarm.bimanual.ros2_control.xacro
+++ /dev/null
@@ -1,157 +0,0 @@
-
-
-
-
-
-
-
-
-
- ${arm_type}
-
- mock_components/GenericSystem
- ${fake_sensor_commands}
- 0.0
-
-
- openarm_hardware/OpenArmHW
- ${left_can_interface}
- ${left_arm_prefix}
- ${can_fd}
- ${ee_type}
- ${control_gains['joint1']['kp']}
- ${control_gains['joint2']['kp']}
- ${control_gains['joint3']['kp']}
- ${control_gains['joint4']['kp']}
- ${control_gains['joint5']['kp']}
- ${control_gains['joint6']['kp']}
- ${control_gains['joint7']['kp']}
- ${control_gains['joint1']['kd']}
- ${control_gains['joint2']['kd']}
- ${control_gains['joint3']['kd']}
- ${control_gains['joint4']['kd']}
- ${control_gains['joint5']['kd']}
- ${control_gains['joint6']['kd']}
- ${control_gains['joint7']['kd']}
-
-
-
-
-
-
-
-
-
-
- ${initial_position}
-
-
-
- 0.0
-
-
-
- 0.0
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ${arm_type}
-
- mock_components/GenericSystem
- ${fake_sensor_commands}
- 0.0
-
-
- openarm_hardware/OpenArmHW
- ${right_can_interface}
- ${right_arm_prefix}
- ${can_fd}
- ${ee_type}
- ${control_gains['joint1']['kp']}
- ${control_gains['joint2']['kp']}
- ${control_gains['joint3']['kp']}
- ${control_gains['joint4']['kp']}
- ${control_gains['joint5']['kp']}
- ${control_gains['joint6']['kp']}
- ${control_gains['joint7']['kp']}
- ${control_gains['joint1']['kd']}
- ${control_gains['joint2']['kd']}
- ${control_gains['joint3']['kd']}
- ${control_gains['joint4']['kd']}
- ${control_gains['joint5']['kd']}
- ${control_gains['joint6']['kd']}
- ${control_gains['joint7']['kd']}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/assets/robot/openarm_v2.0/urdf/ros2_control/openarm.ros2_control.xacro b/assets/robot/openarm_v2.0/urdf/ros2_control/openarm.ros2_control.xacro
deleted file mode 100644
index 59f182b2..00000000
--- a/assets/robot/openarm_v2.0/urdf/ros2_control/openarm.ros2_control.xacro
+++ /dev/null
@@ -1,107 +0,0 @@
-
-
-
-
-
-
-
-
-
- ${arm_type}
- ${arm_prefix}
-
- mock_components/GenericSystem
- ${fake_sensor_commands}
- 0.0
-
-
- openarm_hardware/OpenArmHW
- ${can_interface}
- ${arm_prefix}
- ${hand}
- ${can_fd}
- ${ee_type}
- ${control_gains['joint1']['kp']}
- ${control_gains['joint2']['kp']}
- ${control_gains['joint3']['kp']}
- ${control_gains['joint4']['kp']}
- ${control_gains['joint5']['kp']}
- ${control_gains['joint6']['kp']}
- ${control_gains['joint7']['kp']}
- ${control_gains['joint1']['kd']}
- ${control_gains['joint2']['kd']}
- ${control_gains['joint3']['kd']}
- ${control_gains['joint4']['kd']}
- ${control_gains['joint5']['kd']}
- ${control_gains['joint6']['kd']}
- ${control_gains['joint7']['kd']}
-
-
-
-
-
-
-
-
-
-
-
-
- ${initial_position}
-
-
-
- 0.0
-
-
-
- 0.0
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/assets/sensor/zed/urdf/component.xacro b/assets/sensor/zed/urdf/component.xacro
index 554ded90..c44546ed 100644
--- a/assets/sensor/zed/urdf/component.xacro
+++ b/assets/sensor/zed/urdf/component.xacro
@@ -35,7 +35,7 @@ limitations under the License.
prefix=component_prefix,
root_link_actual=sensor_root_link,
- topology=dict(links=[sensor_root_link], joints=dict()),
+ topology=dict(links=dict(link1=dict(name=sensor_root_link)), joints=dict()),
reference_points=empty_dict,
joint_origins=empty_dict,
joint_axes=empty_dict,
@@ -44,7 +44,8 @@ limitations under the License.
inertials=empty_dict,
visuals=empty_dict,
collisions=empty_dict,
- link_name_map=empty_dict,
+ link_name_map=dict(link1=sensor_root_link),
+ joint_name_map=empty_dict,
default_mount_parent=sensor_root_link,
collapse_empty_end=False,
supports_frame_shift=False,
diff --git a/launch/display_openarm.launch.py b/launch/display_openarm.launch.py
index 3174b273..c5c107d2 100644
--- a/launch/display_openarm.launch.py
+++ b/launch/display_openarm.launch.py
@@ -74,6 +74,7 @@ def robot_state_publisher_spawner(
"arm_type": arm_type_str,
"body_type": "v10",
"bimanual": context.perform_substitution(bimanual),
+ "robot_preset": context.perform_substitution(robot_preset),
"ros2_control": context.perform_substitution(ros2_control),
"use_fake_hardware": context.perform_substitution(use_fake_hardware),
"fake_sensor_commands": context.perform_substitution(fake_sensor_commands),
@@ -81,8 +82,11 @@ def robot_state_publisher_spawner(
else:
mappings = {
"arm_type": arm_type_str,
- "robot_preset": context.perform_substitution(robot_preset),
+ "robot_preset": context.perform_substitution(robot_preset) or "default_bimanual",
"emit_grasp_frame": context.perform_substitution(emit_grasp_frame),
+ "ros2_control": context.perform_substitution(ros2_control),
+ "use_fake_hardware": context.perform_substitution(use_fake_hardware),
+ "fake_sensor_commands": context.perform_substitution(fake_sensor_commands),
}
robot_description = xacro.process_file(
@@ -109,8 +113,8 @@ def generate_launch_description():
)
robot_preset_arg = DeclareLaunchArgument(
"robot_preset",
- default_value="default_bimanual",
- description="Robot preset for v2.0 (e.g. default_bimanual, right_arm, left_arm, right_arm_with_pinch_gripper, left_arm_with_pinch_gripper).",
+ default_value="",
+ description="Robot preset; empty selects the default assembly for the selected version.",
)
rviz_config_arg = DeclareLaunchArgument(
"rviz_config",
diff --git a/test/support.py b/test/support.py
index 870485e4..f40ae610 100644
--- a/test/support.py
+++ b/test/support.py
@@ -106,17 +106,6 @@ def package_share_at(path):
def expand(files=None, version='v2.0', entry=None, **arguments):
- if entry is None:
- files = dict(files or {})
- files['fixture.urdf.xacro'] = '''
-
-
-
-
-
-'''
- entry = 'assets/fixture.urdf.xacro'
entry = entry or f'assets/robot/openarm_{version}/urdf/openarm_{"v10" if version == "v1.0" else "v20"}.urdf.xacro'
arguments = {k: str(v).lower() if isinstance(v, bool) else str(v)
for k, v in arguments.items()}
@@ -143,7 +132,7 @@ def expand(files=None, version='v2.0', entry=None, **arguments):
def model(links=('root',), joints=None):
joints = joints or {}
- return {'struct/topology.yaml': dict(links=list(links), joints=deepcopy(joints)),
+ return {'struct/topology.yaml': dict(links={name: {} for name in links}, joints=deepcopy(joints)),
'struct/reference_points.yaml': {'port': dict(parent=links[-1], emit=False, origin=pose(.1, .2, .3, .2, -.1, .3))},
'joint/joint_origins.yaml': {j: dict(origin=pose(z=.1)) for j in joints},
'joint/joint_axes.yaml': {j: dict(axis=dict(x=0, y=0, z=1)) for j in joints},
@@ -161,13 +150,16 @@ def chain():
def pinch():
- data = model(('ee_base_link', 'ee_link1', 'ee_link2'), {
- 'finger_joint1': dict(type='revolute', parent='ee_base_link', child='ee_link1'),
- 'finger_joint2': dict(type='revolute', parent='ee_base_link', child='ee_link2')})
- data['joint/joint_mimics.yaml'] = {'finger_joint2': dict(
- joint='finger_joint1', multiplier=-1, offset=.1)}
+ data = model(('link1', 'link2', 'link3'), {
+ 'joint1': dict(name='finger_joint1', type='revolute', parent='link1', child='link2'),
+ 'joint2': dict(name='finger_joint2', type='revolute', parent='link1', child='link3')})
+ data['struct/topology.yaml']['links'] = {
+ 'link1': dict(name='ee_base_link'),
+ 'link2': dict(name='ee_link1'), 'link3': dict(name='ee_link2')}
+ data['joint/joint_mimics.yaml'] = {'joint2': dict(
+ joint='joint1', multiplier=-1, offset=.1)}
data['struct/reference_points.yaml'] = {'grasp_frame': dict(
- parent='ee_base_link', emit=False, origin=pose(z=.12))}
+ parent='link1', emit=False, origin=pose(z=.12))}
return data
diff --git a/test/test_assembly.py b/test/test_assembly.py
index c7cb6c41..a5cbc8d2 100644
--- a/test/test_assembly.py
+++ b/test/test_assembly.py
@@ -54,6 +54,12 @@ def test_topology_and_values_come_from_configuration(kind):
@pytest.mark.parametrize('product', ['fixture_tool', 'pinch_gripper'])
def test_names_and_mimics_follow_configuration(product):
data = pinch()
+ topology = data['struct/topology.yaml']
+ topology['joints']['joint1']['name'] = 'drive'
+ topology['joints']['joint2']['name'] = 'follower'
+ topology['links']['link1']['name'] = 'tool_base'
+ topology['links']['link2']['name'] = 'moving_finger'
+ topology['links']['link3'].pop('name')
for item in data['struct/topology.yaml']['joints'].values():
item['type'] = 'prismatic'
for joint in data['joint/joint_axes.yaml'].values():
@@ -62,23 +68,29 @@ def test_names_and_mimics_follow_configuration(product):
b=component('end_effector', product, 'beta_', connection=dict(attach_to='a'),
reflect=dict(x=1, y=-1, z=1)))
robot = assemble(spec, {'a': data, 'b': data})
- mimic = data['joint/joint_mimics.yaml']['finger_joint2']
+ names = {key: cfg.get('name', key) for key, cfg in
+ data['struct/topology.yaml']['joints'].items()}
+ assert {link.get('name') for link in robot.findall('link')} == {'world'} | {
+ prefix + cfg.get('name', key) for prefix in ('alpha_', 'beta_')
+ for key, cfg in topology['links'].items()}
+ mimic = data['joint/joint_mimics.yaml']['joint2']
for prefix in ('alpha_', 'beta_'):
- joint = robot.find(f"joint[@name='{prefix}finger_joint2']")
+ joint = robot.find(f"joint[@name='{prefix}follower']")
assert joint.get('type') == 'prismatic'
for name, configured in data['joint/joint_limits.yaml'].items():
- limit = robot.find(f"joint[@name='{prefix}{name}']/limit")
+ limit = robot.find(f"joint[@name='{prefix}{names[name]}']/limit")
for key in ('lower', 'upper'):
assert float(limit.get(key)) == configured['limit'][key]
- assert joint.find('mimic').get('joint') == prefix + mimic['joint']
+ assert joint.find('mimic').get(
+ 'joint') == prefix + names[mimic['joint']]
for key in ('multiplier', 'offset'):
assert float(joint.find('mimic').get(key)) == mimic[key]
reflection = [[float(i == j) * (1, -1, 1, 1)[i]
for j in range(4)] for i in range(4)]
for name in data['struct/topology.yaml']['joints']:
- right = robot.find(f"joint[@name='alpha_{name}']")
- left = robot.find(f"joint[@name='beta_{name}']")
+ right = robot.find(f"joint[@name='alpha_{names[name]}']")
+ left = robot.find(f"joint[@name='beta_{names[name]}']")
for endpoint in ['lower', 'upper']:
position = float(right.find('limit').get(endpoint))
motions = []
@@ -126,7 +138,7 @@ def test_grasp_emission_combines_configuration_and_argument():
@pytest.mark.parametrize('tool', [False, True])
def test_overrides_are_applied_before_reflection(tool):
data = pinch() if tool else chain()
- name = 'finger_joint1' if tool else 'pivot'
+ name = 'joint1' if tool else 'pivot'
origin = pose(.03, .04, .05, .2, -.3, .4)
limit = dict(lower=-.2, upper=.7, effort=12, velocity=4)
spec = preset(unit=component('end_effector' if tool else 'robot',
@@ -134,7 +146,9 @@ def test_overrides_are_applied_before_reflection(tool):
reflect=dict(x=1, y=-1, z=1),
origin_override_joints={name: origin}, limit_override_joints={name: limit}))
robot = assemble(spec, {'unit': data})
- joint = robot.find(f"joint[@name='unit_{name}']")
+ emitted_name = data['struct/topology.yaml']['joints'][name].get(
+ 'name', name)
+ joint = robot.find(f"joint[@name='unit_{emitted_name}']")
expected = deepcopy(origin)
for key in ('y', 'roll', 'yaw'):
expected[key] *= -1
@@ -151,10 +165,10 @@ def test_reflection_selection_preserves_unselected_joints(product):
for joint in data['joint/joint_axes.yaml'].values():
joint['axis'].update(x=.6, y=.8, z=0.)
spec = preset(tool=component('end_effector', product, 'tool_',
- reflect=dict(x=1, y=-1, z=1, include=dict(links=['ee_base_link'], joints=[], reference_points=[]))))
+ reflect=dict(x=1, y=-1, z=1, include=dict(links=['link1'], joints=[], reference_points=[]))))
robot = assemble(spec, {'tool': data})
base = robot.find("link[@name='tool_ee_base_link']/inertial")
- source = data['inertials/nominal.yaml']['ee_base_link']
+ source = data['inertials/nominal.yaml']['link1']
assert float(base.find('mass').get('value')) == source['mass']
expected = deepcopy(source['origin'])
expected['y'] *= -1
@@ -163,7 +177,9 @@ def test_reflection_selection_preserves_unselected_joints(product):
sign = -1 if key in ('xy', 'yz') else 1
assert float(base.find('inertia').get('i'+key)) == sign * value
for name in data['struct/topology.yaml']['joints']:
- joint = robot.find(f"joint[@name='tool_{name}']")
+ emitted_name = data['struct/topology.yaml']['joints'][name].get(
+ 'name', name)
+ joint = robot.find(f"joint[@name='tool_{emitted_name}']")
near(transform(joint.find('origin')), transform(
data['joint/joint_origins.yaml'][name]['origin']))
assert [float(v) for v in joint.find('axis').get('xyz').split()] == list(
@@ -181,24 +197,24 @@ def test_folding_preserves_physical_properties_and_frames():
assert robot.find("link[@name='arm_tip']") is not None
spec, data = installed_tool(False)
- data['tool']['struct/topology.yaml']['joints']['finger_joint2']['parent'] = 'ee_link1'
+ data['tool']['struct/topology.yaml']['joints']['joint2']['parent'] = 'link2'
data['arm']['struct/reference_points.yaml']['port']['emit'] = True
geometry = dict(mesh='package://fixture_meshes/shape.stl',
scale=dict(x=1, y=1, z=1))
shape = dict(origin=pose(.02, -.04, .01, .2, .1, -.3), geometry=geometry)
- data['tool']['link/visuals.yaml']['ee_base_link'] = deepcopy(shape)
- data['tool']['link/collisions.yaml']['ee_base_link'] = deepcopy(shape)
+ data['tool']['link/visuals.yaml']['link1'] = deepcopy(shape)
+ data['tool']['link/collisions.yaml']['link1'] = deepcopy(shape)
spec['tool']['reflect'] = dict(x=1, y=-1, z=1, include=dict(
- links=['ee_base_link'], joints=[], reference_points=[]))
+ links=['link1'], joints=[], reference_points=[]))
spec['tool']['origin_override_joints'] = {
- 'finger_joint1': pose(.04, .03, .02, .3, .2, .1)}
+ 'joint1': pose(.04, .03, .02, .3, .2, .1)}
first = assemble(spec, data, emit_grasp_frame=True)
data['arm']['struct/topology.yaml']['collapse_empty_end'] = True
second = assemble(spec, data, emit_grasp_frame=True)
physical_equal(first, second)
for frame in ('arm_port', 'tool_grasp_frame'):
near(poses(first)[frame], poses(second)[frame])
- mass = data['tool']['inertials/nominal.yaml']['ee_base_link']['mass']
+ mass = data['tool']['inertials/nominal.yaml']['link1']['mass']
assert float(second.find(
"link[@name='tool_ee_base_link']/inertial/mass").get('value')) == mass
diff --git a/test/test_entrypoints.py b/test/test_entrypoints.py
index 3cfa0134..e618f95b 100644
--- a/test/test_entrypoints.py
+++ b/test/test_entrypoints.py
@@ -16,7 +16,7 @@
import xacro
import yaml
-from support import expand, multiply, near, pinch, pose, transform
+from support import expand, model, multiply, near, pinch, pose, transform
def write_configuration(directory, data):
@@ -26,9 +26,23 @@ def write_configuration(directory, data):
path.write_text(yaml.safe_dump(value, sort_keys=False))
+def test_parallel_entry_forwards_tcp_arguments(tmp_path):
+ data = model(('link7',))
+ data['struct/reference_points.yaml'] = {
+ 'hand_tcp': dict(parent='link7', emit=True, origin=pose(z=.4))}
+ write_configuration(tmp_path, data)
+ robot = expand(entry='assets/end_effector/parallel_link/urdf/parallel_link_standalone.urdf.xacro',
+ ee_config_dir=tmp_path, reflect_y=-1, tcp_xyz='.01 .02 .10', tcp_rpy='.2 .3 .4')
+ joint = robot.find("joint[@name='hand_tcp_joint']")
+ assert joint.find('parent').get(
+ 'link') == data['struct/reference_points.yaml']['hand_tcp']['parent']
+ near(transform(joint.find('origin')),
+ transform(pose(.01, .02, .1, .2, .3, .4)))
+
+
def test_pinch_entry_forwards_reference_options(tmp_path):
data = pinch()
- reference = dict(parent='ee_base_link', emit=True,
+ reference = dict(parent='link1', emit=True,
origin=pose(.01, .02, .03, .2, -.1, .3))
data['struct/reference_points.yaml']['probe'] = reference
write_configuration(tmp_path, data)
@@ -44,10 +58,10 @@ def test_pinch_entry_forwards_reference_options(tmp_path):
data = pinch()
joints = data['struct/topology.yaml']['joints']
if invalid == 'unknown link':
- joints['finger_joint1']['parent'] = 'missing'
+ joints['joint1']['parent'] = 'missing'
else:
- joints['finger_joint1']['parent'] = joints['finger_joint2']['child']
- joints['finger_joint2']['parent'] = joints['finger_joint1']['child']
+ joints['joint1']['parent'] = joints['joint2']['child']
+ joints['joint2']['parent'] = joints['joint1']['child']
write_configuration(tmp_path, data)
with pytest.raises(xacro.XacroException, match=invalid):
expand(entry='assets/end_effector/pinch_gripper/urdf/pinch_gripper_standalone.urdf.xacro',
diff --git a/test/test_interfaces.py b/test/test_interfaces.py
index 64d7ff1a..5d79f5d1 100644
--- a/test/test_interfaces.py
+++ b/test/test_interfaces.py
@@ -67,3 +67,164 @@ def test_broken_component_hook_does_not_use_fallback(interface):
files['body/fixture_a/urdf/component.xacro'] = interface
with pytest.raises((xacro.XacroException, ExpatError)):
support.expand(files, robot_preset='fixture', ros2_control=False)
+
+
+def control_input():
+ names = ['root'] + [f'link{i}' for i in range(1, 8)]
+ data = support.model(names, {f'joint{i}': dict(
+ type='revolute', parent=names[i-1], child=names[i]) for i in range(1, 8)})
+ data['control/control_gains.yaml'] = {
+ f'joint{i}': dict(kp=10+i, kd=i/10) for i in range(1, 8)}
+ spec = support.preset(arm=support.component('robot', 'fixture_control', 'openarm_right_'),
+ tool=support.component('end_effector', 'pinch_gripper', 'openarm_right_', connection=dict(attach_to='arm')))
+ spec['systems'] = {'fixture_system': dict(
+ hardware_plugin='openarm_hardware/OpenArmHW', can_interface='can_test', can_fd=True,
+ joints=dict(arm={name: dict(idx=i) for i, name in enumerate(data['struct/topology.yaml']['joints'])},
+ tool=dict(joint1=dict(idx=8))))}
+ return spec, {'arm': data, 'tool': support.pinch()}
+
+
+def test_control_joints_follow_model_names_and_enabled_components():
+ spec, data = control_input()
+ spec['arm']['prefix'], spec['tool']['prefix'] = 'drive_', 'tool_'
+ arm_joints = data['arm']['struct/topology.yaml']['joints']
+ arm_joints['joint7']['name'] = 'wrist'
+ selection = spec['systems']['fixture_system']['joints']['arm']
+ spec['systems']['fixture_system']['joints']['arm'] = dict(
+ reversed(list(selection.items())))
+ assert not support.assemble(
+ spec, data, ros2_control=False).findall('ros2_control')
+ for tool_enabled in (False, True):
+ spec['tool']['enabled'] = tool_enabled
+ robot = support.assemble(
+ spec, data, ros2_control=True, use_fake_hardware=True)
+ expected = {spec['arm']['prefix'] + cfg.get('name', name)
+ for name, cfg in arm_joints.items()}
+ if tool_enabled:
+ expected.update(spec['tool']['prefix'] + cfg.get('name', name)
+ for name, cfg in data['tool']['struct/topology.yaml']['joints'].items()
+ if name not in data['tool']['joint/joint_mimics.yaml'])
+ active = {joint.get('name') for joint in robot.findall('joint')
+ if joint.get('type') != 'fixed' and joint.find('mimic') is None}
+ assert active == expected
+ assert {joint.get('name')
+ for joint in robot.findall('ros2_control/joint')} == active
+ expected_indices = {spec[component]['prefix'] + data[component]['struct/topology.yaml']['joints'][name].get('name', name): cfg['idx']
+ for component, joints in spec['systems']['fixture_system']['joints'].items()
+ if spec[component]['enabled'] for name, cfg in joints.items()}
+ actual_indices = {joint.get('name'): int(joint.find("param[@name='idx']").text)
+ for joint in robot.findall('ros2_control/joint')}
+ assert actual_indices == expected_indices
+ assert list(actual_indices.values()) == sorted(
+ expected_indices.values())
+
+ data['arm']['struct/topology.yaml']['collapse_empty_end'] = True
+ spec['tool']['connection']['parent_reference_point'] = 'port'
+ spec['systems']['fixture_system']['joints']['tool']['joint2'] = dict(
+ idx=9)
+ files = support.files_for(spec, data)
+ files['end_effector/pinch_gripper/urdf/component.xacro'] = '''
+
+
+
+
+ '''
+ robot = support.expand(files, robot_preset='fixture',
+ ros2_control=True, use_fake_hardware=True)
+ assert robot.find("joint[@name='tool_finger_joint2']/mimic") is None
+ expected.add('tool_finger_joint2')
+ active = {joint.get('name') for joint in robot.findall('joint')
+ if joint.get('type') != 'fixed' and joint.find('mimic') is None}
+ assert active == expected
+ assert {joint.get('name')
+ for joint in robot.findall('ros2_control/joint')} == active
+
+ spec, data = control_input()
+ joints = list(data['arm']['struct/topology.yaml']['joints'])
+ spec['systems'] = {
+ 'shoulder': dict(joints=dict(arm={name: dict(idx=2*i-1) for i, name in enumerate(joints[:4], 1)})),
+ 'wrist': dict(joints=dict(arm={name: dict(idx=2*i-1) for i, name in enumerate(joints[4:], 1)},
+ tool=dict(joint1=dict(idx=7))))}
+ robot = support.assemble(
+ spec, data, ros2_control=True, use_fake_hardware=True)
+ for name, cfg in spec['systems'].items():
+ expected = {spec[component]['prefix'] + data[component]['struct/topology.yaml']['joints'][joint].get('name', joint) for component,
+ names in cfg['joints'].items() for joint in names}
+ assert {joint.get('name') for joint in robot.find(
+ f"ros2_control[@name='{name}']").findall('joint')} == expected
+ spec['systems']['shoulder'].update(
+ hardware_plugin='openarm_hardware/OpenArmHW', can_interface='can_test')
+ with pytest.raises(xacro.XacroException, match='seven arm joints'):
+ support.assemble(spec, data, ros2_control=True,
+ use_fake_hardware=False)
+ spec['systems']['wrist']['joints']['arm'][joints[0]] = dict(idx=9)
+ with pytest.raises(xacro.XacroException, match='duplicate joint assignment'):
+ support.assemble(spec, data, ros2_control=True, use_fake_hardware=True)
+ spec['systems']['wrist']['joints']['arm']['missing'] = spec['systems']['wrist']['joints']['arm'].pop(
+ joints[0])
+ with pytest.raises(xacro.XacroException, match='unknown joint'):
+ support.assemble(spec, data, ros2_control=True, use_fake_hardware=True)
+ del spec['systems']['wrist']['joints']['arm']['missing']
+ for invalid_idx in (-1, True, 1.5):
+ spec['systems']['wrist']['joints']['tool']['joint1']['idx'] = invalid_idx
+ with pytest.raises(xacro.XacroException, match='non-negative integer idx'):
+ support.assemble(spec, data, ros2_control=True,
+ use_fake_hardware=True)
+ spec['systems']['wrist']['joints']['tool']['joint1']['idx'] = 1
+ with pytest.raises(xacro.XacroException, match='duplicate idx'):
+ support.assemble(spec, data, ros2_control=True, use_fake_hardware=True)
+
+
+def test_hardware_parameters_follow_input():
+ spec, data = control_input()
+ control = spec['systems']['fixture_system']
+ for prefix, can_interface in [('openarm_left_', 'can_left_test'),
+ ('openarm_right_', 'can_right_test')]:
+ control.update(can_interface=can_interface, can_fd=False)
+ for name in ('arm', 'tool'):
+ spec[name]['prefix'] = prefix
+ robot = support.assemble(spec, data, ros2_control=True,
+ use_fake_hardware=False)
+ hardware = robot.find('ros2_control/hardware')
+ assert hardware.find('plugin').text == control['hardware_plugin']
+ params = {p.get('name'): p.text for p in hardware.findall('param')}
+ assert len(params) == len(hardware.findall('param'))
+ assert params['can_interface'] == control['can_interface']
+ assert params['can_fd'].lower() == 'false'
+ assert params['arm_prefix'] == prefix.removeprefix('openarm_')
+ assert params['ee_type'] == spec['tool']['product']
+ for name, gains in data['arm']['control/control_gains.yaml'].items():
+ for key, value in gains.items():
+ assert float(params[key+name.removeprefix('joint')]) == value
+
+ for side in ('left', 'right'):
+ spec['systems'] = {f'openarm_{side}_hardware_interface': control}
+ control.update(can_fd=True)
+ overrides = dict(left_can_interface='runtime_left',
+ right_can_interface='runtime_right', can_fd=False)
+ robot = support.assemble(spec, data, ros2_control=True,
+ use_fake_hardware=False, **overrides)
+ hardware = robot.find('ros2_control/hardware')
+ params = {p.get('name'): p.text for p in hardware.findall('param')}
+ assert params['can_interface'] == overrides[side + '_can_interface']
+ assert params['can_fd'].lower() == 'false'
+
+ robot = support.assemble(spec, data, ros2_control=True,
+ use_fake_hardware=True, fake_sensor_commands=True)
+ hardware = robot.find('ros2_control/hardware')
+ assert hardware.find('plugin').text == 'mock_components/GenericSystem'
+ params = {p.get('name'): p.text for p in hardware.findall('param')}
+ assert params['mock_sensor_commands'].lower() == 'true'
+ assert float(params['position_state_following_offset']) == 0.0
+ assert 'fake_sensor_commands' not in params and 'state_following_offset' not in params
+
+ control.update(command_interfaces=[
+ 'position'], state_interfaces=['position'])
+ robot = support.assemble(
+ spec, data, ros2_control=True, use_fake_hardware=True)
+ for joint in robot.findall('ros2_control/joint'):
+ assert [i.get('name') for i in joint.findall(
+ 'command_interface')] == ['position']
+ assert [i.get('name')
+ for i in joint.findall('state_interface')] == ['position']
diff --git a/test/test_models.py b/test/test_models.py
new file mode 100644
index 00000000..46ae330d
--- /dev/null
+++ b/test/test_models.py
@@ -0,0 +1,43 @@
+# Copyright 2026 Enactic, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from pathlib import Path
+from urllib.parse import urlparse
+
+from support import ROOT, expand, packages
+
+
+def test_shipped_presets_expand_and_resolve_resources():
+ robots = []
+ for version in ('v1.0', 'v2.0'):
+ folder = ROOT/f'assets/robot/openarm_{version}/config/robot_presets'
+ robots.append((version, '', expand(version=version, ros2_control=True,
+ use_fake_hardware=True, emit_grasp_frame=True)))
+ for path in sorted(folder.glob('*.yaml')):
+ robot = expand(version=version, robot_preset=path.stem, ros2_control=True,
+ use_fake_hardware=True, emit_grasp_frame=True)
+ robots.append((version, path.stem, robot))
+ for path in sorted((ROOT/'assets/end_effector').glob('*/urdf/*_standalone.urdf.xacro')):
+ robots.append(('standalone', path.name, expand(
+ entry=str(path.relative_to(ROOT)))))
+ for version, name, robot in robots:
+ for mesh in robot.findall('.//geometry/mesh'):
+ uri = urlparse(mesh.get('filename'))
+ if uri.scheme == 'package':
+ share = ROOT if uri.netloc == 'openarm_description' else Path(
+ packages.get_package_share_directory(uri.netloc))
+ assert (share/uri.path.lstrip('/')
+ ).is_file(), (version, name, mesh.attrib)
+ elif uri.scheme in ('', 'file'):
+ assert Path(uri.path).is_file(), (version, name, mesh.attrib)