Skip to content

Commit

Permalink
Description refactoring (#41)
Browse files Browse the repository at this point in the history
* Add description with ros2_control tag

This uses the ur_description without a ros2_control tag and adds an own one for gazebo classic.

* Add tests for generated description

* Use ur_description in upstream workspace
  • Loading branch information
fmauch authored Dec 20, 2023
1 parent 3c9289d commit 5b395da
Show file tree
Hide file tree
Showing 9 changed files with 235 additions and 22 deletions.
4 changes: 4 additions & 0 deletions Universal_Robots_ROS2_Gazebo_Simulation.humble.repos
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
repositories:
ur_description:
type: git
url: https://github.com/UniversalRobots/Universal_Robots_ROS2_Description
version: humble

gazebo_ros2_control:
type: git
Expand Down
4 changes: 4 additions & 0 deletions Universal_Robots_ROS2_Gazebo_Simulation.iron.repos
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
repositories:
ur_description:
type: git
url: https://github.com/UniversalRobots/Universal_Robots_ROS2_Description
version: iron

gazebo_ros2_control:
type: git
Expand Down
4 changes: 4 additions & 0 deletions Universal_Robots_ROS2_Gazebo_Simulation.rolling.repos
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
repositories:
ur_description:
type: git
url: https://github.com/UniversalRobots/Universal_Robots_ROS2_Description
version: rolling

gazebo_ros2_control:
type: git
Expand Down
8 changes: 7 additions & 1 deletion ur_simulation_gazebo/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,14 @@ project(ur_simulation_gazebo)

find_package(ament_cmake REQUIRED)

install(DIRECTORY config launch
install(DIRECTORY config launch urdf
DESTINATION share/${PROJECT_NAME}
)

if(BUILD_TESTING)
find_package(ament_cmake_pytest REQUIRED)

ament_add_pytest_test(description test/test_description.py)
endif()

ament_package()
23 changes: 2 additions & 21 deletions ur_simulation_gazebo/launch/ur_sim_control.launch.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,6 @@ def launch_setup(context, *args, **kwargs):
# General arguments
runtime_config_package = LaunchConfiguration("runtime_config_package")
controllers_file = LaunchConfiguration("controllers_file")
description_package = LaunchConfiguration("description_package")
description_file = LaunchConfiguration("description_file")
prefix = LaunchConfiguration("prefix")
start_joint_controller = LaunchConfiguration("start_joint_controller")
initial_joint_controller = LaunchConfiguration("initial_joint_controller")
Expand All @@ -65,15 +63,15 @@ def launch_setup(context, *args, **kwargs):
)

rviz_config_file = PathJoinSubstitution(
[FindPackageShare(description_package), "rviz", "view_robot.rviz"]
[FindPackageShare("ur_description"), "rviz", "view_robot.rviz"]
)

robot_description_content = Command(
[
PathJoinSubstitution([FindExecutable(name="xacro")]),
" ",
PathJoinSubstitution(
[FindPackageShare(description_package), "urdf", description_file]
[FindPackageShare("ur_simulation_gazebo"), "urdf", "ur_gazebo.urdf.xacro"]
),
" ",
"safety_limits:=",
Expand All @@ -94,8 +92,6 @@ def launch_setup(context, *args, **kwargs):
"prefix:=",
prefix,
" ",
"sim_gazebo:=true",
" ",
"simulation_controllers:=",
initial_joint_controllers,
]
Expand Down Expand Up @@ -223,21 +219,6 @@ def generate_launch_description():
description="YAML file with the controllers configuration.",
)
)
declared_arguments.append(
DeclareLaunchArgument(
"description_package",
default_value="ur_description",
description="Description package with robot URDF/XACRO files. Usually the argument \
is not set, it enables use of a custom description.",
)
)
declared_arguments.append(
DeclareLaunchArgument(
"description_file",
default_value="ur.urdf.xacro",
description="URDF/XACRO description file with the robot.",
)
)
declared_arguments.append(
DeclareLaunchArgument(
"prefix",
Expand Down
6 changes: 6 additions & 0 deletions ur_simulation_gazebo/package.xml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@
<exec_depend>urdf</exec_depend>
<exec_depend>xacro</exec_depend>

<test_depend>ament_cmake_pytest</test_depend>
<test_depend>launch_testing_ament_cmake</test_depend>
<test_depend>launch_testing_ros</test_depend>
<test_depend>liburdfdom-tools</test_depend>
<test_depend>xacro</test_depend>

<export>
<build_type>ament_cmake</build_type>
</export>
Expand Down
118 changes: 118 additions & 0 deletions ur_simulation_gazebo/test/test_description.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
# Copyright (c) 2023 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: Lukas Sackewitz

import os
import shutil
import subprocess
import tempfile
import pytest

from ament_index_python.packages import get_package_share_directory


@pytest.mark.parametrize(
"ur_type", ["ur3", "ur3e", "ur5", "ur5e", "ur10", "ur10e", "ur16e", "ur20"]
)
@pytest.mark.parametrize("prefix", ["", "my_ur_"])
def test_ur_urdf_xacro(ur_type, prefix):
# Initialize Arguments
safety_limits = "true"
safety_pos_margin = "0.15"
safety_k_position = "20"
# General Arguments
description_package = "ur_description"

joint_limit_params = os.path.join(
get_package_share_directory(description_package), "config", ur_type, "joint_limits.yaml"
)
kinematics_params = os.path.join(
get_package_share_directory(description_package),
"config",
ur_type,
"default_kinematics.yaml",
)
physical_params = os.path.join(
get_package_share_directory(description_package),
"config",
ur_type,
"physical_parameters.yaml",
)
visual_params = os.path.join(
get_package_share_directory(description_package),
"config",
ur_type,
"visual_parameters.yaml",
)

description_file_path = os.path.join(
get_package_share_directory("ur_simulation_gazebo"), "urdf", "ur_gazebo.urdf.xacro"
)

(_, tmp_urdf_output_file) = tempfile.mkstemp(suffix=".urdf")

# Compose `xacro` and `check_urdf` command
xacro_command = (
f"{shutil.which('xacro')}"
f" {description_file_path}"
f" joint_limit_params:={joint_limit_params}"
f" kinematics_params:={kinematics_params}"
f" physical_params:={physical_params}"
f" visual_params:={visual_params}"
f" safety_limits:={safety_limits}"
f" safety_pos_margin:={safety_pos_margin}"
f" safety_k_position:={safety_k_position}"
f" name:={ur_type}"
f" prefix:={prefix}"
f" > {tmp_urdf_output_file}"
)
check_urdf_command = f"{shutil.which('check_urdf')} {tmp_urdf_output_file}"

# Try to call processes but finally remove the temp file
try:
xacro_process = subprocess.run(
xacro_command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True
)

assert xacro_process.returncode == 0, " --- XACRO command failed ---"

check_urdf_process = subprocess.run(
check_urdf_command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True
)

assert (
check_urdf_process.returncode == 0
), "\n --- URDF check failed! --- \nYour xacro does not unfold into a proper urdf robot description. Please check your xacro file."

finally:
os.remove(tmp_urdf_output_file)


if __name__ == "__main__":
test_ur_urdf_xacro()
29 changes: 29 additions & 0 deletions ur_simulation_gazebo/urdf/ur_gazebo.ros2_control.xacro
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?xml version="1.0"?>
<robot xmlns:xacro="http://www.ros.org/wiki/xacro">

<xacro:include filename="$(find ur_description)/urdf/inc/ur_joint_control.xacro" />

<xacro:macro name="ur_ros2_control" params="
name
tf_prefix
transmission_hw_interface:=hardware_interface/PositionJointInterface
initial_positions:=${dict(shoulder_pan_joint=0.0,shoulder_lift_joint=-1.57,elbow_joint=0.0,wrist_1_joint=-1.57,wrist_2_joint=0.0,wrist_3_joint=0.0)}
">


<!-- Add URDF transmission elements (for ros_control) -->
<!--<xacro:ur_arm_transmission prefix="${prefix}" hw_interface="${transmission_hw_interface}" />-->
<!-- Placeholder for ros2_control transmission which don't yet exist -->

<ros2_control name="${name}" type="system">
<hardware>
<plugin>gazebo_ros2_control/GazeboSystem</plugin>
</hardware>

<xacro:ur_joint_control_description
tf_prefix="${tf_prefix}"
initial_positions="${initial_positions}"
/>
</ros2_control>
</xacro:macro>
</robot>
61 changes: 61 additions & 0 deletions ur_simulation_gazebo/urdf/ur_gazebo.urdf.xacro
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?xml version="1.0"?>
<robot xmlns:xacro="http://wiki.ros.org/xacro" name="$(arg name)">
<!-- robot name parameter -->
<xacro:arg name="name" default="ur"/>
<!-- import main macro -->
<xacro:include filename="$(find ur_description)/urdf/ur_macro.xacro"/>

<xacro:include filename="$(find ur_simulation_gazebo)/urdf/ur_gazebo.ros2_control.xacro" />

<!-- possible 'ur_type' values: ur3, ur3e, ur5, ur5e, ur10, ur10e, ur16e, ur20 -->
<!-- the default value should raise an error in case this was called without defining the type -->
<xacro:arg name="ur_type" default="ur5x"/>

<!-- parameters -->
<xacro:arg name="tf_prefix" default="" />
<xacro:arg name="joint_limit_params" default="$(find ur_description)/config/$(arg ur_type)/joint_limits.yaml"/>
<xacro:arg name="kinematics_params" default="$(find ur_description)/config/$(arg ur_type)/default_kinematics.yaml"/>
<xacro:arg name="physical_params" default="$(find ur_description)/config/$(arg ur_type)/physical_parameters.yaml"/>
<xacro:arg name="visual_params" default="$(find ur_description)/config/$(arg ur_type)/visual_parameters.yaml"/>
<xacro:arg name="transmission_hw_interface" default=""/>
<xacro:arg name="safety_limits" default="false"/>
<xacro:arg name="safety_pos_margin" default="0.15"/>
<xacro:arg name="safety_k_position" default="20"/>

<xacro:arg name="simulation_controllers" default="" />

<!-- create link fixed to the "world" -->
<link name="world" />

<!-- arm -->
<xacro:ur_robot
name="$(arg name)"
tf_prefix="$(arg tf_prefix)"
parent="world"
joint_limits_parameters_file="$(arg joint_limit_params)"
kinematics_parameters_file="$(arg kinematics_params)"
physical_parameters_file="$(arg physical_params)"
visual_parameters_file="$(arg visual_params)"
safety_limits="$(arg safety_limits)"
safety_pos_margin="$(arg safety_pos_margin)"
safety_k_position="$(arg safety_k_position)"
force_abs_paths="true"
>
<origin xyz="0 0 0" rpy="0 0 0" /> <!-- position robot in the world -->
</xacro:ur_robot>

<gazebo reference="world">
</gazebo>
<gazebo>
<plugin filename="libgazebo_ros2_control.so" name="gazebo_ros2_control">
<parameters>$(arg simulation_controllers)</parameters>
</plugin>
</gazebo>

<!-- ros2 control instance -->
<xacro:ur_ros2_control
name="$(arg name)"
tf_prefix="$(arg tf_prefix)"
transmission_hw_interface="$(arg transmission_hw_interface)"
/>
</robot>

0 comments on commit 5b395da

Please sign in to comment.