├── .github ├── ISSUE_TEMPLATE │ └── bug_report.md └── workflows │ ├── ci.yaml │ └── pages.yaml ├── .gitignore ├── .pre-commit-config.yaml ├── Doxyfile ├── LICENSE ├── README.md ├── doc ├── Architecture.drawio ├── Architecture.png ├── logo_cpr.jpg └── logo_igus_lca.jpg ├── irc_ros.repos ├── irc_ros_bringup ├── CMakeLists.txt ├── README.md ├── config │ ├── controller_cpr_platform_medium.yaml │ ├── controller_dio_module.yaml │ ├── controller_igus_rebel_4dof.yaml │ ├── controller_igus_rebel_6dof.yaml │ └── controller_igus_robolink_rl_dp_5.yaml ├── launch │ ├── additional_controllers.launch.py │ ├── cpr_platform.launch.py │ ├── rebel.launch.py │ ├── rebel_on_platform.launch.py │ ├── robolink_rl_dp_5.launch.py │ ├── sick_s300_2.launch.py │ ├── sick_s300_2_two_scanners_merged.launch.py │ └── two_rebels.launch.py ├── package.xml └── params │ └── sick_s300.yaml ├── irc_ros_controllers ├── CMakeLists.txt ├── README.md ├── dashboard_controller.xml ├── dio_controller.xml ├── include │ └── irc_ros_controllers │ │ ├── dashboard_controller.hpp │ │ ├── dashboard_semantic_component_interface.hpp │ │ ├── dio_controller.hpp │ │ └── schmalz_ecbpmi_controller.hpp ├── package.xml ├── schmalz_ecbpmi_controller.xml └── src │ ├── dashboard_controller.cpp │ ├── dio_controller.cpp │ └── schmalz_ecbpmi_controller.cpp ├── irc_ros_dashboard ├── README.md ├── doc │ ├── dashboard.drawio │ ├── dashboard.png │ ├── dashboard_process.drawio │ └── dashboard_process.png ├── irc_ros_dashboard │ ├── __init__.py │ └── cli_dashboard.py ├── package.xml ├── resource │ └── irc_ros_dashboard ├── setup.cfg ├── setup.py └── test │ ├── test_copyright.py │ ├── test_flake8.py │ └── test_pep257.py ├── irc_ros_description ├── CMakeLists.txt ├── README.md ├── doc │ ├── urdf_structure.drawio │ ├── urdf_structure.png │ └── visualize.png ├── launch │ └── visualize.launch.py ├── meshes │ ├── cpr_platform_medium │ │ ├── body.dae │ │ ├── bodyColl.dae │ │ ├── wheel.dae │ │ └── wheelColl.dae │ ├── gripper_schmalz_ecbpmi │ │ ├── Joint0.dae │ │ └── Joint0Coll.dae │ ├── igus_rebel_4dof_00 │ │ ├── Joint0.dae │ │ ├── Joint0Coll.dae │ │ ├── Joint1.dae │ │ ├── Joint1Coll.dae │ │ ├── Joint2.dae │ │ ├── Joint2Coll.dae │ │ ├── Joint3.dae │ │ ├── Joint3Coll.dae │ │ ├── Joint4.dae │ │ └── Joint4Coll.dae │ ├── igus_rebel_4dof_pre │ │ ├── Joint0.dae │ │ ├── Joint0Coll.dae │ │ ├── Joint1.dae │ │ ├── Joint1Coll.dae │ │ ├── Joint2.dae │ │ ├── Joint2Coll.dae │ │ ├── Joint3.dae │ │ ├── Joint3Coll.dae │ │ ├── Joint4.dae │ │ └── Joint4Coll.dae │ ├── igus_rebel_6dof_00 │ │ ├── Joint0.dae │ │ ├── Joint0Coll.dae │ │ ├── Joint1.dae │ │ ├── Joint1Coll.dae │ │ ├── Joint2.dae │ │ ├── Joint2Coll.dae │ │ ├── Joint3.dae │ │ ├── Joint3Coll.dae │ │ ├── Joint4.dae │ │ ├── Joint4Coll.dae │ │ ├── Joint5.dae │ │ ├── Joint5Coll.dae │ │ ├── Joint6.dae │ │ └── Joint6Coll.dae │ ├── igus_rebel_6dof_pre │ │ ├── Joint0.dae │ │ ├── Joint0Coll.dae │ │ ├── Joint1.dae │ │ ├── Joint1Coll.dae │ │ ├── Joint2.dae │ │ ├── Joint2Coll.dae │ │ ├── Joint3.dae │ │ ├── Joint3Coll.dae │ │ ├── Joint4.dae │ │ ├── Joint4Coll.dae │ │ ├── Joint5.dae │ │ ├── Joint5Coll.dae │ │ ├── Joint6.dae │ │ └── Joint6Coll.dae │ └── igus_robolink_rl_dp_5 │ │ ├── Joint0.dae │ │ ├── Joint0Coll.dae │ │ ├── Joint1.dae │ │ ├── Joint1Coll.dae │ │ ├── Joint2.dae │ │ ├── Joint2Coll.dae │ │ ├── Joint3.dae │ │ ├── Joint3Coll.dae │ │ ├── Joint4.dae │ │ ├── Joint4Coll.dae │ │ ├── Joint5.dae │ │ └── Joint5Coll.dae ├── package.xml ├── rviz │ ├── platform.rviz │ └── rebel.rviz └── urdf │ ├── cpr_platform_medium.urdf.xacro │ ├── grippers │ ├── ext_dio_gripper.description.xacro │ ├── ext_dio_gripper.ros2_control.xacro │ ├── grippers.macro.xacro │ └── schmalz_ecbpmi.description.xacro │ ├── igus_rebel_4dof.urdf.xacro │ ├── igus_rebel_6dof.urdf.xacro │ ├── igus_robolink_rl_dp_5.urdf.xacro │ ├── modules │ ├── din_rail.ros2_control.xacro │ └── rebel.ros2_control.xacro │ ├── platforms │ ├── cpr_platform_medium.description.xacro │ ├── cpr_platform_medium.macro.xacro │ └── cpr_platform_medium.ros2_control.xacro │ ├── rebel_on_platform.urdf.xacro │ └── robots │ ├── igus_rebel_4dof.macro.xacro │ ├── igus_rebel_4dof_00.description.xacro │ ├── igus_rebel_4dof_00.ros2_control.xacro │ ├── igus_rebel_4dof_01.description.xacro │ ├── igus_rebel_4dof_01.ros2_control.xacro │ ├── igus_rebel_6dof.macro.xacro │ ├── igus_rebel_6dof_00.description.xacro │ ├── igus_rebel_6dof_00.ros2_control.xacro │ ├── igus_rebel_6dof_01.description.xacro │ ├── igus_rebel_6dof_01.ros2_control.xacro │ ├── igus_rebel_6dof_pre.description.xacro │ ├── igus_rebel_6dof_pre.ros2_control.xacro │ ├── igus_robolink_rl_dp_5.description.xacro │ ├── igus_robolink_rl_dp_5.macro.xacro │ └── igus_robolink_rl_dp_5.ros2_control.xacro ├── irc_ros_examples ├── CMakeLists.txt ├── README.md ├── doc │ ├── pick_and_place.gif │ └── pick_and_place_vacuum.gif ├── include │ └── irc_ros_examples │ │ └── pick_and_place_base.hpp ├── irc_ros_examples │ └── __init__.py ├── launch │ ├── baristabot.launch.py │ ├── nav2_simple_commander_example.launch.py │ ├── pick_and_place.launch.py │ └── pick_and_place_vacuum.launch.py ├── package.xml ├── resource │ └── irc_ros_examples ├── scripts │ ├── baristabot.py │ └── nav2_simple_commander_example.py └── src │ ├── pick_and_place.cpp │ └── pick_and_place_vacuum.cpp ├── irc_ros_hardware ├── CMakeLists.txt ├── README.md ├── doc │ ├── candump.txt │ ├── jitter.png │ └── parse_candump.py ├── include │ └── irc_ros_hardware │ │ ├── CAN │ │ ├── can_interface.hpp │ │ ├── can_message.hpp │ │ ├── can_socket.hpp │ │ ├── cprcan_v2.hpp │ │ ├── digital_io.hpp │ │ ├── joint.hpp │ │ ├── module.hpp │ │ └── modulestates.hpp │ │ ├── CRI │ │ ├── cri_keywords.hpp │ │ ├── cri_messages.hpp │ │ └── cri_socket.hpp │ │ ├── common │ │ └── errorstate.hpp │ │ ├── irc_ros_can.hpp │ │ └── irc_ros_cri.hpp ├── irc_ros_hardware.xml ├── package.xml └── src │ ├── CAN │ ├── can_interface.cpp │ ├── can_message.cpp │ ├── can_socket.cpp │ ├── digital_io.cpp │ ├── joint.cpp │ └── module.cpp │ ├── CRI │ ├── cri_messages.cpp │ └── cri_socket.cpp │ ├── irc_ros_can.cpp │ └── irc_ros_cri.cpp ├── irc_ros_moveit_config ├── CMakeLists.txt ├── README.md ├── config │ ├── controllers.yaml │ ├── igus_rebel_6dof.srdf.xacro │ ├── initial_positions.yaml │ ├── joint_limits.yaml │ ├── kinematics.yaml │ ├── moveit_controllers.yaml │ ├── moveit_py.yaml │ ├── ompl.yaml │ ├── pilz_cartesian_limits.yaml │ └── ros2_controllers.yaml ├── launch │ └── rebel.launch.py ├── package.xml └── rviz │ └── moveit.rviz ├── irc_ros_msgs ├── CMakeLists.txt ├── README.md ├── msg │ ├── CanModuleCommand.msg │ ├── CanModuleState.msg │ ├── CanModuleStates.msg │ ├── DioCommand.msg │ ├── DioState.msg │ ├── DioStates.msg │ ├── GripperCommand.msg │ └── GripperState.msg ├── package.xml └── srv │ ├── CanModuleCommand.srv │ ├── DioCommand.srv │ └── GripperCommand.srv └── irc_ros_navigation2 ├── CMakeLists.txt ├── README.md ├── doc └── slam.png ├── launch └── cpr_platform.launch.py ├── map ├── map.pgm ├── map.yaml ├── map_office.pgm └── map_office.yaml ├── package.xml ├── params └── cpr_platform_medium.yaml └── rviz └── platform.rviz /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: 'bug' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Description** 11 | A clear and concise description of what the bug is. 12 | 13 | **Your environment** 14 | 15 | ROS Distro: [Humble|Iron|Rolling] 16 | OS Version: e.g. Ubuntu 22.04 17 | Branch/Commit hash: e.g. humble #9878a63 18 | Protocol: [Mock Hardware|CPRCANv2|CRI] 19 | Module Firmware version(s) (CPRCAN only, seen in ROS): e.g. 03.03 20 | 21 | **To Reproduce** 22 | 1. Start launchfile via 'ros2 launch foo bar param_1:=asd' 23 | 2. Publish message to '/buggy/topic' 24 | 3. ROS crashes 25 | 26 | **Expected behavior** 27 | A clear and concise description of what you expected to happen. 28 | 29 | **Actual behavior** 30 | Backtrace or Console output 31 | -------------------------------------------------------------------------------- /.github/workflows/ci.yaml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: 3 | push: 4 | branches: [ humble ] 5 | pull_request: 6 | 7 | jobs: 8 | pre-commit: 9 | name: pre-commit 10 | runs-on: ubuntu-22.04 11 | strategy: 12 | fail-fast: false 13 | steps: 14 | - uses: actions/checkout@v3 15 | - uses: ros-tooling/setup-ros@v0.6 16 | - run: sudo apt-get install -y ros-humble-ament-clang-format ros-humble-ament-flake8 ros-humble-ament-xmllint ros-humble-ament-lint 17 | - uses: pre-commit/action@v3.0.0 18 | with: 19 | extra_args: --hook-stage manual 20 | - uses: pre-commit-ci/lite-action@v1.0.1 21 | if: always() 22 | - uses: ros-tooling/action-ros-ci@v0.2 23 | with: 24 | package-name: | 25 | irc_ros_bringup 26 | irc_ros_controllers 27 | irc_ros_dashboard 28 | irc_ros_description 29 | irc_ros_examples 30 | irc_ros_hardware 31 | irc_ros_moveit_config 32 | irc_ros_msgs 33 | irc_ros_navigation2 34 | 35 | import-token: ${{ secrets.GITHUB_TOKEN }} 36 | target-ros2-distro: humble # TODO: Add rolling, maybe iron once released? 37 | skip-tests: true 38 | vcs-repo-file-url: "${{ github.workspace }}/irc_ros.repos" 39 | -------------------------------------------------------------------------------- /.github/workflows/pages.yaml: -------------------------------------------------------------------------------- 1 | name: GitHub Pages 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | #pull_request: 8 | 9 | jobs: 10 | deploy: 11 | runs-on: ubuntu-22.04 12 | permissions: 13 | contents: write 14 | concurrency: 15 | group: ${{ github.workflow }}-${{ github.ref }} 16 | steps: 17 | - uses: actions/checkout@v3 18 | 19 | - uses: mattnotmitt/doxygen-action@v1.9.5 20 | 21 | - name: Deploy 22 | uses: peaceiris/actions-gh-pages@v3 23 | if: ${{ github.ref == 'refs/heads/master' }} 24 | with: 25 | github_token: ${{ secrets.GITHUB_TOKEN }} 26 | publish_dir: ./doc/html 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | 34 | #Editor 35 | .vscode 36 | 37 | #ROS 38 | log 39 | build 40 | install -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | # Based on https://github.com/UniversalRobots/Universal_Robots_ROS2_Driver/blob/main/.pre-commit-config.yaml 2 | # Lint cpp, py, xml, cmake 3 | 4 | repos: 5 | - repo: https://github.com/asottile/pyupgrade 6 | rev: v1.25.0 7 | hooks: 8 | - id: pyupgrade 9 | args: [--py36-plus] 10 | 11 | - repo: https://github.com/psf/black 12 | rev: 23.1.0 13 | hooks: 14 | - id: black 15 | 16 | - repo: local 17 | hooks: 18 | - id: ament_clang_format 19 | name: ament_clang_format 20 | stages: [commit] 21 | entry: ament_clang_format 22 | language: system 23 | files: \.(c|cc|cxx|cpp|frag|glsl|h|hpp|hxx|ih|ispc|ipp|java|js|m|proto|vert)$ 24 | args: ["--reformat"] 25 | 26 | - repo: local 27 | hooks: 28 | - id: ament_flake8 29 | name: ament_flake8 30 | stages: [commit] 31 | entry: ament_flake8 32 | language: system 33 | files: \.py$ 34 | 35 | - repo: local 36 | hooks: 37 | - id: ament_xmllint 38 | name: ament_xmllint 39 | stages: [commit] 40 | entry: ament_xmllint 41 | language: system 42 | files: \.xml$ 43 | 44 | - repo: local 45 | hooks: 46 | - id: ament_lint_cmake 47 | name: ament_lint_cmake 48 | stages: [commit] 49 | entry: ament_lint_cmake 50 | language: system 51 | files: CMakeLists.txt$ 52 | 53 | # Spellcheck in comments and docs 54 | # skipping of *.svg files is not working... 55 | - repo: https://github.com/codespell-project/codespell 56 | rev: v2.0.0 57 | hooks: 58 | - id: codespell 59 | args: ['--write-changes -q4 -L dout,DOUT'] 60 | exclude: \.(svg|pyc|drawio|txt)$ -------------------------------------------------------------------------------- /doc/Architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonplaceRobotics/iRC_ROS/41701e6df3398087d217f0f478622e60f694de41/doc/Architecture.png -------------------------------------------------------------------------------- /doc/logo_cpr.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonplaceRobotics/iRC_ROS/41701e6df3398087d217f0f478622e60f694de41/doc/logo_cpr.jpg -------------------------------------------------------------------------------- /doc/logo_igus_lca.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonplaceRobotics/iRC_ROS/41701e6df3398087d217f0f478622e60f694de41/doc/logo_igus_lca.jpg -------------------------------------------------------------------------------- /irc_ros.repos: -------------------------------------------------------------------------------- 1 | repositories: 2 | ira_laser_tools: 3 | type: git 4 | url: https://github.com/nakai-omer/ira_laser_tools.git 5 | version: humble 6 | joint_state_publisher: 7 | type: git 8 | url: https://github.com/ros/joint_state_publisher.git 9 | version: ros2 10 | rqt_robot_steering: 11 | type: git 12 | url: https://github.com/cpr-fer/rqt_robot_steering.git 13 | version: twiststamped 14 | sicks300_2: 15 | type: git 16 | url: https://github.com/ajtudela/sicks300_2.git 17 | version: humble 18 | -------------------------------------------------------------------------------- /irc_ros_bringup/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5) 2 | project(irc_ros_bringup) 3 | 4 | set(CMAKE_CXX_STANDARD 17) 5 | #set(CMAKE_AUTOMOC ON) 6 | #set(CMAKE_AUTOUIC ON) 7 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 8 | 9 | 10 | ## Find catkin macros and libraries 11 | ## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz) 12 | ## is used, also find other catkin packages 13 | find_package(ament_cmake REQUIRED) 14 | 15 | 16 | install(DIRECTORY config launch params 17 | DESTINATION share/${PROJECT_NAME} 18 | ) 19 | 20 | ament_package() 21 | -------------------------------------------------------------------------------- /irc_ros_bringup/README.md: -------------------------------------------------------------------------------- 1 | # iRC ROS Bringup 2 | 3 | This contains the basic, non-MoveIt2 launch files and ROS2 controller configs. 4 | 5 | When you want to use just a ReBeL arm the launch files here should suffice. 6 | 7 | ## Install 8 | ### ReBeL standalone 9 | - nothing besides this repository required 10 | ### Mobile Platform 11 | In case you are planning to use a mobile platform look at `irc_ros_navigation2` as well. 12 | - For the mobile platforms laser scanners install the following packages (Add them to your workspace folder) 13 | - [Sick300 ROS2](https://github.com/ajtudela/sicks300_2) 14 | - [IRA Laser Tools (humble PR)](https://github.com/nakai-omer/ira_laser_tools/tree/humble) 15 | - [rqt_robot_steering](https://github.com/ros-visualization/rqt_robot_steering) (Also in the ubuntu repos) 16 | 17 | ## Usage 18 | You can start the robot driver as follows: 19 | 20 | ``` console 21 | $ ros2 launch irc_ros_bringup rebel.launch.py rebel_version:=00 gripper:=schmalz_ecbpmi use_rviz:=false 22 | ``` 23 | 24 | Manual joint states then can be send in different ways. For actual applications please refer to the MoveIt pkg. 25 | 26 | ### Control via command line 27 | Found [here](https://git.nilsschulte.de/nils/dynamixel_ros2_control). Change values accordingly. 28 | 29 | #### Rebel 6DOF 30 | ``` console 31 | $ ros2 topic pub /joint_trajectory_controller/joint_trajectory trajectory_msgs/msg/JointTrajectory '{header: {stamp: {sec: '"$(date '+%s + 6' | bc)"'}}, joint_names: ["joint1", "joint2", "joint3", "joint4", "joint5", "joint6"], points: [{positions: [0.0, 0.0, 0.0, 0.0, 0.0, 0.0], time_from_start: {sec: 0}}]}' --once 32 | ``` 33 | 34 | #### Rebel 4DOF 35 | ``` console 36 | $ ros2 topic pub /joint_trajectory_controller/joint_trajectory trajectory_msgs/msg/JointTrajectory '{header: {stamp: {sec: '"$(date '+%s + 6' | bc)"'}}, joint_names: ["joint1", "joint2", "joint3", "joint4"], points: [{positions: [0.0, 0.0, 0.0, 0.0], time_from_start: {sec: 0}}]}' --once 37 | ``` 38 | 39 | #### Mobile platform (x linear and z angular) 40 | ``` console 41 | $ ros2 topic pub /cpr_platform_controller/cmd_vel geometry_msgs/msg/TwistStamped '{header: {stamp: {sec: '"$(date '+%s + 6' | bc)"'}}, twist: { linear: {x: 0.0, y: 0, z: 0}, angular: {x: 0, y: 0, z: 0.0}}}' --once 42 | ``` 43 | or 44 | ``` console 45 | $ ros2 topic pub /cpr_platform_controller/cmd_vel_unstamped geometry_msgs/msg/Twist '{linear: {x: 0.0, y: 0, z: 0}, angular: {x: 0, y: 0, z: 0.0}}' --once 46 | ``` 47 | 48 | ### ROS actions 49 | ``` console 50 | $ ros2 action send_goal /joint_trajectory_controller/follow_joint_trajectory control_msgs/action/FollowJointTrajectory [...] 51 | ``` 52 | 53 | ### Control via rqt_robot_steering (Mobile platform only) 54 | Note: Currently only works with `geometry_msgs/msg/Twist`, while we want `TwistStamped` instead, PR is [here](https://github.com/ros-visualization/rqt_robot_steering/pull/14). In the meantime the type is set to `Twist` in the controller config file. 55 | - Select topic as `/cpr_platform_controller/cmd_vel` 56 | - W,A,S,D for directions 57 | - Space to reset speed to 0 58 | 59 | ## Launch files 60 | Use `ros2 launch irc_ros_bringup [...].launch.py --show-args` for more information about the available launch arguments. 61 | 62 | ## Controller files 63 | - `controller_igus_rebel_*dof.yaml` implements position control via a JointTrajectoryController 64 | - `controller_cpr_platform_medium.yaml` implements velocity control via a DiffDriveController. While the position commands are more precise for repeatability, the use of velocity commands causes smoother and straighter driving. -------------------------------------------------------------------------------- /irc_ros_bringup/config/controller_cpr_platform_medium.yaml: -------------------------------------------------------------------------------- 1 | /controller_manager: 2 | ros__parameters: 3 | update_rate: 100 # 100Hz for CAN and 10Hz for CRI 4 | 5 | joint_state_broadcaster: 6 | type: joint_state_broadcaster/JointStateBroadcaster 7 | 8 | cpr_platform_controller: 9 | type: diff_drive_controller/DiffDriveController 10 | 11 | /cpr_platform_controller: 12 | ros__parameters: 13 | 14 | left_wheel_names: ["joint_wheel_1"] 15 | right_wheel_names: ["joint_wheel_2"] 16 | 17 | odom_frame_id: odom 18 | base_frame_id: base_link 19 | 20 | enable_odom_tf: true 21 | 22 | wheel_separation: 0.47285 23 | wheel_radius: 0.07457 # Measured, should be 0.07308 according to the CPRog settings 24 | 25 | command_interfaces: 26 | - velocity 27 | 28 | state_interfaces: 29 | - position 30 | - velocity 31 | 32 | state_publish_rate: 100.0 # Defaults to 50 33 | action_monitor_rate: 100.0 # Defaults to 20 34 | 35 | open_loop_control: true 36 | allow_partial_joints_goal: true 37 | 38 | # TODO: Goal_pose commands from Rviz2 send Twist instead of TwistStamped 39 | # See if it is possible to change the rviz behaviour as TwistStamped is 40 | # becoming the new standard 41 | use_stamped_vel: false -------------------------------------------------------------------------------- /irc_ros_bringup/config/controller_dio_module.yaml: -------------------------------------------------------------------------------- 1 | /controller_manager: 2 | ros__parameters: 3 | update_rate: 100 # 100Hz for CAN and 10Hz for CRI 4 | 5 | external_dio_controller: 6 | type: irc_ros_controllers/DIOController 7 | 8 | 9 | /external_dio_controller: 10 | ros__parameters: 11 | digital_inputs: 12 | - dio_ext/digital_input_0 13 | - dio_ext/digital_input_1 14 | - dio_ext/digital_input_2 15 | - dio_ext/digital_input_3 16 | - dio_ext/digital_input_4 17 | - dio_ext/digital_input_5 18 | - dio_ext/digital_input_6 19 | digital_outputs: 20 | - dio_ext/digital_output_0 21 | - dio_ext/digital_output_1 22 | - dio_ext/digital_output_2 23 | - dio_ext/digital_output_3 24 | - dio_ext/digital_output_4 25 | - dio_ext/digital_output_5 26 | - dio_ext/digital_output_6 -------------------------------------------------------------------------------- /irc_ros_bringup/config/controller_igus_rebel_4dof.yaml: -------------------------------------------------------------------------------- 1 | /controller_manager: 2 | ros__parameters: 3 | update_rate: 100 # 100Hz for CAN and 10Hz for CRI 4 | 5 | joint_state_broadcaster: 6 | type: joint_state_broadcaster/JointStateBroadcaster 7 | 8 | joint_trajectory_controller: 9 | type: joint_trajectory_controller/JointTrajectoryController 10 | 11 | dio_controller: 12 | type: irc_ros_controllers/DIOController 13 | 14 | /joint_trajectory_controller: 15 | ros__parameters: 16 | joints: 17 | - joint1 18 | - joint2 19 | - joint3 20 | - joint4 21 | 22 | command_interfaces: 23 | - position 24 | 25 | state_interfaces: 26 | - position 27 | 28 | state_publish_rate: 100.0 # Defaults to 50 29 | action_monitor_rate: 100.0 # Defaults to 20 30 | 31 | open_loop_control: true 32 | allow_partial_joints_goal: true 33 | 34 | /dio_controller: 35 | ros__parameters: 36 | digital_inputs: 37 | - dio_arm/digital_input_0 38 | - dio_arm/digital_input_1 39 | - dio_base/digital_input_0 40 | - dio_base/digital_input_1 41 | - dio_base/digital_input_2 42 | - dio_base/digital_input_3 43 | - dio_base/digital_input_4 44 | - dio_base/digital_input_5 45 | - dio_base/digital_input_6 46 | 47 | digital_outputs: 48 | - dio_arm/digital_output_0 49 | - dio_arm/digital_output_1 50 | - dio_base/digital_output_0 51 | - dio_base/digital_output_1 52 | - dio_base/digital_output_2 53 | - dio_base/digital_output_3 54 | - dio_base/digital_output_4 55 | - dio_base/digital_output_5 56 | - dio_base/digital_output_6 -------------------------------------------------------------------------------- /irc_ros_bringup/config/controller_igus_rebel_6dof.yaml: -------------------------------------------------------------------------------- 1 | /controller_manager: 2 | ros__parameters: 3 | update_rate: 100 # 100Hz for CAN and 10Hz for CRI 4 | 5 | joint_state_broadcaster: 6 | type: joint_state_broadcaster/JointStateBroadcaster 7 | 8 | joint_trajectory_controller: 9 | type: joint_trajectory_controller/JointTrajectoryController 10 | 11 | dio_controller: 12 | type: irc_ros_controllers/DIOController 13 | 14 | ecbpmi_controller: 15 | type: irc_ros_controllers/EcbpmiController 16 | 17 | dashboard_controller: 18 | type: irc_ros_controllers/DashboardController 19 | 20 | /joint_trajectory_controller: 21 | ros__parameters: 22 | joints: 23 | - joint1 24 | - joint2 25 | - joint3 26 | - joint4 27 | - joint5 28 | - joint6 29 | 30 | command_interfaces: 31 | - position 32 | 33 | state_interfaces: 34 | - position 35 | 36 | state_publish_rate: 100.0 # Defaults to 50 37 | action_monitor_rate: 100.0 # Defaults to 20 38 | 39 | open_loop_control: true 40 | allow_partial_joints_goal: true 41 | 42 | 43 | /dio_controller: 44 | ros__parameters: 45 | digital_inputs: 46 | - dio_arm/digital_input_0 47 | - dio_arm/digital_input_1 48 | - dio_base/digital_input_0 49 | - dio_base/digital_input_1 50 | - dio_base/digital_input_2 51 | - dio_base/digital_input_3 52 | - dio_base/digital_input_4 53 | - dio_base/digital_input_5 54 | - dio_base/digital_input_6 55 | 56 | digital_outputs: 57 | - dio_arm/digital_output_0 58 | - dio_arm/digital_output_1 59 | - dio_base/digital_output_0 60 | - dio_base/digital_output_1 61 | - dio_base/digital_output_2 62 | - dio_base/digital_output_3 63 | - dio_base/digital_output_4 64 | - dio_base/digital_output_5 65 | - dio_base/digital_output_6 66 | 67 | # TODO: Rate limit this from 100Hz (Issue #74) 68 | /dashboard_controller: 69 | ros__parameters: 70 | joints: 71 | - joint1 72 | - joint2 73 | - joint3 74 | - joint4 75 | - joint5 76 | - joint6 77 | # - joint_wheel_1 78 | # - joint_wheel_2 79 | 80 | gpios: 81 | - dio_arm 82 | - dio_base 83 | # - dio_ext 84 | 85 | joint_state_interfaces: 86 | - position 87 | - velocity 88 | - effort 89 | 90 | joint_command_interface: 91 | - position 92 | # - velocity 93 | # - effort 94 | 95 | digital_inputs: 96 | - dio_arm/digital_input_0 97 | - dio_arm/digital_input_1 98 | - dio_base/digital_input_0 99 | - dio_base/digital_input_1 100 | - dio_base/digital_input_2 101 | - dio_base/digital_input_3 102 | - dio_base/digital_input_4 103 | - dio_base/digital_input_5 104 | - dio_base/digital_input_6 105 | 106 | digital_outputs: 107 | - dio_arm/digital_output_0 108 | - dio_arm/digital_output_1 109 | - dio_base/digital_output_0 110 | - dio_base/digital_output_1 111 | - dio_base/digital_output_2 112 | - dio_base/digital_output_3 113 | - dio_base/digital_output_4 114 | - dio_base/digital_output_5 115 | - dio_base/digital_output_6 116 | 117 | /ecbpmi_controller: 118 | ros__parameters: 119 | output_grip: dio_arm/digital_output_0 120 | output_release: dio_arm/digital_output_1 121 | input_grasped: dio_arm/digital_input_0 122 | -------------------------------------------------------------------------------- /irc_ros_bringup/config/controller_igus_robolink_rl_dp_5.yaml: -------------------------------------------------------------------------------- 1 | /controller_manager: 2 | ros__parameters: 3 | update_rate: 100 # 100Hz for CAN and 10Hz for CRI 4 | 5 | joint_state_broadcaster: 6 | type: joint_state_broadcaster/JointStateBroadcaster 7 | 8 | joint_trajectory_controller: 9 | type: joint_trajectory_controller/JointTrajectoryController 10 | 11 | /joint_trajectory_controller: 12 | ros__parameters: 13 | joints: 14 | - joint1 15 | - joint2 16 | - joint3 17 | - joint4 18 | - joint5 19 | 20 | command_interfaces: 21 | - position 22 | 23 | state_interfaces: 24 | - position 25 | 26 | state_publish_rate: 100.0 # Defaults to 50 27 | action_monitor_rate: 100.0 # Defaults to 20 28 | 29 | open_loop_control: true 30 | allow_partial_joints_goal: true -------------------------------------------------------------------------------- /irc_ros_bringup/launch/additional_controllers.launch.py: -------------------------------------------------------------------------------- 1 | from launch import LaunchDescription 2 | from launch.actions import DeclareLaunchArgument 3 | from launch.conditions import IfCondition 4 | from launch.substitutions import ( 5 | LaunchConfiguration, 6 | PythonExpression, 7 | ) 8 | from launch_ros.actions import Node 9 | 10 | 11 | def generate_launch_description(): 12 | launch_dashboard_controller_arg = DeclareLaunchArgument( 13 | "launch_dashboard_controller", default_value="true" 14 | ) 15 | launch_dio_controller_arg = DeclareLaunchArgument( 16 | "launch_dio_controller", default_value="true" 17 | ) 18 | dio_controller_node = Node( 19 | package="controller_manager", 20 | executable="spawner", 21 | namespace=LaunchConfiguration("namespace"), 22 | arguments=[ 23 | "dio_controller", 24 | "-c", 25 | LaunchConfiguration("controller_manager_name"), 26 | ], 27 | condition=IfCondition( 28 | PythonExpression( 29 | [ 30 | "'", 31 | LaunchConfiguration("hardware_protocol"), 32 | "' == 'cprcanv2' ", 33 | "and '", 34 | LaunchConfiguration("launch_dio_controller"), 35 | "' in ['1', 'true', 'True']", 36 | ] 37 | ) 38 | ), 39 | ) 40 | 41 | external_dio_controller_node = Node( 42 | package="controller_manager", 43 | executable="spawner", 44 | namespace=LaunchConfiguration("namespace"), 45 | arguments=[ 46 | "external_dio_controller", 47 | "-c", 48 | LaunchConfiguration("controller_manager_name"), 49 | ], 50 | condition=IfCondition( 51 | PythonExpression( 52 | [ 53 | "'", 54 | LaunchConfiguration("hardware_protocol"), 55 | "' == 'cprcanv2' ", 56 | "and '", 57 | LaunchConfiguration("gripper"), 58 | "' == 'ext_dio_gripper' ", 59 | ] 60 | ) 61 | ), 62 | ) 63 | 64 | ecbpmi_controller_node = Node( 65 | package="controller_manager", 66 | executable="spawner", 67 | namespace=LaunchConfiguration("namespace"), 68 | arguments=[ 69 | "ecbpmi_controller", 70 | "-c", 71 | LaunchConfiguration("controller_manager_name"), 72 | ], 73 | condition=IfCondition( 74 | PythonExpression( 75 | [ 76 | "'", 77 | LaunchConfiguration("hardware_protocol"), 78 | "' == 'cprcanv2' ", 79 | "and '", 80 | LaunchConfiguration("gripper"), 81 | "' == 'schmalz_ecbpmi' ", 82 | ] 83 | ) 84 | ), 85 | ) 86 | 87 | dashboard_controller_node = Node( 88 | package="controller_manager", 89 | executable="spawner", 90 | namespace=LaunchConfiguration("namespace"), 91 | arguments=[ 92 | "dashboard_controller", 93 | "-c", 94 | LaunchConfiguration("controller_manager_name"), 95 | ], 96 | condition=IfCondition( 97 | PythonExpression( 98 | [ 99 | "'", 100 | LaunchConfiguration("hardware_protocol"), 101 | "' == 'cprcanv2' ", 102 | "and '", 103 | LaunchConfiguration("launch_dashboard_controller"), 104 | "' in ['1', 'true', 'True']", 105 | ] 106 | ) 107 | ), 108 | ) 109 | 110 | description = LaunchDescription() 111 | description.add_action(launch_dashboard_controller_arg) 112 | description.add_action(launch_dio_controller_arg) 113 | 114 | description.add_action(dio_controller_node) 115 | description.add_action(external_dio_controller_node) 116 | description.add_action(ecbpmi_controller_node) 117 | description.add_action(dashboard_controller_node) 118 | 119 | return description 120 | -------------------------------------------------------------------------------- /irc_ros_bringup/launch/sick_s300_2.launch.py: -------------------------------------------------------------------------------- 1 | from launch import LaunchDescription 2 | from launch.actions import RegisterEventHandler, EmitEvent, DeclareLaunchArgument 3 | from launch.events import matches_action 4 | from launch.substitutions import PathJoinSubstitution, LaunchConfiguration 5 | from launch_ros.actions import LifecycleNode 6 | from launch_ros.substitutions import FindPackageShare 7 | from launch_ros.event_handlers import OnStateTransition 8 | from launch_ros.events.lifecycle import ChangeState 9 | 10 | import lifecycle_msgs.msg 11 | 12 | 13 | def generate_launch_description(): 14 | # Parameters to make including this multiple times over IncludeLaunchDescription easy 15 | laserscanner_name = LaunchConfiguration("laserscanner_name") 16 | laserscanner_name_arg = DeclareLaunchArgument( 17 | "laserscanner_name", 18 | default_value="sick_s300", 19 | description="Name of the laserscanner node", 20 | ) 21 | 22 | namespace = LaunchConfiguration("namespace") 23 | namespace_arg = DeclareLaunchArgument( 24 | "namespace", default_value="", description="Namespace for the laserscanner node" 25 | ) 26 | 27 | default_param_file = PathJoinSubstitution( 28 | [ 29 | FindPackageShare("sicks300_2"), 30 | "params", 31 | "default.yaml", 32 | ] 33 | ) 34 | params_file = LaunchConfiguration("params_file") 35 | params_file_arg = DeclareLaunchArgument( 36 | "params_file", 37 | default_value=default_param_file, 38 | description="Path to the parameter file containing the laser scanner's config", 39 | ) 40 | 41 | sicks300_2_node = LifecycleNode( 42 | package="sicks300_2", 43 | namespace=namespace, 44 | executable="sicks300_2", 45 | name=laserscanner_name, 46 | parameters=[params_file], 47 | emulate_tty=True, 48 | ) 49 | 50 | # When the sick node reaches the 'inactive' state, make it take the 'activate' transition. 51 | register_event_handler_for_sick_reaches_inactive_state = RegisterEventHandler( 52 | OnStateTransition( 53 | target_lifecycle_node=sicks300_2_node, 54 | goal_state="inactive", 55 | entities=[ 56 | EmitEvent( 57 | event=ChangeState( 58 | lifecycle_node_matcher=matches_action(sicks300_2_node), 59 | transition_id=lifecycle_msgs.msg.Transition.TRANSITION_ACTIVATE, 60 | ) 61 | ), 62 | ], 63 | ) 64 | ) 65 | 66 | # Make the sicks300_2 node take the 'configure' transition. 67 | emit_event_to_request_that_sick_does_configure_transition = EmitEvent( 68 | event=ChangeState( 69 | lifecycle_node_matcher=matches_action(sicks300_2_node), 70 | transition_id=lifecycle_msgs.msg.Transition.TRANSITION_CONFIGURE, 71 | ) 72 | ) 73 | 74 | description = LaunchDescription() 75 | 76 | description.add_action(laserscanner_name_arg) 77 | description.add_action(namespace_arg) 78 | description.add_action(params_file_arg) 79 | 80 | description.add_action(sicks300_2_node) 81 | description.add_action(register_event_handler_for_sick_reaches_inactive_state) 82 | description.add_action(emit_event_to_request_that_sick_does_configure_transition) 83 | 84 | return description 85 | -------------------------------------------------------------------------------- /irc_ros_bringup/launch/sick_s300_2_two_scanners_merged.launch.py: -------------------------------------------------------------------------------- 1 | from launch import LaunchDescription 2 | from launch.actions import DeclareLaunchArgument, IncludeLaunchDescription 3 | from launch.launch_description_sources import PythonLaunchDescriptionSource 4 | from launch.substitutions import PathJoinSubstitution, LaunchConfiguration 5 | from launch_ros.actions import Node 6 | from launch_ros.substitutions import FindPackageShare 7 | from nav2_common.launch import ReplaceString 8 | 9 | 10 | def generate_launch_description(): 11 | destination_frame_arg = DeclareLaunchArgument( 12 | "destination_frame_arg", 13 | default_value=[LaunchConfiguration("prefix"), "base_link"], 14 | description="The frame to which the scans are transformed", 15 | ) 16 | in_topics_arg = DeclareLaunchArgument( 17 | "in_topics", 18 | default_value=[ 19 | LaunchConfiguration("namespace"), 20 | "/scan_front", 21 | " ", 22 | LaunchConfiguration("namespace"), 23 | "/scan_back", 24 | ], 25 | description="The topics from which to read the scans", 26 | ) 27 | out_topic_arg = DeclareLaunchArgument( 28 | "out_topic", 29 | default_value=[LaunchConfiguration("namespace"), "/scan"], 30 | description="The topic where the transformed and merged scans are published", 31 | ) 32 | namespace = LaunchConfiguration("namespace") 33 | prefix = LaunchConfiguration("prefix") 34 | 35 | destination_frame = LaunchConfiguration("destination_frame_arg") 36 | in_topics = LaunchConfiguration("in_topics") 37 | out_topic = LaunchConfiguration("out_topic") 38 | 39 | # Sick S300 Laser scanners 40 | irc_ros_bringup_launch_dir = PathJoinSubstitution( 41 | [ 42 | FindPackageShare("irc_ros_bringup"), 43 | "launch", 44 | ] 45 | ) 46 | 47 | sick_s300_params_file = PathJoinSubstitution( 48 | [ 49 | FindPackageShare("irc_ros_bringup"), 50 | "params", 51 | "sick_s300.yaml", 52 | ] 53 | ) 54 | 55 | sick_s300_params = ReplaceString( 56 | source_file=sick_s300_params_file, 57 | replacements={ 58 | "": namespace, 59 | "": prefix, 60 | }, 61 | ) 62 | 63 | sicks300_2_stack_front = IncludeLaunchDescription( 64 | PythonLaunchDescriptionSource( 65 | [irc_ros_bringup_launch_dir, "/sick_s300_2.launch.py"] 66 | ), 67 | launch_arguments={ 68 | "laserscanner_name": "laserscanner_front", 69 | "namespace": namespace, 70 | "params_file": sick_s300_params, 71 | }.items(), 72 | ) 73 | 74 | sicks300_2_stack_back = IncludeLaunchDescription( 75 | PythonLaunchDescriptionSource( 76 | [irc_ros_bringup_launch_dir, "/sick_s300_2.launch.py"] 77 | ), 78 | launch_arguments={ 79 | "laserscanner_name": "laserscanner_back", 80 | "namespace": namespace, 81 | "params_file": sick_s300_params, 82 | }.items(), 83 | ) 84 | laser_merger_node = Node( 85 | package="ira_laser_tools", 86 | namespace=namespace, 87 | executable="laserscan_multi_merger", 88 | name="laserscan_multi_merger", 89 | parameters=[ 90 | { 91 | "destination_frame": destination_frame, 92 | "scan_destination_topic": out_topic, 93 | "laserscan_topics": in_topics, 94 | } 95 | ], 96 | ) 97 | 98 | description = LaunchDescription() 99 | description.add_action(destination_frame_arg) 100 | description.add_action(in_topics_arg) 101 | description.add_action(out_topic_arg) 102 | 103 | # description.add_action(namespace_arg) 104 | # description.add_action(prefix_arg) 105 | 106 | description.add_action(sicks300_2_stack_front) 107 | description.add_action(sicks300_2_stack_back) 108 | 109 | description.add_action(laser_merger_node) 110 | 111 | return description 112 | -------------------------------------------------------------------------------- /irc_ros_bringup/launch/two_rebels.launch.py: -------------------------------------------------------------------------------- 1 | from launch import LaunchDescription 2 | from launch.actions import IncludeLaunchDescription, GroupAction 3 | from launch.substitutions import PathJoinSubstitution 4 | from launch_ros.substitutions import FindPackageShare 5 | from launch.launch_description_sources import PythonLaunchDescriptionSource 6 | 7 | 8 | def generate_launch_description(): 9 | irc_ros_bringup_launch_dir = PathJoinSubstitution( 10 | [ 11 | FindPackageShare("irc_ros_bringup"), 12 | "launch", 13 | ] 14 | ) 15 | 16 | # We need different controller configs for this setup 17 | robot_controller_file_1 = PathJoinSubstitution( 18 | [ 19 | FindPackageShare("irc_ros_bringup"), 20 | "config", 21 | "controller_igus_rebel_6dof_namespace_1.yaml", 22 | ] 23 | ) 24 | robot_controller_file_2 = PathJoinSubstitution( 25 | [ 26 | FindPackageShare("irc_ros_bringup"), 27 | "config", 28 | "controller_igus_rebel_6dof_namespace_2.yaml", 29 | ] 30 | ) 31 | rebel_1_nodes = GroupAction( 32 | [ 33 | IncludeLaunchDescription( 34 | PythonLaunchDescriptionSource( 35 | [irc_ros_bringup_launch_dir, "/rebel.launch.py"] 36 | ), 37 | launch_arguments={ 38 | "namespace": "/rebel_1", 39 | "prefix": "rebel_1_", 40 | "gripper": "none", 41 | "launch_dashboard_controller": "false", 42 | "launch_dio_controller": "false", 43 | "use_rviz": "false", 44 | }.items(), 45 | ) 46 | ], 47 | scoped=True, 48 | ) 49 | rebel_2_nodes = GroupAction( 50 | [ 51 | IncludeLaunchDescription( 52 | PythonLaunchDescriptionSource( 53 | [irc_ros_bringup_launch_dir, "/rebel.launch.py"] 54 | ), 55 | launch_arguments={ 56 | "namespace": "/rebel_2", 57 | "prefix": "rebel_2_", 58 | "gripper": "none", 59 | "launch_dashboard_controller": "false", 60 | "launch_dio_controller": "false", 61 | "use_rviz": "false", 62 | }.items(), 63 | ) 64 | ], 65 | scoped=True, 66 | ) 67 | 68 | description = LaunchDescription() 69 | description.add_action(rebel_1_nodes) 70 | description.add_action(rebel_2_nodes) 71 | return description 72 | -------------------------------------------------------------------------------- /irc_ros_bringup/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | irc_ros_bringup 4 | 0.1.0 5 | The irc_ros_bringup package 6 | 7 | Felix Reuter 8 | Apache-2.0 9 | cpr-robots.com 10 | https://github.com/CommonplaceRobotics/iRC_ROS 11 | Björn Schenke 12 | Felix Reuter 13 | 14 | rclcpp 15 | std_msgs 16 | sensor_msgs 17 | control_msgs 18 | controller_manager 19 | controller_manager_msgs 20 | controller_interface 21 | hardware_interface 22 | rclcpp_lifecyle 23 | rviz2 24 | ros2_control 25 | ira_laser_tools 26 | nav2_common 27 | 28 | joint_state_broadcaster 29 | joint_state_publisher 30 | joint_trajectory_controller 31 | ros2_controllers_test_nodes 32 | irc_ros_hardware 33 | irc_ros_description 34 | 35 | 36 | 37 | 38 | 39 | 40 | ament_cmake 41 | 42 | 43 | -------------------------------------------------------------------------------- /irc_ros_bringup/params/sick_s300.yaml: -------------------------------------------------------------------------------- 1 | # Front laser 2 | /laserscanner_front: 3 | ros__parameters: 4 | port: /dev/ttyUSB0 5 | baud: 500000 6 | scan_duration: 0.025 # No info about that in SICK-docu, but 0.025 is believable and looks good in rviz 7 | scan_cycle_time: 0.040 # SICK-docu says S300 scans every 40ms 8 | inverted: false 9 | scan_id: 7 10 | frame_id: laser_front 11 | scan_topic: scan_front 12 | debug: false 13 | fields: 14 | '1': 15 | scale: 0.01 16 | 17 | # Laser scanners are configured to only send 180° 18 | # If we set another value here it stretches the points. 19 | # Reconfigure the laser scanners when changing this 20 | start_angle: -1.57 # -2.36 21 | stop_angle: 1.57 #2.36 22 | 23 | # Back laser 24 | /laserscanner_back: 25 | ros__parameters: 26 | port: /dev/ttyUSB1 27 | baud: 500000 28 | scan_duration: 0.025 # No info about that in SICK-docu, but 0.025 is believable and looks good in rviz 29 | scan_cycle_time: 0.040 # SICK-docu says S300 scans every 40ms 30 | inverted: false 31 | scan_id: 7 32 | frame_id: laser_back 33 | scan_topic: scan_back 34 | debug: false 35 | fields: 36 | '1': 37 | scale: 0.01 38 | start_angle: -1.57 39 | stop_angle: 1.57 -------------------------------------------------------------------------------- /irc_ros_controllers/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5) 2 | project(irc_ros_controllers) 3 | 4 | if(NOT CMAKE_CXX_STANDARD) 5 | set(CMAKE_CXX_STANDARD 17) 6 | endif() 7 | 8 | find_package(ament_cmake REQUIRED) 9 | find_package(controller_interface REQUIRED) 10 | find_package(example_interfaces REQUIRED) 11 | find_package(hardware_interface REQUIRED) 12 | find_package(irc_ros_hardware REQUIRED) 13 | find_package(irc_ros_msgs REQUIRED) 14 | find_package(pluginlib REQUIRED) 15 | find_package(rclcpp REQUIRED) 16 | find_package(rclcpp_lifecycle REQUIRED) 17 | 18 | set(INCLUDE_DEPENDS 19 | ament_cmake 20 | controller_interface 21 | example_interfaces 22 | hardware_interface 23 | irc_ros_hardware 24 | irc_ros_msgs 25 | pluginlib 26 | rclcpp 27 | rclcpp_lifecycle 28 | ) 29 | 30 | include_directories(include) 31 | 32 | add_library(${PROJECT_NAME} SHARED 33 | src/dashboard_controller.cpp 34 | src/dio_controller.cpp 35 | src/schmalz_ecbpmi_controller.cpp 36 | ) 37 | 38 | target_include_directories(${PROJECT_NAME} PRIVATE 39 | include 40 | ) 41 | 42 | ament_target_dependencies(${PROJECT_NAME} 43 | ${INCLUDE_DEPENDS} 44 | ) 45 | 46 | pluginlib_export_plugin_description_file(controller_interface dashboard_controller.xml) 47 | pluginlib_export_plugin_description_file(controller_interface dio_controller.xml) 48 | pluginlib_export_plugin_description_file(controller_interface schmalz_ecbpmi_controller.xml) 49 | 50 | 51 | install( 52 | DIRECTORY include/ 53 | DESTINATION include 54 | ) 55 | 56 | install( 57 | TARGETS ${PROJECT_NAME} 58 | RUNTIME DESTINATION bin 59 | ARCHIVE DESTINATION lib 60 | LIBRARY DESTINATION lib 61 | ) 62 | 63 | 64 | ament_export_dependencies( 65 | ${INCLUDE_DEPENDS} 66 | ) 67 | 68 | ament_export_include_directories( 69 | include 70 | ) 71 | 72 | ament_export_libraries( 73 | ${PROJECT_NAME} 74 | ) 75 | 76 | ament_package() -------------------------------------------------------------------------------- /irc_ros_controllers/dashboard_controller.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | Controller for interfacing with the hardware over external tools, such as the TUI Dashboard. Offers most module/joint/dio states, as well as the option to send commands. 7 | 8 | 9 | -------------------------------------------------------------------------------- /irc_ros_controllers/dio_controller.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | Controller for interacting with digital IOs. 7 | 8 | 9 | -------------------------------------------------------------------------------- /irc_ros_controllers/include/irc_ros_controllers/dashboard_controller.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "controller_interface/controller_interface.hpp" 9 | #include "irc_ros_controllers/dashboard_semantic_component_interface.hpp" 10 | #include "irc_ros_msgs/msg/can_module_states.hpp" 11 | #include "irc_ros_msgs/srv/can_module_command.hpp" 12 | 13 | namespace irc_ros_controllers 14 | { 15 | 16 | class DashboardController : public controller_interface::ControllerInterface 17 | { 18 | public: 19 | CallbackReturn on_init() override; 20 | 21 | CallbackReturn on_configure(const rclcpp_lifecycle::State & previous_state) override; 22 | 23 | controller_interface::InterfaceConfiguration command_interface_configuration() const override; 24 | controller_interface::InterfaceConfiguration state_interface_configuration() const override; 25 | 26 | CallbackReturn on_activate(const rclcpp_lifecycle::State & previous_state) override; 27 | 28 | CallbackReturn on_deactivate(const rclcpp_lifecycle::State & previous_state) override; 29 | 30 | controller_interface::return_type update( 31 | const rclcpp::Time & time, const rclcpp::Duration & period) override; 32 | 33 | private: 34 | void publish(); 35 | 36 | void dashboard_command_callback( 37 | irc_ros_msgs::srv::CanModuleCommand_Request::SharedPtr req, 38 | irc_ros_msgs::srv::CanModuleCommand_Response::SharedPtr resp); 39 | 40 | // Service, Subscriber, Publisher for all in-/outputs 41 | rclcpp::Publisher::SharedPtr dashboard_publisher_; 42 | rclcpp::Service::SharedPtr can_module_service_; 43 | std::vector> module_interfaces_; 44 | 45 | std::vector joints_; 46 | std::vector gpios_; 47 | 48 | std::vector module_command_interfaces_ = { 49 | "dashboard_command", 50 | }; 51 | std::vector module_state_interfaces_ = { 52 | "can_id", 53 | "hardware_ident", 54 | "version_major", 55 | "version_minor", 56 | "controller_type", 57 | "temperature_board", 58 | "temperature_motor", 59 | "supply_voltage", 60 | "motor_current" 61 | "command_mode", 62 | "error_state", 63 | "motor_state", 64 | "reset_state", 65 | 66 | }; 67 | 68 | // How long to wait for the acknowledgement of commands by the hardware interface 69 | const std::chrono::duration timeout_ = std::chrono::milliseconds(1000); 70 | }; 71 | } // namespace irc_ros_controllers -------------------------------------------------------------------------------- /irc_ros_controllers/include/irc_ros_controllers/dashboard_semantic_component_interface.hpp: -------------------------------------------------------------------------------- 1 | // Used the ROS2 driver for the iiwa by ICube as a template for the implementation 2 | // https://github.com/ICube-Robotics/iiwa_ros2/tree/main/iiwa_controllers/external_torque_sensor_broadcaster 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #include "irc_ros_hardware/CAN/modulestates.hpp" 11 | #include "irc_ros_msgs/msg/can_module_states.hpp" 12 | #include "semantic_components/semantic_component_interface.hpp" 13 | 14 | namespace irc_ros_controllers 15 | { 16 | 17 | class DashboardSCI 18 | : public semantic_components::SemanticComponentInterface 19 | { 20 | public: 21 | explicit DashboardSCI( 22 | const std::string & name, const std::string module_type, 23 | std::vector state_interfaces) 24 | : SemanticComponentInterface(name, state_interfaces.size()), module_type_(module_type) 25 | { 26 | for (auto si : state_interfaces) { 27 | interface_names_.emplace_back(name_ + "/" + si); 28 | } 29 | } 30 | 31 | virtual ~DashboardSCI() = default; 32 | DashboardSCI(const DashboardSCI &) = delete; 33 | DashboardSCI & operator=(const DashboardSCI &) = delete; 34 | 35 | // TODO: Cast the state enums to strings? (Add map in modulestates.hpp) 36 | // Easier to just print the states/show them inside a GUI, but then parsing the state 37 | // depends on the exact string assigned to it instead of an enum comparison, which on the other 38 | // hand would require to include the fitting .hpp file. 39 | bool get_values_as_message(irc_ros_msgs::msg::CanModuleState & message) 40 | { 41 | message.name = name_; 42 | for (auto && si : state_interfaces_) { 43 | std::string name = si.get().get_name(); 44 | 45 | // Here all possible StateInterfaces need to be handled 46 | if (name == (name_ + "/" + "can_id")) { 47 | std::stringstream ss; 48 | ss << "0x" << std::hex << static_cast(si.get().get_value()); 49 | message.can_id = ss.str().c_str(); 50 | } else if (name == (name_ + "/" + "hardware_ident")) { 51 | message.hardware_ident = static_cast(si.get().get_value()); 52 | } else if (name == (name_ + "/" + "version_major")) { 53 | message.version_major = static_cast(si.get().get_value()); 54 | } else if (name == (name_ + "/" + "version_minor")) { 55 | message.version_minor = static_cast(si.get().get_value()); 56 | } else if (name == (name_ + "/" + "temperature_board")) { 57 | message.temperature_board = si.get().get_value(); 58 | } else if (name == (name_ + "/" + "temperature_motor")) { 59 | message.temperature_motor = si.get().get_value(); 60 | } else if (name == (name_ + "/" + "supply_voltage")) { 61 | message.supply_voltage = si.get().get_value(); 62 | } else if (name == (name_ + "/" + "motor_current")) { 63 | message.motor_current = si.get().get_value(); 64 | } else if (name == (name_ + "/" + "error_state")) { 65 | message.error_state = static_cast(si.get().get_value()); 66 | } else if (name == (name_ + "/" + "reset_state")) { 67 | message.reset_state = static_cast(si.get().get_value()); 68 | } else if (name == (name_ + "/" + "motor_state")) { 69 | message.motor_state = static_cast(si.get().get_value()); 70 | } else if (name == (name_ + "/" + "command_mode")) { 71 | message.command_mode = static_cast(si.get().get_value()); 72 | } else { 73 | // Unexpected StateInterface 74 | // TODO: Once only the fitting interfaces are assigned in the dashboard controller return 75 | // false and handle the error. (Issue #75) 76 | // return false; 77 | } 78 | } 79 | 80 | return true; 81 | } 82 | 83 | private: 84 | std::string module_type_; 85 | }; 86 | } // namespace irc_ros_controllers -------------------------------------------------------------------------------- /irc_ros_controllers/include/irc_ros_controllers/dio_controller.hpp: -------------------------------------------------------------------------------- 1 | // Inspired by UR ROS2 driver 2 | // https://github.com/UniversalRobots/Universal_Robots_ROS2_Driver/blob/main/ur_controllers/include/ur_controllers/gpio_controller.hpp 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "controller_interface/controller_interface.hpp" 12 | #include "irc_ros_msgs/msg/dio_command.hpp" 13 | #include "irc_ros_msgs/msg/dio_state.hpp" 14 | #include "irc_ros_msgs/srv/dio_command.hpp" 15 | #include "std_msgs/msg/bool.hpp" 16 | 17 | namespace irc_ros_controllers 18 | { 19 | 20 | class DIOController : public controller_interface::ControllerInterface 21 | { 22 | public: 23 | controller_interface::InterfaceConfiguration command_interface_configuration() const override; 24 | 25 | controller_interface::InterfaceConfiguration state_interface_configuration() const override; 26 | 27 | controller_interface::return_type update( 28 | const rclcpp::Time & time, const rclcpp::Duration & period) override; 29 | 30 | CallbackReturn on_configure(const rclcpp_lifecycle::State & previous_state) override; 31 | 32 | CallbackReturn on_activate(const rclcpp_lifecycle::State & previous_state) override; 33 | 34 | CallbackReturn on_deactivate(const rclcpp_lifecycle::State & previous_state) override; 35 | 36 | CallbackReturn on_init() override; 37 | 38 | private: 39 | void set_outputs_service_callback( 40 | irc_ros_msgs::srv::DioCommand_Request::SharedPtr req, 41 | irc_ros_msgs::srv::DioCommand_Response::SharedPtr resp); 42 | 43 | void set_outputs_sub_callback(const irc_ros_msgs::msg::DioCommand & command); 44 | 45 | void publish(); 46 | 47 | // Service, Subscriber, Publisher for all in-/outputs 48 | rclcpp::Service::SharedPtr outputs_service; 49 | rclcpp::Subscription::SharedPtr outputs_subscriber; 50 | rclcpp::Publisher::SharedPtr outputs_publisher; 51 | rclcpp::Publisher::SharedPtr inputs_publisher; 52 | 53 | // Names parsed from the controller.yaml 54 | std::vector digital_inputs; 55 | std::vector digital_outputs; 56 | }; 57 | } // namespace irc_ros_controllers -------------------------------------------------------------------------------- /irc_ros_controllers/include/irc_ros_controllers/schmalz_ecbpmi_controller.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "controller_interface/controller_interface.hpp" 9 | #include "example_interfaces/srv/set_bool.hpp" 10 | #include "irc_ros_msgs/msg/gripper_command.hpp" 11 | #include "irc_ros_msgs/msg/gripper_state.hpp" 12 | #include "irc_ros_msgs/srv/gripper_command.hpp" 13 | #include "std_msgs/msg/bool.hpp" 14 | 15 | namespace irc_ros_controllers 16 | { 17 | 18 | class EcbpmiController : public controller_interface::ControllerInterface 19 | { 20 | public: 21 | controller_interface::InterfaceConfiguration command_interface_configuration() const override; 22 | 23 | controller_interface::InterfaceConfiguration state_interface_configuration() const override; 24 | 25 | controller_interface::return_type update( 26 | const rclcpp::Time & time, const rclcpp::Duration & period) override; 27 | 28 | CallbackReturn on_configure(const rclcpp_lifecycle::State & previous_state) override; 29 | 30 | CallbackReturn on_activate(const rclcpp_lifecycle::State & previous_state) override; 31 | 32 | CallbackReturn on_deactivate(const rclcpp_lifecycle::State & previous_state) override; 33 | 34 | CallbackReturn on_init() override; 35 | 36 | private: 37 | void set_gripper_srv_callback( 38 | const std::shared_ptr req, 39 | std::shared_ptr resp); 40 | 41 | void set_gripper_sub_callback(const irc_ros_msgs::msg::GripperCommand & command); 42 | 43 | void publish_state(); 44 | 45 | // Service, Subscriber, Publisher for all in-/outputs 46 | rclcpp::Service::SharedPtr ecbpmi_service; 47 | rclcpp::Subscription::SharedPtr ecbpmi_subscriber; 48 | rclcpp::Publisher::SharedPtr ecbpmi_publisher; 49 | 50 | // Names parsed from the controller.yaml 51 | std::string output_grip; 52 | std::string output_release; 53 | std::string input_grasped; 54 | 55 | // How long to wait for the successfully grasped signal 56 | const std::chrono::duration timeout = std::chrono::milliseconds(1000); 57 | }; 58 | } // namespace irc_ros_controllers 59 | -------------------------------------------------------------------------------- /irc_ros_controllers/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | irc_ros_controllers 5 | 0.1.0 6 | The irc_ros_controllers package 7 | 8 | Felix Reuter 9 | Apache-2.0 10 | cpr-robots.com 11 | https://github.com/CommonplaceRobotics/iRC_ROS 12 | Felix Reuter 13 | 14 | ament_lint_auto 15 | ament_lint_common 16 | ament_cmake_gtest 17 | 18 | ros2_control 19 | controller_interface 20 | lifecycle_node 21 | example_interfaces 22 | irc_ros_msgs 23 | irc_ros_hardware 24 | 25 | 26 | 27 | 28 | 29 | ament_cmake 30 | 31 | 32 | -------------------------------------------------------------------------------- /irc_ros_controllers/schmalz_ecbpmi_controller.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | Controller for the Schmalz ECBPMI vacuum gripper. Supports gripping and the default feedback signal. 7 | 8 | 9 | -------------------------------------------------------------------------------- /irc_ros_dashboard/README.md: -------------------------------------------------------------------------------- 1 | # iRC ROS Dashboard 2 | 3 | This project contains a barebone dashboard with a text user interface. It is mostly intended for debugging purposes. Once the interfaces work and all desired functionality is achievable it may be superseded by a nicer RQt/Rviz plugin/Web interface. 4 | 5 | The ROS+TUI idea was inspired by [RTUI](https://github.com/eduidl/rtui). 6 | 7 | ## Usage 8 | Requires [textual](https://github.com/Textualize/textual). 9 | 10 | Define which modules to plot in the controllers .yaml configuration. The dashboard will then connect to the corrosponding controller interfaces and show the data in a table. In the future it will be possible to also send commands from there and showing more in-depth information, this is currently work in progress. 11 | 12 | ## Structure 13 | Information is provided by DashboardController, DioController, JointStates and standard ros2_control controllers: 14 | 15 | ![The dataflow to and from the dashboard](doc/dashboard.png) 16 | 17 | ### Dashboard commands 18 | 19 | ![The dataflow of sending commands to the dashboard](doc/dashboard_process.png) -------------------------------------------------------------------------------- /irc_ros_dashboard/doc/dashboard.drawio: -------------------------------------------------------------------------------- 1 | 7VtZk+MmEP41fhyXJHRYjzv2TjJb2Yors9nNPGIL2yRYuBC+9tcHWegCn7IOVybzsCUaaJmvv26aRtsDw+XuFwZXi680QKRnGcGuB0Y9y/IcQ/wbC/aJwHTcQSKZMxxIWS54wz+RFMqJ8zUOUFQayCklHK/KwikNQzTlJRlkjG7Lw2aUlN+6gnOkCd6mkOjSHzjgi0Q6sLxc/ivC80X6ZtP1k54lTAfLlUQLGNBtQQQ+98CQUcqTp+VuiEgMXopLMu/lRG/2wxgK+TUTvhrvhHz/Y7L94jGEv43w8z/Ok9SygWQtF9yzXCL0PQd4Ix7n8aOw6lrgITvEGwp9cm18nwLG6DoMUPxOQ3RvF5ijtxWcxr1bQREhW/AlES0zm71BjKPdyWWZGViCZYguEWd7MUROACm+kmF22t7m5gKulC0KpkplUDJknqnOQRQPEscbMLU0TL9QLBbzaEhlqBSQMq02kQIaUqPX3zvHybYfDSdbxwlGiwmFLBDiIQ05o4Qg1jl0jluGzjzijJbdJnTONQGugObxGKfNeENLGHI8vXrCkC5XNETh1RP4a8gRm8XGkp0Tpg5/sFDsKtbPLN2Z43ia9b/9+SoEBYN3jJlllDF7MnXMXKNNzMxjLnMPSjNMyJASykQ7FD7Q3m52dN/PGFg/cu5l5FAYfIrTUtGaEhhFIoSUwJqu2eYAbNwQULD9XzHKfc9J2+/FztFO2iBp7WUreS0KtNxWQVck05DNEb8UQHUrFFB2joCcyhgikONN+WccA16+YZxkSnlEcUpGtlXbRXTNpmic5VcvJxR5ZlkR8BRFCQ6aogMPsmXfQQ09EtVGDReAEjf6hnjbeX4cWmPEsFgXYv810jhGTaQxFNKoipomzaA50nzMcGLXxAzX75gZfnPMAJ6vhBNj8KHDiVXTHuQOjE5JY9VQ7NEPQhxyFFU+otxG0h3mheglWu8pAcVzzs24UaKm3CddUyH2pbh3J68TYlzi9RX8tzvlv6+c6tSTx/XbqVIc8Fvmv9UA/8W5fgnDILqH75FYOK/iBp43KDpC5hYnXEE0VDIX3MP01DQyzys78g/zTgeRxDP6grOgzL2eelZs0oMU4gOn6g6iKMqKBxc8KFeUDqSzWYSa8bKqh+BbvaBwNvbcNgN7Z4F4YJY5bPp9u3Iq0geCTelfWbFj9I3Cnwmcq1gmbAf3hWGreEB0bj1lNvvpcnJGJipr5SfQD1VpyDfSZEalq6DEb3CCSJmOkOB5GHMVhQcSPcf1LDyF5JPsWOIgiHU8MxThn3By0BczTSIjlDvPPWd0riAm7zXl5F52m1hk5Rk/PBMTDcfzS/inF1dVadpCbNGrKIcLo9quQIqlygDN4Jrwc8apfqd07GKk3dK4VbW4UDlbqZS0N1SnqC/1SDjZ1Z5gqxmBXTG1sJ2Ok/NjFQ0t2x5TEZ1fvsffmLz0+/0bsvQ8PrRxmdZYHFFvPbqPI8DQDHf43CHZS8frCcHR4mHjsnr99gB4HqvS1FTa66roC4zjRmgnRgJHKdZWLWDY6n2A2W6MBPr3Mg1v2aaXtmPGPMXnAu+eGsPj7+b+/7t5HUzVv1gSR4L8QFg7Za/lSmcxaHBin7nVsqoitZTUtGH1j0P+lj8wOnF4brHCb/jq1VXnJcw0PboYeTo9RlhqvKhKT0v5BEzdapump158TAoEpyo7HyD0OKdS3FttqypyzJpsK5r5Z/DJ8Pw/E4DP/wI= -------------------------------------------------------------------------------- /irc_ros_dashboard/doc/dashboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonplaceRobotics/iRC_ROS/41701e6df3398087d217f0f478622e60f694de41/irc_ros_dashboard/doc/dashboard.png -------------------------------------------------------------------------------- /irc_ros_dashboard/doc/dashboard_process.drawio: -------------------------------------------------------------------------------- 1 | 7VrbTuMwEP2aPiLl0ob2sRRY0C5SpK60jyuTTBMLJw62S9r9+rUb5+oApfSCgKc6M844Pmc847E7cGfJ6gdDWXxHQyADxwpXA/dy4Dj22PLkj5KsC8loNCkEEcOh7lQL5vgfaKGlpUscAm91FJQSgbO2MKBpCoFoyRBjNG93W1DSHjVDERiCeYCIKf2DQxEX0vHIquU3gKO4HNm2tCZBZWct4DEKad4QuVcDd8YoFUUrWc2AKPBKXIr3rp/RVh/GIBXbvDDy737PuTcf+dfcjv+K3PH9M23lCZGlnvAl4vE9RSwcOB6Rhi/umWxFqjWjSYLSHgVXn1BMUqxL5BhdpiGowW3ZJY+xgHmGAqXNpa9IWSwSotX6M4AJWD07P7tCTbob0AQEW8su5Qsl0NrTbE8/5zVvVZ+4wVnZD2lXiSrTNZqyoQF9A7jOXsBFwUNKcwJhBMkGZ4tBAPhJQntqyIfDjwa5a0A+B/aEJQQKtsclcAmghxKFRXrPswqHUzqu10bRGZ4axZGBogESpOFUhVf5lNIU2qDUCFoVRMp/3wpQA4BRz/xLGQOChFwQ7eDfA4oewad4s440/o7Vxt8dd3DldMkC0G81I+xrhpyOIYFYBMIwtOGomvbutHlfm7Yu2tvSNjwxbedfirZumt7fausaOjBtY4M2ncK5wj9dJpWyy6ZMFaJNIReMPsCMEspqiheYkI4IERyl8jGQXIKUX6jEg+VudaoVCQ5DNUxv2upzlHdlLoMC2zYzl9vjS+6hMldZNjRYuVWAONfT2c/PS4Td2Yi5PRsx76g8mIXFZw5qRgrZNaidOhfZZs3yzdsWvI280yYj++XCh2c05WYiOnq92IH79JWOPezx96ICX9ANwTVc3uOSloozvjmpmsoOtpetNvCU+rJwv5F1fi6xuVUpYqFgfa7onwskerSlRM6s+JhS/FnT2Nn5pD/6Nf1jeFT/6CuF9+QfjcMgaybfYZQQYF+P9PEWQeG4pPcV0vsn/Xu5d5jvPT48LvM71eKh5LTKog1alNxHQkKdbiSO5VZklZcJjgGs4l7fg0hH/Ph7KGP9uh0Tu+6hDEOH3kOZFf03+W8k37Um+yHfMHRo8ievk89jlKlmsGRkfcFQ8ADi9X1ze5O9IDi70W2C7oH4lGOBqXISVtBTReVfHX0Vncs4TmAhXoriXW8KMYNAG0spU/5xkGOgsWfE8apP0wm7xe3+bt7MYyCf0QA4x2k0ULfF+rLtQ6bW/iDwPoo6p65DuyfV7umESD7Wt9rF+qz/G+Be/Qc= -------------------------------------------------------------------------------- /irc_ros_dashboard/doc/dashboard_process.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonplaceRobotics/iRC_ROS/41701e6df3398087d217f0f478622e60f694de41/irc_ros_dashboard/doc/dashboard_process.png -------------------------------------------------------------------------------- /irc_ros_dashboard/irc_ros_dashboard/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonplaceRobotics/iRC_ROS/41701e6df3398087d217f0f478622e60f694de41/irc_ros_dashboard/irc_ros_dashboard/__init__.py -------------------------------------------------------------------------------- /irc_ros_dashboard/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | irc_ros_dashboard 5 | 0.1.0 6 | A dashboard for monitoring and controlling modules 7 | 8 | Felix Reuter 9 | Apache-2.0 10 | cpr-robots.com 11 | https://github.com/CommonplaceRobotics/iRC_ROS 12 | Felix Reuter 13 | 14 | ament_copyright 15 | ament_flake8 16 | ament_pep257 17 | python3-pytest 18 | 19 | irc_ros_msgs 20 | 21 | 22 | ament_python 23 | 24 | 25 | -------------------------------------------------------------------------------- /irc_ros_dashboard/resource/irc_ros_dashboard: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonplaceRobotics/iRC_ROS/41701e6df3398087d217f0f478622e60f694de41/irc_ros_dashboard/resource/irc_ros_dashboard -------------------------------------------------------------------------------- /irc_ros_dashboard/setup.cfg: -------------------------------------------------------------------------------- 1 | [develop] 2 | script_dir=$base/lib/irc_ros_dashboard 3 | [install] 4 | install_scripts=$base/lib/irc_ros_dashboard 5 | -------------------------------------------------------------------------------- /irc_ros_dashboard/setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | 3 | package_name = "irc_ros_dashboard" 4 | 5 | setup( 6 | name=package_name, 7 | version="0.1.0", 8 | packages=[package_name], 9 | data_files=[ 10 | ("share/ament_index/resource_index/packages", ["resource/" + package_name]), 11 | ("share/" + package_name, ["package.xml"]), 12 | ], 13 | install_requires=["setuptools"], 14 | zip_safe=True, 15 | maintainer="Felix Reuter", 16 | maintainer_email="fer@cpr-robots.com", 17 | description="A dashboard for monitoring and controlling modules", 18 | license="Apache-2.0", 19 | tests_require=["pytest"], 20 | entry_points={ 21 | "console_scripts": ["cli_dashboard = irc_ros_dashboard.cli_dashboard:main"], 22 | }, 23 | ) 24 | -------------------------------------------------------------------------------- /irc_ros_dashboard/test/test_copyright.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Open Source Robotics Foundation, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from ament_copyright.main import main 16 | import pytest 17 | 18 | 19 | # Remove the `skip` decorator once the source file(s) have a copyright header 20 | @pytest.mark.skip( 21 | reason="No copyright header has been placed in the generated source file." 22 | ) 23 | @pytest.mark.copyright 24 | @pytest.mark.linter 25 | def test_copyright(): 26 | rc = main(argv=[".", "test"]) 27 | assert rc == 0, "Found errors" 28 | -------------------------------------------------------------------------------- /irc_ros_dashboard/test/test_flake8.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Open Source Robotics Foundation, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from ament_flake8.main import main_with_errors 16 | import pytest 17 | 18 | 19 | @pytest.mark.flake8 20 | @pytest.mark.linter 21 | def test_flake8(): 22 | rc, errors = main_with_errors(argv=[]) 23 | assert rc == 0, "Found %d code style errors / warnings:\n" % len( 24 | errors 25 | ) + "\n".join(errors) 26 | -------------------------------------------------------------------------------- /irc_ros_dashboard/test/test_pep257.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Open Source Robotics Foundation, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from ament_pep257.main import main 16 | import pytest 17 | 18 | 19 | @pytest.mark.linter 20 | @pytest.mark.pep257 21 | def test_pep257(): 22 | rc = main(argv=[".", "test"]) 23 | assert rc == 0, "Found code style errors / warnings" 24 | -------------------------------------------------------------------------------- /irc_ros_description/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5) 2 | project(irc_ros_description) 3 | 4 | if(NOT CMAKE_CXX_STANDARD) 5 | set(CMAKE_CXX_STANDARD 17) 6 | endif() 7 | 8 | find_package(ament_cmake REQUIRED) 9 | 10 | install( 11 | DIRECTORY meshes launch urdf rviz 12 | DESTINATION share/${PROJECT_NAME} 13 | ) 14 | 15 | ament_package() -------------------------------------------------------------------------------- /irc_ros_description/doc/urdf_structure.drawio: -------------------------------------------------------------------------------- 1 | 5VnbbuIwEP0aHotyaVL62ALbai9SpT7s9gmZ2AGrjp21nQL79TtOnBsJS6koFdsn7PF4bJ9zOh6nA3+crO8kSpc/BCZs4Dl4PfAnA89zA9+HH2PZFBb/+rowLCTF1qk2PNI/xBoda80oJqrlqIVgmqZtYyQ4J5Fu2ZCUYtV2iwVrr5qiBekYHiPEutafFOtlYR0FTm2/J3SxLFd2HTuSoNLZGtQSYbFqmPzpwB9LIXTRStZjwgx4JS7FvC87RquNScL1aybEc+drFj6t7ubT7xdKza7uv60uLBkviGX2wHazelMiIEXGMTFB3IF/u1pSTR5TFJnRFXAOtqVOmB2OKWNjwYSEPiYxyhjs7dYuQqQm6527dytMQExEJETLDbjYCRcljFZHoe2ualKCK2tbNgkp+UBWCIsqdI0VNCxcB0DnBueKne98PHjuuYLnjj4evA52UswFo/x5JtkMpzNQZpiffy6htTCtYSZxPFyjSIp/AO0cBvTA8zEiozgCu9JSPJPGSBiNyDw+DgmjNgc9FLheDwXhezHgv4WBxID/v1Dg9eSQ03Jw+RYOoJaIJE01Ffz8mCjTt/fR0HdvvldAL4XyZlCmATTs/LAvJ4RbV+mHcxHuv0gJxzemFIYeF5y0YWxjDjDIzS/TGfpQulvDk/XNO5N103eyafYeiKRwLCJL45rqIlpge0+NkTqS6ZSBiu0T3KnLtziCI4pMRmR/itBILojel867nDdv+B5KS5skDGn60t5uH892hQdB4SCVpIIdiiojFKe0k5r1/Vacqt4oM/TVVqAChk6gXHXVqd8uxKv3EmIYuk0hOsNreEOenxiDcxAjqGjoXB5HkJ2SYTsHvrMgR+8lyOCQvPh6Be1Vxo6r6TTKcC93FIAH56nrrQdVcFpZlF+WGrqYcnyRKUgUnmOeSRDW1icOFBlkkH9d0ohyyhcmOjdkLakyA0iZcWRkBaO5M+VKIx6ZpohzV9OcPAQd+UEdotuaaxcvVpPNSseaEKMLDt0IRGQS3K2pamiE2I0dSCjGZpneKqqt7COURf7WI7nngVZ90TtJVeR6HZLHBYeqYiSxHGMSA7XmSdBmTBKVkij/k4EOFLggx7GRiALoPGe+ybmOWIYLXRSzrGIQNz4qRSurGqTyJfmmoRBV2iX5nVFpwn4WhfS9H08skW7lPBZJCuhxrbZobghmaP6W61dknRxqYT1TThLItVEurqYrQJ2ro/AT8CM7SSYXRb59QBflBYwxxULmMqwfUZ9HLH2vrGOJBbr1N/jijqn/k+FP/wI= -------------------------------------------------------------------------------- /irc_ros_description/doc/urdf_structure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonplaceRobotics/iRC_ROS/41701e6df3398087d217f0f478622e60f694de41/irc_ros_description/doc/urdf_structure.png -------------------------------------------------------------------------------- /irc_ros_description/doc/visualize.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonplaceRobotics/iRC_ROS/41701e6df3398087d217f0f478622e60f694de41/irc_ros_description/doc/visualize.png -------------------------------------------------------------------------------- /irc_ros_description/launch/visualize.launch.py: -------------------------------------------------------------------------------- 1 | # Based on the visualize_franka script licensed under the Apache license which can be found here: 2 | # https://github.com/frankaemika/franka_ros2/blob/develop/franka_description/launch/visualize_franka.launch.py 3 | 4 | from launch import LaunchDescription 5 | from launch.substitutions import ( 6 | Command, 7 | FindExecutable, 8 | PathJoinSubstitution, 9 | LaunchConfiguration, 10 | ) 11 | from launch_ros.substitutions import FindPackageShare 12 | from launch.actions import DeclareLaunchArgument 13 | from launch_ros.actions import Node 14 | 15 | 16 | def generate_launch_description(): 17 | # Equals the name of the file in irc_ros_description/urdf/ except the file ending 18 | robot_name_arg = DeclareLaunchArgument( 19 | "robot_name", 20 | default_value="igus_rebel_6dof", 21 | description="Which robot to use", 22 | ) 23 | 24 | # Required to concatenate name with .urdf.xacro 25 | xacro_filename_arg = DeclareLaunchArgument( 26 | "xacro_filename", 27 | default_value=[LaunchConfiguration("robot_name"), ".urdf.xacro"], 28 | description="Name of the .urdf.xacro file to use", 29 | ) 30 | 31 | # Fully qualified path to the urdf/xacro file, can also be used directly 32 | # for files outside the irc_ros_description package. 33 | xacro_path_arg = DeclareLaunchArgument( 34 | "xacro_path", 35 | default_value=PathJoinSubstitution( 36 | [ 37 | FindPackageShare("irc_ros_description"), 38 | "urdf", 39 | LaunchConfiguration("xacro_filename"), 40 | ] 41 | ), 42 | description="Path to the .urdf.xacro file to use", 43 | ) 44 | 45 | rebel_version_arg = DeclareLaunchArgument( 46 | "rebel_version", 47 | default_value="01", 48 | choices=["pre", "00", "01"], 49 | description="If visualizing an igus ReBel, chose which version to use", 50 | ) 51 | 52 | gripper_arg = DeclareLaunchArgument( 53 | "gripper", 54 | default_value="none", 55 | choices=["none", "schmalz_ecbpmi", "ext_dio_gripper"], 56 | description="Which gripper to attach to the flange", 57 | ) 58 | 59 | xacro_path = LaunchConfiguration("xacro_path") 60 | # Parameters for rebel.urdf.xacro 61 | rebel_version = LaunchConfiguration("rebel_version") 62 | gripper = LaunchConfiguration("gripper") 63 | 64 | robot_description = Command( 65 | [ 66 | FindExecutable(name="xacro"), 67 | " ", 68 | xacro_path, 69 | " rebel_version:=", 70 | rebel_version, 71 | " gripper:=", 72 | gripper, 73 | ] 74 | ) 75 | 76 | rviz_file = PathJoinSubstitution( 77 | [FindPackageShare("irc_ros_description"), "rviz", "rebel.rviz"] 78 | ) 79 | 80 | # Nodes 81 | robot_state_publisher_node = Node( 82 | package="robot_state_publisher", 83 | executable="robot_state_publisher", 84 | name="robot_state_publisher", 85 | parameters=[{"robot_description": robot_description}], 86 | ) 87 | 88 | joint_state_publisher_gui_node = Node( 89 | package="joint_state_publisher_gui", 90 | executable="joint_state_publisher_gui", 91 | name="joint_state_publisher_gui", 92 | ) 93 | 94 | rviz_node = Node( 95 | package="rviz2", 96 | executable="rviz2", 97 | name="rviz2", 98 | arguments=["-d", rviz_file], 99 | ) 100 | 101 | description = LaunchDescription() 102 | 103 | # Launch args 104 | description.add_action(robot_name_arg) 105 | description.add_action(xacro_filename_arg) 106 | description.add_action(xacro_path_arg) 107 | description.add_action(rebel_version_arg) 108 | description.add_action(gripper_arg) 109 | 110 | # Nodes 111 | description.add_action(robot_state_publisher_node) 112 | description.add_action(joint_state_publisher_gui_node) 113 | 114 | # Visualization 115 | description.add_action(rviz_node) 116 | 117 | return description 118 | -------------------------------------------------------------------------------- /irc_ros_description/meshes/igus_robolink_rl_dp_5/Joint1Coll.dae: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ctmconv 6 | 7 | 8 | 2023-01-10T16:34:00 9 | 2023-01-10T16:34:00 10 | 11 | 12 | 13 | 14 | 15 | -0.085 0.0905 0 0.085 0.0905 0 -0.085 -0.0905 0 0.085 -0.0905 0 0 0 0 0 0 0 -0.2335 0.0339372 0.0469164 -0.0833973 0.0339372 0.0469164 -0.2335 -0.0339372 0.0469164 -0.0833973 -0.0339372 0.0469164 -0.2335 0.0339372 0.117084 -0.0810003 0.0339372 0.117084 -0.2335 -0.0339372 0.117084 -0.0810003 -0.0339372 0.117084 -0.08 0.0905 0.146366 0.08 0.0905 0.146366 0.08 -0.0905 0.146366 -0.08 -0.0905 0.146366 0 0 0 0 0 0 0 0 0 -0.08 0.0905 0.191188 0.08 0.0905 0.191188 0.08 -0.0905 0.191188 -0.08 -0.0905 0.191188 0 0 0 0 0.0905 0.237376 0 0 0 0 0 0 0 -0.0905 0.237376 0 0 0 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -1.56988 1.53665 -1.51717 1.56988 1.53665 -1.51717 -1.56988 -1.53665 -1.51717 1.56988 -1.53665 -1.51717 0 0 0 0 0 0 -1.5708 1.5708 -1.5708 -4.70964 1.60494 -1.40991 -1.5708 -1.5708 -1.5708 -4.70964 -1.60494 -1.40991 -1.5708 1.5708 1.5708 -4.70964 1.53665 1.73168 -1.5708 -1.5708 1.5708 -4.70964 -1.53665 1.73168 -3.14068 3.17574 0.053629 3.14068 3.17574 0.053629 3.14068 -3.17574 0.053629 -3.14068 -3.17574 0.053629 0 0 0 0 0 0 0 0 0 -2.35619 2.09439 1.36035 2.35619 2.09439 1.36035 2.35619 -2.09439 1.36035 -2.35619 -2.09439 1.36035 0 0 0 0 2.09439 2.7207 0 0 0 0 0 0 0 -2.09439 2.7207 0 0 0 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 |

