From 3ef8057f9240db5cacd45f5e459976ed759fe262 Mon Sep 17 00:00:00 2001 From: Felix Exner Date: Fri, 10 Oct 2025 12:31:29 +0200 Subject: [PATCH 1/3] Add support for UR18 (#1524) (cherry picked from commit 233d524db55647a2aee5e03b7feb3948c7678464) # Conflicts: # ur_moveit_config/launch/ur_moveit.launch.py # ur_robot_driver/launch/ur_rsp.launch.py # ur_robot_driver/urdf/ur.urdf.xacro --- README.md | 2 +- ur_moveit_config/launch/ur_moveit.launch.py | 42 ++ ur_robot_driver/config/ur18_update_rate.yaml | 3 + ur_robot_driver/doc/usage/startup.rst | 4 +- ur_robot_driver/launch/ur18.launch.py | 101 ++++ ur_robot_driver/launch/ur_control.launch.py | 1 + ur_robot_driver/launch/ur_rsp.launch.py | 456 +++++++++++++++++++ ur_robot_driver/test/test_common.py | 1 + ur_robot_driver/urdf/ur.urdf.xacro | 106 +++++ 9 files changed, 713 insertions(+), 3 deletions(-) create mode 100644 ur_robot_driver/config/ur18_update_rate.yaml create mode 100644 ur_robot_driver/launch/ur18.launch.py create mode 100644 ur_robot_driver/launch/ur_rsp.launch.py create mode 100644 ur_robot_driver/urdf/ur.urdf.xacro diff --git a/README.md b/README.md index 9ce977bcf..b60f5c0ee 100644 --- a/README.md +++ b/README.md @@ -124,7 +124,7 @@ For getting started, you'll basically need three steps: details. ```bash - # Replace ur5e with one of ur3, ur5, ur10, ur3e, ur5e, ur7e, ur10e, ur12e, ur16e, ur8long, ur15, ur20, ur30 + # Replace ur5e with one of ur3, ur3e, ur5, ur5e, ur7e, ur10, ur10e, ur12e, ur16e, ur8long, ur15, ur18, ur20, ur30 # Replace the IP address with the IP address of your actual robot / URSim ros2 launch ur_robot_driver ur_control.launch.py ur_type:=ur5e robot_ip:=192.168.56.101 ``` diff --git a/ur_moveit_config/launch/ur_moveit.launch.py b/ur_moveit_config/launch/ur_moveit.launch.py index fe4447a77..e022b69ff 100644 --- a/ur_moveit_config/launch/ur_moveit.launch.py +++ b/ur_moveit_config/launch/ur_moveit.launch.py @@ -82,6 +82,7 @@ def launch_setup(context, *args, **kwargs): robot_description_content = Command( [ +<<<<<<< HEAD PathJoinSubstitution([FindExecutable(name="xacro")]), " ", PathJoinSubstitution([FindPackageShare(description_package), "urdf", description_file]), @@ -124,6 +125,47 @@ def launch_setup(context, *args, **kwargs): "prefix:=", prefix, " ", +======= + DeclareLaunchArgument("launch_rviz", default_value="true", description="Launch RViz?"), + DeclareLaunchArgument( + "ur_type", + description="Typo/series of used UR robot.", + choices=[ + "ur3", + "ur5", + "ur10", + "ur3e", + "ur5e", + "ur7e", + "ur10e", + "ur12e", + "ur16e", + "ur8long", + "ur15", + "ur18", + "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="false", + description="Using or not time from simulation", + ), + DeclareLaunchArgument( + "publish_robot_description_semantic", + default_value="true", + description="MoveGroup publishes robot description semantic", + ), +>>>>>>> 233d524 (Add support for UR18 (#1524)) ] ) robot_description = { diff --git a/ur_robot_driver/config/ur18_update_rate.yaml b/ur_robot_driver/config/ur18_update_rate.yaml new file mode 100644 index 000000000..66ef3d736 --- /dev/null +++ b/ur_robot_driver/config/ur18_update_rate.yaml @@ -0,0 +1,3 @@ +controller_manager: + ros__parameters: + update_rate: 500 # Hz diff --git a/ur_robot_driver/doc/usage/startup.rst b/ur_robot_driver/doc/usage/startup.rst index f8c2024ab..1e1576b1f 100644 --- a/ur_robot_driver/doc/usage/startup.rst +++ b/ur_robot_driver/doc/usage/startup.rst @@ -22,8 +22,8 @@ nodes for UR robots. The only required arguments are the ``ur_type`` and ``robot $ ros2 launch ur_robot_driver ur_control.launch.py ur_type:=ur5e robot_ip:=192.168.56.101 -Allowed ``ur_type`` strings: ``ur3``, ``ur5``, ``ur10``, ``ur3e``, ``ur5e``, ``ur7e``, ``ur10e``, -``ur12e``, ``ur16e``, ``ur8long``, ``ur15``, ``ur20``, ``ur30``. +Allowed ``ur_type`` strings: ``ur3``, ``ur3e``, ``ur5``, ``ur5e``, ``ur7e``, ``ur10``, ``ur10e``, +``ur12e``, ``ur16e``, ``ur8long``, ``ur15``, ``ur18``, ``ur20``, ``ur30``. Other important arguments are: diff --git a/ur_robot_driver/launch/ur18.launch.py b/ur_robot_driver/launch/ur18.launch.py new file mode 100644 index 000000000..abd444d68 --- /dev/null +++ b/ur_robot_driver/launch/ur18.launch.py @@ -0,0 +1,101 @@ +# Copyright (c) 2025 Universal Robots A/S +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# * Neither the name of the {copyright_holder} nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +from launch import LaunchDescription +from launch.actions import DeclareLaunchArgument, IncludeLaunchDescription +from launch.launch_description_sources import PythonLaunchDescriptionSource +from launch.substitutions import LaunchConfiguration, ThisLaunchFileDir + + +def generate_launch_description(): + # Declare arguments + declared_arguments = [] + declared_arguments.append( + DeclareLaunchArgument( + "robot_ip", + description="IP address by which the robot can be reached.", + ) + ) + declared_arguments.append( + DeclareLaunchArgument( + "use_mock_hardware", + default_value="false", + description="Start robot with mock hardware mirroring command to its states.", + ) + ) + declared_arguments.append( + DeclareLaunchArgument( + "mock_sensor_commands", + default_value="false", + description="Enable mock command interfaces for sensors used for simple simulations. " + "Used only if 'use_mock_hardware' parameter is true.", + ) + ) + declared_arguments.append( + DeclareLaunchArgument( + "initial_joint_controller", + default_value="scaled_joint_trajectory_controller", + description="Initially loaded robot controller.", + choices=[ + "scaled_joint_trajectory_controller", + "joint_trajectory_controller", + "forward_velocity_controller", + "forward_position_controller", + "freedrive_mode_controller", + "passthrough_trajectory_controller", + ], + ) + ) + declared_arguments.append( + DeclareLaunchArgument( + "activate_joint_controller", + default_value="true", + description="Activate loaded joint controller.", + ) + ) + + # Initialize Arguments + robot_ip = LaunchConfiguration("robot_ip") + use_mock_hardware = LaunchConfiguration("use_mock_hardware") + mock_sensor_commands = LaunchConfiguration("mock_sensor_commands") + initial_joint_controller = LaunchConfiguration("initial_joint_controller") + activate_joint_controller = LaunchConfiguration("activate_joint_controller") + + base_launch = IncludeLaunchDescription( + PythonLaunchDescriptionSource([ThisLaunchFileDir(), "/ur_control.launch.py"]), + launch_arguments={ + "ur_type": "ur18", + "robot_ip": robot_ip, + "use_mock_hardware": use_mock_hardware, + "mock_sensor_commands": mock_sensor_commands, + "initial_joint_controller": initial_joint_controller, + "activate_joint_controller": activate_joint_controller, + }.items(), + ) + + return LaunchDescription(declared_arguments + [base_launch]) diff --git a/ur_robot_driver/launch/ur_control.launch.py b/ur_robot_driver/launch/ur_control.launch.py index 49f4f33f7..b93280d06 100644 --- a/ur_robot_driver/launch/ur_control.launch.py +++ b/ur_robot_driver/launch/ur_control.launch.py @@ -424,6 +424,7 @@ def generate_launch_description(): "ur16e", "ur8long", "ur15", + "ur18", "ur20", "ur30", ], diff --git a/ur_robot_driver/launch/ur_rsp.launch.py b/ur_robot_driver/launch/ur_rsp.launch.py new file mode 100644 index 000000000..225d251d7 --- /dev/null +++ b/ur_robot_driver/launch/ur_rsp.launch.py @@ -0,0 +1,456 @@ +# Copyright (c) 2024 FZI Forschungszentrum Informatik +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# * Neither the name of the {copyright_holder} nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +# +# Author: Felix Exner + +from launch_ros.actions import Node +from launch_ros.substitutions import FindPackageShare +from launch_ros.parameter_descriptions import ParameterValue + +from launch import LaunchDescription +from launch.actions import DeclareLaunchArgument +from launch.substitutions import ( + Command, + FindExecutable, + LaunchConfiguration, + PathJoinSubstitution, +) + + +def generate_launch_description(): + ur_type = LaunchConfiguration("ur_type") + robot_ip = LaunchConfiguration("robot_ip") + safety_limits = LaunchConfiguration("safety_limits") + safety_pos_margin = LaunchConfiguration("safety_pos_margin") + safety_k_position = LaunchConfiguration("safety_k_position") + # General arguments + kinematics_params_file = LaunchConfiguration("kinematics_params_file") + physical_params_file = LaunchConfiguration("physical_params_file") + visual_params_file = LaunchConfiguration("visual_params_file") + joint_limit_params_file = LaunchConfiguration("joint_limit_params_file") + description_file = LaunchConfiguration("description_file") + tf_prefix = LaunchConfiguration("tf_prefix") + use_mock_hardware = LaunchConfiguration("use_mock_hardware") + mock_sensor_commands = LaunchConfiguration("mock_sensor_commands") + headless_mode = LaunchConfiguration("headless_mode") + use_tool_communication = LaunchConfiguration("use_tool_communication") + tool_parity = LaunchConfiguration("tool_parity") + tool_baud_rate = LaunchConfiguration("tool_baud_rate") + tool_stop_bits = LaunchConfiguration("tool_stop_bits") + tool_rx_idle_chars = LaunchConfiguration("tool_rx_idle_chars") + tool_tx_idle_chars = LaunchConfiguration("tool_tx_idle_chars") + tool_device_name = LaunchConfiguration("tool_device_name") + tool_tcp_port = LaunchConfiguration("tool_tcp_port") + tool_voltage = LaunchConfiguration("tool_voltage") + reverse_ip = LaunchConfiguration("reverse_ip") + script_command_port = LaunchConfiguration("script_command_port") + reverse_port = LaunchConfiguration("reverse_port") + script_sender_port = LaunchConfiguration("script_sender_port") + trajectory_port = LaunchConfiguration("trajectory_port") + + script_filename = PathJoinSubstitution( + [ + FindPackageShare("ur_client_library"), + "resources", + "external_control.urscript", + ] + ) + input_recipe_filename = PathJoinSubstitution( + [FindPackageShare("ur_robot_driver"), "resources", "rtde_input_recipe.txt"] + ) + output_recipe_filename = PathJoinSubstitution( + [FindPackageShare("ur_robot_driver"), "resources", "rtde_output_recipe.txt"] + ) + + robot_description_content = Command( + [ + PathJoinSubstitution([FindExecutable(name="xacro")]), + " ", + description_file, + " ", + "robot_ip:=", + robot_ip, + " ", + "joint_limit_params:=", + joint_limit_params_file, + " ", + "kinematics_params:=", + kinematics_params_file, + " ", + "physical_params:=", + physical_params_file, + " ", + "visual_params:=", + visual_params_file, + " ", + "safety_limits:=", + safety_limits, + " ", + "safety_pos_margin:=", + safety_pos_margin, + " ", + "safety_k_position:=", + safety_k_position, + " ", + "name:=", + ur_type, + " ", + "script_filename:=", + script_filename, + " ", + "input_recipe_filename:=", + input_recipe_filename, + " ", + "output_recipe_filename:=", + output_recipe_filename, + " ", + "tf_prefix:=", + tf_prefix, + " ", + "use_mock_hardware:=", + use_mock_hardware, + " ", + "mock_sensor_commands:=", + mock_sensor_commands, + " ", + "headless_mode:=", + headless_mode, + " ", + "use_tool_communication:=", + use_tool_communication, + " ", + "tool_parity:=", + tool_parity, + " ", + "tool_baud_rate:=", + tool_baud_rate, + " ", + "tool_stop_bits:=", + tool_stop_bits, + " ", + "tool_rx_idle_chars:=", + tool_rx_idle_chars, + " ", + "tool_tx_idle_chars:=", + tool_tx_idle_chars, + " ", + "tool_device_name:=", + tool_device_name, + " ", + "tool_tcp_port:=", + tool_tcp_port, + " ", + "tool_voltage:=", + tool_voltage, + " ", + "reverse_ip:=", + reverse_ip, + " ", + "script_command_port:=", + script_command_port, + " ", + "reverse_port:=", + reverse_port, + " ", + "script_sender_port:=", + script_sender_port, + " ", + "trajectory_port:=", + trajectory_port, + " ", + ] + ) + robot_description = { + "robot_description": ParameterValue(robot_description_content, value_type=str) + } + + declared_arguments = [] + # UR specific arguments + declared_arguments.append( + DeclareLaunchArgument( + "ur_type", + description="Typo/series of used UR robot.", + choices=[ + "ur3", + "ur5", + "ur10", + "ur3e", + "ur5e", + "ur7e", + "ur10e", + "ur12e", + "ur16e", + "ur8long", + "ur15", + "ur18", + "ur20", + "ur30", + ], + ) + ) + declared_arguments.append( + DeclareLaunchArgument( + "robot_ip", description="IP address by which the robot can be reached." + ) + ) + declared_arguments.append( + DeclareLaunchArgument( + "safety_limits", + default_value="true", + description="Enables the safety limits controller if true.", + ) + ) + declared_arguments.append( + DeclareLaunchArgument( + "safety_pos_margin", + default_value="0.15", + description="The margin to lower and upper limits in the safety controller.", + ) + ) + declared_arguments.append( + DeclareLaunchArgument( + "safety_k_position", + default_value="20", + description="k-position factor in the safety controller.", + ) + ) + declared_arguments.append( + DeclareLaunchArgument( + "joint_limit_params_file", + default_value=PathJoinSubstitution( + [ + FindPackageShare("ur_description"), + "config", + ur_type, + "joint_limits.yaml", + ] + ), + description="Config file containing the joint limits (e.g. velocities, positions) of the robot.", + ) + ) + declared_arguments.append( + DeclareLaunchArgument( + "kinematics_params_file", + default_value=PathJoinSubstitution( + [ + FindPackageShare("ur_description"), + "config", + ur_type, + "default_kinematics.yaml", + ] + ), + description="The calibration configuration of the actual robot used.", + ) + ) + declared_arguments.append( + DeclareLaunchArgument( + "physical_params_file", + default_value=PathJoinSubstitution( + [ + FindPackageShare("ur_description"), + "config", + ur_type, + "physical_parameters.yaml", + ] + ), + description="Config file containing the physical parameters (e.g. masses, inertia) of the robot.", + ) + ) + declared_arguments.append( + DeclareLaunchArgument( + "visual_params_file", + default_value=PathJoinSubstitution( + [ + FindPackageShare("ur_description"), + "config", + ur_type, + "visual_parameters.yaml", + ] + ), + description="Config file containing the visual parameters (e.g. meshes) of the robot.", + ) + ) + declared_arguments.append( + DeclareLaunchArgument( + "description_file", + default_value=PathJoinSubstitution( + [FindPackageShare("ur_robot_driver"), "urdf", "ur.urdf.xacro"] + ), + description="URDF/XACRO description file with the robot.", + ) + ) + declared_arguments.append( + DeclareLaunchArgument( + "tf_prefix", + default_value="", + description="tf_prefix of the joint names, useful for " + "multi-robot setup. If changed, also joint names in the controllers' configuration " + "have to be updated.", + ) + ) + declared_arguments.append( + DeclareLaunchArgument( + "use_mock_hardware", + default_value="false", + description="Start robot with mock hardware mirroring command to its states.", + ) + ) + declared_arguments.append( + DeclareLaunchArgument( + "mock_sensor_commands", + default_value="false", + description="Enable mock command interfaces for sensors used for simple simulations. " + "Used only if 'use_mock_hardware' parameter is true.", + ) + ) + declared_arguments.append( + DeclareLaunchArgument( + "headless_mode", + default_value="false", + description="Enable headless mode for robot control", + ) + ) + declared_arguments.append( + DeclareLaunchArgument( + "use_tool_communication", + default_value="false", + description="Only available for e series!", + ) + ) + declared_arguments.append( + DeclareLaunchArgument( + "tool_parity", + default_value="0", + description="Parity configuration for serial communication. Only effective, if " + "use_tool_communication is set to True.", + ) + ) + declared_arguments.append( + DeclareLaunchArgument( + "tool_baud_rate", + default_value="115200", + description="Baud rate configuration for serial communication. Only effective, if " + "use_tool_communication is set to True.", + ) + ) + declared_arguments.append( + DeclareLaunchArgument( + "tool_stop_bits", + default_value="1", + description="Stop bits configuration for serial communication. Only effective, if " + "use_tool_communication is set to True.", + ) + ) + declared_arguments.append( + DeclareLaunchArgument( + "tool_rx_idle_chars", + default_value="1.5", + description="RX idle chars configuration for serial communication. Only effective, " + "if use_tool_communication is set to True.", + ) + ) + declared_arguments.append( + DeclareLaunchArgument( + "tool_tx_idle_chars", + default_value="3.5", + description="TX idle chars configuration for serial communication. Only effective, " + "if use_tool_communication is set to True.", + ) + ) + declared_arguments.append( + DeclareLaunchArgument( + "tool_device_name", + default_value="/tmp/ttyUR", + description="File descriptor that will be generated for the tool communication device. " + "The user has be be allowed to write to this location. " + "Only effective, if use_tool_communication is set to True.", + ) + ) + declared_arguments.append( + DeclareLaunchArgument( + "tool_tcp_port", + default_value="54321", + description="Remote port that will be used for bridging the tool's serial device. " + "Only effective, if use_tool_communication is set to True.", + ) + ) + declared_arguments.append( + DeclareLaunchArgument( + "tool_voltage", + default_value="0", # 0 being a conservative value that won't destroy anything + description="Tool voltage that will be setup.", + ) + ) + declared_arguments.append( + DeclareLaunchArgument( + "reverse_ip", + default_value="0.0.0.0", + description="IP that will be used for the robot controller to communicate back to the driver.", + ) + ) + declared_arguments.append( + DeclareLaunchArgument( + "script_command_port", + default_value="50004", + description="Port that will be opened to forward URScript commands to the robot.", + ) + ) + declared_arguments.append( + DeclareLaunchArgument( + "reverse_port", + default_value="50001", + description="Port that will be opened to send cyclic instructions from the driver to the robot controller.", + ) + ) + declared_arguments.append( + DeclareLaunchArgument( + "script_sender_port", + default_value="50002", + description="The driver will offer an interface to query the external_control URScript on this port.", + ) + ) + declared_arguments.append( + DeclareLaunchArgument( + "trajectory_port", + default_value="50003", + description="Port that will be opened for trajectory control.", + ) + ) + + return LaunchDescription( + declared_arguments + + [ + Node( + package="robot_state_publisher", + executable="robot_state_publisher", + output="both", + parameters=[robot_description], + ), + ] + ) diff --git a/ur_robot_driver/test/test_common.py b/ur_robot_driver/test/test_common.py index 41bc50d08..a256dbf7a 100644 --- a/ur_robot_driver/test/test_common.py +++ b/ur_robot_driver/test/test_common.py @@ -405,6 +405,7 @@ def _declare_launch_arguments(): "ur16e", "ur8long", "ur15", + "ur18", "ur20", "ur30", ], diff --git a/ur_robot_driver/urdf/ur.urdf.xacro b/ur_robot_driver/urdf/ur.urdf.xacro new file mode 100644 index 000000000..e14476d0e --- /dev/null +++ b/ur_robot_driver/urdf/ur.urdf.xacro @@ -0,0 +1,106 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From d0c72cda31c42c38c4abc94c35aac7db9dc4dee0 Mon Sep 17 00:00:00 2001 From: Felix Exner Date: Wed, 22 Oct 2025 12:58:02 +0000 Subject: [PATCH 2/3] Resolve conflicts --- ur_bringup/config/ur18_update_rate.yaml | 3 + ur_bringup/launch/ur18.launch.py | 102 +++++ ur_bringup/launch/ur_control.launch.py | 1 + ur_moveit_config/launch/ur_moveit.launch.py | 43 +- ur_robot_driver/launch/ur_rsp.launch.py | 456 -------------------- ur_robot_driver/urdf/ur.ros2_control.xacro | 312 -------------- ur_robot_driver/urdf/ur.urdf.xacro | 106 ----- 7 files changed, 107 insertions(+), 916 deletions(-) create mode 100644 ur_bringup/config/ur18_update_rate.yaml create mode 100644 ur_bringup/launch/ur18.launch.py delete mode 100644 ur_robot_driver/launch/ur_rsp.launch.py delete mode 100644 ur_robot_driver/urdf/ur.ros2_control.xacro delete mode 100644 ur_robot_driver/urdf/ur.urdf.xacro diff --git a/ur_bringup/config/ur18_update_rate.yaml b/ur_bringup/config/ur18_update_rate.yaml new file mode 100644 index 000000000..66ef3d736 --- /dev/null +++ b/ur_bringup/config/ur18_update_rate.yaml @@ -0,0 +1,3 @@ +controller_manager: + ros__parameters: + update_rate: 500 # Hz diff --git a/ur_bringup/launch/ur18.launch.py b/ur_bringup/launch/ur18.launch.py new file mode 100644 index 000000000..2b804bc77 --- /dev/null +++ b/ur_bringup/launch/ur18.launch.py @@ -0,0 +1,102 @@ +# Copyright (c) 2021 PickNik, Inc. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# * Neither the name of the {copyright_holder} nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +# +# Author: Denis Stogl + +from launch import LaunchDescription +from launch.actions import DeclareLaunchArgument, IncludeLaunchDescription +from launch.launch_description_sources import PythonLaunchDescriptionSource +from launch.substitutions import LaunchConfiguration, ThisLaunchFileDir + + +def generate_launch_description(): + # Declare arguments + declared_arguments = [] + declared_arguments.append( + DeclareLaunchArgument( + "robot_ip", + description="IP address by which the robot can be reached.", + ) + ) + declared_arguments.append( + DeclareLaunchArgument( + "use_fake_hardware", + default_value="false", + description="Start robot with fake hardware mirroring command to its states.", + ) + ) + declared_arguments.append( + DeclareLaunchArgument( + "fake_sensor_commands", + default_value="false", + description="Enable fake command interfaces for sensors used for simple simulations. \ + Used only if 'use_fake_hardware' parameter is true.", + ) + ) + declared_arguments.append( + DeclareLaunchArgument( + "initial_joint_controller", + default_value="scaled_joint_trajectory_controller", + description="Initially loaded robot controller.", + choices=[ + "scaled_joint_trajectory_controller", + "joint_trajectory_controller", + "forward_velocity_controller", + "forward_position_controller", + ], + ) + ) + declared_arguments.append( + DeclareLaunchArgument( + "activate_joint_controller", + default_value="true", + description="Activate loaded joint controller.", + ) + ) + + # Initialize Arguments + robot_ip = LaunchConfiguration("robot_ip") + use_fake_hardware = LaunchConfiguration("use_fake_hardware") + fake_sensor_commands = LaunchConfiguration("fake_sensor_commands") + initial_joint_controller = LaunchConfiguration("initial_joint_controller") + activate_joint_controller = LaunchConfiguration("activate_joint_controller") + + base_launch = IncludeLaunchDescription( + PythonLaunchDescriptionSource([ThisLaunchFileDir(), "/ur_control.launch.py"]), + launch_arguments={ + "ur_type": "ur18", + "robot_ip": robot_ip, + "use_fake_hardware": use_fake_hardware, + "fake_sensor_commands": fake_sensor_commands, + "initial_joint_controller": initial_joint_controller, + "activate_joint_controller": activate_joint_controller, + }.items(), + ) + + return LaunchDescription(declared_arguments + [base_launch]) diff --git a/ur_bringup/launch/ur_control.launch.py b/ur_bringup/launch/ur_control.launch.py index 90a5f57a3..5af282305 100644 --- a/ur_bringup/launch/ur_control.launch.py +++ b/ur_bringup/launch/ur_control.launch.py @@ -62,6 +62,7 @@ def generate_launch_description(): "ur16e", "ur8long", "ur15", + "ur18", "ur20", "ur30", ], diff --git a/ur_moveit_config/launch/ur_moveit.launch.py b/ur_moveit_config/launch/ur_moveit.launch.py index e022b69ff..af4d94c29 100644 --- a/ur_moveit_config/launch/ur_moveit.launch.py +++ b/ur_moveit_config/launch/ur_moveit.launch.py @@ -82,7 +82,6 @@ def launch_setup(context, *args, **kwargs): robot_description_content = Command( [ -<<<<<<< HEAD PathJoinSubstitution([FindExecutable(name="xacro")]), " ", PathJoinSubstitution([FindPackageShare(description_package), "urdf", description_file]), @@ -125,47 +124,6 @@ def launch_setup(context, *args, **kwargs): "prefix:=", prefix, " ", -======= - DeclareLaunchArgument("launch_rviz", default_value="true", description="Launch RViz?"), - DeclareLaunchArgument( - "ur_type", - description="Typo/series of used UR robot.", - choices=[ - "ur3", - "ur5", - "ur10", - "ur3e", - "ur5e", - "ur7e", - "ur10e", - "ur12e", - "ur16e", - "ur8long", - "ur15", - "ur18", - "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="false", - description="Using or not time from simulation", - ), - DeclareLaunchArgument( - "publish_robot_description_semantic", - default_value="true", - description="MoveGroup publishes robot description semantic", - ), ->>>>>>> 233d524 (Add support for UR18 (#1524)) ] ) robot_description = { @@ -337,6 +295,7 @@ def generate_launch_description(): "ur16e", "ur8long", "ur15", + "ur18", "ur20", "ur30", ], diff --git a/ur_robot_driver/launch/ur_rsp.launch.py b/ur_robot_driver/launch/ur_rsp.launch.py deleted file mode 100644 index 225d251d7..000000000 --- a/ur_robot_driver/launch/ur_rsp.launch.py +++ /dev/null @@ -1,456 +0,0 @@ -# Copyright (c) 2024 FZI Forschungszentrum Informatik -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# -# * Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# -# * Neither the name of the {copyright_holder} nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -# POSSIBILITY OF SUCH DAMAGE. - -# -# Author: Felix Exner - -from launch_ros.actions import Node -from launch_ros.substitutions import FindPackageShare -from launch_ros.parameter_descriptions import ParameterValue - -from launch import LaunchDescription -from launch.actions import DeclareLaunchArgument -from launch.substitutions import ( - Command, - FindExecutable, - LaunchConfiguration, - PathJoinSubstitution, -) - - -def generate_launch_description(): - ur_type = LaunchConfiguration("ur_type") - robot_ip = LaunchConfiguration("robot_ip") - safety_limits = LaunchConfiguration("safety_limits") - safety_pos_margin = LaunchConfiguration("safety_pos_margin") - safety_k_position = LaunchConfiguration("safety_k_position") - # General arguments - kinematics_params_file = LaunchConfiguration("kinematics_params_file") - physical_params_file = LaunchConfiguration("physical_params_file") - visual_params_file = LaunchConfiguration("visual_params_file") - joint_limit_params_file = LaunchConfiguration("joint_limit_params_file") - description_file = LaunchConfiguration("description_file") - tf_prefix = LaunchConfiguration("tf_prefix") - use_mock_hardware = LaunchConfiguration("use_mock_hardware") - mock_sensor_commands = LaunchConfiguration("mock_sensor_commands") - headless_mode = LaunchConfiguration("headless_mode") - use_tool_communication = LaunchConfiguration("use_tool_communication") - tool_parity = LaunchConfiguration("tool_parity") - tool_baud_rate = LaunchConfiguration("tool_baud_rate") - tool_stop_bits = LaunchConfiguration("tool_stop_bits") - tool_rx_idle_chars = LaunchConfiguration("tool_rx_idle_chars") - tool_tx_idle_chars = LaunchConfiguration("tool_tx_idle_chars") - tool_device_name = LaunchConfiguration("tool_device_name") - tool_tcp_port = LaunchConfiguration("tool_tcp_port") - tool_voltage = LaunchConfiguration("tool_voltage") - reverse_ip = LaunchConfiguration("reverse_ip") - script_command_port = LaunchConfiguration("script_command_port") - reverse_port = LaunchConfiguration("reverse_port") - script_sender_port = LaunchConfiguration("script_sender_port") - trajectory_port = LaunchConfiguration("trajectory_port") - - script_filename = PathJoinSubstitution( - [ - FindPackageShare("ur_client_library"), - "resources", - "external_control.urscript", - ] - ) - input_recipe_filename = PathJoinSubstitution( - [FindPackageShare("ur_robot_driver"), "resources", "rtde_input_recipe.txt"] - ) - output_recipe_filename = PathJoinSubstitution( - [FindPackageShare("ur_robot_driver"), "resources", "rtde_output_recipe.txt"] - ) - - robot_description_content = Command( - [ - PathJoinSubstitution([FindExecutable(name="xacro")]), - " ", - description_file, - " ", - "robot_ip:=", - robot_ip, - " ", - "joint_limit_params:=", - joint_limit_params_file, - " ", - "kinematics_params:=", - kinematics_params_file, - " ", - "physical_params:=", - physical_params_file, - " ", - "visual_params:=", - visual_params_file, - " ", - "safety_limits:=", - safety_limits, - " ", - "safety_pos_margin:=", - safety_pos_margin, - " ", - "safety_k_position:=", - safety_k_position, - " ", - "name:=", - ur_type, - " ", - "script_filename:=", - script_filename, - " ", - "input_recipe_filename:=", - input_recipe_filename, - " ", - "output_recipe_filename:=", - output_recipe_filename, - " ", - "tf_prefix:=", - tf_prefix, - " ", - "use_mock_hardware:=", - use_mock_hardware, - " ", - "mock_sensor_commands:=", - mock_sensor_commands, - " ", - "headless_mode:=", - headless_mode, - " ", - "use_tool_communication:=", - use_tool_communication, - " ", - "tool_parity:=", - tool_parity, - " ", - "tool_baud_rate:=", - tool_baud_rate, - " ", - "tool_stop_bits:=", - tool_stop_bits, - " ", - "tool_rx_idle_chars:=", - tool_rx_idle_chars, - " ", - "tool_tx_idle_chars:=", - tool_tx_idle_chars, - " ", - "tool_device_name:=", - tool_device_name, - " ", - "tool_tcp_port:=", - tool_tcp_port, - " ", - "tool_voltage:=", - tool_voltage, - " ", - "reverse_ip:=", - reverse_ip, - " ", - "script_command_port:=", - script_command_port, - " ", - "reverse_port:=", - reverse_port, - " ", - "script_sender_port:=", - script_sender_port, - " ", - "trajectory_port:=", - trajectory_port, - " ", - ] - ) - robot_description = { - "robot_description": ParameterValue(robot_description_content, value_type=str) - } - - declared_arguments = [] - # UR specific arguments - declared_arguments.append( - DeclareLaunchArgument( - "ur_type", - description="Typo/series of used UR robot.", - choices=[ - "ur3", - "ur5", - "ur10", - "ur3e", - "ur5e", - "ur7e", - "ur10e", - "ur12e", - "ur16e", - "ur8long", - "ur15", - "ur18", - "ur20", - "ur30", - ], - ) - ) - declared_arguments.append( - DeclareLaunchArgument( - "robot_ip", description="IP address by which the robot can be reached." - ) - ) - declared_arguments.append( - DeclareLaunchArgument( - "safety_limits", - default_value="true", - description="Enables the safety limits controller if true.", - ) - ) - declared_arguments.append( - DeclareLaunchArgument( - "safety_pos_margin", - default_value="0.15", - description="The margin to lower and upper limits in the safety controller.", - ) - ) - declared_arguments.append( - DeclareLaunchArgument( - "safety_k_position", - default_value="20", - description="k-position factor in the safety controller.", - ) - ) - declared_arguments.append( - DeclareLaunchArgument( - "joint_limit_params_file", - default_value=PathJoinSubstitution( - [ - FindPackageShare("ur_description"), - "config", - ur_type, - "joint_limits.yaml", - ] - ), - description="Config file containing the joint limits (e.g. velocities, positions) of the robot.", - ) - ) - declared_arguments.append( - DeclareLaunchArgument( - "kinematics_params_file", - default_value=PathJoinSubstitution( - [ - FindPackageShare("ur_description"), - "config", - ur_type, - "default_kinematics.yaml", - ] - ), - description="The calibration configuration of the actual robot used.", - ) - ) - declared_arguments.append( - DeclareLaunchArgument( - "physical_params_file", - default_value=PathJoinSubstitution( - [ - FindPackageShare("ur_description"), - "config", - ur_type, - "physical_parameters.yaml", - ] - ), - description="Config file containing the physical parameters (e.g. masses, inertia) of the robot.", - ) - ) - declared_arguments.append( - DeclareLaunchArgument( - "visual_params_file", - default_value=PathJoinSubstitution( - [ - FindPackageShare("ur_description"), - "config", - ur_type, - "visual_parameters.yaml", - ] - ), - description="Config file containing the visual parameters (e.g. meshes) of the robot.", - ) - ) - declared_arguments.append( - DeclareLaunchArgument( - "description_file", - default_value=PathJoinSubstitution( - [FindPackageShare("ur_robot_driver"), "urdf", "ur.urdf.xacro"] - ), - description="URDF/XACRO description file with the robot.", - ) - ) - declared_arguments.append( - DeclareLaunchArgument( - "tf_prefix", - default_value="", - description="tf_prefix of the joint names, useful for " - "multi-robot setup. If changed, also joint names in the controllers' configuration " - "have to be updated.", - ) - ) - declared_arguments.append( - DeclareLaunchArgument( - "use_mock_hardware", - default_value="false", - description="Start robot with mock hardware mirroring command to its states.", - ) - ) - declared_arguments.append( - DeclareLaunchArgument( - "mock_sensor_commands", - default_value="false", - description="Enable mock command interfaces for sensors used for simple simulations. " - "Used only if 'use_mock_hardware' parameter is true.", - ) - ) - declared_arguments.append( - DeclareLaunchArgument( - "headless_mode", - default_value="false", - description="Enable headless mode for robot control", - ) - ) - declared_arguments.append( - DeclareLaunchArgument( - "use_tool_communication", - default_value="false", - description="Only available for e series!", - ) - ) - declared_arguments.append( - DeclareLaunchArgument( - "tool_parity", - default_value="0", - description="Parity configuration for serial communication. Only effective, if " - "use_tool_communication is set to True.", - ) - ) - declared_arguments.append( - DeclareLaunchArgument( - "tool_baud_rate", - default_value="115200", - description="Baud rate configuration for serial communication. Only effective, if " - "use_tool_communication is set to True.", - ) - ) - declared_arguments.append( - DeclareLaunchArgument( - "tool_stop_bits", - default_value="1", - description="Stop bits configuration for serial communication. Only effective, if " - "use_tool_communication is set to True.", - ) - ) - declared_arguments.append( - DeclareLaunchArgument( - "tool_rx_idle_chars", - default_value="1.5", - description="RX idle chars configuration for serial communication. Only effective, " - "if use_tool_communication is set to True.", - ) - ) - declared_arguments.append( - DeclareLaunchArgument( - "tool_tx_idle_chars", - default_value="3.5", - description="TX idle chars configuration for serial communication. Only effective, " - "if use_tool_communication is set to True.", - ) - ) - declared_arguments.append( - DeclareLaunchArgument( - "tool_device_name", - default_value="/tmp/ttyUR", - description="File descriptor that will be generated for the tool communication device. " - "The user has be be allowed to write to this location. " - "Only effective, if use_tool_communication is set to True.", - ) - ) - declared_arguments.append( - DeclareLaunchArgument( - "tool_tcp_port", - default_value="54321", - description="Remote port that will be used for bridging the tool's serial device. " - "Only effective, if use_tool_communication is set to True.", - ) - ) - declared_arguments.append( - DeclareLaunchArgument( - "tool_voltage", - default_value="0", # 0 being a conservative value that won't destroy anything - description="Tool voltage that will be setup.", - ) - ) - declared_arguments.append( - DeclareLaunchArgument( - "reverse_ip", - default_value="0.0.0.0", - description="IP that will be used for the robot controller to communicate back to the driver.", - ) - ) - declared_arguments.append( - DeclareLaunchArgument( - "script_command_port", - default_value="50004", - description="Port that will be opened to forward URScript commands to the robot.", - ) - ) - declared_arguments.append( - DeclareLaunchArgument( - "reverse_port", - default_value="50001", - description="Port that will be opened to send cyclic instructions from the driver to the robot controller.", - ) - ) - declared_arguments.append( - DeclareLaunchArgument( - "script_sender_port", - default_value="50002", - description="The driver will offer an interface to query the external_control URScript on this port.", - ) - ) - declared_arguments.append( - DeclareLaunchArgument( - "trajectory_port", - default_value="50003", - description="Port that will be opened for trajectory control.", - ) - ) - - return LaunchDescription( - declared_arguments - + [ - Node( - package="robot_state_publisher", - executable="robot_state_publisher", - output="both", - parameters=[robot_description], - ), - ] - ) diff --git a/ur_robot_driver/urdf/ur.ros2_control.xacro b/ur_robot_driver/urdf/ur.ros2_control.xacro deleted file mode 100644 index b480434b0..000000000 --- a/ur_robot_driver/urdf/ur.ros2_control.xacro +++ /dev/null @@ -1,312 +0,0 @@ - - - - - - - - - - - - - - - - - - - - mock_components/GenericSystem - ${mock_sensor_commands} - 0.0 - true - - - ur_robot_driver/URPositionHardwareInterface - ${robot_ip} - ${script_filename} - ${output_recipe_filename} - ${input_recipe_filename} - ${headless_mode} - ${reverse_port} - ${script_sender_port} - ${reverse_ip} - ${script_command_port} - ${trajectory_port} - ${tf_prefix} - ${non_blocking_read} - 2000 - 0.03 - ${use_tool_communication} - ${kinematics_hash} - ${tool_voltage} - ${tool_parity} - ${tool_baud_rate} - ${tool_stop_bits} - ${tool_rx_idle_chars} - ${tool_tx_idle_chars} - ${tool_device_name} - ${tool_tcp_port} - ${robot_receive_timeout} - - - - - - - - - - - 1.0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 - - - - - - - - diff --git a/ur_robot_driver/urdf/ur.urdf.xacro b/ur_robot_driver/urdf/ur.urdf.xacro deleted file mode 100644 index e14476d0e..000000000 --- a/ur_robot_driver/urdf/ur.urdf.xacro +++ /dev/null @@ -1,106 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From 6b2d8265d569b1755747b8089eb929499798406a Mon Sep 17 00:00:00 2001 From: Felix Exner Date: Wed, 22 Oct 2025 13:00:31 +0000 Subject: [PATCH 3/3] Do not revert sorting the model list --- README.md | 2 +- ur_robot_driver/doc/usage/startup.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index b60f5c0ee..5157db806 100644 --- a/README.md +++ b/README.md @@ -124,7 +124,7 @@ For getting started, you'll basically need three steps: details. ```bash - # Replace ur5e with one of ur3, ur3e, ur5, ur5e, ur7e, ur10, ur10e, ur12e, ur16e, ur8long, ur15, ur18, ur20, ur30 + # Replace ur5e with one of ur3, ur5, ur10, ur3e, ur5e, ur7e, ur10e, ur12e, ur16e, ur8long, ur15, ur18, ur20, ur30 # Replace the IP address with the IP address of your actual robot / URSim ros2 launch ur_robot_driver ur_control.launch.py ur_type:=ur5e robot_ip:=192.168.56.101 ``` diff --git a/ur_robot_driver/doc/usage/startup.rst b/ur_robot_driver/doc/usage/startup.rst index 1e1576b1f..fb16578f9 100644 --- a/ur_robot_driver/doc/usage/startup.rst +++ b/ur_robot_driver/doc/usage/startup.rst @@ -22,7 +22,7 @@ nodes for UR robots. The only required arguments are the ``ur_type`` and ``robot $ ros2 launch ur_robot_driver ur_control.launch.py ur_type:=ur5e robot_ip:=192.168.56.101 -Allowed ``ur_type`` strings: ``ur3``, ``ur3e``, ``ur5``, ``ur5e``, ``ur7e``, ``ur10``, ``ur10e``, +Allowed ``ur_type`` strings: ``ur3``, ``ur5``, ``ur10``, ``ur3e``, ``ur5e``, ``ur7e``, ``ur10e``, ``ur12e``, ``ur16e``, ``ur8long``, ``ur15``, ``ur18``, ``ur20``, ``ur30``. Other important arguments are: