ros-industrial / ros2_canopen

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

Errors In Driver Bootup When Using A Real CAN Bus #269

Closed kurtist123 closed 2 months ago

kurtist123 commented 3 months ago

Describe the bug I've been able to get everything setup and working using the virtual CAN bus vcan0. After transitioning to using real hardware and a real can bus, can0, I'm running into issues getting the drivers to boot properly.

When using vcan0, upon launch I see the following output:

[device_container_node-2] [WARN] [1710790278.676793451] [can0_comm]: Wait for device to boot. [basic_slave_node-1] [INFO] [1710790278.892142196] [can0_com_node]: Reaching inactive state. [INFO] [launch.user]: node 'basic_slave_node' reached the 'inactive' state, 'activating'. [basic_slave_node-1] [INFO] [1710790278.893996146] [can0_com_node]: Reaching active state. [basic_slave_node-1] [INFO] [1710790278.895287643] [can0_com_node]: Created slave for node_id 6. [device_container_node-2] [INFO] [1710790278.896020850] [can0_comm]: Driver booted and ready. [device_container_node-2] [INFO] [1710790278.896136007] [can0_comm]: Starting with event mode.

When using can0, I see:

[device_container_node-2] [WARN] [1710791761.807096601] [can0_comm]: Wait for device to boot. [INFO] [launch.user]: node 'basic_slave_node' reached the 'inactive' state, 'activating'. [basic_slave_node-1] [INFO] [1710791762.023111597] [can0_com_node]: Reaching inactive state. [basic_slave_node-1] [INFO] [1710791762.024751476] [can0_com_node]: Reaching active state. [basic_slave_node-1] [INFO] [1710791762.026134468] [can0_com_node]: Created slave for node_id 6.

When using can0 I don't see the "Driver booted and ready" and "Starting with event mode." messages. If I try to send a read or write SDO service call I get the following message:

[device_container_node-2] [ERROR] [1710859534.896904852] [can0_comm]: Could not read from SDO because driver not activated.

So it appears the driver is not starting successfully when using can0. I can see can0 is set up using ip link show and I can use cansend and candump utilities to send and read the can bus.

Here is my bus config:

options: dcf_path: "@BUS_CONFIG_PATH@"

master: node_id: 5 driver: "ros2_canopen::MasterDriver" package: "canopen_master_driver" baud_rate: 250 heartbeat_consumer: false heartbeat_producer: 2000 start_nodes: true sync_period: 5000000

defaults: dcf: "acu_can0.eds" driver: "ros2_canopen::ProxyDriver" package: "canopen_proxy_driver" polling: false heartbeat_consumer: false heartbeat_producer: 2000 boot: true period: 10 diagnostics: enable: false

nodes: can0_comm: node_id: 6

I'm using a ProxyDriver while most examples I've seen use the Cia402Driver. I'm not controlling anything that follows the 402 standard, I just want to have a simple can node that interfaces with the can bus and forwards that info to ROS messages like the ProxyDriver does.

  1. Does the ProxyDriver actually work using a real can bus or do I need to use the Cia402Driver?
  2. Is there some setup linking the CAN driver to the node? I'm confident the can bus is up and running.

I'm using a fake slave. Looking through this example it says if you are using a real can bus to remove launching the fake slave. I've tried to not launch my fake slave and the ProxyDriver node did not even start.

  1. Where is it documented when and why to use the fake slaves and when they are not needed. Should I be using a fake slave on the real can bus?

Setup:

Additional context This issue appears to be slightly related to https://github.com/ros-industrial/ros2_canopen/issues/26 and https://github.com/ros-industrial/ros2_canopen/issues/183.

hellantos commented 3 months ago

Do you have a CANopen device connected to real bus? It won't work without device.

kurtist123 commented 3 months ago

Do you have a CANopen device connected to real bus? It won't work without device.

I have a PEAK USB to CAN adapter (product number IPEH-002021) connected to my computer and the real can bus. There are other devices on the can bus and I can see their output using candump on my computer. So I'm confident my can bus is up and running and my adapter is working. The other devices are not necessarily talking CANopen though. Most of them are using the J1939 protocol. I don't plan to actually mix CANopen and J1939 on the same bus, I'm just trying to get something working right now.

I also ran the following commands just to be safe:

sudo modprobe -v peak_usb sudo ip link set can0 txqueuelen 1000 sudo ip link set can0 up type can bitrate 250000 sudo ip link set up can0