7 7 14 14 0 0 9 9 7 7 0 0 2 2 9 9 0 0 1 1 2 2 0 0 15 15 1 1 0 0 14 14 15 15 0 0 15 15 3 3 1 1 3 3 2 2 1 1 3 3 17 17 2 2 16 16 17 17 3 3 13 13 9 9 2 2 17 17 13 13 2 2 15 15 16 16 3 3 11 11 7 7 6 6 10 10 11 11 6 6 7 7 8 8 6 6 12 12 10 10 6 6 8 8 12 12 6 6 11 11 14 14 7 7 9 9 8 8 7 7 9 9 12 12 8 8 13 13 12 12 9 9 13 13 11 11 10 10 12 12 13 13 10 10 13 13 17 17 11 11 17 17 14 14 11 11 17 17 24 24 14 14 24 24 21 21 14 14 21 21 15 15 14 14 22 22 16 16 15 15 21 21 26 26 15 15 26 26 22 22 15 15 22 22 23 23 16 16 29 29 24 24 17 17 16 16 29 29 17 17 23 23 29 29 16 16 24 24 29 29 21 21 29 29 26 26 21 21 26 26 23 23 22 22 26 26 29 29 23 23

41 |
42 |
43 |
44 |
45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 |
56 | -------------------------------------------------------------------------------- /irc_ros_description/meshes/igus_robolink_rl_dp_5/Joint2Coll.dae: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ctmconv 6 | 7 | 8 | 2023-01-10T16:34:00 9 | 2023-01-10T16:34:00 10 | 11 | 12 | 13 | 14 | 15 | -0 -0.0735 -0.0887221 0 0 0 0 0.0735 -0.0887221 0 0 0 0 0 0 0.0768356 -0.0735 -0.044361 -0.0768356 -0.0735 -0.044361 0.0768356 0.0735 -0.044361 -0.0768356 0.0735 -0.044361 0 0 0 0.0623027 -0.0735 0.38597 -0.0623027 -0.0735 0.38597 0.0623027 0.0735 0.38597 -0.0623027 0.0735 0.38597 0 0 0 0 -0.0735 0.421941 0 0 0 0 0 0 0 0.0735 0.421941 0 0 0 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -0 -2.09439 -2.7207 0 0 0 0 2.09439 -2.7207 0 0 0 0 0 0 2.3553 -2.06064 -1.30733 -2.3553 -2.06064 -1.30733 2.3553 2.06064 -1.30733 -2.3553 2.06064 -1.30733 0 0 0 2.3553 -2.12815 1.41337 -2.3553 -2.12815 1.41337 2.3553 2.12815 1.41337 -2.3553 2.12815 1.41337 0 0 0 0 -2.09439 2.7207 0 0 0 0 0 0 0 2.09439 2.7207 0 0 0 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 |

