Parallel robots in ROS

Hi everyone,

in our lab we developed a small educational kit to build a wide variety of parallel robots, it is called PARA-ENGINEER. These robots serve as compact examples for teaching and demonstrations. Some of them can be seen in the image below. Until now, the entire software stack was implemented as a single Python script handling user input, applications, motion and trajectory planning, kinematics, and stepper control. We are currently migrating this system to a modular, ROS-based architecture.

Using ROS with parallel robots presents several challenges, especially when the goal is to support arbitrary kinematic structures. One of the first major issues we encountered was the description of closed kinematic loops in URDF. There are existing approaches to address this limitation, such as using SDFormat, but they did not meet our requirement of a simple, structure-only description without assuming prior knowledge of a specific configuration .

In common parallel robot modelling, closed loops are typically converted into tree structures by “cutting” the loops and introducing additional loop-closure equations. URDF is well suited to describe the resulting tree structure. However, it lacks a way to explicitly describe the cuts themselves .

To address this, we introduced a new constraint element in our URDF version. This element is derived from the standard joint description and contains origins and axes for both parent and child frames. It allows us to define the two cut frames and reconnect them using different joint types. A second axis is included where necessary, e.g. to describe universal joints.

<constraint name=“Name” type=“Type”>
<parent link=“Parent_Name”/>
<parent_origin xyz=“Offset_Child” rpy=“RPY_Parent”/>
<parent_axis xyz=“Joint_Axis_Parent”/>
<child link=“Child_Name”/>
<child_origin xyz=“Offset_Child” rpy=“RPY_Child”/>
<child_axis xyz=“Joint_Axis_Child”/>
</constraint>

By adding new elements rather than modifying existing ones, all standard ROS tools remain fully compatible: they simply ignore the additional constraint elements. Constraint solving is handled in a separate package. We use a Newton–Raphson algorithm to solve the loop-closure equations and compute a valid robot state based on the current configura tion.

We are currently validating this approach using Rviz, while working on implementing our solution into the ROS framework. We are preparing a pull request for URDFDOM and URDFDOM-Headers with our proposed extensions. In future projects, we want to add the constraints and solver to the robot-state-publisher and implement an additional kinematics solver for MoveIt to consider the passive structures of the robot. Additionally, we want to validate the results with our industrial grade parallel robots and use it for further projects and research.

Best regards

Fabian Finkbeiner

6 Likes

Can you give us links to the repositories with the code if it is open-source?

Hi Fabian,

This is some very interesting work! My thesis also involves closed-loop kinematics, and I spent quite a bit of time trying to solve it both in simulation and on real hardware while still sticking to the common ROS methodology.

The approach I ended up taking was to keep the URDF tree ROS-compatible while enforcing the closed-loop constraints separately through the control and kinematics layers, while using the gz_attach_links plugin to recreate the missing closed-loop constraints inside simulation. This allowed me to keep using the standard ROS 2 tooling pipeline (robot_state_publisher, ros2_control, RViz, Gazebo, etc.) and maintain the same architecture between simulation and the real hardware.

Here is a demo I published that could maybe serve as a guide:
ros2_closed_loop_ws

I always knew this approach was not perfect and came with some limitations, so your suggested direction actually looks very interesting and seems like it could solve many of those issues. I’d be very happy to talk more about it and hopefully contribute as well!

I am double checking, which repositories i can put open source. I will post the links here as soon as possible. Use these links to find our urdfdom_headers and urdfdom fork.

Hi Tamir,
your approach looks interesting as well. I’ll have a look into it in the next few days. If you want, we can have a quick chat about the approaches, their limitations and how to solve these issues. Just write me a message so we can schedule a meeting.

1 Like

I’ve open-sourced my packages. An example of my approach can be found here:

1 Like

Hi Fabian,
This is a brilliant approach. Trying to hack closed kinematic loops into standard URDF trees using dummy joints has always been a nightmare, and your <constraint> extension plus the Newton-Raphson solver is incredibly elegant.

I’m working on a related problem space but on the execution side, which might be highly relevant as you move this from RViz validation to your industrial-grade physical parallel robots.

In parallel/closed-loop mechanisms, even minor physical execution errors (like a stepper motor skipping a step, or slight trajectory timing jitter) can cause massive antagonistic forces/internal stress across the passive linkages, sometimes damaging the structure before the controller realizes it.

I recently open-sourced runtime_integrity, a zero-friction ROS 2 physical execution auditor. While I initially built it to monitor /cmd_vel vs /odom consistency for mobile robots (detecting things like wheel slip or loc jumps), its core architecture is just a kinematic intent vs. physical feedback residual observer.

It seems like it would be a perfect fit to extend this concept to closed-loop parallel robots: observing the residual between the commanded joint trajectory (from your solver/steppers) and the actual encoder feedback (/joint_states). If one arm lags and breaks the physical loop constraints, the observer could instantly flag a KINEMATIC_LOOP_VIOLATION diagnostic before physical damage occurs.

Would love to hear your thoughts on whether you see execution-consistency monitoring as a critical bottleneck as you port this to physical hardware.

Great work again!

Disclosure: I work on Modeloop, so discount any tooling bias accordingly.

In my opinion, monitoring the commanded-vs-encoder position residual is often a weak proxy for safety. In a closed kinematic loop, what actually destroys the hardware is the constraint reaction force. The real danger is that internal preload can hide in the null space of the actuation: you could have two legs effectively “crushing” each other while the platform pose and task-space wrench appear perfectly fine.

Secondly, an observe-only approach cannot provide protection. Logging to CSV is invaluable for Sim2Real debugging, but the failure mode in parallel robots is often “force builds up faster than the controller can react.” Therefore, the protective monitor shouldn’t live at the telemetry rate; it needs to be integrated directly into the control loop through independent high-frequency safety channel with the authority to trigger an immediate state transition (e.g., E-Stop or Gravity Compensation).

Finally, for consistency, the monitor should be derived from the same constraint model as your Newton-Raphson solver. If the solver and the monitor are authored separately, they will inevitably drift.

As far as i am aware of antagonistic forces in parallel robots, these mostly appear when a redundant actuated structure is used, for example in cable-driven parallel robots. In such cases, a model-based controller with an antagonistic filter is used to eliminate the forces in the null space and prevent significant opposing forces from building up.
To use these parallel robots one task would be to include such a controller with an antagonistic filter to ros2_control using a URDF-based model.

I thought it might be useful to share a small repository for others following this discussion:

The repository contains a closed-loop simulation demo with three different robot mechanisms at the moment, together with setup instructions and implementation details. The work was put together over the last few weeks while discussing closed-loop mechanisms with @hhn_finkbeiner and exploring different approaches to the problem.

My hope is that it can provide another hands-on example for people interested in experimenting with closed-loop mechanisms in ROS 2 and Gazebo.

I’d be interested to hear about other approaches and experiences from the community as well.