June 26, 2026
Sony AI's Ace (Nature cover, beat a pro table tennis player) — running on ROS 2

Can you believe this is running ROS 2? :ping_pong:

Sony’s Ace Robot Beats Top Table Tennis Pros in Real Matches

Sony AI’s Ace just landed on the cover of Nature — the first robot ever to beat a professional table tennis player.

Let that sink in for a second:

• It tracks a ball moving at 20 m/s with spin over 9,000 rpm
• Perceives it in 10.2 ms (event-based vision)
• Decides and swings on a 1 kHz control loop
• And returns the ball at up to 19.6 m/s

This is physical AI right at the edge of what’s possible — and we’ve been working on the ROS 2 integration and support underneath it. The fact that ROS 2 holds up in a system this demanding says a lot about where the ecosystem is heading.

Huge respect to the Sony AI team. Take a look :backhand_index_pointing_down:

3 posts - 3 participants

Read full topic

by tomoyafujita on June 26, 2026 12:51 AM

June 25, 2026
A tutorial to make your quadruped robot on ROS

Hello guys !

I made a tutorial to make your own quadruped using ros2 jazzy !

If you have any feed back I am happy to hear it

1 post - 1 participant

Read full topic

by joschma on June 25, 2026 05:05 PM

Rclnodejs 2.1: Native ESM for a Web-Native ROS 2 SDK

Hi all,

rclnodejs 2.1.0 is out — and it’s a step toward making rclnodejs a web-native SDK for ROS 2: a platform for bringing ROS 2 to the browser and the modern JavaScript ecosystem. With 2.1.0, the whole package is now native ESM, so building web dashboards, teleop UIs, and browser bridges on ROS 2 feels native to today’s web tooling — with the full ROS 2 runtime still underneath whenever you need real nodes.

TL;DR — 2.1.0 makes rclnodejs native ESM end-to-end. import rclnodejs from 'rclnodejs' just works, the browser SDK (rclnodejs/web) brings ROS 2 to the web, and existing require() nodes keep running untouched — the full ROS 2 runtime is still underneath.

:sparkles: A web-native SDK for ROS 2

  • ROS 2 on the web — reach ROS 2 from a web page with rclnodejs/web: typed APIs over WebSocket, no proxy, no codegen.
  • Native ESM — first-class import and top-level await, ready for Vite/esbuild and the modern web toolchain.
  • Full ROS 2 runtime underneath — real nodes, pub/sub, services, actions, parameters, lifecycle, whenever you need them.
  • Backward compatible — every existing CommonJS (require) project upgrades with zero code changes.

:package: One package, both module systems

// Modern Node / browser — ESM
import rclnodejs from 'rclnodejs';        // full ROS 2 node API
import { connect } from 'rclnodejs/web';  // typed browser SDK
// Existing CommonJS nodes — unchanged
const rclnodejs = require('rclnodejs');

:compass: Where this is heading

Each release moves rclnodejs one step closer to a typed, web-native way into ROS 2:

  • 2.0.0 :globe_with_meridians: — a typed browser SDK (rclnodejs/web) backed by a capability runtime that exposes only what web.json declares, with HTTP call / publish for non-JS clients.
  • 2.1.0 :high_voltage: — native ESM across the whole package, so rclnodejs sits naturally alongside the rest of your web stack.

The arc: from “a Node.js client that happens to run in browsers”“a typed, allow-listed Web SDK for ROS 2”

:wrench: Try it

npm i rclnodejs

Feedback welcome — especially from anyone wiring ROS 2 into web frontends. :raising_hands:

Cheers,
Minggang

1 post - 1 participant

Read full topic

by minggangw on June 25, 2026 02:19 AM

Anomaly Detection. Beta testers wanted