6 6 8 8 0 0 8 8 2 2 0 0 5 5 10 10 0 0 11 11 6 6 0 0 10 10 11 11 0 0 2 2 5 5 0 0 8 8 13 13 2 2 13 13 12 12 2 2 12 12 7 7 2 2 7 7 5 5 2 2 7 7 10 10 5 5 11 11 13 13 6 6 13 13 8 8 6 6 12 12 10 10 7 7 15 15 11 11 10 10 12 12 15 15 10 10 15 15 18 18 11 11 18 18 13 13 11 11 13 13 18 18 12 12 18 18 15 15 12 12

41 |
42 |
43 |
44 |
45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 |
56 | -------------------------------------------------------------------------------- /irc_ros_description/meshes/igus_robolink_rl_dp_5/Joint3Coll.dae: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ctmconv 6 | 7 | 8 | 2023-01-10T16:34:00 9 | 2023-01-10T16:34:00 10 | 11 | 12 | 13 | 14 | 15 | -0.0616363 -0.0575 -0.0355857 -0.0616363 0.0575 -0.0355857 0 0 0 -0.0520947 -0.0575 0.300077 -0.0520947 0.0575 0.300077 0 0 0 6e-09 -0.0575 -0.0711715 6e-09 -0.0575 0.330154 6e-09 0.0575 -0.0711715 6e-09 0.0575 0.330154 0 0 0 0.0520947 -0.0575 0.300077 0.0520947 0.0575 0.300077 0.0616363 -0.0575 -0.0355857 0.0616363 0.0575 -0.0355857 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -2.35556 -2.06598 -1.31572 -2.35556 2.06598 -1.31572 0 0 0 -2.35556 -2.12281 1.40498 -2.35556 2.12281 1.40498 0 0 0 0 -2.09439 -2.7207 0 -2.09439 2.7207 0 2.09439 -2.7207 0 2.09439 2.7207 0 0 0 2.35556 -2.12281 1.40498 2.35556 2.12281 1.40498 2.35556 -2.06598 -1.31572 2.35556 2.06598 -1.31572 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 |

