Universal_Robots_ROS2_Driver icon indicating copy to clipboard operation
Universal_Robots_ROS2_Driver copied to clipboard

Connect o3de with ur

Open TheMassimo opened this issue 9 months ago • 2 comments

Affected ROS2 Driver version(s)

latest

Used ROS distribution.

Other

Which combination of platform is the ROS driver running on.

Ubuntu Linux with standard kernel

How is the UR ROS2 Driver installed.

From binary packets

Which robot platform is the driver connected to.

URSim in linux, Real robot, URSim in a virtual machine, URSim in docker, UR E-series robot, UR CB3 robot

Robot SW / URSim version(s)

latest

How is the ROS driver used.

Others

Issue details

Summary

I want to use the default example of ur robot in o3de extra and move it with rviz

Issue details

In o3de-extras there is a example that include universal robot: https://github.com/o3de/o3de-extras/tree/development/Templates/Ros2RoboticManipulationTemplate. There is also a launch file but is only for panda robot. So I try to create a launch file following that one. But it does not work and my launch wait for /robot_description topic. Also there are some warning at the start that i'don't undestand why

Steps to Reproduce

download o3de and o3de-extras (latest version 2409.2). Download ur_drivere and ur_movit (latest version). Now run o3de project and run the launch file (ros2 launch my_test.launch.py ur_type:=ur10)

Expected Behavior

The flow should be the same as the provided in panda example

Actual Behavior

it doesn't work

##My launch file

import os
import yaml

from pathlib import Path

from launch import LaunchDescription
from launch.actions import DeclareLaunchArgument, RegisterEventHandler
from launch.conditions import IfCondition
from launch.event_handlers import OnProcessExit
from launch.substitutions import (
    LaunchConfiguration,
    PathJoinSubstitution,
)

from launch_ros.actions import Node
from launch_ros.substitutions import FindPackageShare

from moveit_configs_utils import MoveItConfigsBuilder

from ament_index_python.packages import get_package_share_directory

from launch_ros.actions import ComposableNodeContainer
from launch_ros.descriptions import ComposableNode


def load_yaml(package_name, file_path):
    package_path = get_package_share_directory(package_name)
    absolute_file_path = os.path.join(package_path, file_path)

    try:
        with open(absolute_file_path) as file:
            return yaml.safe_load(file)
    except OSError:  # parent of IOError, OSError *and* WindowsError where available
        return None



def declare_arguments():
    return LaunchDescription(
        [
            DeclareLaunchArgument(
                "launch_rviz",
                default_value="true",
                description="Launch RViz?"
            ),
            DeclareLaunchArgument(
                "ur_type",
                description="Typo/series of used UR robot.",
                choices=[
                    "ur3",
                    "ur3e",
                    "ur5",
                    "ur5e",
                    "ur10",
                    "ur10e",
                    "ur16e",
                    "ur20",
                    "ur30",
                ],
            ),
            DeclareLaunchArgument(
                "warehouse_sqlite_path",
                default_value=os.path.expanduser("~/.ros/warehouse_ros.sqlite"),
                description="Path where the warehouse database should be stored",
            ),
            DeclareLaunchArgument(
                "launch_servo", default_value="false", description="Launch Servo?"
            ),
            DeclareLaunchArgument(
                "use_sim_time",
                default_value="true",
                description="Using or not time from simulation",
            ),
            DeclareLaunchArgument(
                "publish_robot_description_semantic",
                default_value="true",
                description="MoveGroup publishes robot description semantic",
            ),
        ]
    )


