diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 0000000..b745632 --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,10 @@ +FROM murilomarinho/sas:jazzy +LABEL authors="murilomarinho" +SHELL ["/bin/bash", "-c"] +ENV BASH_ENV="/etc/bash_env" + +RUN sudo apt-get update && sudo apt-get upgrade -y +RUN python3 -m pip install --upgrade dqrobotics --break-system-packages +RUN mkdir -p /root/sas_ur_control_template_ci/src +COPY . /root/sas_ur_control_template_ci/src/sas_ur_control_template +RUN chmod +x /root/sas_ur_control_template_ci/src/sas_ur_control_template/scripts/joint_interface_example.py \ No newline at end of file diff --git a/docker/compose.yml b/docker/compose.yml new file mode 100644 index 0000000..843c2d7 --- /dev/null +++ b/docker/compose.yml @@ -0,0 +1,6 @@ +services: + sas_ur_control_template: + build: + context: .. + dockerfile: docker/Dockerfile + entrypoint: ["/bin/bash", "/root/sas_ur_control_template_ci/src/sas_ur_control_template/docker/test_ci.sh"] \ No newline at end of file diff --git a/docker/coppeliasim/.env b/docker/coppeliasim/.env new file mode 100644 index 0000000..87862b3 --- /dev/null +++ b/docker/coppeliasim/.env @@ -0,0 +1,12 @@ +# ROS 2 Domain ID (must match across all connected nodes) +ROS_DOMAIN_ID=0 + +# Display (for GUI rendering) +DISPLAY=:0 + +# CoppeliaSim scene configuration +COPPELIA_SIM_SCENE_FILE=UR3e_4100rev0_sas.ttt +COPPELIA_SIM_CONTAINER_SCENE_PATH=/root/sas_tutorial_workspace/src/sas_ur_control_template/scenes/ + +# Kinematics topic name (used by kinematic simulation demo) +XD_TOPIC_NAME=/sas_robot_driver_coppeliasim/object/xd \ No newline at end of file diff --git a/docker/coppeliasim/simulation_demo_v2/compose.yml b/docker/coppeliasim/simulation_demo_v2/compose.yml index 93b645e..068b387 100644 --- a/docker/coppeliasim/simulation_demo_v2/compose.yml +++ b/docker/coppeliasim/simulation_demo_v2/compose.yml @@ -1,6 +1,8 @@ services: sas_ur_control_template: - build: https://github.com/MarinhoLab/sas_ur_control_template.git#main:docker/sas_ur_control_template + build: + context: ../../.. + dockerfile: docker/sas_ur_control_template/Dockerfile stop_signal: SIGINT environment: - ROS_DOMAIN_ID diff --git a/docker/coppeliasim/simulation_demo_v2_kinematic/compose.yml b/docker/coppeliasim/simulation_demo_v2_kinematic/compose.yml index 33a3781..3b935e9 100644 --- a/docker/coppeliasim/simulation_demo_v2_kinematic/compose.yml +++ b/docker/coppeliasim/simulation_demo_v2_kinematic/compose.yml @@ -1,6 +1,8 @@ services: sas_ur_control_template: - build: https://github.com/MarinhoLab/sas_ur_control_template.git#main:docker/sas_ur_control_template + build: + context: ../../.. + dockerfile: docker/sas_ur_control_template/Dockerfile stop_signal: SIGINT environment: - ROS_DOMAIN_ID diff --git a/docker/gazebo/.env b/docker/gazebo/.env new file mode 100644 index 0000000..2993220 --- /dev/null +++ b/docker/gazebo/.env @@ -0,0 +1,10 @@ +# ROS 2 Domain ID (must match across all connected nodes) +ROS_DOMAIN_ID=0 + +# UR3e Gazebo simulation configuration +WORLD_NAME=ur3e_world +ROBOT_NAME=ur3e +ROBOT_TOPIC_NAME=ur3e_sim + +# Display (for GUI rendering) +DISPLAY=:0 \ No newline at end of file diff --git a/docker/gazebo/compose_simulation.yml b/docker/gazebo/compose_simulation.yml new file mode 100644 index 0000000..30c11bb --- /dev/null +++ b/docker/gazebo/compose_simulation.yml @@ -0,0 +1,45 @@ +services: + sas_ur_control_template: + container_name: sas_ur_control_template_simulation + build: + context: ../.. + dockerfile: docker/sas_ur_control_template/Dockerfile + stop_signal: SIGINT + environment: + - ROS_DOMAIN_ID + command: /bin/bash -c " + source /root/sas_tutorial_workspace/install/setup.bash + && cd /root/sas_tutorial_workspace/src/sas_ur_control_template + && python3 docker/gazebo/ur3e_simulation_example_py_launch.py \ + robot_topic_name:=ur3e_sim" + + gazebo: + container_name: sas_ur_control_template_gazebo + build: https://raw.githubusercontent.com/MarinhoLab/sas_robot_driver_gazebo/refs/heads/jazzy/docker/Dockerfile + stop_signal: SIGINT + environment: + - DISPLAY + - ROS_DOMAIN_ID + - WORLD_NAME=${WORLD_NAME} + - ROBOT_NAME=${ROBOT_NAME} + - ROBOT_TOPIC_NAME=${ROBOT_TOPIC_NAME} + privileged: true # Needed for some gpu configurations. + volumes: + - /tmp/.X11-unix:/tmp/.X11-unix # x server related + - ~/.Xauthority:/root/.Xauthority # x server related + command: /bin/bash -c " + export GZ_SIM_RESOURCE_PATH=$$GZ_SIM_RESOURCE_PATH:$$(ros2 pkg prefix sas_robot_driver_gazebo)/sdf/ + && cd $$(ros2 pkg prefix sas_robot_driver_gazebo --share)/sdf + && (gz sim "$$WORLD_NAME".sdf &) + && (ros2 launch sas_robot_driver_gazebo robot_driver_server_launch.py \ + joint_states_topic:="/world/$$WORLD_NAME/model/$$ROBOT_NAME/model/$${ROBOT_NAME}_position_controller/model/$$ROBOT_NAME/joint_state" \ + joint_names:='['shoulder_pan_joint','shoulder_lift_joint','elbow_joint','wrist_1_joint','wrist_2_joint','wrist_3_joint']' \ + robot_name:="$$ROBOT_TOPIC_NAME" + &) + && (ros2 launch sas_robot_driver_gazebo server_launch.py \ + autostart:=true \ + set_pose_service_name:=/world/"$$WORLD_NAME"/set_pose \ + get_pose_topic_name:=/world/"$$WORLD_NAME"/pose/info \ + entity_names:='['base', 'tool0']' \ + control_service_name:=/world/"$$WORLD_NAME"/control \ + )" \ No newline at end of file diff --git a/docker/gazebo/ur3e_simulation_example_py_launch.py b/docker/gazebo/ur3e_simulation_example_py_launch.py new file mode 100644 index 0000000..f92a2c2 --- /dev/null +++ b/docker/gazebo/ur3e_simulation_example_py_launch.py @@ -0,0 +1,48 @@ +"""Launch the UR3e simulation control template for Gazebo. + +Run directly with: + python3 ur3e_simulation_example_py_launch.py [robot_topic_name:=ur3e_sim] + +Or via Docker Compose: + docker compose -f docker/gazebo/compose_simulation.yml up +""" +import sys + +from launch import LaunchDescription, LaunchService +from launch.actions import DeclareLaunchArgument +from launch.substitutions import LaunchConfiguration +from launch_ros.actions import Node + + +def generate_launch_description(robot_topic_name='ur3e_sim'): + """Generate the launch description for UR3e Gazebo simulation.""" + # Parse command-line args like robot_topic_name:=foo + args = dict( + (k, v) + for arg in sys.argv[1:] + if ':=' in arg + for k, v in [arg.split(':=', 1)] + ) + topic = args.get('robot_topic_name', robot_topic_name) + + return LaunchDescription([ + DeclareLaunchArgument( + 'robot_topic_name', + default_value=topic, + description='Robot topic name for the UR3e Gazebo simulation driver.', + ), + Node( + package='sas_ur_control_template', + executable='joint_interface_example.py', + output='screen', + emulate_tty=True, + name='sas_ur_control_template_ur3e_simulation', + parameters=[{"robot_topic_name": topic}], + ), + ]) + + +if __name__ == '__main__': + ls = LaunchService() + ls.add_launch_description(generate_launch_description()) + ls.run() \ No newline at end of file diff --git a/docker/robot_demo/compose.yml b/docker/robot_demo/compose.yml index 6af2e80..df4162d 100644 --- a/docker/robot_demo/compose.yml +++ b/docker/robot_demo/compose.yml @@ -1,7 +1,9 @@ services: sas_ur_control_template: container_name: sas_ur_control_template_robot_demo - build: https://github.com/MarinhoLab/sas_ur_control_template.git#main:docker/sas_ur_control_template + build: + context: ../.. + dockerfile: docker/sas_ur_control_template/Dockerfile stop_signal: SIGINT stop_grace_period: 1m network_mode: "host" # Reverse connection with UR robot diff --git a/docker/teleop_demo/Dockerfile b/docker/teleop_demo/Dockerfile index 2b0b6e5..5f9af76 100644 --- a/docker/teleop_demo/Dockerfile +++ b/docker/teleop_demo/Dockerfile @@ -5,7 +5,7 @@ ENV BASH_ENV="/etc/bash_env" RUN mkdir -p cd ~/sas_tutorial_workspace/src RUN cd ~/sas_tutorial_workspace/src && git clone https://github.com/MarinhoLab/sas_ur_control_template.git -RUN cd ~/sas_tutorial_workspace/src/sas_ur_control_template/.devel/scripts && chmod +x setup_environment.sh -RUN cd ~/sas_tutorial_workspace/src/sas_ur_control_template/.devel/scripts && ./setup_environment.sh +RUN cd ~/sas_tutorial_workspace/src/sas_ur_control_template/docker/scripts && chmod +x setup_environment.sh +RUN cd ~/sas_tutorial_workspace/src/sas_ur_control_template/docker/scripts && ./setup_environment.sh RUN sudo apt-get update && sudo apt-get install qtcreator gdb -y diff --git a/docker/teleop_demo/compose.yml b/docker/teleop_demo/compose.yml index c3f3809..24f84f8 100644 --- a/docker/teleop_demo/compose.yml +++ b/docker/teleop_demo/compose.yml @@ -1,6 +1,8 @@ services: sas_ur_control_template: - build: . + build: + context: ../.. + dockerfile: docker/sas_ur_control_template/Dockerfile stop_signal: SIGINT stop_grace_period: 1m volumes: diff --git a/docker/test_ci.sh b/docker/test_ci.sh new file mode 100644 index 0000000..3a262ea --- /dev/null +++ b/docker/test_ci.sh @@ -0,0 +1,27 @@ +#!/bin/bash +set -e + +cd /root/sas_ur_control_template_ci +source /opt/ros/jazzy/setup.bash + +echo "=== Building package ===" +colcon build +echo "=== Build complete ===" + +source install/setup.bash + +echo "=== Package available ===" +ros2 pkg list | grep sas_ur_control_template + +echo "=== Checking executables ===" +PKG_LIB=$(ros2 pkg prefix sas_ur_control_template)/lib/sas_ur_control_template +test -x "$PKG_LIB/joint_interface_example.py" && echo "Python node OK" +test -x "$PKG_LIB/joint_interface_example_cpp" && echo "C++ node OK" + +echo "=== Launch file syntax ===" +for launch in $(ros2 pkg prefix sas_ur_control_template --share)/launch/*.py; do + echo "Checking: $launch" + python3 -c "import ast; ast.parse(open('$launch').read())" && echo "OK" +done + +echo "=== All tests passed ===" \ No newline at end of file