ros-industrial / ros2_canopen

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

How to work with Heartbeat #288

Closed ghanim-mukhtar closed 3 months ago

ghanim-mukhtar commented 6 months ago

Describe the question I am using the library on an Embedded onboard PC the problem is if I send a non-zero command to my motors and for one reason or other the ROS application is shut down the robot keep moving with this command, very risky business.

So I want to set the motors (the slaves) to be consumers of a Heartbeat, the supplier already showed me how to activate it on their controllers so that is done. Now I need my master to send it.

I started following the exercise here with the virtual CAN to have a prove of concept. So I focused on the Service Interface with ros2 launch canopen_tests cia402_setup.launch.py and did the following:

response: lifecycle_msgs.srv.GetState_Response(current_state=lifecycle_msgs.msg.State(id=3, label='active'))


- Final the node info to see if I have the service `~/set_heartbeat` there:

$ ros2 node info /cia402_node_1 /cia402_node_1 Subscribers: /parameter_events: rcl_interfaces/msg/ParameterEvent Publishers: /cia402_node_1/transition_event: lifecycle_msgs/msg/TransitionEvent /parameter_events: rcl_interfaces/msg/ParameterEvent /rosout: rcl_interfaces/msg/Log Service Servers: /cia402_node_1/change_state: lifecycle_msgs/srv/ChangeState /cia402_node_1/describe_parameters: rcl_interfaces/srv/DescribeParameters /cia402_node_1/get_available_states: lifecycle_msgs/srv/GetAvailableStates /cia402_node_1/get_available_transitions: lifecycle_msgs/srv/GetAvailableTransitions /cia402_node_1/get_parameter_types: rcl_interfaces/srv/GetParameterTypes /cia402_node_1/get_parameters: rcl_interfaces/srv/GetParameters /cia402_node_1/get_state: lifecycle_msgs/srv/GetState /cia402_node_1/get_transition_graph: lifecycle_msgs/srv/GetAvailableTransitions /cia402_node_1/list_parameters: rcl_interfaces/srv/ListParameters /cia402_node_1/set_parameters: rcl_interfaces/srv/SetParameters /cia402_node_1/set_parameters_atomically: rcl_interfaces/srv/SetParametersAtomically Service Clients:

Action Servers:

Action Clients:



So we can see there no heartbeat service nor in the can trace, What I am missing here ? I expected the presence of the service and a continuous can trace every second, did I misunderstood that ?

**Logs**
- Launch log of `cia402_setup.launch.py`: 
[cia402_setup_launch_output.txt](https://github.com/ros-industrial/ros2_canopen/files/15435018/cia402_setup_launch_output.txt)

- Candump of vcan0: 
[candump_vcan0.txt](https://github.com/ros-industrial/ros2_canopen/files/15435021/candump_vcan0.txt)

**Setup:**
 - Device: EAC-3000 with processor: ARMv8 Processor rev 0 (v8l) × 8
 - OS: Native is: Ubuntu 20.04.5 LTS, but the application running on Docker container based on ros:humble-ros-base-jammy 
 - ROS-Distro: humble
 - Branch/Commit: humble

**Additional context**
I tried to look up the code on my side and I was surprised to see that in neither:

-  `canopen_master_driver/include/canopen_master_driver/node_interfaces/node_canopen_basic_master.hpp` [here](https://github.com/ros-industrial/ros2_canopen/blob/humble/canopen_master_driver/include/canopen_master_driver/node_interfaces/node_canopen_basic_master.hpp), nor
- `canopen_master_driver/include/canopen_master_driver/node_interfaces/node_canopen_basic_master_impl.hpp` [here](https://github.com/ros-industrial/ros2_canopen/blob/humble/canopen_master_driver/include/canopen_master_driver/node_interfaces/node_canopen_basic_master_impl.hpp)
There is no use of `canopen_interfaces/srv/co_heartbeat_id.hpp`, and I even look through the whole repos and it is not used anywhere. I mean it is defined and built as we can see in `canopen_interface` [here](https://github.com/ros-industrial/ros2_canopen/blob/humble/canopen_interfaces/srv/COHeartbeatID.srv) but not used afterwards.

Does this mean that I need to write the service myself?
hellantos commented 4 months ago

Hi, thanks for the comment and sorry for the confusion. We removed the service at some point because the possibility to fix heartbeat settings in the yaml for master and devices seemed sufficient. Actually this is a problem in the documentation. I have created PR #294 for adjusting this.

ghanim-mukhtar commented 3 months ago

Hi, thanks for the comment and sorry for the confusion. We removed the service at some point because the possibility to fix heartbeat settings in the yaml for master and devices seemed sufficient. Actually this is a problem in the documentation. I have created PR #294 for adjusting this.

Thanks for the reply and the correction, but still for me I am a bit confused about how to set the heartbeat in such a way that the PC is producer and the motors are consumers. Can you provide yaml examples please ?

hellantos commented 3 months ago

You would need to add heartbeat_producer: 1000 to master node and heartbeat_consumer: true to driver node in bus.yml.

ghanim-mukhtar commented 3 months ago

Thanks for the tip, I will check and get back to you ASAP to conclude the issue

ghanim-mukhtar commented 3 months ago

I did the test today and just wanted to double check something because I didn't get the behavior expected. I am in contact with our CANOpen motor controller to see if the error is in their side (most likely), meanwhile I have a small doubt about lily_core_libraries that I want to clear up with you.

Basically the bus.yml is configured as indicated above.

image

But after compiling I checked the resulting file cli.py in ~my_workspace/install/lely_core_libraries/lib/python3.10/site-packages/dcfgen/ and these caught my eyes (i attached it as .txt for your convenience):

image image

So my question is: Is this normal ? I mean the fact that in this autogenerated cli.py in lily_core_libraries the slave class is set as not a consumer of heartbeat and master class is set as non producer of heartbeat ?

cli.txt