ros-industrial / ros2_canopen

CANopen driver framework for ROS2
https://ros-industrial.github.io/ros2_canopen/manual/rolling/
131 stars 55 forks source link

Robot system with ros2_control #182

Closed Lau86 closed 11 months ago

Lau86 commented 1 year ago

Hello, I'm currently working on creating a robot system with ros2_control. I have followed the instructions in the manual. However, I'm having problems building my package. More specifically, I'm getting the following errors:

Traceback (most recent call last): File "/home/ros2_humble/install/lely_core_libraries/bin/cogen", line 33, in sys.exit(load_entry_point('cogen==0.2.7', 'console_scripts', 'cogen')()) File "/home/ros2_humble/install/lely_core_libraries/local/lib/python3.10/dist-packages/cogen/cogen.py", line 59, in main nodes[node_name][entry_name] = defaults[entry_name] TypeError: list indices must be integers or slices, not dict gmake[2]: [CMakeFiles/robot_control.dir/build.make:73: robot_control] Error 1 gmake[1]: [CMakeFiles/Makefile2:165: CMakeFiles/robot_control.dir/all] Error 2 gmake: *** [Makefile:146: all] Error 2

Failed <<< canopen_robot_control_example [0.66s, exited with code 2]

(ros2_humble is the name of my workspace)

Have any of you already encountered this error when building this package? If so, could you help me understand the underlying cause of this error and find a solution?

Any help or suggestions would be greatly appreciated. Thank you in advance for your support!

hellantos commented 12 months ago

Looks like there is an issue with the nodes section. It seems to be yaml issue in the config file. Can't say more without the config file though.

flippybit commented 12 months ago

Hi @ipa-cmh im having the same error and using the exact config files from the tutorial "How to create a robot system with ros2_control" (using the humble readthedocs)

Files used following the tutorials #### ros2_controllers.yaml ``` yaml controller_manager: ros__parameters: update_rate: 100 # Hz joint_state_broadcaster: type: joint_state_broadcaster/JointStateBroadcaster forward_position_controller: type: forward_command_controller/ForwardCommandController forward_position_controller: ros__parameters: joints: - joint1 - joint2 interface_name: position ``` #### bus.yml ``` yaml options: dcf_path: "@BUS_CONFIG_PATH@" master: node_id: 1 driver: "ros2_canopen::MasterDriver" package: "canopen_master_driver" sync_period: 10000 defaults: dcf: "cia402_slave.eds" driver: "ros2_canopen::Cia402Driver" package: "canopen_402_driver" period: 10 position_mode: 1 revision_number: 0 sdo: - {index: 0x60C2, sub_index: 1, value: 50} # Set interpolation time for cyclic modes to 50 ms - {index: 0x60C2, sub_index: 2, value: -3} # Set base 10-3s - {index: 0x6081, sub_index: 0, value: 1000} - {index: 0x6083, sub_index: 0, value: 2000} - {index: 0x6060, sub_index: 0, value: 7} tpdo: # TPDO needed statusword, actual velocity, actual position, mode of operation 1: enabled: true cob_id: "auto" transmission: 0x01 mapping: - {index: 0x6041, sub_index: 0} # status word - {index: 0x6061, sub_index: 0} # mode of operation display 2: enabled: true cob_id: "auto" transmission: 0x01 mapping: - {index: 0x6064, sub_index: 0} # position actual value - {index: 0x606c, sub_index: 0} # velocity actual position rpdo: # RPDO needed controlword, target position, target velocity, mode of operation 1: enabled: true cob_id: "auto" mapping: - {index: 0x6040, sub_index: 0} # controlword - {index: 0x6060, sub_index: 0} # mode of operation 2: enabled: true cob_id: "auto" mapping: - {index: 0x607A, sub_index: 0} # target position nodes: - joint_1: node_id: 2 - joint_2: node_id: 3 ```

My idiot investigations/probing:

What i found very interesting ( pardon my stupidity in advance ) is that i could NOT build the package with the instructions given in point 1