6 6 3 3 0 0 1 1 6 6 0 0 3 3 4 4 0 0 4 4 1 1 0 0 4 4 8 8 1 1 8 8 6 6 1 1 6 6 11 11 3 3 11 11 7 7 3 3 7 7 9 9 3 3 9 9 4 4 3 3 9 9 12 12 4 4 12 12 8 8 4 4 13 13 11 11 6 6 8 8 13 13 6 6 11 11 12 12 7 7 12 12 9 9 7 7 12 12 14 14 8 8 14 14 13 13 8 8 13 13 14 14 11 11 14 14 12 12 11 11

41 |
42 |
43 |
44 |
45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 |
56 | -------------------------------------------------------------------------------- /irc_ros_description/meshes/igus_robolink_rl_dp_5/Joint4Coll.dae: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ctmconv 6 | 7 | 8 | 2023-01-10T16:34:00 9 | 2023-01-10T16:34:00 10 | 11 | 12 | 13 | 14 | 15 | 0.0267956 0.0395 0.179 -0.0267956 0.0395 0.179 0.0267956 -0.0395 0.179 -0.0267956 -0.0395 0.179 0 0 0 0.0532335 0.0395 -0.0307344 -0.0532336 0.0395 -0.0307344 0.0532335 -0.0395 -0.0307344 -0.0532336 -0.0395 -0.0307344 0 0 0 0 0 0 1.1e-08 0.0395 -0.0614688 1.1e-08 -0.0395 -0.0614688 0 0 0 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 1.55846 1.69619 1.76725 -1.55846 1.69619 1.76725 1.55846 -1.69619 1.76725 -1.55846 -1.69619 1.76725 0 0 0 2.34386 1.969 -1.1639 -2.34386 1.969 -1.1639 2.34386 -1.969 -1.1639 -2.34386 -1.969 -1.1639 0 0 0 0 0 0 0 2.0944 -2.7207 0 -2.0944 -2.7207 0 0 0 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 |