Hi, I used to work at a robotics startup that built robotic dishwashers. (https://armstrong.ai/) And part of my job was to set up diagnostics, monitoring and alerting.

Aside from not being the most interesting part of my job, it was just plain tedious to manually set (and continually tune) thresholds for various signals, topics, etc. I frequently thought it would be nice to have a system that would automate that part of my job and now that the company has closed, I built it.

Now I have reached the point where the useful next step is real robots. The system performs well on recorded public datasets and on some production infrastructure (see below), but what I do not have yet is enough hours on a variety of real robots, doing real work.

Details are here at the Transitive Robotics website:

What it is

The system watches your robot’s topics and tells you when something is wrong. No threshold tuning, no hardcoded rules. It learns what normal looks like on your robot, then flags and reports anomalies in real time.

How to get involved

Reply to this thread or email shane@targetnode.ai. I will help you get it installed and monitored.

What you get and what I am asking for

What you get:

  • Anomaly detection for free on your robot with no manual threshold tuning to maintain.

  • Direct influence over the direction of the system/project. I want to know what is missing, what is confusing, and what breaks on real robots in production.

What I am asking for:

  • Honest and detailed feedback

Where it has been tested

I evaluated the system against public datasets that cover real hardware faults across very different platforms. The system has been tested successfully on the following datasets:

  • CASPER. A UR3e collaborative robot arm with real IMU fault data, from Cardiff University. (paper)

  • PADRE, Parrot Bebop 2. Real propeller damage on a quadrotor, recorded from onboard IMUs. (paper)

  • PADRE, 3DR Solo. Real propeller damage on a second quadrotor airframe, with IMU and barometer data.

  • ALFA. A CarbonZ T-28 fixed-wing aircraft with real engine and actuator faults, from Carnegie Mellon University’s AirLab. (data)

  • UAV-SEAD. A large set of real PX4 flights with naturally occurring state-estimation anomalies, from Istanbul Technical University. (paper)

Additionally, I am running the system on my production servers. They are not robots, per se, but they are live production systems that get used every day. Right now the system is watching CPU, memory, disk/network operations (29 signals total) all without me setting or tuning thresholds. In the last 200 hours of operation (since Tuesday, June 16, 2026) there have been no false alerts.

Thanks for checking out this post and if you have any questions, reach out to me at shane@targetnode.ai

2 posts - 2 participants

Read full topic

by Shane_Hill on June 25, 2026 12:01 AM

June 24, 2026
VL53L0X Time-of-Flight sensor as a Nav2 obstacle layer (ESP32 + ROS 2 Humble)

demo

Sharing a small open-source project that integrates a low-cost VL53L0X Time-of-Flight sensor into the Nav2 costmap as an obstacle source, in case it’s useful to anyone working with cheap range sensors on small robots.

Pipeline

VL53L0X --I2C–> ESP32 --USB serial–> serial_bridge → sensor_msgs/Range
→ tof_to_scan → sensor_msgs/LaserScan → nav2_costmap_2d::ObstacleLayer

What’s included

  • ESP32 firmware (Arduino, Pololu VL53L0X library) streaming distance over serial with sensor-disconnect recovery
  • An rclpy serial-bridge node publishing sensor_msgs/Range, with a threaded reader and automatic serial reconnect
  • A Range → LaserScan converter that synthesizes a configurable narrow fan from the single beam (default ±0.15 rad, 31 rays), emitting +inf for out-of-range readings so the obstacle layer can raytrace-clear
  • A full Nav2 costmap config wiring the scan into local and global costmaps (marking + clearing, inf_is_valid: true)
  • RViz config and a troubleshooting guide

Built and tested on ROS 2 Humble / Ubuntu 22.04. Python packages (ament_python).

Scope / limitations (up front)

This is a supplementary obstacle sensor, not a LiDAR replacement — a single narrow-FOV ToF sees one thin cone.

One thing I’d be curious about others’ experience on: raytrace clearing on a stationary base leaves residual cells at the edges of the cone, since the clearing rays never cross them. It resolves once the robot moves and the cone sweeps, but I’d be interested whether anyone has handled static-case clearing for single-beam sensors more elegantly. Widening the FOV and increasing ray count helped, but felt like a workaround.

A config gotcha that may save someone time: obstacle marking worked but clearing silently didn’t, until I set obstacle_max_range < raytrace_max_range, with raytrace_max_range equal to the sensor’s true range_max. A mismatch there breaks clearing while marking still functions, so it presents as “obstacles never disappear.”

Repo (MIT): GitHub - Arjunros/nav2-vl53l1x-obstacle-layer: Low-cost VL53L0X ToF sensor as a Nav2 obstacle layer via ESP32 · GitHub

Feedback and suggestions welcome.

1 post - 1 participant

Read full topic

by Arjun_R on June 24, 2026 07:12 PM

Embeddable React telemetry components — a browser ground station for MAVROS

I maintain Altara, a set of MIT-licensed React components for real-time robotics telemetry (PFD, moving map, gauges, event log), and I wrote up building a small drone ground station with them that talks to MAVROS over rosbridge.

The thing I was trying to solve: I wanted a status dashboard our team could open in a browser tab and drop into our own app, rather than running a separate native GCS. So the components are embeddable and themeable rather than a standalone tool.

Writeup (the rosbridge/MAVROS wiring is the interesting part): [ Building a real-time drone ground control station in React - DEV Community ]
Live demo: [ Altara Demo ] · Source: [https://github.com/JayaSaiKishanChapparam/altara\]

If you’ve built browser dashboards for a ROS2 stack, I’d like to know what you ended up reading off your topics, and where existing tools forced you into a standalone app when you wanted something embedded.

2 posts - 2 participants

Read full topic

by Jaya_Sai_Kishan on June 24, 2026 02:52 PM

KRS Unleashed: Easier Hardware Acceleration Prototyping on FPGA

Hey All,

I want to present KRS Unleashed, the tool I am now developing/refactoring/extending since 1 year as part of my PhD.

Some of you might still know KRS (short for Kria Robotic Stack as originally developed by Xilinx/AMD for their Kria platform) as the toolchain developed until 2023 by the ROS 2 Hardware Acceleration Working Group · GitHub .

(Short Summary for those who don’t)


It was a proof-of-concept framework that allowed to synthesize bitstreams, create a sysroot and cross-compile application against it to create robotics applications running on KV260, KR260 (and also claimed jetson, Ultra96v2,.. but i have never tested/verified that so far). So basically the main point of it is to replace this “docker container to compile” flow with ROS 2 colcon mixin and in parallel integrate all the necessary and optional things for hardware acceleration like sysroot creation or vendor-driven bitstream synthesis in a ROS 2 command.


The flow works, but I found it really hard to use:

  • long build times whenever you cleaned your build/install folders, as even the sysroot and bitstream needed to resynthesize when you just changed a variable in a package (if you know what you are doing you can keep the untouched compiled packages but its not really stable nor trivial)
  • cross-references and dependency cycles made it hard to change configuration like different Vitis version, other firmware OS,..
  • hard to understand what each package actually did and which ones were necessary for your task - the original guide simply copied all available packages in

Basically it wasn’t really fun to use and whenever you start with a new project, you fight cmake configurations for a while until you can start coding..


My tool refactored these individual components into 3 separate logical workspaces:

  • os → for firmware and sysroot creation - allows to reuse across projects (save lots of memory space, no rebuild necessary, parallel development possible by different team)
  • vitis → vendor-driven toolchain necessary to automate your “accelerator bitstream flow”. I refactored also the automation into a nice Python CLI scripted way such that I can also use the Vitis workspace and manually adjust things, but this is more a FPGA developer nice-to-have. Could also be replaced with a flow for other accelerators
  • krs → lightweight integration of firmware via single package, that provides the colcon mixin integration. Further a tracetools-kernels package that allows to trace arbitrary code regions in any ROS 2 application extending ros-tracing.

You can also use any of these components in isolated areas - I use for example also vitis + os for standalone faster iteration on host code variations. It might be a little bit harder to setup for the first time, but I can iterate really fast with it (built times up to 80x faster) and the setup is the same for all projects so once you understand it, its relatively easy and doesn’t require changes all over the project but just in very small, well defined areas.


I also created a Hackster Series for the brave.

I continue to develop it, current public version is still humble but I already have an internal jazzy version which I will release once I published a new paper.

Github: GitHub - TUD-ADS/KRS-Unleashed · GitHub

Hackster Series (5 Parts): 1. Getting Started

Paper: https://ieeexplore.ieee.org/document/11231288/

1 post - 1 participant

Read full topic

by B4demeister on June 24, 2026 01:45 PM

June 23, 2026
Minimum CMake version to support Humble at this time

REP 2000 specifies MacOS support for CMake 3.14.4 in Humble:

This is the lowest number for the whole Humble release.

However, MacOS has this note:

" ** " means that the dependency may see multiple version changes, because the dependency uses a package manager that continually updates the dependency without a stable API.

I don’t work with MacOS myself, so I don’t know how it behaves. Is it still needed nowadays to support 3.14.4 to get full support for Humble on MacOS, or can I just ignore this and upgrade to 3.16.3 from Focal (assuming that MacOS currently uses a much newer version)?

And on the other hand: Homebrew Formulae: cmake shows CMake version 4.3.4 . Does it mean that even people building Humble on MacOS will use this version? So do I need to make sure the package also builds with this version?

1 post - 1 participant

Read full topic

by peci1 on June 23, 2026 09:51 AM

Dual-Arm Nero Reinforcement Learning in Isaac Lab: Reach Task Training Example

Robotic manipulation remains one of the most important research directions in embodied AI. While traditional kinematics-based controllers provide stable motion execution, they often struggle in unstructured environments where adaptability is required.

Recent advances in Reinforcement Learning (RL) have enabled robotic arms to learn task-oriented behaviors directly from interaction, making it possible to achieve robust control policies without manually designing every motion strategy.

In this project, we extend the original SO-ARM101 Isaac Lab implementation by integrating the AgileX Dual-Arm Nero Manipulator, allowing developers to quickly train and validate dual-arm RL policies using NVIDIA Isaac Lab.

Reposity

Open-source implementation:

GitHub - smalleha/isaac_so_arm101: Isaac Lab external project for SO-ARM100/101 arm robot. · GitHub

Project Structure


├── robots

│   ├── dual_nero

│   │   ├── dual_nero.py

│   │   ├── __init__.py

│   │   ├── meshes

│   │   └── urdf

│   │       └── dual_nero.urdf

├── scripts

│   ├── rl_games

│   │   ├── play.py

│   │   └── train.py

│   └── zero_agent.py

├── tasks

│   ├── __init__.py

│   └── reach

│       ├── agents

│       ├── dual_nero_joint_pos_env_cfg.py

│       ├── dual_nero_reach_env_cfg.py

│       ├── __init__.py

│       └── mdp

└── ui_extension_example.py

Key additions include:

Column 1 Column 2
Component Description
rl_games RL-Games training framework
dual_nero_reach_env_cfg.py Reach task environment definition
dual_nero_joint_pos_env_cfg.py Joint position control configuration
dual_nero Dual-arm robot model

3. Importing the Robot into Isaac Lab

3.1 Preparing the URDF

Before importing the robot into Isaac Lab, mesh references inside the URDF should be converted to relative paths.

For example:


  <link name="base_link">

    <inertial>

      <origin rpy="0 0 0" xyz="-0.0592395620981769 -0.068642440505388 0.0562764736144042"/>

      <mass value="4.46524857458863"/>

      <inertia ixx="0.0608289280191989" ixy="-2.54649959130438E-06" ixz="1.11851948046933E-07" iyy="0.0218722514454004" iyz="-0.000689477252402357" izz="0.0680524540174318"/>

    </inertial>

    <visual>

      <origin rpy="0 0 0" xyz="0 0 0"/>

      <geometry>

        <mesh filename="../meshes/base_link.dae"/>

      </geometry>

      <material name="">

        <color rgba="0.776470588235294 0.756862745098039 0.737254901960784 1"/>

      </material>

    </visual>

    <collision>

      <origin rpy="0 0 0" xyz="0 0 0"/>

      <geometry>

        <mesh filename="../meshes/base_link.dae"/>

      </geometry>

    </collision>

  </link>

This ensures that the asset loader can correctly locate mesh resources during simulation.

3.2 Creating the Robot Configuration

Next, create a robot configuration file:

isaac_so_arm101/robots/dual_nero/dual_nero.py

This file defines:

  • Robot articulation properties

  • Joint stiffness and damping

  • Actuator configuration

  • Initial joint states

  • Gripper settings

The resulting DUAL_NERO_CFG object becomes the robot asset used by Isaac Lab during training.

from pathlib import Path

import isaaclab.sim as sim_utils
from isaaclab.actuators import ImplicitActuatorCfg
from isaaclab.assets.articulation import ArticulationCfg

TEMPLATE_ASSETS_DATA_DIR = Path(__file__).resolve().parent

DUAL_NERO_CFG = ArticulationCfg(
    spawn=sim_utils.UrdfFileCfg(
        fix_base=True,
        merge_fixed_joints=False,
        replace_cylinders_with_capsules=True,
        asset_path=f"{TEMPLATE_ASSETS_DATA_DIR}/urdf/dual_nero.urdf",
        activate_contact_sensors=False, # set as false while waiting for capsule implementation
        rigid_props=sim_utils.RigidBodyPropertiesCfg(
            disable_gravity=False,
            max_depenetration_velocity=5.0,
        ),
        articulation_props=sim_utils.ArticulationRootPropertiesCfg(
            enabled_self_collisions=True,
            solver_position_iteration_count=8,
            solver_velocity_iteration_count=0,
        ),
        joint_drive=sim_utils.UrdfConverterCfg.JointDriveCfg(
            gains=sim_utils.UrdfConverterCfg.JointDriveCfg.PDGainsCfg(stiffness=0, damping=0)
        ),
    ),
    init_state=ArticulationCfg.InitialStateCfg(
        rot=(1.0, 0.0, 0.0, 0.0),
        joint_pos={
                "left_joint.*": 0.0,
                "right_joint.*": 0.0,
                "left_gripper_joint.*": 0.0,  
                "right_gripper_joint.*": 0.0,  
        },
        # Set initial joint velocities to zero
        joint_vel={".*": 0.0},
    ),
    actuators={
            "arm": ImplicitActuatorCfg(
                joint_names_expr=["left_joint.*", "right_joint.*"],
                effort_limit=25.0, 
                velocity_limit=1.5,
               
                stiffness={
                    "left_joint1": 200.0, 
                    "left_joint2": 170.0,
                    "left_joint3": 120.0,
                    "left_joint4": 80.0,
                    "left_joint5": 50.0,
                    "left_joint6": 20.0,
                    "left_joint7": 10.0,
                    "right_joint1": 200.0, 
                    "right_joint2": 170.0,
                    "right_joint3": 120.0,
                    "right_joint4": 80.0,
                    "right_joint5": 50.0,
                    "right_joint6": 20.0,
                    "right_joint7": 10.0
                },
               
                damping={
                    "left_joint1": 100.0,
                    "left_joint2": 60.0,
                    "left_joint3": 70.0,
                    "left_joint4": 24.0,
                    "left_joint5": 20.0,
                    "left_joint6": 10.0,
                    "left_joint7": 5,
                    "right_joint1": 100.0,
                    "right_joint2": 60.0,
                    "right_joint3": 70.0,
                    "right_joint4": 24.0,
                    "right_joint5": 20.0,
                    "right_joint6": 10.0,
                    "right_joint7": 5,
                },
            ),
        "gripper": ImplicitActuatorCfg(
            joint_names_expr=["left_gripper_joint.*","right_gripper_joint.*"],
            effort_limit_sim=22,  # Increased from 1.9 to 2.5 for stronger grip
            velocity_limit_sim=1.5,
            stiffness=800.0,  # Increased from 25.0 to 60.0 for more reliable closing
            damping=20.0,  # Increased from 10.0 to 20.0 for stability
        ),

        },
    soft_joint_pos_limit_factor=0.9,
)

Create an init.py file inside the dual_nero directory so that Python recognizes it as a package.

4. Building the Reach Environment

Two environment configuration files are required:


tasks/reach/

├── dual_nero_joint_pos_env_cfg.py

└── dual_nero_reach_env_cfg.py

4.1 Joint Position Environment Configuration

dual_nero_joint_pos_env_cfg.py specifies:

  • Controlled joints

  • End-effector links

  • Action spaces

  • Command targets

import math

import isaaclab_tasks.manager_based.manipulation.reach.mdp as mdp
from isaaclab.utils import configclass
from isaac_so_arm101.robots import DUAL_NERO_CFG # noqa: F401   
from isaac_so_arm101.tasks.reach.dual_nero_reach_env_cfg import Dual_NeroReachEnvCfg
from isaaclab.assets.articulation import ArticulationCfg

@configclass
class Dual_Nero_ReachEnvCfg(Dual_NeroReachEnvCfg):
    def __post_init__(self):
        # post init of parent
        super().__post_init__()

        # switch robot to OpenArm
        self.scene.robot = DUAL_NERO_CFG.replace(prim_path="{ENV_REGEX_NS}/Robot",)

        # override rewards
        self.rewards.left_end_effector_position_tracking.params["asset_cfg"].body_names = ["left_gripper_base"]
        self.rewards.left_end_effector_position_tracking_fine_grained.params["asset_cfg"].body_names = [
            "left_gripper_base"
        ]
        self.rewards.left_end_effector_orientation_tracking.params["asset_cfg"].body_names = ["left_gripper_base"]

        self.rewards.right_end_effector_position_tracking.params["asset_cfg"].body_names = ["right_gripper_base"]
        self.rewards.right_end_effector_position_tracking_fine_grained.params["asset_cfg"].body_names = [
            "right_gripper_base"
        ]
        self.rewards.right_end_effector_orientation_tracking.params["asset_cfg"].body_names = ["right_gripper_base"]

        # override actions
        self.actions.left_arm_action = mdp.JointPositionActionCfg(
            asset_name="robot",
            joint_names=[
                "left_joint.*",
            ],
            scale=0.5,
            use_default_offset=True,
        )

        self.actions.right_arm_action = mdp.JointPositionActionCfg(
            asset_name="robot",
            joint_names=[
                "right_joint.*",
            ],
            scale=0.5,
            use_default_offset=True,
        )
        # override command generator body
        # end-effector is along z-direction
        self.commands.left_ee_pose.body_name = "left_gripper_base"
        self.commands.right_ee_pose.body_name = "right_gripper_base"

@configclass    
class Dual_Nero_ReachEnvCfg_PLAY(Dual_Nero_ReachEnvCfg):
    def __post_init__(self):
        # post init of parent
        super().__post_init__()
        # make a smaller scene for play
        self.scene.num_envs = 50
        self.scene.env_spacing = 2.5
        # disable randomization for play
        self.observations.policy.enable_corruption = False

4.2 Reach Task Definition

dual_nero_reach_env_cfg.py contains the full RL environment definition.

This includes:

1.Scene Configuration

  • Ground plane

  • Lighting

  • Robot asset

2.Command Generation

3.Observation Space

4.Reward Design

5.Curriculum Learning

6.Episode Settings


import math
from dataclasses import MISSING

import isaaclab.sim as sim_utils
from isaaclab.assets import ArticulationCfg, AssetBaseCfg
from isaaclab.envs import ManagerBasedRLEnvCfg
from isaaclab.managers import ActionTermCfg as ActionTerm
from isaaclab.managers import CurriculumTermCfg as CurrTerm
from isaaclab.managers import EventTermCfg as EventTerm
from isaaclab.managers import ObservationGroupCfg as ObsGroup
from isaaclab.managers import ObservationTermCfg as ObsTerm
from isaaclab.managers import RewardTermCfg as RewTerm
from isaaclab.managers import SceneEntityCfg
from isaaclab.managers import TerminationTermCfg as DoneTerm
from isaaclab.scene import InteractiveSceneCfg
from isaaclab.utils import configclass
from isaaclab.utils.noise import AdditiveUniformNoiseCfg as Unoise

import isaaclab_tasks.manager_based.manipulation.reach.mdp as mdp
##
# Scene definition
##
@configclass
class Dual_NeroReachSceneCfg(InteractiveSceneCfg):
    """Configuration for the scene with a robotic arm."""

    # world
    ground = AssetBaseCfg(
        prim_path="/World/ground",
        spawn=sim_utils.GroundPlaneCfg(),
        init_state=AssetBaseCfg.InitialStateCfg(pos=(0.0, 0.0, 0)),
    )

    # robots
    robot: ArticulationCfg = MISSING

    # lights
    light = AssetBaseCfg(
        prim_path="/World/light",
        spawn=sim_utils.DomeLightCfg(color=(0.75, 0.75, 0.75), intensity=2500.0),
    )
##
# MDP settings
##
@configclass
class CommandsCfg:
    """Command terms for the MDP."""

    left_ee_pose = mdp.UniformPoseCommandCfg(
        asset_name="robot",
        body_name=MISSING,
        resampling_time_range=(4.0, 4.0),
        debug_vis=True,
        ranges=mdp.UniformPoseCommandCfg.Ranges(
            pos_x=(0.5, 0.5),
            pos_y=(0.15, 0.25),
            pos_z=(0.3, 0.5),
            roll=(-math.pi / 6, math.pi / 6),
            pitch=(3 * math.pi / 2, 3 * math.pi / 2),
            yaw=(8 * math.pi / 9, 10 * math.pi / 9),
        ),
    )

    right_ee_pose = mdp.UniformPoseCommandCfg(
        asset_name="robot",
        body_name=MISSING,
        resampling_time_range=(4.0, 4.0),
        debug_vis=True,
        ranges=mdp.UniformPoseCommandCfg.Ranges(
            pos_x=(0.5, 0.5),
            pos_y=(-0.25, -0.15),
            pos_z=(0.3, 0.5),
            roll=(-math.pi / 6, math.pi / 6),
            pitch=(3 * math.pi / 2, 3 * math.pi / 2),
            yaw=(8 * math.pi / 9, 10 * math.pi / 9),
        ),
    )

@configclass
class ActionsCfg:
    """Action specifications for the MDP."""
    left_arm_action: ActionTerm = MISSING
    right_arm_action: ActionTerm = MISSING
@configclass
class ObservationsCfg:
    """Observation specifications for the MDP."""

    @configclass
    class PolicyCfg(ObsGroup):
        """Observations for policy group."""

        # observation terms (order preserved)
        left_joint_pos = ObsTerm(
            func=mdp.joint_pos_rel,
            params={
                "asset_cfg": SceneEntityCfg(
                    "robot",
                    joint_names=[
                        "left_joint.*",
                    ],
                )
            },
            noise=Unoise(n_min=-0.01, n_max=0.01),
        )

        right_joint_pos = ObsTerm(
            func=mdp.joint_pos_rel,
            params={
                "asset_cfg": SceneEntityCfg(
                    "robot",
                    joint_names=[
                        "right_joint.*",
                    ],
                )
            },
            noise=Unoise(n_min=-0.01, n_max=0.01),
        )

        left_joint_vel = ObsTerm(
            func=mdp.joint_vel_rel,
            params={
                "asset_cfg": SceneEntityCfg(
                    "robot",
                    joint_names=[
                        "left_joint.*",
                    ],
                )
            },
            noise=Unoise(n_min=-0.01, n_max=0.01),
        )
        right_joint_vel = ObsTerm(
            func=mdp.joint_vel_rel,
            params={
                "asset_cfg": SceneEntityCfg(
                    "robot",
                    joint_names=[
                        "right_joint.*",
                    ],
                )
            },
            noise=Unoise(n_min=-0.01, n_max=0.01),
        )
        left_pose_command = ObsTerm(func=mdp.generated_commands, params={"command_name": "left_ee_pose"})
        right_pose_command = ObsTerm(func=mdp.generated_commands, params={"command_name": "right_ee_pose"})
        left_actions = ObsTerm(func=mdp.last_action, params={"action_name": "left_arm_action"})
        right_actions = ObsTerm(func=mdp.last_action, params={"action_name": "right_arm_action"})

        def __post_init__(self):
            self.enable_corruption = True
            self.concatenate_terms = True

    # observation groups
    policy: PolicyCfg = PolicyCfg()

@configclass
class EventCfg:
    """Configuration for events."""

    reset_robot_joints = EventTerm(
        func=mdp.reset_joints_by_scale,
        mode="reset",
        params={
            "position_range": (0.5, 1.5),
            "velocity_range": (0.0, 0.0),
        },
    )

@configclass
class RewardsCfg:
    """Reward terms for the MDP."""
    left_end_effector_position_tracking = RewTerm(
        func=mdp.position_command_error,
        weight=-0.2,
        params={
            "asset_cfg": SceneEntityCfg("robot", body_names=MISSING),
            "command_name": "left_ee_pose",
        },
    )
    right_end_effector_position_tracking = RewTerm(
        func=mdp.position_command_error,
        weight=-0.25,
        params={
            "asset_cfg": SceneEntityCfg("robot", body_names=MISSING),
            "command_name": "right_ee_pose",
        },
    )
    left_end_effector_position_tracking_fine_grained = RewTerm(
        func=mdp.position_command_error_tanh,
        weight=0.1,
        params={
            "asset_cfg": SceneEntityCfg("robot", body_names=MISSING),
            "std": 0.1,
            "command_name": "left_ee_pose",
        },
    )
    right_end_effector_position_tracking_fine_grained = RewTerm(
        func=mdp.position_command_error_tanh,
        weight=0.2,
        params={
            "asset_cfg": SceneEntityCfg("robot", body_names=MISSING),
            "std": 0.1,
            "command_name": "right_ee_pose",
        },
    )
    left_end_effector_orientation_tracking = RewTerm(
        func=mdp.orientation_command_error,
        weight=-0.1,
        params={
            "asset_cfg": SceneEntityCfg("robot", body_names=MISSING),
            "command_name": "left_ee_pose",
        },
    )

    right_end_effector_orientation_tracking = RewTerm(
        func=mdp.orientation_command_error,
        weight=-0.1,
        params={
            "asset_cfg": SceneEntityCfg("robot", body_names=MISSING),
            "command_name": "right_ee_pose",
        },
    )
    # action penalty
    action_rate = RewTerm(func=mdp.action_rate_l2, weight=-0.0001)
    left_joint_vel = RewTerm(
        func=mdp.joint_vel_l2,
        weight=-0.0001,
        params={
            "asset_cfg": SceneEntityCfg(
                "robot",
                joint_names=[
                    "left_joint.*",
                ],
            )
        },
    )
    right_joint_vel = RewTerm(
        func=mdp.joint_vel_l2,
        weight=-0.0001,
        params={
            "asset_cfg": SceneEntityCfg(
                "robot",
                joint_names=[
                    "right_joint.*",
                ],
            )
        },
    )
@configclass
class TerminationsCfg:
    """Termination terms for the MDP."""
    time_out = DoneTerm(func=mdp.time_out, time_out=True)
@configclass
class CurriculumCfg:
    """Curriculum terms for the MDP."""
    action_rate = CurrTerm(
        func=mdp.modify_reward_weight,
        params={"term_name": "action_rate", "weight": -0.005, "num_steps": 4500},
    )

    left_joint_vel = CurrTerm(
        func=mdp.modify_reward_weight,
        params={"term_name": "left_joint_vel", "weight": -0.001, "num_steps": 4500},
    )

    right_joint_vel = CurrTerm(
        func=mdp.modify_reward_weight,
        params={"term_name": "right_joint_vel", "weight": -0.001, "num_steps": 4500},
    )
##
# Environment configuration
##
@configclass
class Dual_NeroReachEnvCfg(ManagerBasedRLEnvCfg):
    """Configuration for the reach end-effector pose tracking environment."""
    # Scene settings
    scene: Dual_NeroReachSceneCfg = Dual_NeroReachSceneCfg(num_envs=4096, env_spacing=2.5)
    # Basic settings
    observations: ObservationsCfg = ObservationsCfg()
    actions: ActionsCfg = ActionsCfg()
    commands: CommandsCfg = CommandsCfg()
    # MDP settings
    rewards: RewardsCfg = RewardsCfg()
    terminations: TerminationsCfg = TerminationsCfg()
    events: EventCfg = EventCfg()
    curriculum: CurriculumCfg = CurriculumCfg()

    def __post_init__(self):
        """Post initialization."""
        # general settings
        self.decimation = 2
        self.sim.render_interval = self.decimation
        self.episode_length_s = 24.0
        self.viewer.eye = (3.5, 3.5, 3.5)
        # simulation settings
        self.sim.dt = 1.0 / 60.0



\`\`\`



**### 4.3 Registering the Environment**



Register the task inside:\`src/isaac_so_arm101/tasks/reach/\__init_\_.py\`



\`\`\`PYTHON

gym.register(

    id="Isaac-Dual-Nero-Reach-v0",

    entry_point="isaaclab.envs:ManagerBasedRLEnv",

    kwargs={

        "env_cfg_entry_point":f"{\__name_\_}.dual_nero_joint_pos_env_cfg:Dual_Nero_ReachEnvCfg",

        "rsl_rl_cfg_entry_point": f"{agents.\__name_\_}.rsl_rl_ppo_cfg:ReachPPORunnerCfg",

        "rl_games_cfg_entry_point": f"{agents.\__name_\_}:rl_games_ppo_cfg.yaml",



    },

    disable_env_checker=True,

)

5. Training the Reach Policy

Step 1.Activate the Isaac Lab Environment


conda activate env_isaaclab

Step 2.Navigate to the project directory:


cd isaac_so_arm101

Step 3.Train the whole project

Option 1:RSL-RL

  • Train:

uv run train \

    --task Isaac-Dual-Nero-Reach-v0 \

    --headless

  • Evaluate:

uv run play \

    --task Isaac-Dual-Nero-Reach-v0

  • Training result:

dual_nero_rsl_rl.gif

dual_nero_rsl_rl

Option 2: RL-Games

  • Train:

python3 scripts/rl_games/train.py \
    --task Isaac-Dual-Nero-Reach-v0 \
    --headless

  • Evaluate:

python3 scripts/rl_games/play.py \
    --task Isaac-Dual-Nero-Reach-v0
  • Training result:

dual_nero_rl_games.gif

dual_nero_rl_games

6. Results and Observations

Both frameworks successfully learn the dual-arm reaching task.

However, in our experiments:

  • RL-Games converges faster

  • Motion trajectories appear smoother

  • Final reaching accuracy is generally higher

For relatively complex robot morphologies such as dual-arm manipulators, RL-Games currently provides more stable performance and is recommended as the default training backend.

FAQ

Q1: Why is my Dual-Nero robot collapsing or shaking violently after loading the URDF?

This is usually caused by incorrect actuator parameters or unrealistic inertial properties.

Common causes include:

  1. Joint stiffness set too high

  2. Damping values too low

  3. Incorrect mass distribution in the URDF

  4. Self-collision configuration issues

  5. Unstable simulation timestep

Before starting RL training, verify that the robot can remain stable under gravity using only PD control.

Quick check: If the robot cannot stand still without RL, the issue is likely in the robot model rather than the training algorithm.

Q2: Why does the reward improve, but the robot never reaches the target accurately?

A rising reward does not always indicate successful task completion.

Typical reasons include:

  • Reward weights are unbalanced

  • Orientation rewards dominate position rewards

  • Action penalties are too strong

  • Command sampling range is too large

  • End-effector link is incorrectly configured

In most reach tasks, incorrect reward shaping is the primary reason for poor final accuracy.

Q3: How do I verify that the end-effector link is configured correctly?

One of the most common mistakes in Isaac Lab reach tasks is assigning the wrong end-effector body.

For Dual-Nero, the target link should be:


left_gripper_base

right_gripper_base

Symptoms of an incorrect configuration include:

  • Reward remains low

  • Robot moves randomly

  • Training appears to converge but fails visually

  • End-effector does not move toward the target marker

Always verify the body name in Isaac Sim before launching large-scale training.

Q4: Why does RL-Games perform better than RSL-RL for this task?

Both frameworks are PPO-based, but their implementations differ.

For large-scale manipulation environments:

RL-Games generally scales better with thousands of parallel environments

PPO updates are often more stable

Training throughput is higher on modern GPUs

For Dual-Nero reach experiments, RL-Games typically achieves smoother trajectories and faster convergence.

However, results may vary depending on reward design and task complexity.

Q5: My policy works in simulation but fails on the real robot. Why?

This is the most common Sim-to-Real issue.

Possible causes include:

  • Joint friction mismatch

  • Encoder noise

  • Latency differences

  • Payload variations

  • Inaccurate motor models

  • Unmodeled cable effects

To improve transfer performance:

  • Apply domain randomization

  • Add observation noise

  • Randomize dynamics parameters

  • Validate trajectories at low speed first

Successful simulation training is only the first step toward real-world deployment.

:speech_balloon: Have Question?

If you encounter any issues with environment installation, parameter configuration, or RL training, feel free to leave your questions for further discussion.

1 post - 1 participant

Read full topic

by Agilex_Robotics on June 23, 2026 03:50 AM

June 22, 2026
Open-source ROS2 LiDAR robot vacuum cleaner

Hello, would you be interested in building a ROS2 vacuum cleaner robot?

If yes

  1. Build/develop vs convert existing?
  2. 3D print vs off-the-shelf?
  3. Convert existing - root or swap board?

I’d really appreciate your input.

As an example of what I’m doing

1 post - 1 participant

Read full topic

by iliao on June 22, 2026 06:12 PM

June 21, 2026
AIC Phase 1: How to run custom aic_model service in Flowstate with AIC_ROUTER_ADDR?

Hi Intrinsic / AIC team,

I’m working on AIC Phase 1 in Flowstate and trying to run my participant model as a custom Service instance named exactly aic_model.

The baseline AIC Phase 1 Submission process expects:

  • lifecycle service: /aic_model/change_state
  • action server: /insert_cable

I have a local Docker image:

my-solution:phase1_basic_control_ladder

The image works in local Docker Compose when launched with the AIC router environment variables. Its entrypoint requires:

AIC_ROUTER_ADDR

and may require AIC_MODEL_PASSWD if ACL is enabled.

From inspecting the SDK/Flowstate tooling, it looks like the possible path is:

inctl asset install <bundle.tar> --org ... --cluster ...
inctl service add <service_asset_id_version> --cluster ... --name aic_model

I can package the Docker image as a Service asset bundle, but I don’t want to guess the router environment contract.

Questions:

  1. For a custom Flowstate Service instance named aic_model, does Flowstate automatically inject AIC_ROUTER_ADDR and AIC_MODEL_PASSWD?
  2. If not, what should AIC_ROUTER_ADDR be set to in simulation inside the Flowstate VM?
  3. What is the approved way to provide AIC_MODEL_PASSWD without exposing secrets?
  4. Is inctl asset install + inctl service add --name aic_model the intended local Flowstate testing workflow for AIC Phase 1, or is there another approved way to make the participant model available to the solution?

Thanks!

1 post - 1 participant

Read full topic

by Young_Jeff on June 21, 2026 06:21 AM

June 20, 2026
Introducing CycloneDDS Insight - Graphical DDS Inspection and Debugging for ROS 2

Introducing CycloneDDS Insight - Graphical DDS Inspection and Debugging for ROS 2.

CycloneDDS Insight is a graphical DDS inspection and debugging tool for ROS 2 and Eclipse Cyclone DDS.

The tool provides visibility into DDS participants, topics, publishers and subscribers, helping users understand system topology, diagnose discovery issues and analyze communication behavior in distributed ROS 2 systems.

Features include:
* Live inspection of DDS entities
* Discovery and communication debugging
* Visualization of communication architectures
* DDS traffic and statistics monitoring
* Support for complex multi-host ROS 2 deployments

CycloneDDS Insight is completely free and open source, making advanced DDS inspection and debugging capabilities accessible to everyone in the ROS 2 community.

Repository:
https://github.com/eclipse-cyclonedds/cyclonedds-insight

Feedback and contributions are welcome.

1 post - 1 participant

Read full topic

by trittsv on June 20, 2026 10:10 PM

Scale Models of ROS robots

A few months ago I had an odd thought (as an occasional modelmaker), has anyone ever made a model of a ROS robot? An AGV, a PR2 to sit on your desk? A Moose? It should be fairly straightforward even, because practically all robot description packages ship a mesh of the robot for rviz which can be fixed up a little and 3D printed to get an exact replica.

I’ve searched quite a bit but couldn’t find anything like that online. So I guess it fell to me to make the first entry.

I got the idea when looking at the ST3045M, the microservo variant of the really practical ST3215 that everyone’s using in SO-ARMs. Something so tiny with full positional and velocity control, low speed torque, odom feedback, and one wire control is like the holy grail for modelmaking.

My first plan was Segway’s Nova Carter, since it’s a fairly aesthetic design, but some miscalculations later I realized it’s way too narrow for it to work with these servos. Clearpath’s Husky or Jackal would work, but then I found Husarion’s Lynx which both looks cooler and the wheel shafts line up almost perfectly when scaled down.

So a few months later, here’s the end result: A 1/5 scale model with most of the capabilities of the real thing, except maybe runtime and a slightly lower scale top speed:

The shell is 3D printed PLA, spray painted, plus some minor weathering with chrome paint, the tires are just off the shelf 1/24 scale crawler wheels with printed hubs. I’ve used double ended LED filaments to make the RGB strips, even the WS2812C is too large at this scale.

I had to modify the servos a bit, sawing off the mounting plates on one side so the shafts would be close enough to the end of the chassis without them poking out. They occupy the entire bottom third:

I was planning to use a Pi Zero 2, but the performance meant it would never be able to run anything useful. The only realistic other option was a CM4 + a drone carrier board to leave me enough space for the other stuff. Expensive but totally worth it imo, since it also has very compact pixhawk connectors and an external antenna plug. I had to take some creative liberties in the rear, extending it out a bit and flattening it so the parts would fit.

(no the tiny estop doesn’t work, sorry :joy:)

As for how I made it run nav2 without a lidar is… well that it does actually have a built in lidar. There’s a Vl53L7CX in the front that behaves a lot like a really garbage stereo camera with only 64 pixels, from which I can extract a horizontal line or two, make some hilarious assumptions and boom a laserscan. Needless to say slam_toolbox recoils in horror unless I disable scan matching, but the wheel odom + BNO085 is actually totally enough to map that way for short periods.

And here are the internals, I’m not really patient enough to make my own PCBs, so it’s just a bunch of dev boards with gratuitous components removed, wrapped in kapton tape and shoved in there.

My enemy throughout the build was heat. I’ve never attempted anything this compact before and with such high power components the second chassis just melted around the CM4. I thought passive cooling will be enough, but even with a heatsink the size of the entire rear end it didn’t really help. So it needs the fan, and extra vents in the wheel wells and the top to help keep the battery cool too. The wheels are ultra soft, which is nice for grip (it can climb up a 30 deg slope out of smooth metal) but they also almost tear off when turning in place on rough surfaces.

The pogo pins in the front are for charging and I have an apriltag dock planned, but I still need to find a usb webcam that looks scale and design a gantry that mounts on top…

I’ve documented most of the setup, since it’s convoluted enough that I’ll forget half of it in two months otherwise, but hopefully it comes in useful for anyone else, there’s some videos there too:

I wouldn’t really recommend anyone to try and recreate it strictly based on that since it’s hardly complete, but I really hope it comes in handy as an inspiration or learning reference. I would just love to see if anyone else has already made something but just never posted it, or if hopefully this gives someone the idea to make something similar. I think a Nova Carter is genuinely doable with geared micro steppers after seeing this thing the other day.

9 posts - 4 participants

Read full topic

by MoffKalast on June 20, 2026 01:46 PM

June 19, 2026
ZeroDDS: a pure-Rust RMW for ROS 2 (rc.3), built against 349 real ROS↔DDS pain reports

Full disclosure up front: I work on ZeroDDS, so this is our project, not a neutral review. Sharing it here because it’s specifically aimed at problems this community has been reporting for years, and we’d genuinely like the feedback.

What it is: an alternative RMW for ROS 2, with the whole DDS stack underneath written from scratch in Rust (memory-safe, Apache-2.0, no per-seat license). It speaks native RTPS 2.5 and interoperates with your existing setup: ROS 2 over `rmw_zerodds` talks to ROS 2 over `rmw_cyclonedds` bidirectionally (20/20 in our pub/sub + service tests). It’s a drop-in `RMW_IMPLEMENTATION`, not a fork of your graph.

We didn’t guess at the pain, we catalogued it. Before writing “ROS 2 support” anywhere, we collected 349 real-world ROS↔DDS pain reports from this forum, GitHub and elsewhere, and engineered against the recurring ones:

  • Silent QoS / type mismatches — the classic where two endpoints just never match and nothing is logged. Fixed the keyed/no-key entity-id case, and shipped `zerodds-ros2-shim doctor`, a discovery-independent check that flags the most common WiFi misconfig (multicast-free with no unicast peers) as a hard error instead of a silent no-match.

  • WiFi discovery loss — a single SPDP beacon dropped during 802.11 power-save leaves you at `participants=0`. We send an initial-announcement burst (10×200 ms until matched), like FastDDS’ `initial_announcements`. Verified on a real WiFi rig, not just loopback.

  • Large fleets / WAN — a `multi_robot()` profile: unicast-only discovery, no multicast storm.

  • DDS-Security / SROS2. ZeroDDS consumes SROS2 enclave files (identity/permissions CA, cert, key, governance, permissions) and fails hard on a broken config (no silent downgrade). Caveat for ROS-users: today you point it at the enclave via a ZERODDS_SECURITY_DIR env var, not the standard ROS_SECURITY_KEYSTORE / ROS_SECURITY_ENABLE variables yet. Wiring those up so ros2 security works unmodified is still open.

  • Introspection — `ros2 topic info -v` resolves endpoint GUIDs to node names.

Works with rclpy and rclcpp.

New in rc.3: zero-copy shared memory now works on Windows too (via `CreateFileMapping` + `LockFileEx`), tested on a real Windows runner.

Next (rc.4): a continuous multi-distro live `ros2` smoke as a CI gate across Humble, Iron and Jazzy, so interop is proven on every commit rather than by hand. The `rmw_zerodds` surface itself is code-complete (pub/sub, services, wait-sets, loaned messages, REP-2009 type hash + endpoint info; nothing left `UNSUPPORTED`).

Honest about maturity: it’s a release candidate, not years-hardened. On performance we’re on par with the established stacks across real workloads, not uniformly ahead, and we don’t claim to beat RT-tuned commercial configs. An OMG Vendor-ID is filed but not yet assigned. We are not safety-certified.

Try it:

If you hit a mismatch with your Cyclone/Fast-DDS nodes, or a QoS combination that doesn’t behave, that’s exactly the feedback we want. Tell us where it breaks.

(For the DDS/non-ROS folks who wander in: the same codebase also covers XTypes, DDS-Security, RPC, bridges, seven language bindings, and a full CORBA 3.3 ORB. Happy to go into any of it, but I’ll keep this post ROS-focused.)

1 post - 1 participant

Read full topic

by SandraK82 on June 19, 2026 10:12 PM

A VS Code extension for quickly running ROS2 launch files, Python nodes, and C++ nodes

ROS2 Quick Runner

This is a VSCode extension I recently wrote, and I’ve been using it lately

A VS Code extension for quickly running ROS2 launch files, Python nodes, and C++ nodes.

GitHub - Knighthood2001/vscode-ros2-quick-runner: Quickly run ROS 2 launch, Python, and C++ files in VSCode · GitHub

Features

1. Launch ROS2 Files

Right-click any .launch.py file and select “ros2 launch” to:

  • Automatically find the ROS2 workspace
  • Source the workspace’s install/setup.bash
  • Execute ros2 launch <package_name> <launch_file>

2. Run ROS2 Nodes

Right-click any .py or .cpp file and select “ros2 run” to:

  • Automatically find the ROS2 workspace and package name
  • Source the workspace’s install/setup.bash
  • Execute ros2 run <package_name> <node_name>

3. Get Workspace Name

Right-click any file and select “ros2 source” to:

  • Display the workspace name
  • Source the workspace in a new terminal

4. Build ROS2 Workspace

Right-click any folder in your ROS2 workspace and select “colcon build” to:

  • Automatically find the ROS2 workspace root
  • Open a terminal at the workspace root
  • Execute colcon build

Smart path detection:

  • Right-click xxx_ws/ → build in xxx_ws/
  • Right-click xxx_ws/src/ → build in xxx_ws/
  • Right-click any sub-folder (e.g. xxx_ws/src/pkg_a) → build in xxx_ws/

How It Works

The extension automatically:

  1. Finds the ROS2 workspace by searching for directories whose src/ subdirectory contains at least one package with package.xml
  2. Extracts the package name by parsing the package.xml file in the package directory
  3. Executes commands in a new VS Code terminal

Usage

  1. Search for ros2-quick-runner in VS Code extensions and install it
  2. Open your ROS2 project in VS Code
  3. Right-click on a file in the explorer:
    • .launch.py files → “ros2 launch”
    • .py or .cpp files → “ros2 run”
    • Any file → “ros2 source”
    • Any folder → “colcon build”

Commands

Command Description
ros2-quick-runner.ros2launch Launch a .launch.py file
ros2-quick-runner.ros2run Run a Python or C++ node
ros2-quick-runner.getWorkspaceName Get and source the workspace
ros2-quick-runner.colconBuild Build the ROS2 workspace

Requirements

  • VS Code 1.80.0 or higher
  • ROS2 installed (e.g., ROS 2 Humble)
  • A compiled ROS2 workspace with install/ directory

Release Notes

For detailed changelog, please see: vscode-ros2-quick-runner/CHANGELOG.md at main · Knighthood2001/vscode-ros2-quick-runner · GitHub

0.0.3

  • Initial release
  • Support for ROS2 launch files, Python nodes, and C++ nodes
  • Automatic workspace detection
  • Automatic package name extraction

1 post - 1 participant

Read full topic

by Knighthood2001 on June 19, 2026 12:22 AM

June 18, 2026
ROS 2 Robot V1.0.0 - A Modern GUI for ROS 2 Workspace Management (Like GitHub Desktop for ROS)

Hi everyone,

“ROS is used to build robots, but isn’t it time for ROS to have its own robot?�

I’m excited to share a tool I’ve been working on to make ROS 2 development a bit smoother: Ros2 Robot.

As developers, we spend a lot of time typing repetitive terminal commands just to manage packages, source workspaces, and inspect topics. I wanted to build a tool that handles the boilerplate so we can focus on actual robotics innovation. It also serves as a great stepping stone for newcomers who find the ROS 2 CLI overwhelming.

What is it?
Ros2 Robot is a PyQt/PySide6 based GUI that acts like “GitHub Desktop� for your ROS 2 projects.

Key Features in V1.0.0:

  • Create packages, rebuild, and source them all with one click.
  • Run and manage nodes all from one place.
  • Inspect topics in real-time.
  • Manage ROS bags effortlessly.
  • Build launch files by adding blocks.
  • Visualize your URDF files and control your joints.
  • Open your favorite ROS Plugins directly from the interface.
  • Educational: understand what each feature does in the background CLI.
  • Supports Native Linux (Tested On Ubuntu 22.04/24.04) and Windows with WSL 2!

:rocket: Installed with ��� ����, and launched with ��� �������. :rocket:

:laptop: GitHub Repository: GitHub - saheraalreqeb/Ros2_Robot: Ros2 Robot is a simple GUI designed to help you manage your ROS 2 projects a. Think of it as GitHub Desktop, but for ROS 2. It eliminates those repetitive, soul-crushing terminal commands so you can actually focus on coding and development. · GitHub
(I’ll be posting a full video tutorial later today showing it in action!)

I’m releasing this as V1.0.0 because the core features are stable, but this is just the beginning. I would love for the community to test it out. If you encounter bugs, have ideas for new features, or want to contribute code, please head over to the GitHub repo and open an issue or a PR.

Let me know what you think!

screenshots_carousel

2 posts - 1 participant

Read full topic

by saheralreqeb on June 18, 2026 03:03 PM

Seeking feedback: Is dependency blocking during ROS development a significant pain point?

Seeking Feedback from Robotics Software Engineers / ROS Developers

Hello everyone,

I hope you are doing well.

I am a BE Computer Science student with a strong interest in robotics software. I am currently researching a potential software product and, before investing significant time into building it, I would like to validate whether the problem I am trying to solve is a genuine challenge faced by robotics engineers.

From my research, I have observed that robotics engineers are often blocked because another part of the robot is not yet available or is temporarily broken. For example:

  • A navigation engineer cannot continue because localization is not ready.
  • A manipulation engineer cannot continue because MoveIt is unavailable or malfunctioning.
  • A docking engineer cannot test their feature because the navigation stack is incomplete.

To continue development, engineers often write temporary Python scripts, use ROS CLI commands, or create custom test nodes just to simulate missing robot components.

The idea I am exploring is a ROS-native platform that allows engineers to discover, call, mock, save, and reuse ROS 2 Actions and Services through a visual interface, helping them continue development without waiting for missing dependencies.

Before building anything, I would sincerely appreciate your honest opinion.

  1. Have you experienced dependency-blocking situations like these in your projects?
  2. How do you currently work around these problems?
  3. If this problem exists, how painful is it in day-to-day development?
  4. Do you think a tool like this would provide meaningful value, or am I solving the wrong problem?
  5. Is there any existing tool that already solves this problem well?
  6. Is there anything important that I might be overlooking?

I genuinely welcome honest criticism, even if your opinion is that this problem is not worth solving. Constructive feedback would help me avoid spending months building something that isn’t valuable to the robotics community.

If anyone is willing to discuss this in more detail, I would be sincerely grateful for even 10–15 minutes of your time through a direct message, phone call, or Google Meet at your convenience.

Thank you very much for taking the time to read this post. I truly appreciate any feedback, suggestions, or guidance you are willing to share.
is this good and worth posting

2 posts - 2 participants

Read full topic

by kameshwaran on June 18, 2026 03:02 PM

Has anyone tried conformal prediction for sensor gating in a nav stack?

Been thinking about this for a while.

The chi-squared gate in most localization stacks assumes Gaussian noise. When when we look outdoors… it rarely is. Like doing multipath near buildings, or under tree canopy, and even around field equipment.

I came across this conformal prediction (Angelopoulos & Bates 2022). The idea is: instead of assuming a distribution, you basically test each new measurement against your own empirical data. It states coverage guarantees hold regardless of noise shape.

Has anyone tried something like this in a nav stack? And honestly… is GPS covariance mismatch painful enough in real deployments that it’s worth a proper fix, or does tuning R get you 90% of the way there?

7 posts - 2 participants

Read full topic

by manankharwar on June 18, 2026 04:14 AM

June 16, 2026
ROS2 on STM32 serial to SBC

Hi all,

I’m building a small ROS 2 robot with an STM32 microcontroller and an SBC running a Zenoh router (rmw_zenoh). I want to keep the MCU side Zenoh-native with Zephyr RTOS, and I’m trying to figure out the best communication stack between the STM32 and the rest of the graph.

I’ve been looking at three options:

  1. micro-ROS (classic) — well documented, but I’m not sure whether I’d still need zenoh-bridge-dds on the SBC side given I’m already running rmw_zenoh there
  2. Zenoh-Pico with rmw_zenoh_pico (eSOL) — conceptually a perfect fit, but the repo seems to only target Linux/RPi so far, and I’m not sure how much work porting to STM32 + Zephyr would be
  3. Pico-ROS — appeals to me architecturally (native Zenoh, no micro-ROS overhead), but documentation is very sparse and I couldn’t find real-world STM32 examples

I’m not necessarily looking for a solution that works out of the box — I’m happy to do integration work. What I’m really after is whether anyone has actually tried any of these on STM32 + Zephyr, what pain points they hit, and whether there’s a better path I’m missing.

Any experience or pointers would be greatly appreciated!

7 posts - 5 participants

Read full topic

by Alvin0523 on June 16, 2026 04:05 PM

June 15, 2026
Bringing the ROS Community Together: Meetups in Heilbronn and Karlsruhe

Beyond the large annual conferences, some of the most valuable moments in the ROS ecosystem happen at a smaller scale, when local developers, researchers, and companies gather in one room for an afternoon of talks, demos, and conversation. Over the spring, the robotics community had two such occasions: the first-ever ROS Meetup in Heilbronn in March, followed by the second ROS Meetup in Karlsruhe in May. Both events reflected a healthy, growing grassroots scene around ROS 2, and both reaffirmed why face-to-face exchange remains so important to the open-source robotics community.

A First for Heilbronn

On 23 March 2026, the robotics community came together at the TUM Campus Heilbronn (Bildungscampus) for the first ROS Meetup ever hosted in the city. The event was organized jointly by Neobotix GmbH, TUM Campus Heilbronn, and Fraunhofer IPA, and brought together developers, researchers, and students for an afternoon of talks, lab tours, and networking over a shared lunch at the Bildungscampus.

The afternoon opened with an introduction from Neobotix GmbH before moving into a full technical program. Denis Stogl of b-robotized presented recent improvements to real-time control in ros2_control, focusing on coordinating multiple robots, an area where reliable, deterministic control is essential for industrial adoption. Robert Wilbrandt of the FZI Forschungszentrum Informatik for Information Technology introduced a reusable, MoveIt-based manipulation planning component designed to simplify the integration of motion planning across projects. Vishnuprasad Prachandabhanu and Sanjeev Kumar from Fraunhofer IPA followed with a talk on developing ROS 2 controllers for the Unitree G1 humanoid platform.

The lineup also reached into learning, general-purpose robotics, and safety. Pauline Steffel, a PhD student in the AImotion department, presented work toward a configurable and reusable reinforcement-learning training infrastructure for autonomous mobile robots in ROS 2. Tobias Weyer of TNG Technology Consulting shared a broader perspective on general-purpose robotics with ROS, and Zhen Zhang of TUM Campus Heilbronn closed the talks with research on safe, LLM-controlled robots that provide formal guarantees through reachability analysis.

The presentations were complemented by hands-on demonstrations. Attendees were given an inside look at the research underway in the TUM Cyber-Physical Systems labs, and Neobotix showed several of its professional-grade mobile robots running live. As is often the case, the networking session afterward proved just as valuable as the talks themselves, providing the kind of informal, face-to-face exchange that turns into future collaboration.

Organizing a community event from scratch is no small undertaking, and the success of this first edition owed much to the team at Neobotix together with TUM Campus Heilbronn's Cyber-Physical Systems group, including Prof. Amr Alanwar, Zhen Zhang, and Hadi Elnemr, and the support staff who made the venue and logistics work. ROS-Industrial Europe and Fraunhofer IPA were glad to collaborate on bringing the meetup to life. For a first event, it set an encouraging precedent and showed clear appetite for a recurring gathering in the region.

A Second Round in Karlsruhe

Two months later, on 21 May 2026, the community reconvened at the FZI Forschungszentrum Informatik House of Living Labs in Karlsruhe for the second ROS Meetup hosted there. With six presentations spanning research and industry, the afternoon offered a broad cross-section of how ROS is being applied today, from manipulation and motion planning to medical robotics and industrial machine tools.

Robert Wilbrandt of the FZI Forschungszentrum Informatik for Information Technology opened the technical program with an overview of how ROS sits at the core of FZI's robotics projects. He highlighted several open-source packages the center maintains, including vdb_mapping for long-term, large-scale 3D mapping and navigation, behavior-tree-based approaches for the automatic, LLM-driven generation of assembly and disassembly programs. Dr. Jennifer Bühler and Dr. Denis Stogl of the b-robotized group followed with their approach to the Intrinsic Industrial AI Challenge using HIL-SERL (Human-in-the-Loop Sample-Efficient Reinforcement Learning), a method that combines a small number of demonstrations with targeted human interventions during training so that manipulation tasks can be learned with far less task-specific data than many current approaches.

The motion-planning thread continued with Sebastian Jahr of the ZEISS Group, who introduced OInK, an optimal inverse kinematics solver built on Roboplan, an emerging library based on Pinocchio. OInK is a QP-based differential IK solver written in C++ that computes joint commands in real time while tracking multiple objectives and respecting constraints and safety barriers. Dr.-Ing. Marius Siegfarth and Javier Moviglia from the Mannheim Institute for Intelligent Systems in Medicine (Medical Faculty Mannheim of Heidelberg University) then turned the focus to medical robotics, showing how they use ROS to develop robotic prototypes for operating-room automation, integrate them with imaging modalities such as CT and MRI, and connect devices within the OR environment.

Rounding out the program, Matthias Mayr of Mayr Robotics presented a Cartesian impedance control stack for torque-controlled manipulators. Built with ros2_control, it enables the compliant interaction that many real-world manipulation tasks require and generalizes across platforms such as the Franka Research 3 and the KUKA iiwa. Finally, Matthias Marquart (ISW, University of Stuttgart) and Benjamin Kaiser (ISG – Industrielle Steuerungstechnik GmbH) bridged ROS and industrial CNC. Motivated by use cases such as robotic timber milling, they showed a hybrid architecture in which a TwinCAT CNC triggers a MoveIt planner for collision-free path planning and then executes the resulting path back on the CNC, combining industrial reliability with the flexibility of the ROS ecosystem, before looking ahead to native integration of the ISG-Kernel SDK into ROS.

The meetup wrapped up with a tour of FZI's robotics labs, including a showcase of the center's custom-developed legged robots, followed by more networking.

Why These Events Matter

Taken together, the Heilbronn and Karlsruhe meetups illustrate something the ROS-Industrial community has long believed: real-world progress depends as much on people connecting as on code being written. The talks spanned the full breadth of the field, from low-level real-time control and inverse kinematics to reinforcement learning, medical automation, and CNC integration, while the demos and lab tours grounded those ideas in working hardware.

A sincere thank you goes to everyone who made these gatherings possible: the organizers at Neobotix, TUM Campus Heilbronn, FZI Forschungszentrum Informatik, and Fraunhofer IPA, the speakers who shared their work, and the many attendees who brought their curiosity and ideas. With two successful meetups behind us, we look forward to seeing this regional community continue to grow, and to many more afternoons of talks, demos, and good conversation.

Image.png
5N3A2045-2.jpg
5N3A2072-2.jpg
5N3A2140-2.jpg
5N3A2189-2.jpg
5N3A2320-2.jpg
5N3A2294-2.jpg
5N3A2369-2.jpg
5N3A2336-2.jpg

by Vishnuprasad Prachandabhanu on June 15, 2026 06:20 PM

Looking for a repository within ROS2 to support

Hello guys, I have history with C, python and have worked with ROS2 and ROS2 controls, for Control Theory stuff. I would like to be involved in supporting a repository or a stable project. Kindly recommend a starting point. You can also check my github to see if I woul be suitable for your project at KevinKipkorir254.

3 posts - 3 participants

Read full topic

by Kevin_Kipkorir on June 15, 2026 01:52 PM

ROS2 Studio Update

ROS2-STUDIO update— new Bag Recorder features!

Just pushed some improvements to the bag recorder in ROS2-STUDIO:

Storage format selection — choose between sqlite3 and mcap directly from the GUI
Timed recording — set a duration (in seconds) and the recorder auto-stops when done
Batch/split recording— split bags into chunks every N seconds (--max-bag-duration style)

All options are configurable from the UI without touching the terminal.

:link: GitHub - Sourav0607/ROS2-STUDIO: A comprehensive ROS2 monitoring and management tool with an intuitive GUI for performance monitoring, bag recording, and bag playback. · GitHub

Feedback and contributions welcome!

1 post - 1 participant

Read full topic

by Sourav24 on June 15, 2026 06:38 AM

June 13, 2026
LSEP v0.2 — now a buildable ROS 2 reference implementation: typed lsep_msgs + managed lifecycle node, green CI

Hi everyone,

v0.2.0 now ships a runnable ROS 2 reference implementation — a package you can colcon build in a couple of minutes, with typed messages, a managed lifecycle node, and green CI. Before anything gets locked towards a 1.0, I’d like people who run real robots to poke holes in the architecture.

What’s in v0.2

1. Typed interfaces (lsep_msgs) lsep_msgs/Signal carries the state twice: as a uint8 enum for machines and as a state_name string for debugging via ros2 topic echo. Undefined physics are encoded as NaN instead of magic numbers (e.g. TTC when closing velocity is zero). Light, Sound, and Motion are separate message types — currently nested inside Signal on a single topic. The win today is type reuse and zero parsing overhead versus our previous JSON-in-String transport; whether modalities should get their own topics is an open question I’d like your input on (see below).

2. Managed lifecycle node The core lsep_node is an rclpy.lifecycle.Node following the ROS 2 managed-nodes design, so a safety supervisor can orchestrate configure/activate/deactivate deterministically and keep the signaling layer isolated from the navigation stack.

3. Engine v2.1 — two blind spots in my original state machine, fixed

  • Dwell-based de-escalation: a calmer raw state must remain stable for dwell_de_escalation_s (default 1.5 s) before the machine steps down. Escalation stays immediate; THREAT (< 0.5 s TTC) bypasses everything.
  • Input watchdog: if the sensor stream dies or occludes for longer than input_timeout_s, the reported state degrades to LOW_CONF instead of confidently latching the last danger state on dead sensors.

4. Deprecation policy The old JSON string on /lsep/state is kept as a deprecated mirror behind a publish_json parameter, so nothing existing breaks during migration.

Evidence

CI builds the workspace in a ros:jazzy container on every push, runs the 9/9 unit tests (the engine is testable without a ROS installation), and runs a headless smoke-test where a simulated human approaches, lingers, and retreats. The CI job hard-fails unless the observed state ladder actually reaches THREAT and then de-escalates — so green CI proves the temporal behavior, not just compilation. Ordered ladder from the smoke-test (two full cycles):

INTEGRITY → AWARENESS → INTENT → CARE → CRITICAL → THREAT → AWARENESS → IDLE
          → AWARENESS → INTENT → CARE → CRITICAL → THREAT → AWARENESS
                                            └─ dwell-based de-escalation, 2x ─┘

The THREAT -> AWARENESS step is the one that matters: it shows the dwell timer stepping the robot down only after the danger has genuinely cleared, rather than oscillating.

What I’d genuinely like review on

  1. State representation: uint8 enum + mirror string in one message — sane, or would you model this differently?
  2. NaN convention: NaN in float32 fields for undefined physics — acceptable, or do you prefer explicit validity bools?
  3. QoS: what profile would you expect for a safety-adjacent signaling topic at 10 Hz — reliable vs. best effort, what depth?
  4. Topic layout: one Signal topic with nested modalities (current), or per-modality topics (lsep/light, …) so e.g. an LED driver subscribes only to what it renders?
  5. Naming/namespacing conventions you’d want before this touches real fleets.

Known limits (honestly)

The TTC computation is currently 1D (distance / closing_velocity) — a placeholder; 2D time-to-intercept with trajectory prediction is on the roadmap. No hardware-in-the-loop testing yet — validation so far is the ros:jazzy CI build plus the simulated human, not a physical robot. This is a reference implementation, not certified production safety code.

Repo & 5 minute quick start: GitHub - NemanjaGalic/LSEP: Open protocol for standardized human-robot communication — 9 states, 3 modalities, 1 grammar. Physics-based. EU AI Act ready. · GitHub Release: Release ROS 2 Reference Implementation v0.2.0 · NemanjaGalic/LSEP · GitHub

Thanks for any time you spend tearing this apart.

— Nemanja

3 posts - 2 participants

Read full topic

by NemanjaGalic on June 13, 2026 04:51 PM

Measure serialized topic bandwidth and serialization times using ros_babel_fish_tools

Greetings fellow roboticists :rocket:,

I’ve just added something to ros_babel_fish which could be useful to you as well.
I wanted to know how much bandwidth the serialized message on a topic consumes and how much latency the serialization adds.
So, ros_babel_fish_tools got a new tool: stats
While the existing echo allows subscribing to any topic and outputs the message content as JSON or yaml, the new stats also subscribes to any topic, measures the received rate, message latency (if the message has a header and requires synchronized clocks), the deserialization time from serialized message to ROS message, and the bandwidth (based on the size of the serialized message).
Additionally, you can check how compression of the serialized message would affect the bandwidth and latency.
For example, for our filtered point cloud, it makes quite a difference, but for our compressed wide-angle image, it is wasted time.

Thank you for reading to the end, here’s your image:

1 post - 1 participant

Read full topic

by StefanFabian on June 13, 2026 12:58 PM

June 12, 2026
ROS2 multi-machine with WSL2 + Linux (NVIDIA Jetson Orin Nano)

Hi everyone,

I am trying setting up a ROS2 multi-machine communication between WSL2 (Ubuntu 22.04) running on a local Windows11 machine and a Linux-native platform, i.e., NVIDIA Jetson Orin Nano. My objective is generating data on my WSL2 machine, and process them using the Jetson.

However, I am experiencing issues related to the fact that the two machines cannot see the respective topics / nodes. They are both connected to the same network, and I have activated the mirroring mode networking in WSL2 using the flag networkingMode=mirrored. I have also tried using Cyclone and FastDDS using custom configuration files, but nothing worked so far.

I was thus wondering if anybody has succeded in setting up a proper ROS2 communication between WSL2 and a native Linux machine. If you need any further information, please do not hesitate to ask.

Thank you in advance!

Simone

4 posts - 2 participants

Read full topic

by simonespring on June 12, 2026 11:24 PM


Powered by the awesome: Planet