ros2 pkg create --dependencies ros2_canopen lely_core_libraries --build-type ament_cmake {package_name}
This generated a CMakeLists.txt file like this ```cmake cmake_minimum_required(VERSION 3.8) project(robot_sys_prueba) if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") add_compile_options(-Wall -Wextra -Wpedantic) endif() # find dependencies find_package(ament_cmake REQUIRED) find_package(ros2_canopen REQUIRED) <----- THIS IS THE LINE THAT GAVE ME THE TROUBLES find_package(lely_core_libraries REQUIRED) if(BUILD_TESTING) find_package(ament_lint_auto REQUIRED) # the following line skips the linter which checks for copyrights # comment the line when a copyright and license is added to all source files set(ament_cmake_copyright_FOUND TRUE) # the following line skips cpplint (only works in a git repo) # comment the line when this package is in a git repo and when # a copyright and license is added to all source files set(ament_cmake_cpplint_FOUND TRUE) ament_lint_auto_find_test_dependencies() endif() ament_package() ```
This gave me this error output ``` bash $ colcon build --packages-select robot_sys_prueba --symlink-install Starting >>> robot_sys_prueba --- stderr: robot_sys_prueba CMake Error at CMakeLists.txt:10 (find_package): By not providing "Findros2_canopen.cmake" in CMAKE_MODULE_PATH this project has asked CMake to find a package configuration file provided by "ros2_canopen", but CMake did not find one. Could not find a package configuration file provided by "ros2_canopen" with any of the following names: ros2_canopenConfig.cmake ros2_canopen-config.cmake Add the installation prefix of "ros2_canopen" to CMAKE_PREFIX_PATH or set "ros2_canopen_DIR" to a directory containing one of the above files. If "ros2_canopen" provides a separate development package or SDK, be sure it has been installed. --- Failed <<< robot_sys_prueba [1.00s, exited with code 1] Summary: 0 packages finished [1.22s] 1 package failed: robot_sys_prueba 1 package had stderr output: robot_sys_prueba ```

What i did..

To get get to the package to build was to modify the CMakeList.txt file changing the name to:

find_package(canopen_ros2_control REQUIRED)
Modified CMakeLists.txt ```cmake cmake_minimum_required(VERSION 3.8) project(canopen_robot_control_example) if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") add_compile_options(-Wall -Wextra -Wpedantic) endif() # find dependencies find_package(ament_cmake REQUIRED) find_package(canopen_ros2_control REQUIRED) <---- THIS LINE find_package(lely_core_libraries REQUIRED) cogen_dcf(robot_control) install(DIRECTORY launch urdf DESTINATION share/${PROJECT_NAME}) if(BUILD_TESTING) find_package(ament_lint_auto REQUIRED) # the following line skips the linter which checks for copyrights # comment the line when a copyright and license is added to all source files set(ament_cmake_copyright_FOUND TRUE) # the following line skips cpplint (only works in a git repo) # comment the line when this package is in a git repo and when # a copyright and license is added to all source files set(ament_cmake_cpplint_FOUND TRUE) ament_lint_auto_find_test_dependencies() endif() ament_package() ```
Resulting in the same error @Lau86 gets.. ```bash $ colcon build --packages-select canopen_robot_control_example --symlink-install Starting >>> canopen_robot_control_example --- stderr: canopen_robot_control_example Traceback (most recent call last): File "/home/water/ROS2PORT/canopen_ws/install/lely_core_libraries/bin/cogen", line 33, in sys.exit(load_entry_point('cogen==0.2.7', 'console_scripts', 'cogen')()) File "/home/water/ROS2PORT/canopen_ws/install/lely_core_libraries/local/lib/python3.10/dist-packages/cogen/cogen.py", line 59, in main nodes[node_name][entry_name] = defaults[entry_name] TypeError: list indices must be integers or slices, not dict gmake[2]: *** [CMakeFiles/robot_control.dir/build.make:73: robot_control] Error 1 gmake[1]: *** [CMakeFiles/Makefile2:165: CMakeFiles/robot_control.dir/all] Error 2 gmake: *** [Makefile:146: all] Error 2 --- Failed <<< canopen_robot_control_example [0.52s, exited with code 2] Summary: 0 packages finished [0.75s] 1 package failed: canopen_robot_control_example 1 package had stderr output: canopen_robot_control_example ```

Conclusion

Any help would be apreciated, I'm trying to use this package to communicate with my robots servo motors "the proper way" but i guess i am condemned to use arduino code like a noob 4eva

  // Set synchronous velocity profile
    if (input == "set\n"){
        Serial.print("received:");
        Serial.print(input);
        CAN0.sendMsgBuf(0x601, 0, 8, set_sync_control);
        CAN0.sendMsgBuf(0x601, 0, 8, set_profile_vel_mode); 

BTW you guys are the best ! :heart: would love to contribute to this repo even if only to correct some of the typos or outdated docs (but to scared to do so) :fearful:

ipa-vsp commented 12 months ago

Hi @flippybit and @Lau86,

To create a package, please use the following command instead of the one in the documentation:

ros2 pkg create --dependencies canopen lely_core_libraries --build-type ament_cmake {package_name}

Also, to remove TypeError: list indices must be integers or slices, not dict change the following in bus.yml.

nodes:
    joint_1:
      node_id: 2
    joint_2:
      node_id: 3

This will be fixed in #176

Lau86 commented 12 months ago

Thank you very much for your help !

flippybit commented 12 months ago

Hi @ipa-vsp and @Lau86,

First of all thnx @ipa-vsp for pointing me in the right direction and @Lau86 for starting this thread. I dont know if im breaching github etiquette with the following post please correct me if i should open a new issue instead.

I have continued with the "How to create a robot system with ros2_control" (using the humble readthedocs) And have found other potential pitfalls for others following this guide.

Point 11. Start your launch file

FileNotFoundError: [Errno 2] No such file or directory:

At this point you should have built your package and sourced setup.bash file and be ready to launch your newly built package, if following the guide should be called canopen_robot_control_example

The command to do this should look like this:

$ ros2 launch canopen_robot_control_example robot_control.launch.py 
But i got the following error output: ```bash [INFO] [launch]: All log files can be found below /home/water/.ros/log/2023-08-10-18-58-35-285345-water-tender-18171 [INFO] [launch]: Default logging verbosity is set to INFO [ERROR] [launch]: Caught exception in launch (see debug for traceback): executed command failed. Command: /opt/ros/humble/bin/xacro /home/water/ROS2PORT/canopen_ws/install/canopen_tests/share/canopen_tests/robot_controller/robot_controller.urdf.xacro Captured stderr output: Traceback (most recent call last): File "/opt/ros/humble/local/lib/python3.10/dist-packages/xacro/__init__.py", line 1012, in parse inp = f = open(filename) FileNotFoundError: [Errno 2] No such file or directory: '/home/water/ROS2PORT/canopen_ws/install/canopen_tests/share/canopen_tests/robot_controller/robot_controller.urdf.xacro' During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/opt/ros/humble/local/lib/python3.10/dist-packages/xacro/__init__.py", line 1119, in _process doc = process_file(input_file_name, **opts) File "/opt/ros/humble/local/lib/python3.10/dist-packages/xacro/__init__.py", line 1096, in process_file doc = parse(None, input_file_name) File "/opt/ros/humble/local/lib/python3.10/dist-packages/xacro/__init__.py", line 1016, in parse raise XacroException(e.strerror + ": " + e.filename, exc=e) xacro.XacroException: No such file or directory: /home/water/ROS2PORT/canopen_ws/install/canopen_tests/share/canopen_tests/robot_controller/robot_controller.urdf.xacro [Errno 2] No such file or directory: '/home/water/ROS2PORT/canopen_ws/install/canopen_tests/share/canopen_tests/robot_controller/robot_controller.urdf.xacro' During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/opt/ros/humble/bin/xacro", line 33, in sys.exit(load_entry_point('xacro==2.0.8', 'console_scripts', 'xacro')()) File "/opt/ros/humble/local/lib/python3.10/dist-packages/xacro/__init__.py", line 1171, in main _process(input_file_name, vars(opts)) File "/opt/ros/humble/local/lib/python3.10/dist-packages/xacro/__init__.py", line 1124, in _process except xml.parsers.expat.ExpatError as e: AttributeError: module 'xml' has no attribute 'parsers' ```

It seems like there is a FileNotFoundError:

FileNotFoundError: [Errno 2] No such file or directory: '/home/water/ROS2PORT/canopen_ws/install/canopen_tests/share/canopen_tests/robot_controller/robot_controller.urdf.xacro'

(my path and workspace name will not be the same as yours, in my case my workspace name is called canopen_ws )

/home/water/ROS2PORT/canopen_ws/install/canopen_tests/share/canopen_tests/robot_controller/robot_controller.urdf.xacro

What is think is happening

Click to expand **robot_control.launch.py** file is trying to access the **robot_controller.urdf.xacro** file in this path: `canopen_ws/install/canopen_tests/share/canopen_tests/robot_controller/robot_controller.urdf.xacro` But it should be looking for the file in this path: (note the **urdf** directory) `canopen_ws/install/canopen_tests/share/canopen_tests/urdf/robot_controller/robot_controller.urdf.xacro`

SOLUTION what i did (please correct me if im wrong)

I modified the robot_control.launch.py of the canopen_robot_control_example package to point it to the correct path into the urdf directory.


def generate_launch_description():
    robot_description_content = Command(
        [
            PathJoinSubstitution([FindExecutable(name="xacro")]),
            " ",
            PathJoinSubstitution(
                [
                    FindPackageShare("canopen_tests"),
                    "urdf", #<---- THIS LINE
                    "robot_controller",
                    "robot_controller.urdf.xacro",
                ]
            ),
        ]
    )

Conclusion

You should now be able to run the canopen_robot_control_example package with:

ros2 launch canopen_robot_control_example robot_control.launch.py

Hurray !! :tada:

Click to see full modified robot_control.launch.py file ```python from launch import LaunchDescription from launch.actions import DeclareLaunchArgument from launch.substitutions import Command, FindExecutable, LaunchConfiguration, PathJoinSubstitution from launch_ros.actions import Node from launch_ros.substitutions import FindPackageShare from launch.actions import IncludeLaunchDescription from launch.launch_description_sources import PythonLaunchDescriptionSource def generate_launch_description(): robot_description_content = Command( [ PathJoinSubstitution([FindExecutable(name="xacro")]), " ", PathJoinSubstitution( [ FindPackageShare("canopen_tests"), "urdf", "robot_controller", "robot_controller.urdf.xacro", ] ), ] ) robot_description = {"robot_description": robot_description_content} robot_control_config = PathJoinSubstitution( [FindPackageShare("canopen_tests"), "config/robot_control", "ros2_controllers.yaml"] ) control_node = Node( package="controller_manager", executable="ros2_control_node", parameters=[robot_description, robot_control_config], output="screen", ) joint_state_broadcaster_spawner = Node( package="controller_manager", executable="spawner", arguments=["joint_state_broadcaster", "--controller-manager", "/controller_manager"], ) forward_position_controller_spawner = Node( package="controller_manager", executable="spawner", arguments=["forward_position_controller", "--controller-manager", "/controller_manager"], ) robot_state_publisher_node = Node( package="robot_state_publisher", executable="robot_state_publisher", output="both", parameters=[robot_description], ) slave_config = PathJoinSubstitution( [FindPackageShare("canopen_tests"), "config/robot_control", "cia402_slave.eds"] ) slave_launch = PathJoinSubstitution( [FindPackageShare("canopen_fake_slaves"), "launch", "cia402_slave.launch.py"] ) slave_node_1 = IncludeLaunchDescription( PythonLaunchDescriptionSource(slave_launch), launch_arguments={ "node_id": "2", "node_name": "slave_node_1", "slave_config": slave_config, }.items(), ) slave_node_2 = IncludeLaunchDescription( PythonLaunchDescriptionSource(slave_launch), launch_arguments={ "node_id": "3", "node_name": "slave_node_2", "slave_config": slave_config, }.items(), ) nodes_to_start = [ control_node, joint_state_broadcaster_spawner, forward_position_controller_spawner, robot_state_publisher_node, slave_node_1, slave_node_2 ] return LaunchDescription(nodes_to_start) ```
hellantos commented 12 months ago

@flippybit Many thanks for the review! I would really appreciate a PR if you can do that?

flippybit commented 11 months ago

@ipa-cmh Thanx to you! for your awesome ROS2 package I would be honored to do so! Im not sure if ill do it right. But ill give it my best try. :sweat_smile:

hellantos commented 11 months ago

@flippybit thanks for your help, we @ipa-vsp merged the your changes with #176. I will close this.