11 11 1 1 0 0 5 5 11 11 0 0 2 2 5 5 0 0 1 1 3 3 0 0 3 3 2 2 0 0 11 11 6 6 1 1 6 6 8 8 1 1 8 8 3 3 1 1 12 12 7 7 2 2 3 3 12 12 2 2 8 8 12 12 3 3 7 7 5 5 2 2 7 7 11 11 5 5 11 11 12 12 6 6 12 12 8 8 6 6 12 12 11 11 7 7

41 |
42 |
43 |
44 |
45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 |
56 | -------------------------------------------------------------------------------- /irc_ros_description/meshes/igus_robolink_rl_dp_5/Joint5Coll.dae: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ctmconv 6 | 7 | 8 | 2023-01-10T16:34:00 9 | 2023-01-10T16:34:00 10 | 11 | 12 | 13 | 14 | 15 | 0.0174992 0.0303096 0 -0.0174992 0.0303096 0 0.0174992 0.0303096 0.0111 -0.0174992 0.0303096 0.0111 0 0 0 0 0 0 0.0349985 0 0 0.0349985 0 0.0111 0 0 0 0 0 0 0 0 0 -0.0349985 0 0 -0.0349985 0 0.0111 0 0 0 0 0 0 0 0 0 0 0 0 0.0174992 -0.0303096 0 -0.0174992 -0.0303096 0 0.0174992 -0.0303096 0.0111 -0.0174992 -0.0303096 0.0111 0 0 0 0 0 0 0 0 0 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 1.36035 2.35619 -2.09439 -1.36035 2.35619 -2.09439 1.36035 2.35619 2.09439 -1.36035 2.35619 2.09439 0 0 0 0 0 0 2.7207 0 -2.09439 2.7207 0 2.09439 0 0 0 0 0 0 0 0 0 -2.7207 -0 -2.09439 -2.7207 0 2.09439 0 0 0 0 0 0 0 0 0 0 0 0 1.36035 -2.35619 -2.09439 -1.36035 -2.35619 -2.09439 1.36035 -2.35619 2.09439 -1.36035 -2.35619 2.09439 0 0 0 0 0 0 0 0 0 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 |

1 1 2 2 0 0 2 2 7 7 0 0 7 7 6 6 0 0 6 6 1 1 0 0 11 11 3 3 1 1 3 3 2 2 1 1 6 6 17 17 1 1 17 17 11 11 1 1 3 3 7 7 2 2 11 11 12 12 3 3 12 12 7 7 3 3 7 7 19 19 6 6 19 19 17 17 6 6 12 12 19 19 7 7 18 18 12 12 11 11 20 20 19 19 12 12 18 18 20 20 12 12 17 17 18 18 11 11 19 19 20 20 17 17 20 20 18 18 17 17