def generate_launch_description():
    launch_rviz = LaunchConfiguration("launch_rviz")
    ur_type = LaunchConfiguration("ur_type")
    warehouse_sqlite_path = LaunchConfiguration("warehouse_sqlite_path")
    launch_servo = LaunchConfiguration("launch_servo")
    use_sim_time = LaunchConfiguration("use_sim_time")
    publish_robot_description_semantic = LaunchConfiguration("publish_robot_description_semantic")

    moveit_config = (
        MoveItConfigsBuilder(robot_name="ur", package_name="ur_moveit_config")
        .robot_description_semantic(Path("srdf") / "ur.srdf.xacro", {"name": ur_type})
        .to_moveit_configs()
    )

    warehouse_ros_config = {
        "warehouse_plugin": "warehouse_ros_sqlite::DatabaseConnection",
        "warehouse_host": warehouse_sqlite_path,
    }

    ld = LaunchDescription()
    ld.add_entity(declare_arguments())

    wait_robot_description = Node(
        package="ur_robot_driver",
        executable="wait_for_robot_description",
        output="screen",
    )
    ld.add_action(wait_robot_description)

    move_group_node = Node(
        package="moveit_ros_move_group",
        executable="move_group",
        output="screen",
        parameters=[
            moveit_config.to_dict(),
            warehouse_ros_config,
            {
                "use_sim_time": use_sim_time,
                "publish_robot_description_semantic": publish_robot_description_semantic,
            },
        ],
    )

    rviz_config_file = PathJoinSubstitution(
        [FindPackageShare("ur_moveit_config"), "config", "moveit.rviz"]
    )
    rviz_node = Node(
        package="rviz2",
        condition=IfCondition(launch_rviz),
        executable="rviz2",
        name="rviz2_moveit",
        output="log",
        arguments=["-d", rviz_config_file],
        parameters=[
            moveit_config.robot_description,
            moveit_config.robot_description_semantic,
            moveit_config.robot_description_kinematics,
            moveit_config.planning_pipelines,
            moveit_config.joint_limits,
            warehouse_ros_config,
            {
                "use_sim_time": use_sim_time,
            },
        ],
    )

    servo_yaml = load_yaml("ur_moveit_config", "config/ur_servo.yaml")
    servo_params = {"moveit_servo": servo_yaml}
    servo_node = Node(
        package="moveit_servo",
        condition=IfCondition(launch_servo),
        executable="servo_node",
        parameters=[
            moveit_config.to_dict(),
            servo_params,
        ],
        output="screen",
    )

    # Static TF
    static_tf = Node(
        package="tf2_ros",
        executable="static_transform_publisher",
        name="static_transform_publisher",
        output="log",
        arguments=["0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "world", "panda_link0"],
    )

    # Publish TF
    robot_state_publisher = Node(
        package="robot_state_publisher",
        executable="robot_state_publisher",
        name="robot_state_publisher",
        output="both",
        parameters=[moveit_config.robot_description],
    )

    rgbd_pc = ComposableNodeContainer(
        name='container0',
        namespace='',
        package='rclcpp_components',
        executable='component_container',
        composable_node_descriptions=[
            ComposableNode(
                package='depth_image_proc',
                plugin='depth_image_proc::PointCloudXyzrgbNode',
                name='point_cloud_xyzrgb_node',
                remappings=[('rgb/camera_info', '/color_camera_info'),
                            ('rgb/image_rect_color', '/camera_image_color'),
                            ('depth_registered/image_rect','/camera_image_depth'),
                            ('/points','/pointcloud')]
            ),
        ],
        output='screen',
        parameters=[{'use_sim_time': True}],
    )


    ld.add_action(
        RegisterEventHandler(
            OnProcessExit(
                target_action=wait_robot_description,
                on_exit=[
                    move_group_node,
                    rviz_node,
                    servo_node,
                    static_tf,
                    robot_state_publisher,
                    rgbd_pc,
                ],
            )
        ),
    )

    return ld

Relevant log output

[INFO] [launch]: All log files can be found below /home/robx/.ros/log/2025-03-05-19-35-14-534067-robx-MS-7D67-316208
[INFO] [launch]: Default logging verbosity is set to INFO
WARNING:root:Cannot infer URDF from `/opt/ros/jazzy/share/ur_moveit_config`. -- using config/ur.urdf
WARNING:root:Cannot infer SRDF from `/opt/ros/jazzy/share/ur_moveit_config`. -- using config/ur.srdf
WARNING:root:"File /opt/ros/jazzy/share/ur_moveit_config/config/ur.urdf doesn't exist"
WARNING:root:The robot description will be loaded from /robot_description topic 
[INFO] [wait_for_robot_description-1]: process started with pid [316211]
[wait_for_robot_description-1] [INFO] [1741199714.811761162] [wait_for_robot_description]: Waiting for message on /robot_description.

Accept Public visibility

  • [x] I agree to make this context public

TheMassimo avatar Mar 05 '25 18:03 TheMassimo

Hi, thank you for reaching out. We appreciate that you try to use other simulators with a UR robot. However, at the moment we only support Gazebo as a simulator.

However, your questions seems more to be related to your custom launch file than the the simulator. Please understand that we also cannot help individual problems when creating custom integrations. Looking at your output, however, it seems that the move_group / the helper node is waiting for the robot description being published. In the driver launch that comes from the robot_state publisher launched in rsp.launch.py.

I don't know how o3de integrates with a URDF / robot_description, so this could be wrong advice. You can also make the move_group load the description. For that, it is easiest to create a custom moveit support package using the moveit setup assistant. The default launchfiles generated from that will load the description. See out custom workcell tutorial on details for that.

urfeex avatar Mar 06 '25 07:03 urfeex

The main difference between O3DE and Gazebo is that O3DE does not publish robot descriptions on /robot_description topic.

The ur_moveit.launch.py script worked fine on ROS 2 Humble (humble branch) without getting any information on the topic, but it was refactored on the main branch and this information is required. I do not know the history behind this change, but we do not have the resources in the O3DE community to maintain the launchers of other robots, as we focus on developing the engine itself. The information about UR robots will be removed from the O3DE documentation.

jhanca-robotecai avatar Mar 18 '25 10:03 jhanca-robotecai