glaciercoder commented 3 months ago

Yeah, I met the same issue. I use ros2 canopen with ros2 control. The servo driver is Kinco on the real bus. The test shows the can bus works right. However, it is said "Wait for device to boot. " all the time. I don't know what is wrong. Have you solved the problem?

kurtist123 commented 3 months ago

Yeah, I met the same issue. I use ros2 canopen with ros2 control. The servo driver is Kinco on the real bus. The test shows the can bus works right. However, it is said "Wait for device to boot. " all the time. I don't know what is wrong. Have you solved the problem?

Unfortunately I have not solved this yet but I am actively working on it.

Are you launching a fake slave? If I do not launch a fake slave I see "Wait for device to boot." but it never boots (on both virtual CAN and a real CAN bus). If I launch a fake slave it gets further into the boot process. The Trinamic Stepper Motor control example is the only place I have seen it documented that you should not launch a fake slave when using a real CAN bus. My suggestion would be to try launching a fake slave and see if that boots the device.

glaciercoder commented 3 months ago

I didn't use a fake slave since I want to test on the real device and it stuck exactly on the "Wait for device to boot". After I search the log message in the source code, I found the error message comes from lely_core_libraries. I searched the relevant docs and found problem seems to be realated with lely_core_libraries, see https://lely_industries.gitlab.io/lely-core/doxygen/nmt__boot_8c.html#details. However, I still don't understand what is wrong. Did you check the can0 dump when launch file is launched?

kurtist123 commented 3 months ago

After doing some digging your comments helped me realize I had a fundamental misunderstanding of how some of these features were supposed to work.

You are correct, since you are using real devices you do not want to start a fake slave. I traced the boot procedure for using fake slaves on the virtual CAN bus back to https://lely_industries.gitlab.io/lely-core/doxygen/nmt_8c.html#a85b77551a12c1c4b9d856b6eff853b77. The process to boot a proxy driver seems to get kicked off when that function is called.

I don't have a good understanding of the underlying CANopen protocol, but is your device supposed to be sending a 700 message when it starts up which when received starts the driver boot up?

kurtist123 commented 3 months ago

I didn't use a fake slave since I want to test on the real device and it stuck exactly on the "Wait for device to boot". After I search the log message in the source code, I found the error message comes from lely_core_libraries. I searched the relevant docs and found problem seems to be realated with lely_core_libraries, see https://lely_industries.gitlab.io/lely-core/doxygen/nmt__boot_8c.html#details. However, I still don't understand what is wrong. Did you check the can0 dump when launch file is launched?

Your device needs to send a heartbeat message with the boot code '00'. For instance, my proxy node has a node ID of 2. So after launching, when you see "Wait for device to boot", if you send a message with ID 0x702 (0x700 + node ID) with a single byte set to zero, ex. cansend can0 702#00 the device will continue booting. I changed my bus.yml to not have the master start the other devices.

I'm running into two other issues now.

  1. For a few seconds, the nodes will broadcast on the can bus but then something happens and they stop. It seems like the entire can bus is taken down and needs to be restarted before it can be used again.
  2. I'm not sure how to send PDOs from my device. The proxy drivers handle PDOs from the remote devices but the master node running on my device does not send out PDOs. I'm not understanding how you are supposed to send CAN messages from your local deivce
glaciercoder commented 3 months ago

I received the 701#00 from my driver, but only once. And it seemes the code is sent by my driver rather than master. However, nothing happened when I dymped these boot codes from all my drivers. It still stucks at "Wait for device to boot", and no messages sent by master. According to your comments, shoud I send boot code manully?

Besides, for PDO, the bus.yaml defines its mapping. For people who uses ros2 canopen robot controller(You can see it in https://ros-industrial.github.io/ros2_canopen/manual/rolling/user-guide/how-to-create-a-robot-system.html). The PDO message is supposed to be sent via command interface of ros2 control. For my Kinco driver, it also defineds a special CAN frame to send PDO message. However, since I'm still "wait for device to boot", I haven't test it.

glaciercoder commented 3 months ago

Besides, I used a MCU to boot the driver and it boots well. I can set the motor via CAN messages. After I boot from MCU, I changed the CAN bus to master, it still said "Wait for device to boot".

glaciercoder commented 3 months ago

Have you solved the problem now? @kurtist123