Ask Your Question
0

Best practices for using ros_control (hardware_interface) to send different data types to a PLC controller?

asked 2020-08-26 07:48:44 -0500

curi_ROS gravatar image

image description

I'm using the ROS(Kinetic) navigation stack with an industrial AGV and a Siemens S7 PLC as the central controller. The motors and encoders are interfaced to the PLC. Currently the PLC communicates with ROS over TCP/IP sockets using ros_control and the diff_drive_controller plugin. This has worked well so far to receive odom feedback and send the corresponding wheel velocity commands.

Now I plan to send some extra information to the PLC, such as current waypoint, pose, goal status etc as part of the “telegram” (in the Write method). This additional data may not really make sense to be represented in the joint space so I’m unsure if a custom hardware interface such as the ones written for force-torque sensors, IMUs etc might make sense here. This information is internally published on various topics from different nodes and has to be inserted into the PC-PLC real time communication.

My understanding is that the controller plugin has to implement all the ROS related non realtime communication so that it is real time safe. The read and write methods implement the realtime specific communication to and from the hardware.

  1. Could I introduce multiple subscribers in the diff_drive_controller plugin to gather this extra data from the ROS side? I notice that the cmd_vel callback in diff_drive_controller uses a Command object to “writeFromNonRT”.

  2. Could I extend this struct to include other datatypes and perform a similar write function from multiple subscriber callbacks? If so, is there a way to ensure all of the callbacks are executed within the control loop “update” cycle? Or am I over complicating this?

How do I go about achieving this in a way that can be easily extended for newer data that I might want to send to the hardware (PLC)?

edit retag flag offensive close merge delete

1 Answer

Sort by » oldest newest most voted
4

answered 2020-08-26 08:33:49 -0500

gvdhoorn gravatar image

updated 2020-08-26 08:56:37 -0500

Could I introduce multiple subscribers in the diff_drive_controller plugin to gather this extra data from the ROS side?

I would not try to fudge this into the diff_drive_controller.

That would make no sense to me: diff_drive_controller has a very narrowly defined scope and responsibility. Would it make sense for it to know/have to deal with the current waypoint or the goal status?

Now I plan to send some extra information to the PLC, such as current waypoint, pose, goal status etc as part of the “telegram” (in the Write method). [..]. This information is internally published on various topics from different nodes and has to be inserted into the PC-PLC real time communication.

In the end, ros_control is a resource management framework. The job of the controller manager, together with the hardware_interface is to make sure no two plugins claim the same resources at the same time. In most cases, concurrent read is OK, but concurrent write is not. Typical examples of such plugins are the controllers in ros_controllers, which implement the type of controllers most people think of when hearing the words "control" (ie: PID and similar concepts from Control Engineering). But there is nothing which limits ros_control controllers to those kinds of controllers.

This additional data may not really make sense to be represented in the joint space so I’m unsure if a custom hardware interface such as the ones written for force-torque sensors, IMUs etc might make sense here.

It's actually perfectly fine to have your hardware_interface make resources available which do not fall in that category (and which are probably not "in the joint space" (whatever you mean by that)), but which are to be used to communicate different kinds of abstractions between the ROS / ros_control side and whatever representations the underlying hardware is comfortable with.

So you could do the following:

  • define ROS-agnostic data structures to encode the types of information you'd like to exchange between your ROS application and the external hw
  • come up with a "resource" which would naturally be the one maintaining/holding onto/owning instances of those data structures (example: a "Cartesian frame resource" could be responsible for maintaining a list of Cartesian coordinate frames which can be read/written from/to the underlying hw). This is really just to be able to reason about your abstraction. You could introduce a "PLC resource", but I would probably go for something a bit more fine-grained, and more abstract (there is no reason any of the data you describe has to come from a PLC for instance)
  • add *Interface and *Handle pairs for those resources (this is ros_control specific, look at the various implementations available in ros_control already)
  • add the necessary infrastructure to your hardware_interface and expose it using the *Interface and *Handle you've defined earlier (so add a way for your hardware_interface to read/write the list of Cartesian frames from/to your PLC and update whatever internal data structure you use to store that inside the hardware_interface ...
(more)
edit flag offensive delete link more

Comments

PS: make sure to use as generic representations as possible of the kinds of data you're looking to exchange (so don't add a MyPlcMyAppFooBar, but a FooBar handle and interface), and derive semantics about how FooBar is used in your application or in this specific configuration from topic names or other aspects. This reduces coupling and increases re-usability of your controllers.

gvdhoorn gravatar image gvdhoorn  ( 2020-08-26 08:38:34 -0500 )edit

Two examples of the approach I describe:

The first provides an Interface and Handle for a industrial_msgs/RobotStatus message (but as a ROS-agnostic data structure) and a controller to publish the contents of that data structure as a RobotStatus message.

The second is part of the UniversalRobots/Universal_Robots_ROS_Driver, and exposes (among other things) the "speed scaling" value from UR controller as publications on a topic through the SpeedScalingStateController.

gvdhoorn gravatar image gvdhoorn  ( 2020-08-26 08:38:47 -0500 )edit

Thanks for that quick and comprehensive answer! Some follow up questions:
1. Can multiple controller plugins be loaded to a single hardware_interface instance?
2. If so, do they run parallely at runtime?
2. Can individual controllers be run simultaneously at separate rates?
3. The examples you provide are really helpful! Do you have any examples of Interface and Handle written to send data From ROS To the Hardware?

curi_ROS gravatar image curi_ROS  ( 2020-08-26 09:44:23 -0500 )edit

1. Can multiple controller plugins be loaded to a single hardware_interface instance?

No.

But you can load multiple plugins into a single ControllerManager.

(yes, this is pedantic, but it pays to be specific in this case: hardware_interfaces do not load controllers, nor do they interact with them directly. ControllerManagers do).

2. If so, do they run parallely at runtime?

Yes, of course.

Provided you do not serialise them through locks or other control flow mechanisms.

2. Can individual controllers be run simultaneously at separate rates?

Yes, but this is obviously limited by the rate the node which runs your hardware_interface and ControllerManager runs at.

3. The examples you provide are really helpful! Do you have any examples of Interface and Handle written to send data From ROS To the Hardware?

All controllers in ros_controllers except the joint_state_controller and the force-torque one?

gvdhoorn gravatar image gvdhoorn  ( 2020-08-26 11:31:35 -0500 )edit

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

1 follower

Stats

Asked: 2020-08-26 07:48:44 -0500

Seen: 446 times

Last updated: Aug 26 '20