ros-industrial / ros_canopen

CANopen driver framework for ROS (http://wiki.ros.org/ros_canopen)
GNU Lesser General Public License v3.0
332 stars 270 forks source link

"Sniffing" PDOs without NMT #404

Closed lkm1321 closed 2 years ago

lkm1321 commented 3 years ago

Hi there,

I'm currently working with a CANOpen joystick receiver. All the device really does, is it sends out TPDOs that contain the state of joystick, without any prior PDO mapping or NMTs.

Initially, I was hoping I'd be able to use canopen_chain_node to forward the PDOs from the bus to ROS, but testing revealed two problems:

  1. The device doesn't respond to NMT reset requests, causing canopen_chain_node to refuse to do anything further after the init service call
  2. The device stops sending out PDOs after the NMT request (!!) The symptom I see is that after a call to the init service, candump or cansniffer doesn't report anything anymore.

My current thinking is that I'd write a simple custom node that makes use of can::FilteredFrameListener in socketcan_interface to filter out the PDO messages by COB-ID rather than going through canopen_master, because canopen_master seems to be the one trying to do NMT requests. Am I correct in making this judgement?

Also, I'm hoping such a node coexists with another canopen_chain_node, because I have other CANOpen motor controllers on the bus. This shouldn't be a problem, right?

mathias-luedtke commented 3 years ago

The device doesn't respond to NMT reset requests

That's very unfortunate :-/ And not standard compliant..

The device stops sending out PDOs after the NMT request (!!)

Even worse!

because canopen_master seems to be the one trying to do NMT requests. Am I correct in making this judgement? Yes. It does thatto ensure that the PDO defaults are reset, because otherwise it does not know what to change in the PDO mapping.

Can you please try to change reset_com to reset in https://github.com/ros-industrial/ros_canopen/blob/2d2ccde1276f1deb85cb366a9f2ffb860c9a7e19/canopen_master/src/node.cpp#L181

My current thinking is that I'd write a simple custom node that makes use of can::FilteredFrameListener in socketcan_interface to filter out the PDO messages by COB-ID rather than going through canopen_master

That's one option, but canopen_chain_node does much more to handle errors etc. as well. I could imagine that we make the init process a little bit more flexible, e.g. with different reset options or even skipping some steps.

Also, I'm hoping such a node coexists with another canopen_chain_node, because I have other CANOpen motor controllers on the bus. This shouldn't be a problem, right?

If the sniffing mode does not send a SYNC or NMT, then it would work. You can even run multiple canopen_chain_node instances on the same bus, if you use the external sync master.

lkm1321 commented 3 years ago

Thanks Mathias.

I tried the patch you describe (reset_com => reset). Good news is that it no longer "kills" the joystick in that the PDOs are still sent out, but the bad news is that canopen_chain_node still responds with could not reset node.

Another issue I had is that there's no EDS file for this device (so I had to hack it by using the EDS file of another device). Upon power-on, it just sends out whatever PDOs it wants to send out without any mapping, and I'm not sure what address is mapped to the PDO.

Because of that, I can't get the PDOs to be published by canopen_chain_node in a normal way, because I don't know what address to use in the publish field of the config file for canopen_chain_node. I suppose I could try reading the registers to figure it out, and then pass it to the config for canopen_chain_node though.

BenArtes commented 3 years ago

Is the device actually CANopen? Or is it just publishing raw CAN bus frames? If the device provides a DBC file it is likely just CAN and not CANopen.

Asking because that behavior sounds more like a raw CAN bus device than a CANopen device and while it is possible to use some CAN bus devices with CANopen devices, they're more than likely to interfere with each other. But also, trying to use CANopen to decode raw CAN frames is going to cause headaches.

lkm1321 commented 3 years ago

I think it is still a CANOpen device because the datasheet says so. It also doesn't have a DBC file (or any files, like an EDS for that matter). The messages it send out also roughly conforms to CANOpen. E.g. COB-IDs of the PDO messages are correct given the node ID listed on the datasheet, and some SDO messages work.

lkm1321 commented 3 years ago

A bit further on reset/reset_com fix: I noticed the device doesn't send out hearbeats. To my understanding, both reset/reset_com functions waits until the device goes to preop, and times out, and checking if node is in preop requires heartbeat messages. Then, shouldn't reset/reset_com's timeout check if heartbeats are actually being sent out before going into a wait/timeout?

Coincidentally, we also have another device (a Roboteq motor controller) that doesn't handle NMTs correctly. This device responds to start/stop correctly, but not reset/reset_com (not sure about preop yet). I think this supports the case of more flexible init process.

lkm1321 commented 3 years ago

For now, we have an internal fix, which is to comment out reset/reset_com, and the PDO sniffer implementation. Thankfully, socketcan_interface is put together nicely, so it didn't take much effort to get the PDO sniffer going! Happy to send that to you, but I suspect it's doesn't conform to the architecture you have here.

I'm all sorted for now, but won't close the issue myself in case you want to have more discussions around the init process.

mathias-luedtke commented 2 years ago

I'm all sorted for now, but won't close the issue myself in case you want to have more discussions around the init process.

For now I will close this one, but I added a new issue (#447) to track this as a feature request