41 |
42 |
43 |
44 |
45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 |
56 | -------------------------------------------------------------------------------- /irc_ros_description/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | irc_ros_description 4 | 0.1.0 5 | The irc_ros_description package 6 | 7 | Felix Reuter 8 | Apache-2.0 9 | cpr-robots.com 10 | https://github.com/CommonplaceRobotics/iRC_ROS 11 | Felix Reuter 12 | 13 | rviz2 14 | urdf 15 | xacro 16 | 17 | ament_lint_auto 18 | ament_lint_common 19 | ament_cmake_gtest 20 | 21 | joint_state_publisher_gui 22 | 23 | 24 | ament_cmake 25 | 26 | 27 | -------------------------------------------------------------------------------- /irc_ros_description/urdf/cpr_platform_medium.urdf.xacro: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /irc_ros_description/urdf/grippers/ext_dio_gripper.description.xacro: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /irc_ros_description/urdf/grippers/ext_dio_gripper.ros2_control.xacro: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | irc_hardware/IrcRosCan 11 | can0 12 | 13 | 14 | 15 | 0x90 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /irc_ros_description/urdf/grippers/grippers.macro.xacro: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /irc_ros_description/urdf/grippers/schmalz_ecbpmi.description.xacro: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /irc_ros_description/urdf/igus_rebel_4dof.urdf.xacro: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 14 | 15 | 16 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /irc_ros_description/urdf/igus_rebel_6dof.urdf.xacro: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 14 | 15 | 16 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /irc_ros_description/urdf/igus_robolink_rl_dp_5.urdf.xacro: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 11 | 12 | 13 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /irc_ros_description/urdf/modules/din_rail.ros2_control.xacro: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | ${position_min} 8 | ${position_max} 9 | 10 | 11 | 12 | -2.16 13 | 2.16 14 | 15 | 16 | 0.0 17 | 18 | ${can_id} 19 | ${gear_scale} 20 | open_loop 21 | ${referencing_required} 22 | ${referencing_priority} 23 | 24 | 25 | -------------------------------------------------------------------------------- /irc_ros_description/urdf/modules/rebel.ros2_control.xacro: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | ${position_min} 8 | ${position_max} 9 | 10 | 11 | 12 | 13 | ${-pi/4} 14 | ${pi/4} 15 | 16 | 17 | 0.0 18 | 19 | 20 | 21 | 0.0 22 | 23 | 24 | ${can_id} 25 | ${gear_scale} 26 | closed_loop 27 | 28 | ${cri_joint_offset} 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /irc_ros_description/urdf/platforms/cpr_platform_medium.description.xacro: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /irc_ros_description/urdf/platforms/cpr_platform_medium.macro.xacro: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /irc_ros_description/urdf/platforms/cpr_platform_medium.ros2_control.xacro: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | mock_components/GenericSystem 8 | 9 | 10 | gazebo_ros2_control/GazeboSystem 11 | 12 | 13 | irc_hardware/IrcRosCan 14 | can0 15 | 16 | 17 | irc_hardware/IrcRosCri 18 | 192.168.3.11 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /irc_ros_description/urdf/rebel_on_platform.urdf.xacro: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /irc_ros_description/urdf/robots/igus_rebel_4dof.macro.xacro: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /irc_ros_description/urdf/robots/igus_rebel_4dof_00.ros2_control.xacro: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | mock_components/GenericSystem 8 | 9 | 10 | gazebo_ros2_control/GazeboSystem 11 | 12 | 13 | irc_hardware/IrcRosCan 14 | can0 15 | 16 | 17 | irc_hardware/IrcRosCri 18 | 192.168.3.11 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 0x70 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 0x80 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /irc_ros_description/urdf/robots/igus_rebel_4dof_01.description.xacro: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | -------------------------------------------------------------------------------- /irc_ros_description/urdf/robots/igus_rebel_4dof_01.ros2_control.xacro: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | mock_components/GenericSystem 8 | 9 | 10 | gazebo_ros2_control/GazeboSystem 11 | 12 | 13 | irc_hardware/IrcRosCan 14 | can0 15 | 16 | 17 | irc_hardware/IrcRosCri 18 | 192.168.3.11 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 0x70 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 0x80 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /irc_ros_description/urdf/robots/igus_rebel_6dof.macro.xacro: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /irc_ros_description/urdf/robots/igus_rebel_6dof_00.ros2_control.xacro: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | mock_components/GenericSystem 8 | 9 | 10 | gazebo_ros2_control/GazeboSystem 11 | 12 | 13 | irc_hardware/IrcRosCan 14 | can0 15 | 16 | 17 | irc_hardware/IrcRosCri 18 | 192.168.3.11 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 0x70 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 0x80 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /irc_ros_description/urdf/robots/igus_rebel_6dof_01.description.xacro: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /irc_ros_description/urdf/robots/igus_rebel_6dof_01.ros2_control.xacro: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | mock_components/GenericSystem 8 | 9 | 10 | gazebo_ros2_control/GazeboSystem 11 | 12 | 13 | irc_hardware/IrcRosCan 14 | can0 15 | 16 | 17 | irc_hardware/IrcRosCri 18 | 192.168.3.11 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 0x70 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 0x80 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /irc_ros_description/urdf/robots/igus_rebel_6dof_pre.ros2_control.xacro: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | mock_components/GenericSystem 8 | 9 | 10 | gazebo_ros2_control/GazeboSystem 11 | 12 | 13 | irc_hardware/IrcRosCan 14 | can0 15 | 16 | 17 | irc_hardware/IrcRosCri 18 | 192.168.3.11 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /irc_ros_description/urdf/robots/igus_robolink_rl_dp_5.macro.xacro: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /irc_ros_description/urdf/robots/igus_robolink_rl_dp_5.ros2_control.xacro: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | mock_components/GenericSystem 11 | 12 | 13 | gazebo_ros2_control/GazeboSystem 14 | 15 | 16 | irc_hardware/IrcRosCan 17 | can0 18 | 19 | 20 | irc_hardware/IrcRosCri 21 | 192.168.3.11 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /irc_ros_examples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.8) 2 | project(irc_ros_examples) 3 | 4 | if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") 5 | add_compile_options(-Wall -Wextra -Wpedantic) 6 | endif() 7 | 8 | # find dependencies 9 | find_package(ament_cmake REQUIRED) 10 | find_package(ament_cmake_python REQUIRED) 11 | find_package(irc_ros_msgs REQUIRED) 12 | find_package(moveit_core REQUIRED) 13 | find_package(moveit_msgs REQUIRED) 14 | find_package(moveit_ros_move_group REQUIRED) 15 | find_package(moveit_ros_planning REQUIRED) 16 | find_package(moveit_ros_planning_interface REQUIRED) 17 | find_package(rclcpp REQUIRED) 18 | find_package(rclpy REQUIRED) 19 | find_package(tf2_ros REQUIRED) 20 | find_package(tf2_geometry_msgs REQUIRED) 21 | 22 | include_directories(include) 23 | 24 | add_executable(pick_and_place 25 | src/pick_and_place.cpp 26 | ) 27 | 28 | add_executable(pick_and_place_vacuum 29 | src/pick_and_place_vacuum.cpp 30 | ) 31 | 32 | target_include_directories(pick_and_place PUBLIC 33 | $ 34 | $) 35 | 36 | ament_target_dependencies( 37 | pick_and_place 38 | "moveit_ros_planning_interface" 39 | "rclcpp" 40 | irc_ros_msgs 41 | ) 42 | 43 | ament_target_dependencies( 44 | pick_and_place_vacuum 45 | "moveit_ros_planning_interface" 46 | "rclcpp" 47 | irc_ros_msgs 48 | tf2_ros 49 | tf2_geometry_msgs 50 | ) 51 | 52 | # Install C++ executables 53 | install( 54 | TARGETS pick_and_place pick_and_place_vacuum 55 | DESTINATION lib/${PROJECT_NAME} 56 | ) 57 | 58 | # Install Python modules 59 | ament_python_install_package(${PROJECT_NAME}) 60 | 61 | # Install Python executables 62 | install(PROGRAMS 63 | scripts/nav2_simple_commander_example.py 64 | scripts/baristabot.py 65 | DESTINATION lib/${PROJECT_NAME} 66 | ) 67 | 68 | # Install launch files 69 | install(DIRECTORY launch 70 | DESTINATION share/${PROJECT_NAME} 71 | ) 72 | 73 | 74 | if(BUILD_TESTING) 75 | find_package(ament_lint_auto REQUIRED) 76 | # the following line skips the linter which checks for copyrights 77 | # comment the line when a copyright and license is added to all source files 78 | set(ament_cmake_copyright_FOUND TRUE) 79 | # the following line skips cpplint (only works in a git repo) 80 | # comment the line when this package is in a git repo and when 81 | # a copyright and license is added to all source files 82 | set(ament_cmake_cpplint_FOUND TRUE) 83 | ament_lint_auto_find_test_dependencies() 84 | endif() 85 | 86 | ament_package() 87 | -------------------------------------------------------------------------------- /irc_ros_examples/README.md: -------------------------------------------------------------------------------- 1 | # iRC ROS Examples 2 | 3 | This package showcases how to implement Igus Robot Control ROS2 for different usecases. 4 | 5 | 6 | ## Pick&Place (MoveIt) 7 | ![](doc/pick_and_place.gif) 8 | 9 | This simple example showcases point-to-point, linear and axis movements, as well as how to interact with the gripper via its controller's service. 10 | 11 | The process runs in an infinite loop. 12 | 13 | For further MoveIt commands see [here](https://moveit.picknik.ai/humble/doc/examples/examples.html#using-moveit-directly-through-the-c-api). 14 | 15 | ### Usage 16 | There are two ways to start this example: 17 | 18 | ``` bash 19 | # Start MoveIt and the example node together 20 | $ LC_NUMERIC=en_US.UTF-8 ros2 launch irc_ros_examples pick_and_place.launch.py 21 | 22 | # Alternatively first start moveit with the right gripper parameter 23 | $ LC_NUMERIC=en_US.UTF-8 ros2 launch irc_ros_moveit_config rebel.launch.py gripper:="ext_dio_gripper" 24 | 25 | # Then, once the startup is complete, run: 26 | $ ros2 run irc_ros_examples pick_and_place 27 | ``` 28 | 29 | ## Pick&Place-Vacuum (MoveIt) 30 | ![](doc/pick_and_place_vacuum.gif) 31 | 32 | Uses the Schmalz ECBPMI vacuum gripper for a vertical pick and place application. 33 | The example showcases how to use the ECBPMI Controller with service calls. 34 | The process picks up small objects out of a tray with uniform distances between the different slots and places them in an identical tray at another position. 35 | Each tray is defined by their own coordinate frame, which requires a tf2 transform as MoveIt only works with the frame_id set via poseReferenceFrame in the pick_and_place_base.hpp. 36 | 37 | The process runs in an infinite loop. 38 | 39 | ### Usage 40 | There are two ways to start this example: 41 | 42 | ``` bash 43 | # Start MoveIt and the example node together 44 | $ LC_NUMERIC=en_US.UTF-8 ros2 launch irc_ros_examples pick_and_place_vacuum.launch.py 45 | 46 | # Alternatively first start moveit with the right gripper parameter 47 | $ LC_NUMERIC=en_US.UTF-8 ros2 launch irc_ros_moveit_config rebel.launch.py gripper:="schmalz_ecbpmi" 48 | 49 | # Publish the tfs to tray_1 and tray_2 50 | $ ros2 run tf2_ros static_transform_publisher [x] [y] [z] [r] [p] [y] base_link tray_1 51 | $ ros2 run tf2_ros static_transform_publisher [x] [y] [z] [r] [p] [y] base_link tray_2 52 | 53 | # Then, once the startup is complete, run: 54 | $ ros2 run irc_ros_examples pick_and_place_vacuum 55 | ``` 56 | 57 | ## Basic Navigation (Nav2 Simple Commander) 58 | **WORK IN PROGRESS EXAMPLE** 59 | This example should showcase simple movements with the mobile platform over the [Nav2 Python API](https://navigation.ros.org/commander_api/index.html). It is also useful for testing Nav2 parameters. 60 | 61 | The platform should drive over the four corners of a square and end where it started. While it achieves that goal already, it is rather slow due to unnecessary turning and detours. 62 | 63 | ## BaristaBot (MoveIt + Nav2 + more) 64 | **WORK IN PROGRESS EXAMPLE** 65 | This example should showcase controlling a ReBeL via MoveItPy and the platform with Nav2 Simple Commander. The process is supposed to be a coffee brewing and delivery process, right now the Nav2 part does not work reliably and the pick and place locations are hardcoded, making it realiant on precise positioning of the platform. 66 | 67 | **The example requires MoveItPy. See [here](https://github.com/ros-planning/moveit2/issues/2014#issuecomment-1532053275) how to install it** 68 | 69 | ### Links 70 | - https://navigation.ros.org/plugin_tutorials/docs/writing_new_bt_plugin.html 71 | - https://navigation.ros.org/tutorials/docs/using_groot.html 72 | -------------------------------------------------------------------------------- /irc_ros_examples/doc/pick_and_place.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonplaceRobotics/iRC_ROS/41701e6df3398087d217f0f478622e60f694de41/irc_ros_examples/doc/pick_and_place.gif -------------------------------------------------------------------------------- /irc_ros_examples/doc/pick_and_place_vacuum.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonplaceRobotics/iRC_ROS/41701e6df3398087d217f0f478622e60f694de41/irc_ros_examples/doc/pick_and_place_vacuum.gif -------------------------------------------------------------------------------- /irc_ros_examples/irc_ros_examples/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonplaceRobotics/iRC_ROS/41701e6df3398087d217f0f478622e60f694de41/irc_ros_examples/irc_ros_examples/__init__.py -------------------------------------------------------------------------------- /irc_ros_examples/launch/nav2_simple_commander_example.launch.py: -------------------------------------------------------------------------------- 1 | from launch_ros.actions import Node 2 | from launch import LaunchDescription 3 | from launch.actions import IncludeLaunchDescription 4 | from launch.launch_description_sources import PythonLaunchDescriptionSource 5 | from launch.substitutions import PathJoinSubstitution 6 | from launch_ros.substitutions import FindPackageShare 7 | 8 | 9 | def generate_launch_description(): 10 | irc_ros_nav2_dir = PathJoinSubstitution( 11 | [ 12 | FindPackageShare("irc_ros_navigation2"), 13 | "launch", 14 | ] 15 | ) 16 | 17 | nav2_node = IncludeLaunchDescription( 18 | PythonLaunchDescriptionSource([irc_ros_nav2_dir, "/cpr_platform.launch.py"]), 19 | ) 20 | 21 | nav2_sc_node = Node( 22 | package="irc_ros_examples", 23 | executable="nav2_simple_commander_example.py", 24 | name="nav2_sc", 25 | ) 26 | 27 | ld = LaunchDescription() 28 | ld.add_entity(nav2_node) 29 | ld.add_entity(nav2_sc_node) 30 | 31 | return ld 32 | -------------------------------------------------------------------------------- /irc_ros_examples/launch/pick_and_place.launch.py: -------------------------------------------------------------------------------- 1 | from pathlib import Path 2 | from launch_ros.actions import Node 3 | from launch import LaunchDescription 4 | from launch.actions import IncludeLaunchDescription, OpaqueFunction 5 | from launch.launch_description_sources import PythonLaunchDescriptionSource 6 | from launch.substitutions import PathJoinSubstitution 7 | from launch_ros.substitutions import FindPackageShare 8 | from launch_param_builder import load_yaml 9 | from nav2_common.launch import ReplaceString 10 | 11 | 12 | def load_pnp(context, *args, **kwargs): 13 | joint_limits_file = PathJoinSubstitution( 14 | [ 15 | FindPackageShare("irc_ros_moveit_config"), 16 | "config", 17 | "joint_limits.yaml", 18 | ] 19 | ) 20 | joint_limits = ReplaceString( 21 | source_file=joint_limits_file, 22 | replacements={ 23 | "": "", 24 | "": "", 25 | }, 26 | ) 27 | 28 | pick_and_place_node = Node( 29 | package="irc_ros_examples", 30 | executable="pick_and_place", 31 | name="pick_and_place", 32 | parameters=[ 33 | load_yaml(Path(joint_limits.perform(context))), 34 | ], 35 | ) 36 | 37 | return [pick_and_place_node] 38 | 39 | 40 | def generate_launch_description(): 41 | irc_ros_moveit_dir = PathJoinSubstitution( 42 | [ 43 | FindPackageShare("irc_ros_moveit_config"), 44 | "launch", 45 | ] 46 | ) 47 | 48 | moveit_node = IncludeLaunchDescription( 49 | PythonLaunchDescriptionSource([irc_ros_moveit_dir, "/rebel.launch.py"]), 50 | launch_arguments={ 51 | "gripper": "ext_dio_gripper", 52 | }.items(), 53 | ) 54 | 55 | ld = LaunchDescription() 56 | ld.add_entity(moveit_node) 57 | # ld.add_entity(pick_and_place_node) 58 | ld.add_action(OpaqueFunction(function=load_pnp)) 59 | return ld 60 | -------------------------------------------------------------------------------- /irc_ros_examples/launch/pick_and_place_vacuum.launch.py: -------------------------------------------------------------------------------- 1 | from launch_ros.actions import Node 2 | from launch import LaunchDescription 3 | from launch.actions import IncludeLaunchDescription 4 | from launch.launch_description_sources import PythonLaunchDescriptionSource 5 | from launch.substitutions import PathJoinSubstitution 6 | from launch_ros.substitutions import FindPackageShare 7 | 8 | 9 | def generate_launch_description(): 10 | irc_ros_moveit_dir = PathJoinSubstitution( 11 | [ 12 | FindPackageShare("irc_ros_moveit_config"), 13 | "launch", 14 | ] 15 | ) 16 | 17 | moveit_node = IncludeLaunchDescription( 18 | PythonLaunchDescriptionSource([irc_ros_moveit_dir, "/rebel.launch.py"]), 19 | launch_arguments={ 20 | "gripper": "schmalz_ecbpmi", 21 | }.items(), 22 | ) 23 | 24 | # Publish tray frames 25 | tray1_tf_node = Node( 26 | package="tf2_ros", 27 | executable="static_transform_publisher", 28 | name="tray_1_static_broadcaster", 29 | arguments=["0.209", "-0.090", "0.318", "0", "0", "0", "base_link", "tray_1"], 30 | ) 31 | 32 | tray2_tf_node = Node( 33 | package="tf2_ros", 34 | executable="static_transform_publisher", 35 | name="tray_2_static_broadcaster", 36 | arguments=["0.209", "-0.015", "0.318", "0", "0", "0", "base_link", "tray_2"], 37 | ) 38 | 39 | pick_and_place_node = Node( 40 | package="irc_ros_examples", 41 | executable="pick_and_place_vacuum", 42 | name="pick_and_place_vacuum", 43 | ) 44 | 45 | ld = LaunchDescription() 46 | ld.add_entity(moveit_node) 47 | ld.add_entity(tray1_tf_node) 48 | ld.add_entity(tray2_tf_node) 49 | ld.add_entity(pick_and_place_node) 50 | 51 | return ld 52 | -------------------------------------------------------------------------------- /irc_ros_examples/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | irc_ros_examples 5 | 0.1.0 6 | This package contains examples on how to use IRC ROS 7 | 8 | Felix Reuter 9 | Apache-2.0 10 | cpr-robots.com 11 | https://github.com/CommonplaceRobotics/iRC_ROS 12 | Felix Reuter 13 | 14 | ament_cmake 15 | ament_cmake_python 16 | 17 | ament_lint_auto 18 | ament_lint_common 19 | 20 | irc_ros_msgs 21 | irc_ros_moveit_config 22 | moveit_ros_planning_interface 23 | moveit_core 24 | moveit_msgs 25 | moveit_ros_move_group_interface 26 | tf2_ros 27 | tf2_geometry_msgs 28 | 29 | 30 | moveit_common 31 | moveit_ros_planning 32 | 33 | 34 | ament_cmake 35 | 36 | 37 | -------------------------------------------------------------------------------- /irc_ros_examples/resource/irc_ros_examples: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonplaceRobotics/iRC_ROS/41701e6df3398087d217f0f478622e60f694de41/irc_ros_examples/resource/irc_ros_examples -------------------------------------------------------------------------------- /irc_ros_examples/scripts/nav2_simple_commander_example.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from nav2_simple_commander.robot_navigator import BasicNavigator, TaskResult 4 | import rclpy 5 | from geometry_msgs.msg import PoseStamped 6 | 7 | rclpy.init() 8 | 9 | nav = BasicNavigator() 10 | 11 | frame_id = "map" 12 | 13 | # Four poses forming a square 14 | 15 | init_pose = PoseStamped() 16 | init_pose.header.frame_id = frame_id 17 | init_pose.pose.position.x = 0.0 18 | init_pose.pose.position.y = 2.0 19 | init_pose.pose.position.z = 0.0 20 | 21 | goal_pose1 = PoseStamped() 22 | goal_pose1.header.frame_id = frame_id 23 | goal_pose1.pose.position.x = 0.0 24 | goal_pose1.pose.position.y = 3.0 25 | goal_pose1.pose.position.z = 0.0 26 | 27 | goal_pose2 = PoseStamped() 28 | goal_pose2.header.frame_id = frame_id 29 | goal_pose2.pose.position.x = 1.0 30 | goal_pose2.pose.position.y = 3.0 31 | goal_pose2.pose.position.z = 0.0 32 | 33 | goal_pose3 = PoseStamped() 34 | goal_pose3.header.frame_id = frame_id 35 | goal_pose3.pose.position.x = 1.0 36 | goal_pose3.pose.position.y = 2.0 37 | goal_pose3.pose.position.z = 0.0 38 | 39 | poses = [init_pose, goal_pose1, goal_pose2, goal_pose3, init_pose] 40 | 41 | nav.setInitialPose(init_pose) 42 | 43 | # if autostarted, else use `lifecycleStartup()` 44 | # nav.waitUntilNav2Active(localizer="slam_toolbox") 45 | 46 | nav.followWaypoints(poses) 47 | 48 | 49 | while not nav.isTaskComplete(): 50 | feedback = nav.getFeedback() 51 | 52 | # if feedback.navigation_time > 600: 53 | # nav.cancelTask() 54 | 55 | result = nav.getResult() 56 | if result == TaskResult.SUCCEEDED: 57 | print("Goal succeeded!") 58 | elif result == TaskResult.CANCELED: 59 | print("Goal was canceled!") 60 | elif result == TaskResult.FAILED: 61 | print("Goal failed!") 62 | -------------------------------------------------------------------------------- /irc_ros_hardware/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5) 2 | project(irc_ros_hardware) 3 | 4 | set(CMAKE_CXX_STANDARD 17) 5 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 6 | 7 | find_package(ament_cmake REQUIRED) 8 | find_package(control_msgs REQUIRED) 9 | find_package(controller_manager REQUIRED) 10 | find_package(controller_manager_msgs REQUIRED) 11 | find_package(hardware_interface REQUIRED) 12 | find_package(irc_ros_msgs REQUIRED) 13 | find_package(rclcpp REQUIRED) 14 | find_package(sensor_msgs REQUIRED) 15 | find_package(std_msgs REQUIRED) 16 | 17 | set(INCLUDE_DEPENDS 18 | ament_cmake 19 | control_msgs 20 | controller_manager 21 | controller_manager_msgs 22 | hardware_interface 23 | irc_ros_msgs 24 | rclcpp 25 | sensor_msgs 26 | std_msgs 27 | ) 28 | 29 | include_directories(include) 30 | 31 | add_library( ${PROJECT_NAME} SHARED 32 | src/irc_ros_cri.cpp 33 | src/CRI/cri_socket.cpp 34 | src/CRI/cri_messages.cpp 35 | src/irc_ros_can.cpp 36 | src/CAN/module.cpp 37 | src/CAN/joint.cpp 38 | src/CAN/digital_io.cpp 39 | src/CAN/can_message.cpp 40 | src/CAN/can_interface.cpp 41 | src/CAN/can_socket.cpp 42 | ) 43 | 44 | target_include_directories( ${PROJECT_NAME} PRIVATE 45 | include 46 | ) 47 | 48 | ament_target_dependencies( ${PROJECT_NAME} 49 | ${INCLUDE_DEPENDS} 50 | ) 51 | 52 | # Export hardware pligins 53 | pluginlib_export_plugin_description_file(hardware_interface irc_ros_hardware.xml) 54 | 55 | install( 56 | TARGETS ${PROJECT_NAME} 57 | ARCHIVE DESTINATION lib 58 | LIBRARY DESTINATION lib 59 | RUNTIME DESTINATION bin 60 | #DESTINATION lib/${PROJECT_NAME} 61 | ) 62 | 63 | install( 64 | DIRECTORY include/ 65 | DESTINATION include 66 | ) 67 | 68 | 69 | ament_export_dependencies( 70 | ${INCLUDE_DEPENDS} 71 | ) 72 | 73 | ament_export_include_directories( 74 | include 75 | ) 76 | 77 | ament_export_libraries( 78 | ${PROJECT_NAME} 79 | ) 80 | 81 | # this must happen before the invocation of ament_package() 82 | if(BUILD_TESTING) 83 | find_package(ament_lint_auto REQUIRED) 84 | ament_lint_auto_find_test_dependencies() 85 | endif() 86 | 87 | ament_package() 88 | -------------------------------------------------------------------------------- /irc_ros_hardware/doc/jitter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonplaceRobotics/iRC_ROS/41701e6df3398087d217f0f478622e60f694de41/irc_ros_hardware/doc/jitter.png -------------------------------------------------------------------------------- /irc_ros_hardware/doc/parse_candump.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import seaborn as sns 3 | import matplotlib.pyplot as plt 4 | 5 | # parse 6 | series = [] 7 | 8 | # Data gathered by 9 | # candump can0,040:FFF -td > "candump.txt" 10 | # Format should look like this" (000.010060) can0 010 [8] 14 00 00 00 00 00 B9 00", 11 | 12 | with open("candump.txt") as f: 13 | lines = f.readlines() 14 | 15 | for msg in lines: 16 | msg_split = msg.split(" ") 17 | 18 | _id = msg_split[5] 19 | _delta_t = float(msg_split[1][1:-1]) 20 | _counter = int(msg_split[17], 16) 21 | _position = int( 22 | "".join(msg_split[12:16]), 16 23 | ) # ''.join() concats the strings with '' as a (no) divider 24 | 25 | series.append([_id, _delta_t, _counter, _position]) 26 | 27 | print(len(series), " samples plotted") 28 | 29 | df = pd.DataFrame(data=series[1:], columns=["id", "delta_t", "counter", "position"]) 30 | 31 | # plot 32 | 33 | sns.relplot( 34 | data=df, 35 | kind="line", 36 | x=df.index, 37 | y="delta_t", # errorbar="sd", 38 | ) 39 | 40 | 41 | plt.xlabel("samples") 42 | plt.ylabel("delta_t [s]") 43 | plt.show() 44 | -------------------------------------------------------------------------------- /irc_ros_hardware/include/irc_ros_hardware/CAN/can_message.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "rclcpp/rclcpp.hpp" 10 | 11 | namespace irc_hardware 12 | { 13 | namespace CAN 14 | { 15 | 16 | using CanMessageID = uint32_t; 17 | using t_timestamp = std::chrono::time_point; 18 | 19 | class CanMessage 20 | { 21 | public: 22 | std::vector data; 23 | CanMessageID id = 0; 24 | 25 | /** 26 | * @brief Default constructor, initializes all values to 0 27 | */ 28 | CanMessage() {} 29 | 30 | /** 31 | * @brief Vector constructor 32 | */ 33 | CanMessage(CanMessageID id, std::vector data); 34 | 35 | /** 36 | * @brief Constructor, uses std::vector for initialisation 37 | * @param id CAN message ID 38 | * @param data message data, 8 bytes max 39 | */ 40 | // template 41 | // CanMessage(CanMessageID id, std::array _data); 42 | 43 | /** 44 | * @brief Constructor, copies length values from the data array 45 | * @param id CAN message ID 46 | * @param length Message length in bytes 47 | * @param data message data array, must at least be length bytes 48 | */ 49 | // CanMessage(CanMessageID id, uint8_t length, uint8_t* data); 50 | CanMessage(CanMessageID id, size_t length, uint8_t * _data); 51 | 52 | /** 53 | * @brief Constructor, copies the parameters into the message. Values are 0 if omitted. 54 | * @param id CAN message ID 55 | * @param length Message length in bytes 56 | * @param data0 message byte 0 57 | * @param data1 message byte 1 58 | * @param data2 message byte 2 59 | * @param data3 message byte 3 60 | * @param data4 message byte 4 61 | * @param data5 message byte 5 62 | * @param data6 message byte 6 63 | * @param data7 message byte 7 64 | */ 65 | CanMessage( 66 | CanMessageID id, uint8_t length, uint8_t data0 = 0, uint8_t data1 = 0, uint8_t data2 = 0, 67 | uint8_t data3 = 0, uint8_t data4 = 0, uint8_t data5 = 0, uint8_t data6 = 0, uint8_t data7 = 0); 68 | 69 | /** 70 | * @brief Converts the CAN message to a human readable string. Data values are given in hex format. 71 | * @return 72 | */ 73 | std::string to_string() const; 74 | }; 75 | 76 | class TimedCanMessage : public CanMessage 77 | { 78 | public: 79 | t_timestamp timestamp; 80 | 81 | TimedCanMessage() {} 82 | 83 | TimedCanMessage(CanMessageID id, uint8_t length, uint8_t * data, t_timestamp timestamp) 84 | : CanMessage(id, length, data), timestamp(timestamp) 85 | { 86 | } 87 | 88 | TimedCanMessage(const CanMessage & message, t_timestamp timestamp) 89 | : CanMessage(message), timestamp(timestamp) 90 | { 91 | } 92 | }; 93 | 94 | } // namespace CAN 95 | } // namespace irc_hardware 96 | -------------------------------------------------------------------------------- /irc_ros_hardware/include/irc_ros_hardware/CAN/can_socket.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @brief CAN interface for SocketCAN (Linux) 3 | */ 4 | 5 | #pragma once 6 | 7 | #include 8 | 9 | #include 10 | 11 | #include "can_interface.hpp" 12 | 13 | namespace irc_hardware 14 | { 15 | namespace CAN 16 | { 17 | 18 | /** 19 | * @brief CAN access via SocketCAN (Linux) 20 | */ 21 | class CanInterfaceSocketCAN : public CanInterface 22 | { 23 | public: 24 | ~CanInterfaceSocketCAN(); 25 | 26 | /** 27 | * @brief Connect to CAN bus 28 | * @return true on success 29 | */ 30 | bool connect(std::string can_port = "can0"); 31 | 32 | /** 33 | * @brief Disconnects from CAN bus 34 | * @return true on success 35 | */ 36 | bool disconnect(); 37 | 38 | /** 39 | * @brief Returns the connection state 40 | * @return true if connected 41 | */ 42 | bool is_connected() const { return is_socket_connected_ && socket_ >= 0; } 43 | 44 | /** 45 | * @brief Sends a CAN message if connected 46 | * @param message CAN message data 47 | * @return true if sent successfully 48 | */ 49 | bool write_message(const CanMessage & message); 50 | 51 | /** 52 | * @brief Translates the interface dependent error code to a human readable string 53 | * @param error_code interface dependent error code 54 | * @return human readable string or raw error code 55 | */ 56 | virtual std::string translate_can_dump_error(int error_code) const; 57 | 58 | private: 59 | /** 60 | * @brief SocketCAN socket number 61 | */ 62 | int socket_ = -1; 63 | 64 | /** 65 | * @brief true if connected, set by read_thread() 66 | */ 67 | bool is_socket_connected_ = false; 68 | 69 | /** 70 | * @brief set to true to stop the read thread and disconnect 71 | */ 72 | bool is_disconnect_requested_ = false; 73 | 74 | /** 75 | * @brief Last error code from sending a message 76 | */ 77 | int last_send_error_ = 0; 78 | 79 | /** 80 | * @brief Count of last error code 81 | */ 82 | int last_send_error_count_ = 0; 83 | 84 | void parse_errorframe(can_frame & frame); 85 | 86 | /** 87 | * @brief Reads CAN messages, stops when is_disconnect_requested_ is set to true 88 | */ 89 | void read_thread(); 90 | 91 | /** 92 | * @brief Static method to call read_thread via std::thread 93 | * @param context pointer to this 94 | */ 95 | static void read_thread_static(void * context); 96 | }; 97 | 98 | } // namespace CAN 99 | } // namespace irc_hardware 100 | -------------------------------------------------------------------------------- /irc_ros_hardware/include/irc_ros_hardware/CAN/cprcan_v2.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @brief Contains all the messages defined in the CPR CAN v2 guide 3 | */ 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "irc_ros_hardware/CAN/can_message.hpp" 13 | 14 | namespace cprcan 15 | { 16 | 17 | using bytevec = const std::vector; 18 | 19 | bytevec ping = {0x01, 0xCC}; 20 | 21 | bytevec reset_error = {0x01, 0x06}; 22 | bytevec reset_error_response = {0x06, 0x00, 0x01, 0x06, 0x00, 0x01, 0x00, 0x00}; 23 | 24 | bytevec set_pos_to_zero = {0x01, 0x08, 0x00, 0x00}; 25 | bytevec set_pos_to_zero_response_1 = {0x06, 0x00, 0x01, 0x08, 0x00, 0x01, 0x00, 0x00}; 26 | bytevec set_pos_to_zero_response_2 = {0x06, 0x00, 0x02, 0x08, 0x00, 0x01, 0x00, 0x00}; 27 | bytevec set_pos_to_zero_response_3 = set_pos_to_zero_response_1; 28 | bytevec set_pos_to_zero_response_4 = {0x06, 0x00, 0x02, 0x08, 0x00, 0x02, 0x00, 0x00}; 29 | 30 | bytevec enable_motor = {0x01, 0x09}; 31 | bytevec enable_motor_response = {0x06, 0x00, 0x01, 0x09, 0x00, 0x01, 0x00, 0x00}; 32 | 33 | bytevec disable_motor = {0x01, 0x0A}; 34 | bytevec disable_motor_response = {0x06, 0x00, 0x01, 0x0A, 0x00, 0x01, 0x00, 0x00}; 35 | 36 | bytevec referencing = {0x01, 0x0B}; 37 | bytevec referencing_response_1 = {0x06, 0x00, 0x02, 0x0B, 0x00, 0x01, 0x00, 0x00}; 38 | bytevec referencing_response_2 = {0x06, 0x00, 0x02, 0x0B, 0x00, 0x02, 0x00, 0x00}; 39 | bytevec referencing_response_error = {0x07, 0x00, 0x02, 0x0B, 0x00, 0x98, 0x00, 0x00}; 40 | 41 | bytevec rotor_alignment = {0x01, 0x0C}; 42 | bytevec rotor_alignment_response_1 = {0x06, 0x00, 0x02, 0x0C, 0x00, 0x01, 0x00, 0x00}; 43 | bytevec rotor_alignment_response_2 = {0x06, 0x00, 0x02, 0x0C, 0x00, 0x02, 0x00, 0x00}; 44 | 45 | // Message headers, only compare the start of the message 46 | bytevec encoder_msg_header = cprcan::bytevec{0xEF, 0x00, 0x00, 0x7E}; 47 | 48 | // While to CPR_CAN_Protocol_V2_UserGuide specifies a startup message as 49 | // {0x01, 0x02, 0x03, 0x04, 0x00}, it is not the only possible one 50 | // {0x01, 0x02, 0x03, 0x04, 0x03} and for CAN DIO Modules {0x01, 0x02, 0x06, 0x00, 0x00} 51 | // are sent. Thus we only compare the first two bytes. 52 | bytevec startup_msg_header = {0x01, 0x02}; 53 | 54 | // This message is not parsed, as the extended error codes are not found inside the 55 | // public protocol specifications. 56 | bytevec extended_error_msg_header = {0xEF, 0x00, 0x00, 0x7E}; 57 | 58 | bytevec environmental_msg_header = {0x12, 0x00}; 59 | 60 | static bool data_has_header(std::vector data, bytevec header) 61 | { 62 | return std::equal(header.begin(), header.end(), data.begin()); 63 | } 64 | 65 | static bytevec position_msg(int32_t pos, uint8_t message_counter, std::bitset<8> digital_out) 66 | { 67 | bytevec cmd = { 68 | 0x14, // [0] Position cmd 69 | 0x00, // [1] unused 70 | (uint8_t)((pos >> 24) & 0xFF), // [2-5] position in [Tics] 71 | (uint8_t)((pos >> 16) & 0xFF), 72 | (uint8_t)((pos >> 8) & 0xFF), 73 | (uint8_t)(pos & 0xFF), 74 | message_counter, // [6] Incrementing counter/ "Timestamp" 75 | (uint8_t)digital_out.to_ulong() // [7] Digital output array 76 | }; 77 | 78 | return cmd; 79 | } 80 | 81 | static bytevec velocity_msg(int16_t vel, uint8_t message_counter) 82 | { 83 | bytevec cmd = { 84 | 0x25, // [0] Velocity cmd 85 | (uint8_t)((vel >> 8) & 0xFF), // [1-2] Velocity in [rpm] 86 | (uint8_t)(vel & 0xFF), 87 | message_counter, // [3] Counter 88 | }; 89 | 90 | return cmd; 91 | } 92 | 93 | /** 94 | * UNTESTED 95 | */ 96 | static bytevec torque_msg(int16_t torque, uint8_t message_counter) 97 | { 98 | torque = std::clamp(torque, (const int16_t)-1024, (const int16_t)1024); 99 | 100 | bytevec cmd = { 101 | 0x16, // [0] Torque cmd 102 | (uint8_t)((torque >> 8) & 0xFF), // [1-2] Torque between [-1024, 1024] in "engineering units", fraction of the maximal possible torque. 103 | (uint8_t)(torque & 0xFF), 104 | message_counter, // [3] Incrementing counter/ "Timestamp" 105 | }; 106 | 107 | return cmd; 108 | } 109 | } // namespace cprcan 110 | -------------------------------------------------------------------------------- /irc_ros_hardware/include/irc_ros_hardware/CAN/digital_io.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "module.hpp" 7 | namespace irc_hardware 8 | { 9 | class DIO : public Module 10 | { 11 | public: 12 | DIO(std::string name, std::shared_ptr can_interface, int can_id); 13 | 14 | void position_cmd() override; 15 | 16 | void read_can() override; 17 | void write_can() override; 18 | 19 | void velocity_cmd() {} 20 | void torque_cmd() {} 21 | 22 | void set_position_to_zero() {} 23 | void referencing() {} 24 | void rotor_alignment() {} 25 | }; 26 | 27 | } // namespace irc_hardware 28 | -------------------------------------------------------------------------------- /irc_ros_hardware/include/irc_ros_hardware/CAN/joint.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "irc_ros_hardware/CAN/can_interface.hpp" 9 | #include "irc_ros_hardware/CAN/can_message.hpp" 10 | #include "irc_ros_hardware/CAN/module.hpp" 11 | #include "irc_ros_hardware/CAN/modulestates.hpp" 12 | 13 | namespace irc_hardware 14 | { 15 | class Joint : public Module 16 | { 17 | public: 18 | using Ptr = std::shared_ptr; 19 | 20 | Joint(std::string name, std::shared_ptr can_interface, int can_id); 21 | ~Joint(); 22 | 23 | int32_t encoder_pos_; 24 | double tics_over_degree_ = 1.0; // [tics]/[deg] 25 | 26 | void position_cmd() override; 27 | void velocity_cmd() override; 28 | void torque_cmd() override; 29 | 30 | void set_position_to_zero() override; 31 | void referencing() override; 32 | void rotor_alignment() override; 33 | 34 | void read_can() override; 35 | void write_can() override; 36 | 37 | private: 38 | void set_position_to_zero_callback(cprcan::bytevec response); 39 | void referencing_callback(cprcan::bytevec response); 40 | void rotor_alignment_callback(cprcan::bytevec response); 41 | void standard_response_callback(CAN::TimedCanMessage message); 42 | void encoder_message_callback(cprcan::bytevec data); 43 | void startup_message_callback(cprcan::bytevec data); 44 | void environmental_message_callback(cprcan::bytevec data); 45 | 46 | // Will be used for the zero-torque mode 47 | // bool zero_torque; 48 | 49 | // While the documentation specifies these DIOs, the current motor 50 | // boards dont have any outputs and only internally used inputs. 51 | // Therefore don't use these two bitsets unless you know what you are 52 | // doing! 53 | // std::bitset<4> digital_in; 54 | // std::bitset<8> digital_out; 55 | 56 | // Saves the timestamp from the last position message 57 | // used to estimate the velocity 58 | CAN::t_timestamp last_stamp_; 59 | 60 | // Used to filter the velocities 61 | std::deque velocity_buffer_; 62 | static constexpr size_t velocity_buffer_size_ = 10; 63 | std::array velocity_buffer_weights_; 64 | }; 65 | 66 | } // namespace irc_hardware 67 | -------------------------------------------------------------------------------- /irc_ros_hardware/include/irc_ros_hardware/CRI/cri_keywords.hpp: -------------------------------------------------------------------------------- 1 | // Based on the TruPhysics ROS project with permission to use 2 | // https://bitbucket.org/truphysics/igus_rebel/src/master/ 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | namespace irc_hardware 9 | { 10 | namespace cri_keywords 11 | { 12 | const std::string START = "CRISTART"; 13 | const std::string END = "CRIEND"; 14 | 15 | const std::string TYPE_STATUS = "STATUS"; 16 | const std::string TYPE_OPINFO = "OPINFO"; 17 | const std::string TYPE_GSIG = "GSIG"; 18 | const std::string TYPE_GRIPPERSTATE = "GRIPPERSTATE"; 19 | const std::string TYPE_RUNSTATE = "RUNSTATE"; 20 | const std::string TYPE_MESSAGE = "MESSAGE"; 21 | const std::string TYPE_CMD = "CMD"; 22 | const std::string TYPE_CMDACK = "CMDACK"; 23 | const std::string TYPE_CMDERROR = "CMDERROR"; 24 | const std::string TYPE_CONFIG = "CONFIG"; 25 | const std::string TYPE_INFO = "INFO"; 26 | const std::string TYPE_EXECACK = "EXECACK"; 27 | const std::string TYPE_EXECPAUSE = "EXECPAUSE"; 28 | const std::string TYPE_EXECEND = "EXECEND"; 29 | const std::string TYPE_EXECERROR = "EXECERROR"; 30 | 31 | const std::string STATUS_MODE = "MODE"; 32 | const std::string STATUS_POSJOINTSETPOINT = "POSJOINTSETPOINT"; 33 | const std::string STATUS_POSJOINTCURRENT = "POSJOINTCURRENT"; 34 | const std::string STATUS_POSCARTROBOT = "POSCARTROBOT"; 35 | const std::string STATUS_POSCARTPLATTFORM = "POSCARTPLATTFORM"; 36 | const std::string STATUS_OVERRIDE = "OVERRIDE"; 37 | const std::string STATUS_DIN = "DIN"; 38 | const std::string STATUS_DOUT = "DOUT"; 39 | const std::string STATUS_ESTOP = "ESTOP"; 40 | const std::string STATUS_SUPPLY = "SUPPLY"; 41 | const std::string STATUS_CURRENTALL = "CURRENTALL"; 42 | const std::string STATUS_CURRENTJOINTS = "CURRENTJOINTS"; 43 | const std::string STATUS_ERROR = "ERROR"; 44 | const std::string STATUS_KINSTATE = "KINSTATE"; 45 | 46 | const std::string COMMAND_CONNECT = "Connect"; 47 | const std::string COMMAND_RESET = "Reset"; 48 | const std::string COMMAND_ENABLE = "Enable"; 49 | const std::string COMMAND_DISABLE = "Disable"; 50 | const std::string COMMAND_DISCONNECT = "Disconnect"; 51 | const std::string COMMAND_MOTIONTYPEJOINT = "MotionTypeJoint"; 52 | const std::string COMMAND_MOTIONTYPECARTBASE = "MotionTypeCartBase"; 53 | 54 | const std::string CONFIG_GETKINEMATICLIMITS = "GetKinematicLimits"; 55 | const std::string CONFIG_GETKINEMATICLIMITS_ANSWER = "KinematicLimits"; 56 | } // namespace cri_keywords 57 | } // namespace irc_hardware 58 | -------------------------------------------------------------------------------- /irc_ros_hardware/include/irc_ros_hardware/CRI/cri_socket.hpp: -------------------------------------------------------------------------------- 1 | // Based on the TruPhysics ROS project with permission to use 2 | // https://bitbucket.org/truphysics/igus_rebel/src/master/ 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | namespace irc_hardware 16 | { 17 | class CriSocket 18 | { 19 | private: 20 | int sock; 21 | std::string ip; 22 | int port; 23 | int timeout; 24 | std::list unprocessedMessages; 25 | 26 | bool continueReceive; 27 | std::thread receiveThread; 28 | std::thread listCheckThread; 29 | std::mutex socketWriteLock; 30 | std::mutex connectionLock; 31 | std::mutex messageLock; 32 | int maxUnprocessedMessages; 33 | int listCheckWaitMs; 34 | 35 | bool connectionNeeded; 36 | static const int bufferSize = 4096; 37 | 38 | std::array fragmentBuffer; 39 | int fragmentLength; 40 | 41 | void MakeConnection(); 42 | void SeparateMessages(const char *); 43 | 44 | void ReceiveThreadFunction(); 45 | void ListCheckThreadFunction(); 46 | 47 | bool IsSocketOk(); 48 | 49 | public: 50 | CriSocket(const std::string &, const int &, const int &); 51 | ~CriSocket(); 52 | 53 | void SetIp(std::string _ip); 54 | void Start(); 55 | void Stop(); 56 | bool HasMessage(); 57 | std::string GetMessage(); 58 | void SendMessage(const std::string &); 59 | }; 60 | } // namespace irc_hardware 61 | -------------------------------------------------------------------------------- /irc_ros_hardware/include/irc_ros_hardware/irc_ros_can.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "CAN/can_socket.hpp" 13 | #include "CAN/module.hpp" 14 | #include "hardware_interface/system_interface.hpp" 15 | #include "hardware_interface/types/hardware_interface_return_values.hpp" 16 | 17 | namespace irc_hardware 18 | { 19 | class IrcRosCan : public hardware_interface::SystemInterface 20 | { 21 | public: 22 | IrcRosCan(); 23 | ~IrcRosCan(); 24 | 25 | // ROS2 Control functions 26 | hardware_interface::CallbackReturn on_init( 27 | const hardware_interface::HardwareInfo & info) override; 28 | hardware_interface::CallbackReturn on_configure( 29 | const rclcpp_lifecycle::State & previous_state) override; 30 | hardware_interface::CallbackReturn on_cleanup( 31 | const rclcpp_lifecycle::State & previous_state) override; 32 | hardware_interface::CallbackReturn on_activate( 33 | const rclcpp_lifecycle::State & previous_state) override; 34 | hardware_interface::CallbackReturn on_deactivate( 35 | const rclcpp_lifecycle::State & previous_state) override; 36 | hardware_interface::return_type prepare_command_mode_switch( 37 | const std::vector & /*start_interfaces*/, 38 | const std::vector & /*stop_interfaces*/) override; 39 | hardware_interface::return_type perform_command_mode_switch( 40 | const std::vector & /*start_interfaces*/, 41 | const std::vector & /*stop_interfaces*/) override; 42 | 43 | std::vector export_state_interfaces() override; 44 | std::vector export_command_interfaces() override; 45 | 46 | hardware_interface::return_type read(const rclcpp::Time &, const rclcpp::Duration &) override; 47 | hardware_interface::return_type write(const rclcpp::Time &, const rclcpp::Duration &) override; 48 | 49 | private: 50 | std::shared_ptr can_interface_; 51 | 52 | std::unordered_map modules_; 53 | 54 | // Name of the can socket 55 | std::string can_socket_; 56 | 57 | // Default values if nothing is specified in the .ros2_control.urdf 58 | const std::string default_can_socket_ = "can0"; 59 | 60 | // This corrosponds to the usual used offset and 61 | // two steps on the CAN address selection wheel on DIN rail modules 62 | const int default_can_id_step_ = 0x10; 63 | 64 | const double default_gear_scale_ = 10.0; 65 | 66 | // Timeouts for the startup process 67 | const std::chrono::duration reset_timeout_ = std::chrono::seconds(3); 68 | const std::chrono::duration motor_enable_timeout_ = std::chrono::seconds(3); 69 | }; 70 | } // namespace irc_hardware 71 | -------------------------------------------------------------------------------- /irc_ros_hardware/include/irc_ros_hardware/irc_ros_cri.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "CRI/cri_messages.hpp" 11 | #include "CRI/cri_socket.hpp" 12 | #include "hardware_interface/system_interface.hpp" 13 | #include "hardware_interface/types/hardware_interface_return_values.hpp" 14 | 15 | namespace irc_hardware 16 | { 17 | class IrcRosCri : public hardware_interface::SystemInterface 18 | { 19 | private: 20 | CriSocket crisocket; 21 | 22 | // This is the maximum number of joints that can be set with CRI 23 | // 6 Robot joints and 3 external axis 24 | // Also 3 values for gripper and 4 for mobile platform joints 25 | static constexpr uint8_t CRI_MAX_N_JOINTS = 9; 26 | 27 | cri_messages::Status currentStatus; 28 | 29 | // Current jogs 30 | // 0-5 are used for internal axis 31 | // 6-8 are used for external axis 32 | std::vector jog_array; 33 | 34 | bool continueAlive; 35 | bool continueMessage; 36 | std::thread aliveThread; 37 | std::thread messageThread; 38 | int aliveWaitMs; 39 | 40 | int cmd_counter; 41 | std::mutex counterLock; 42 | std::mutex aliveLock; 43 | 44 | // Read joint position values 45 | std::vector pos_; // [rad] 46 | std::vector vel_; // Not yet implemented! [rad/s] 47 | 48 | // Values given from the hardware_interface, all have length of N_JOINTS; predefine? 49 | std::vector set_pos_; // [rad] 50 | std::vector set_pos_last_; 51 | std::vector set_vel_; // percentage of the maximum speed 52 | 53 | // Used to counteract the offsets in EmbeddedCtrl, read from .ros2_control.xacro files 54 | std::vector pos_offset_; // [rad] 55 | 56 | // Not implemented! 57 | std::vector digital_in_double_; 58 | std::vector digital_out_double_; 59 | 60 | cri_messages::Kinstate lastKinstate; 61 | std::array lastErrorJoints; 62 | std::string kinstateMessage; 63 | 64 | // Thread functions 65 | void AliveThreadFunction(); 66 | void MessageThreadFunction(); 67 | 68 | // Other functions 69 | int get_cmd_counter(); 70 | void Command(const std::string &); 71 | void GetConfig(const std::string &); 72 | 73 | void GetReferencingInfo(); 74 | 75 | // Function to react to specific status values, to display warnings, error messages, etc. 76 | void ProcessStatus(const cri_messages::Status &); 77 | 78 | bool to_move = false; 79 | double move_velocity = 50.0f; 80 | void CmdMove(); 81 | void CmdDout(); 82 | 83 | public: 84 | IrcRosCri(); 85 | ~IrcRosCri(); 86 | 87 | // ROS2 Control functions 88 | hardware_interface::CallbackReturn on_init( 89 | const hardware_interface::HardwareInfo & info) override; 90 | hardware_interface::CallbackReturn on_activate( 91 | const rclcpp_lifecycle::State & previous_state) override; 92 | hardware_interface::CallbackReturn on_deactivate( 93 | const rclcpp_lifecycle::State & previous_state) override; 94 | 95 | std::vector export_state_interfaces() override; 96 | std::vector export_command_interfaces() override; 97 | 98 | hardware_interface::return_type read(const rclcpp::Time &, const rclcpp::Duration &) override; 99 | hardware_interface::return_type write(const rclcpp::Time &, const rclcpp::Duration &) override; 100 | }; 101 | } // namespace irc_hardware 102 | -------------------------------------------------------------------------------- /irc_ros_hardware/irc_ros_hardware.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | Interfacing over CRI. For more information about this see `irc_ros_hardware/README.md` and the CRI code in that folder. 7 | 8 | 9 | 12 | 13 | Interfacing over CAN. For more information about this see `irc_ros_hardware/README.md` and the CAN code in that folder. 14 | 15 | 16 | -------------------------------------------------------------------------------- /irc_ros_hardware/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | irc_ros_hardware 4 | 0.1.0 5 | ROS package to control an igus ReBeL cobot. 6 | 7 | Felix Reuter 8 | Apache-2.0 9 | cpr-robots.com 10 | https://github.com/CommonplaceRobotics/iRC_ROS 11 | Björn Schenke 12 | Felix Reuter 13 | 14 | rclcpp 15 | std_msgs 16 | sensor_msgs 17 | control_msgs 18 | controller_manager 19 | controller_manager_msgs 20 | controller_interface 21 | hardware_interface 22 | rclcpp_lifecycle 23 | ros2_control 24 | pluginlib 25 | irc_ros_msgs 26 | 27 | ament_lint_auto 28 | 29 | 30 | ament_lint_common 31 | 32 | ros2_controllers_test_nodes 33 | 34 | 35 | ament_cmake 36 | 37 | 38 | -------------------------------------------------------------------------------- /irc_ros_hardware/src/CAN/can_message.cpp: -------------------------------------------------------------------------------- 1 | #include "irc_ros_hardware/CAN/can_message.hpp" 2 | 3 | // #include 4 | // #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace irc_hardware 10 | { 11 | namespace CAN 12 | { 13 | 14 | /** 15 | * @brief Constructor, copies data from data to its internal vector 16 | * @param id CAN message ID 17 | * @param _data message data vector, maximum size of 8 bytes 18 | */ 19 | CanMessage::CanMessage(CanMessageID id, std::vector data) : id(id), data(data) 20 | { 21 | if (data.size() > 8) { 22 | throw std::invalid_argument("Invalid CAN message length"); 23 | } 24 | } 25 | 26 | /** 27 | * @brief Constructor, copies values from the C style data array. This 28 | * constructor should not be used by the user, only called in can_socket.cpp 29 | * @param id CAN message ID 30 | * @param length Message length in bytes 31 | * @param _data message data array, must at least be length bytes 32 | */ 33 | CanMessage::CanMessage(CanMessageID id, size_t length, uint8_t * _data) : id(id) 34 | { 35 | if (length > 8) { 36 | throw std::invalid_argument("Invalid CAN message length"); 37 | } 38 | 39 | for (size_t i = 0; i < length; i++) { 40 | data.push_back(_data[i]); 41 | } 42 | } 43 | 44 | /** 45 | * @brief DEPRECATED! Constructor, copies the parameters into the message. Values are 0 if omitted. 46 | * @param id CAN message ID 47 | * @param length Message length in bytes 48 | * @param data0 message byte 0 49 | * @param data1 message byte 1 50 | * @param data2 message byte 2 51 | * @param data3 message byte 3 52 | * @param data4 message byte 4 53 | * @param data5 message byte 5 54 | * @param data6 message byte 6 55 | * @param data7 message byte 7 56 | */ 57 | CanMessage::CanMessage( 58 | CanMessageID id, uint8_t length, uint8_t data0, uint8_t data1, uint8_t data2, uint8_t data3, 59 | uint8_t data4, uint8_t data5, uint8_t data6, uint8_t data7) 60 | : id(id) 61 | { 62 | if (length > 8) { 63 | throw std::invalid_argument("Invalid CAN message length"); 64 | } 65 | 66 | std::array _data = {data0, data1, data2, data3, data4, data5, data6, data7}; 67 | 68 | for (uint8_t i : _data) { 69 | data.push_back(i); 70 | } 71 | } 72 | 73 | /** 74 | * @brief Converts the CAN message to a human readable string. .data values are given in hex format. The format is based on the candump output. 75 | * @return 76 | */ 77 | std::string CanMessage::to_string() const 78 | { 79 | std::stringstream ss; 80 | ss << std::setfill('0') << std::setw(2) << "0x" << std::hex << id << std::dec << " [" 81 | << std::setw(1) << data.size() << "] " << std::setw(2) << std::hex; 82 | // Implicitily cast the uint8_t to unsigned int, else it will be interpreted as an (ASCII) char 83 | for (unsigned int i : data) { 84 | ss << " " << i; 85 | } 86 | return ss.str(); 87 | } 88 | 89 | } // namespace CAN 90 | } // namespace irc_hardware -------------------------------------------------------------------------------- /irc_ros_moveit_config/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.22) 2 | project(irc_ros_moveit_config) 3 | 4 | find_package(ament_cmake REQUIRED) 5 | 6 | ament_package() 7 | 8 | install(DIRECTORY launch DESTINATION share/${PROJECT_NAME}) 9 | install(DIRECTORY config DESTINATION share/${PROJECT_NAME}) 10 | install(DIRECTORY rviz DESTINATION share/${PROJECT_NAME}) 11 | -------------------------------------------------------------------------------- /irc_ros_moveit_config/README.md: -------------------------------------------------------------------------------- 1 | # iRC MoveIt2 package 2 | 3 | **This is very much WIP. While it appears to run fine the current state is insufficiently tested to let it run without being very cautios** 4 | 5 | ## Usage 6 | Start MoveIt with rviz with the following command: 7 | 8 | ``` bash 9 | $ LC_NUMERIC=en_US.UTF-8 ros2 launch irc_ros_moveit_config rebel.launch.py 10 | ``` 11 | 12 | ### Namespaces and prefixes 13 | Most of the package supports the parameters, only the controllers.yaml does not. For using th erviz plugin successfully change the topic names to match the namespaces and add the moveit namespace parameter. Save the config and restart rviz without rebuilding. -------------------------------------------------------------------------------- /irc_ros_moveit_config/config/controllers.yaml: -------------------------------------------------------------------------------- 1 | controller_names: 2 | - rebel_6dof_controller 3 | 4 | rebel_6dof_controller: 5 | type: FollowJointTrajectory 6 | action_ns: follow_joint_trajectory 7 | default: true 8 | joints: 9 | - joint1 10 | - joint2 11 | - joint3 12 | - joint4 13 | - joint5 14 | - joint6 -------------------------------------------------------------------------------- /irc_ros_moveit_config/config/igus_rebel_6dof.srdf.xacro: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /irc_ros_moveit_config/config/initial_positions.yaml: -------------------------------------------------------------------------------- 1 | # Default initial positions for igus_rebel_6dof's ros2_control fake system 2 | 3 | initial_positions: 4 | joint1: 0 5 | joint2: 0 6 | joint3: 0 7 | joint4: 0 8 | joint5: 0 9 | joint6: 0 -------------------------------------------------------------------------------- /irc_ros_moveit_config/config/joint_limits.yaml: -------------------------------------------------------------------------------- 1 | # joint_limits.yaml allows the dynamics properties specified in the URDF to be overwritten or augmented as needed 2 | robot_description_planning: 3 | 4 | # For beginners, we downscale velocity and acceleration limits. 5 | # You can always specify higher scaling factors (<= 2.0) in your motion requests. # Increase the values below to 2.0 to always move at maximum speed. 6 | default_velocity_scaling_factor: 0.1 7 | default_acceleration_scaling_factor: 0.1 8 | 9 | # Check the irc_ros_description readme before you change these settings 10 | joint_limits: 11 | joint1: 12 | has_velocity_limits: true 13 | max_velocity: 0.785 14 | has_acceleration_limits: true 15 | max_acceleration: 5.240 16 | joint2: 17 | has_velocity_limits: true 18 | max_velocity: 0.785 19 | has_acceleration_limits: true 20 | max_acceleration: 5.240 21 | joint3: 22 | has_velocity_limits: true 23 | max_velocity: 0.785 24 | has_acceleration_limits: true 25 | max_acceleration: 5.240 26 | joint4: 27 | has_velocity_limits: true 28 | max_velocity: 0.785 29 | has_acceleration_limits: true 30 | max_acceleration: 5.240 31 | joint5: 32 | has_velocity_limits: true 33 | max_velocity: 0.785 34 | has_acceleration_limits: true 35 | max_acceleration: 5.240 36 | joint6: 37 | has_velocity_limits: true 38 | max_velocity: 0.785 39 | has_acceleration_limits: true 40 | max_acceleration: 5.240 41 | 42 | # Limits for the Pilz planner 43 | # TODO: Currently not used, remove in case pilz won't be supported 44 | cartesian_limits: 45 | max_trans_vel: 1.0 46 | max_trans_acc: 2.25 47 | max_trans_dec: -5.0 48 | max_rot_vel: 1.57 49 | 50 | -------------------------------------------------------------------------------- /irc_ros_moveit_config/config/kinematics.yaml: -------------------------------------------------------------------------------- 1 | robot_description_kinematics: 2 | rebel_6dof: 3 | kinematics_solver: kdl_kinematics_plugin/KDLKinematicsPlugin 4 | kinematics_solver_search_resolution: 0.005 5 | kinematics_solver_timeout: 0.005 -------------------------------------------------------------------------------- /irc_ros_moveit_config/config/moveit_controllers.yaml: -------------------------------------------------------------------------------- 1 | # MoveIt uses this configuration for controller management 2 | # Currently controllers.yaml is used instead, as the intended loading of this file does not work 3 | 4 | /**: 5 | ros__parameters: 6 | moveit_controller_manager: moveit_simple_controller_manager/MoveItSimpleControllerManager 7 | 8 | moveit_simple_controller_manager: 9 | ros__parameters: 10 | controller_names: 11 | - rebel_6dof_controller 12 | 13 | rebel_6dof_controller: 14 | type: FollowJointTrajectory 15 | action_ns: follow_joint_trajectory 16 | default: true 17 | joints: 18 | - joint1 19 | - joint2 20 | - joint3 21 | - joint4 22 | - joint5 23 | - joint6 -------------------------------------------------------------------------------- /irc_ros_moveit_config/config/moveit_py.yaml: -------------------------------------------------------------------------------- 1 | planning_scene_monitor_options: 2 | name: "planning_scene_monitor" 3 | robot_description: "robot_description" 4 | joint_state_topic: "/joint_states" 5 | attached_collision_object_topic: "/planning_scene_monitor" 6 | publish_planning_scene_topic: "/publish_planning_scene" 7 | monitored_planning_scene_topic: "/monitored_planning_scene" 8 | wait_for_initial_state_timeout: 10.0 9 | 10 | planning_pipelines: 11 | pipeline_names: ["ompl", pilz_industrial_motion_planner] # , "ompl_rrt_star", "pilz_industrial_motion_planner"] #, "chomp", "ompl_rrtc"] 12 | default_planning_pipeline: ompl 13 | 14 | plan_request_params: 15 | planning_attempts: 1 16 | planning_pipeline: ompl 17 | planner_id: "RRTConnectkConfigDefault" 18 | # planning_pipeline: pilz_industrial_motion_planner 19 | # planner_id: "PTP" 20 | max_velocity_scaling_factor: 0.1 21 | max_acceleration_scaling_factor: 0.1 22 | planning_time: 2.0 # TODO: No idea if that's a sane value 23 | 24 | ompl: 25 | plan_request_params: 26 | planning_attempts: 1 27 | planning_pipeline: ompl 28 | planner_id: "RRTConnectkConfigDefault" 29 | max_velocity_scaling_factor: 1.0 30 | max_acceleration_scaling_factor: 1.0 31 | planning_time: 0.5 32 | 33 | ompl_rrtc: 34 | plan_request_params: 35 | planning_attempts: 1 36 | planning_pipeline: ompl 37 | planner_id: "RRTConnectkConfigDefault" 38 | max_velocity_scaling_factor: 1.0 39 | max_acceleration_scaling_factor: 1.0 40 | planning_time: 0.5 41 | 42 | ompl_rrt_star: 43 | plan_request_params: 44 | planning_attempts: 1 45 | planning_pipeline: ompl_rrt_star # Different OMPL pipeline name! 46 | planner_id: "RRTstarkConfigDefault" 47 | max_velocity_scaling_factor: 1.0 48 | max_acceleration_scaling_factor: 1.0 49 | planning_time: 1.5 50 | 51 | pilz_lin: 52 | plan_request_params: 53 | planning_attempts: 1 54 | planning_pipeline: pilz_industrial_motion_planner 55 | planner_id: "PTP" 56 | max_velocity_scaling_factor: 1.0 57 | max_acceleration_scaling_factor: 1.0 58 | planning_time: 0.8 59 | 60 | chomp: 61 | plan_request_params: 62 | planning_attempts: 1 63 | planning_pipeline: chomp 64 | max_velocity_scaling_factor: 1.0 65 | max_acceleration_scaling_factor: 1.0 66 | planning_time: 1.5 67 | -------------------------------------------------------------------------------- /irc_ros_moveit_config/config/pilz_cartesian_limits.yaml: -------------------------------------------------------------------------------- 1 | # Limits for the Pilz planner 2 | # TODO: Currently not used, remove in case pilz won't be supported 3 | cartesian_limits: 4 | max_trans_vel: 1.0 5 | max_trans_acc: 2.25 6 | max_trans_dec: -5.0 7 | max_rot_vel: 1.57 8 | -------------------------------------------------------------------------------- /irc_ros_moveit_config/config/ros2_controllers.yaml: -------------------------------------------------------------------------------- 1 | # This config file is used by ros2_control 2 | /controller_manager: 3 | ros__parameters: 4 | update_rate: 100 # Hz 5 | 6 | rebel_6dof_controller: 7 | type: joint_trajectory_controller/JointTrajectoryController 8 | 9 | joint_state_broadcaster: 10 | type: joint_state_broadcaster/JointStateBroadcaster 11 | 12 | dio_controller: 13 | type: irc_ros_controllers/DIOController 14 | 15 | external_dio_controller: 16 | type: irc_ros_controllers/DIOController 17 | 18 | ecbpmi_controller: 19 | type: irc_ros_controllers/EcbpmiController 20 | 21 | /rebel_6dof_controller: 22 | ros__parameters: 23 | joints: 24 | - joint1 25 | - joint2 26 | - joint3 27 | - joint4 28 | - joint5 29 | - joint6 30 | command_interfaces: 31 | - position 32 | state_interfaces: 33 | - position 34 | - velocity 35 | 36 | /dio_controller: 37 | ros__parameters: 38 | digital_inputs: 39 | - dio_arm/digital_input_0 40 | - dio_arm/digital_input_1 41 | - dio_base/digital_input_0 42 | - dio_base/digital_input_1 43 | - dio_base/digital_input_2 44 | - dio_base/digital_input_3 45 | - dio_base/digital_input_4 46 | - dio_base/digital_input_5 47 | - dio_base/digital_input_6 48 | 49 | digital_outputs: 50 | - dio_arm/digital_output_0 51 | - dio_arm/digital_output_1 52 | - dio_base/digital_output_0 53 | - dio_base/digital_output_1 54 | - dio_base/digital_output_2 55 | - dio_base/digital_output_3 56 | - dio_base/digital_output_4 57 | - dio_base/digital_output_5 58 | - dio_base/digital_output_6 59 | 60 | /external_dio_controller: 61 | ros__parameters: 62 | digital_inputs: 63 | - dio_ext/digital_input_0 64 | - dio_ext/digital_input_1 65 | - dio_ext/digital_input_2 66 | - dio_ext/digital_input_3 67 | - dio_ext/digital_input_4 68 | - dio_ext/digital_input_5 69 | - dio_ext/digital_input_6 70 | digital_outputs: 71 | - dio_ext/digital_output_0 72 | - dio_ext/digital_output_1 73 | - dio_ext/digital_output_2 74 | - dio_ext/digital_output_3 75 | - dio_ext/digital_output_4 76 | - dio_ext/digital_output_5 77 | - dio_ext/digital_output_6 78 | 79 | /ecbpmi_controller: 80 | ros__parameters: 81 | output_grip: dio_arm/digital_output_0 82 | output_release: dio_arm/digital_output_1 83 | input_grasped: dio_arm/digital_input_0 84 | -------------------------------------------------------------------------------- /irc_ros_moveit_config/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | irc_ros_moveit_config 5 | 0.1.0 6 | 7 | The files necessary to use MoveIt with a igus ReBeLs. 8 | 9 | 10 | Felix Reuter 11 | Apache-2.0 12 | cpr-robots.com 13 | https://github.com/CommonplaceRobotics/iRC_ROS 14 | Felix Reuter 15 | 16 | ament_cmake 17 | 18 | moveit_ros_move_group 19 | moveit_kinematics 20 | moveit_planners 21 | moveit_simple_controller_manager 22 | joint_state_publisher 23 | joint_state_publisher_gui 24 | tf2_ros 25 | xacro 26 | 28 | 29 | 30 | controller_manager 31 | irc_ros_description 32 | moveit_configs_utils 33 | moveit_ros_move_group 34 | moveit_ros_visualization 35 | moveit_ros_warehouse 36 | moveit_setup_assistant 37 | robot_state_publisher 38 | rviz2 39 | rviz_common 40 | rviz_default_plugins 41 | tf2_ros 42 | warehouse_ros_mongo 43 | xacro 44 | 45 | 46 | 47 | ament_cmake 48 | 49 | 50 | -------------------------------------------------------------------------------- /irc_ros_msgs/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.8) 2 | project(irc_ros_msgs) 3 | 4 | if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") 5 | add_compile_options(-Wall -Wextra -Wpedantic) 6 | endif() 7 | 8 | # find dependencies 9 | find_package(ament_cmake REQUIRED) 10 | find_package(rclcpp REQUIRED) 11 | find_package(std_msgs REQUIRED) 12 | find_package(sensor_msgs REQUIRED) 13 | find_package(rosidl_default_generators REQUIRED) 14 | 15 | rosidl_generate_interfaces( ${PROJECT_NAME} 16 | "msg/CanModuleCommand.msg" 17 | "msg/CanModuleState.msg" 18 | "msg/CanModuleStates.msg" 19 | "msg/DioCommand.msg" 20 | "msg/DioState.msg" 21 | "msg/DioStates.msg" 22 | "msg/GripperCommand.msg" 23 | "msg/GripperState.msg" 24 | "srv/CanModuleCommand.srv" 25 | "srv/DioCommand.srv" 26 | "srv/GripperCommand.srv" 27 | DEPENDENCIES std_msgs sensor_msgs 28 | ) 29 | 30 | ament_export_dependencies(rosidl_default_runtime) 31 | 32 | if(BUILD_TESTING) 33 | find_package(ament_lint_auto REQUIRED) 34 | # the following line skips the linter which checks for copyrights 35 | # comment the line when a copyright and license is added to all source files 36 | set(ament_cmake_copyright_FOUND TRUE) 37 | # the following line skips cpplint (only works in a git repo) 38 | # comment the line when this package is in a git repo and when 39 | # a copyright and license is added to all source files 40 | set(ament_cmake_cpplint_FOUND TRUE) 41 | ament_lint_auto_find_test_dependencies() 42 | endif() 43 | 44 | ament_package() 45 | -------------------------------------------------------------------------------- /irc_ros_msgs/README.md: -------------------------------------------------------------------------------- 1 | # iRC ROS Messages 2 | 3 | This package contains the message and service definitions for exchanging module, dio and gripper information and commands. -------------------------------------------------------------------------------- /irc_ros_msgs/msg/CanModuleCommand.msg: -------------------------------------------------------------------------------- 1 | string name 2 | 3 | uint8 TYPE_NONE = 0 4 | uint8 TYPE_PING = 1 5 | uint8 TYPE_ERROR_RESET = 1 6 | uint8 TYPE_ENABLE_MOTOR = 2 7 | uint8 TYPE_DISABLE_MOTOR = 3 8 | uint8 TYPE_REFERENCE = 4 9 | uint8 TYPE_SET_POS_TO_ZERO = 5 10 | 11 | uint8 type 12 | 13 | 14 | -------------------------------------------------------------------------------- /irc_ros_msgs/msg/CanModuleState.msg: -------------------------------------------------------------------------------- 1 | # Identifier 2 | string name 3 | string can_id 4 | 5 | # Device information 6 | string hardware_ident 7 | #string controller_type 8 | int8 version_major 9 | int8 version_minor 10 | 11 | # Environmental information 12 | float64 temperature_motor 13 | float64 temperature_board 14 | float64 supply_voltage 15 | float64 motor_current 16 | 17 | # Status 18 | int8 error_state 19 | string reset_state 20 | string motor_state 21 | int8 command_mode 22 | -------------------------------------------------------------------------------- /irc_ros_msgs/msg/CanModuleStates.msg: -------------------------------------------------------------------------------- 1 | std_msgs/Header header 2 | 3 | irc_ros_msgs/CanModuleState[] module_states -------------------------------------------------------------------------------- /irc_ros_msgs/msg/DioCommand.msg: -------------------------------------------------------------------------------- 1 | 2 | std_msgs/Header header 3 | 4 | string[] names 5 | bool[] outputs 6 | -------------------------------------------------------------------------------- /irc_ros_msgs/msg/DioState.msg: -------------------------------------------------------------------------------- 1 | std_msgs/Header header 2 | 3 | string[] names 4 | bool[] inputs 5 | bool[] outputs -------------------------------------------------------------------------------- /irc_ros_msgs/msg/DioStates.msg: -------------------------------------------------------------------------------- 1 | std_msgs/Header header 2 | 3 | irc_ros_msgs/DioState[] dio_states -------------------------------------------------------------------------------- /irc_ros_msgs/msg/GripperCommand.msg: -------------------------------------------------------------------------------- 1 | std_msgs/Header header 2 | 3 | bool grip 4 | -------------------------------------------------------------------------------- /irc_ros_msgs/msg/GripperState.msg: -------------------------------------------------------------------------------- 1 | 2 | std_msgs/Header header 3 | 4 | bool grasped 5 | -------------------------------------------------------------------------------- /irc_ros_msgs/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | irc_ros_msgs 5 | 0.0.0 6 | This package contains the messages required for the interaction between other irc_ros packages 7 | 8 | Felix Reuter 9 | Apache-2.0 10 | cpr-robots.com 11 | https://github.com/CommonplaceRobotics/iRC_ROS 12 | Felix Reuter 13 | 14 | ament_cmake 15 | 16 | std_msgs 17 | sensor_msgs 18 | 19 | ament_lint_auto 20 | ament_lint_common 21 | 22 | rosidl_default_generators 23 | 24 | rosidl_default_runtime 25 | 26 | rosidl_interface_packages 27 | 28 | 29 | ament_cmake 30 | 31 | 32 | -------------------------------------------------------------------------------- /irc_ros_msgs/srv/CanModuleCommand.srv: -------------------------------------------------------------------------------- 1 | string name 2 | 3 | uint8 TYPE_NONE = 0 4 | uint8 TYPE_PING = 1 5 | uint8 TYPE_ERROR_RESET = 2 6 | uint8 TYPE_ENABLE_MOTOR = 3 7 | uint8 TYPE_DISABLE_MOTOR = 4 8 | uint8 TYPE_REFERENCE = 5 9 | uint8 TYPE_SET_POS_TO_ZERO = 6 10 | 11 | uint8 type 12 | --- 13 | bool success 14 | # Or uint8 acknowledge -------------------------------------------------------------------------------- /irc_ros_msgs/srv/DioCommand.srv: -------------------------------------------------------------------------------- 1 | std_msgs/Header header 2 | 3 | string[] names 4 | bool[] outputs 5 | --- 6 | bool success 7 | -------------------------------------------------------------------------------- /irc_ros_msgs/srv/GripperCommand.srv: -------------------------------------------------------------------------------- 1 | bool grip 2 | --- 3 | bool gripped 4 | -------------------------------------------------------------------------------- /irc_ros_navigation2/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.8) 2 | project(irc_ros_navigation2) 3 | 4 | if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") 5 | add_compile_options(-Wall -Wextra -Wpedantic) 6 | endif() 7 | 8 | # find dependencies 9 | find_package(ament_cmake REQUIRED) 10 | 11 | if(BUILD_TESTING) 12 | find_package(ament_lint_auto REQUIRED) 13 | # the following line skips the linter which checks for copyrights 14 | # comment the line when a copyright and license is added to all source files 15 | set(ament_cmake_copyright_FOUND TRUE) 16 | # the following line skips cpplint (only works in a git repo) 17 | # comment the line when this package is in a git repo and when 18 | # a copyright and license is added to all source files 19 | set(ament_cmake_cpplint_FOUND TRUE) 20 | ament_lint_auto_find_test_dependencies() 21 | endif() 22 | 23 | install(DIRECTORY launch params map rviz 24 | DESTINATION share/${PROJECT_NAME} 25 | ) 26 | 27 | 28 | ament_package() 29 | -------------------------------------------------------------------------------- /irc_ros_navigation2/README.md: -------------------------------------------------------------------------------- 1 | # iRC ROS Navigation2 2 | This package aims to provide all necessary features for using the mobile platforms based on CPR modules with ROS2. The model used here is a CPR Platform of medium size, more information about it can be found [here](https://cpr-robots.com/servicerobotics#mobileplatformmedium). Currently basic movement commands and SLAM with the SICK laser scanners work. 3 | 4 | ## Install 5 | Navigation2 and Navigation2-bringup packages need to be installed. The instructions can be found [here](https://navigation.ros.org/build_instructions/index.html). Additionally the `irc_ros_bringup` package and all its requirements are necesssary to use the platform. 6 | 7 | ## Usage 8 | It is possible to manually send position goals via RVIZ. Another option with the Nav2 simple commander API can be found in the `irc_ros_examples` package. 9 | 10 | ![A SLAM test run](doc/slam.png) 11 | -------------------------------------------------------------------------------- /irc_ros_navigation2/doc/slam.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonplaceRobotics/iRC_ROS/41701e6df3398087d217f0f478622e60f694de41/irc_ros_navigation2/doc/slam.png -------------------------------------------------------------------------------- /irc_ros_navigation2/launch/cpr_platform.launch.py: -------------------------------------------------------------------------------- 1 | from launch import LaunchDescription 2 | from launch.actions import DeclareLaunchArgument, IncludeLaunchDescription 3 | from launch.launch_description_sources import PythonLaunchDescriptionSource 4 | from launch.substitutions import PathJoinSubstitution, LaunchConfiguration 5 | from launch_ros.actions import SetRemap 6 | from launch_ros.substitutions import FindPackageShare 7 | 8 | 9 | def generate_launch_description(): 10 | rviz_file = PathJoinSubstitution( 11 | [FindPackageShare("irc_ros_navigation2"), "rviz", "platform.rviz"] 12 | ) 13 | 14 | base_launch_file_arg = DeclareLaunchArgument( 15 | "base_launch_file", 16 | default_value=["cpr_platform.launch.py"], 17 | choices=["cpr_platform.launch.py", "rebel_on_platform.launch.py"], 18 | description="Name of the robot description file", 19 | ) 20 | 21 | base_launch_file = PathJoinSubstitution( 22 | [ 23 | FindPackageShare("irc_ros_bringup"), 24 | "launch", 25 | LaunchConfiguration("base_launch_file"), 26 | ] 27 | ) 28 | 29 | irc_ros_stack = IncludeLaunchDescription( 30 | PythonLaunchDescriptionSource(base_launch_file), 31 | launch_arguments={ 32 | "use_rviz": "true", 33 | "rviz_file": rviz_file, 34 | }.items(), 35 | ) 36 | 37 | params_file = PathJoinSubstitution( 38 | [ 39 | FindPackageShare("irc_ros_navigation2"), 40 | "params", 41 | "cpr_platform_medium.yaml", 42 | ] 43 | ) 44 | 45 | map_file = PathJoinSubstitution( 46 | [ 47 | FindPackageShare("irc_ros_navigation2"), 48 | "map", 49 | "map.yaml", 50 | ] 51 | ) 52 | 53 | nav2_launch_file_dir = PathJoinSubstitution( 54 | [ 55 | FindPackageShare("nav2_bringup"), 56 | "launch", 57 | ] 58 | ) 59 | 60 | nav2_stack = IncludeLaunchDescription( 61 | PythonLaunchDescriptionSource([nav2_launch_file_dir, "/bringup_launch.py"]), 62 | launch_arguments={ 63 | # While we use SLAM and dont use this map, it is required to pass this argument 64 | "map": map_file, 65 | "params_file": params_file, 66 | "slam": "True", 67 | }.items(), 68 | ) 69 | 70 | return LaunchDescription( 71 | [ 72 | base_launch_file_arg, 73 | irc_ros_stack, 74 | # /cmd_vel (comes from either rqt_robot_steering, Navigation2 goal_pose) 75 | # -> 76 | # /cpr_platform_controller/cmd_vel_unstamped (ros2_control input) 77 | SetRemap(src="/cmd_vel", dst="/cpr_platform_controller/cmd_vel_unstamped"), 78 | # SetRemap(src="amcl/get_state", dst="/amcl/get_state"), 79 | nav2_stack, 80 | ] 81 | ) 82 | -------------------------------------------------------------------------------- /irc_ros_navigation2/map/map.pgm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonplaceRobotics/iRC_ROS/41701e6df3398087d217f0f478622e60f694de41/irc_ros_navigation2/map/map.pgm -------------------------------------------------------------------------------- /irc_ros_navigation2/map/map.yaml: -------------------------------------------------------------------------------- 1 | image: map.pgm 2 | mode: trinary 3 | resolution: 0.05 4 | origin: [35, 18.5, 0] 5 | negate: 0 6 | occupied_thresh: 0.65 7 | free_thresh: 0.25 8 | -------------------------------------------------------------------------------- /irc_ros_navigation2/map/map_office.pgm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonplaceRobotics/iRC_ROS/41701e6df3398087d217f0f478622e60f694de41/irc_ros_navigation2/map/map_office.pgm -------------------------------------------------------------------------------- /irc_ros_navigation2/map/map_office.yaml: -------------------------------------------------------------------------------- 1 | image: map_1673264114.pgm 2 | mode: trinary 3 | resolution: 0.05 4 | origin: [-6.53, -5.4, 0] 5 | negate: 0 6 | occupied_thresh: 0.65 7 | free_thresh: 0.25 -------------------------------------------------------------------------------- /irc_ros_navigation2/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | irc_ros_navigation2 5 | 0.1.0 6 | The irc_ros_navigation2 package 7 | 8 | Felix Reuter 9 | Apache-2.0 10 | cpr-robots.com 11 | https://github.com/CommonplaceRobotics/iRC_ROS 12 | Felix Reuter 13 | 14 | ament_cmake 15 | 16 | ament_lint_auto 17 | ament_lint_common 18 | 19 | 20 | ament_cmake 21 | 22 | 23 | --------------------------------------------------------------------------------