Rtde recipe publishing
Implements automatic publishing of requested RTDE data to ROS topics.
A high-level comment: publishing raw std_msgs is considered bad practice. Low semantic value and increased potential for (inadvertent) misuse.
Best practice suggests correctly typed topics should be used wherever possible.
Could the rationale for publishing these raw values be clarified, perhaps here in this issue or in some other place?
A high-level comment: publishing raw
std_msgsis considered bad practice. Low semantic value and increased potential for (inadvertent) misuse.Best practice suggests correctly typed topics should be used wherever possible.
Could the rationale for publishing these raw values be clarified, perhaps here in this issue or in some other place?
The idea is that if users are interested in getting additional data from the RTDE interface they can do so without code modifications, but by only specifying them in the recipe. Publishing raw data is the only option that we see without explicitly preparing a publisher for each possible RTDE data field and instanciating them on-demand. We consider this more of an easy-access power-functionality instead of something out of the box.
We consider this more of an easy-access power-functionality instead of something out of the box.
Unfortunately I expect this -- ie: raw values from RTDE recipies -- to become the default way people will start interacting with the driver over a ROS API.
As I believe one of the goals of this driver is to be an example of how to properly integrate a UR in a ROS environment, it would be nice if we could avoid including anti-patterns in it.
We consider this more of an easy-access power-functionality instead of something out of the box.
Unfortunately I expect this -- ie: raw values from RTDE recipies -- to become the default way people will start interacting with the driver over a ROS API.
As I believe one of the goals of this driver is to be an example of how to properly integrate a UR in a ROS environment, it would be nice if we could avoid including anti-patterns in it.
You are probably right... Thanks for never letting me get away with laziness :-)
We'll take that into consideration and improve this PR.
You are probably right... Thanks for never letting me get away with laziness :-)
That was not my intention, I don't want to be a gatekeeper here.
It's easy for me to write "this is not a nice solution", but it would be nice if I could provide alternatives then.
Perhaps an issue where the requirements and constraints could be listed could be used to drive some discussion?
Dynamic message generation would be possible, as would .msg generation based on RTDE recipies. At the very least we should probably try to use appropriate messages from geometry_msgs for certain types of data (ie: Vector3 and friends).
You are probably right... Thanks for never letting me get away with laziness :-)
That was not my intention, I don't want to be a gatekeeper here.
I meant that in a positive way. The main reason we implemented it this was was laziness on implementing this for each message field. This dropped out of an internal requirement rather than belonging to the original plan.
At the very least we should probably try to use appropriate messages from geometry_msgs for certain types of data (ie: Vector3 and friends).
We've been discussing a bit and also came to this conclusion. We would leave simple datatypes as is, e.g. actual_main_voltage (double), use geometry_msgs where feasible and custom messages for things such as runtime_state, robot_status_bits, etc. where the integer representation has a certain meaning.
So, we took the time to have a closer look at all the published data from RTDE:
Any thoughts on this?
Markdown version:
RTDE datatypes to ROS
| Name | UR-Datatype | Comment | Versioning | ROS Datatype | Comment | Comment 2 |
|---|---|---|---|---|---|---|
timestamp |
DOUBLE |
Time elapsed since the controller was started [s] | Introduced in version | std_msgs/Time | ||
target_q |
VECTOR6D |
Target joint positions | custom_msg | rtde_msgs/JointPosition | ||
target_qd |
VECTOR6D |
Target joint velocities | custom_msg | rtde_msgs/JointVelocity | ||
target_qdd |
VECTOR6D |
Target joint accelerations | custom_msg | rtde_msgs/JointAccelerations | ||
target_current |
VECTOR6D |
Target joint currents | custom_msg | rtde_msgs/JointCurrents | ||
target_moment |
VECTOR6D |
Target joint moments (torques) | custom_msg | rtde_msgs/JointTorques | ||
actual_q |
VECTOR6D |
Actual joint positions | custom_msg | rtde_msgs/JointPosition | ||
actual_qd |
VECTOR6D |
Actual joint velocities | custom_msg | rtde_msgs/JointVelocity | ||
actual_current |
VECTOR6D |
Actual joint currents | custom_msg | rtde_msgs/JointAccelerations | ||
joint_control_output |
VECTOR6D |
Joint control currents | custom_msg | rtde_msgs/JointCurrents | ||
actual_TCP_pose |
VECTOR6D |
Actual Cartesian coordinates of the tool: (x,y,z,rx,ry,rz), where rx, ry and rz is a rotation vector representation of the tool orientation | geometry_msgs/Pose | |||
actual_TCP_speed |
VECTOR6D |
Actual speed of the tool given in Cartesian coordinates | geometry_msgs/Twist | |||
actual_TCP_force |
VECTOR6D |
Generalized forces in the TCP | geometry_msgs/Wrench | Already published through ROS Control | ||
target_TCP_pose |
VECTOR6D |
Target Cartesian coordinates of the tool: (x,y,z,rx,ry,rz), where rx, ry and rz is a rotation vector representation of the tool orientation | geometry_msgs/Pose | |||
target_TCP_speed |
VECTOR6D |
Target speed of the tool given in Cartesian coordinates | geometry_msgs/Twist | |||
actual_digital_input_bits |
UINT64 |
Current state of the digital inputs. 0-7: Standard, 8-15: Configurable, 16-17: Tool | ur_msgs/IOStates | already published | ||
joint_temperatures |
VECTOR6D |
Temperature of each joint in degrees Celsius | custom_msg | rtde_msgs/JointTemperatures | Use sensor_msgs/Temperature as underlying type | |
actual_execution_time |
DOUBLE |
Controller real-time thread execution time | std_msgs/Time | |||
robot_mode |
INT32 |
Robot mode Please see Remote Control Via TCP/IP - 16496 | ur_dashboards_msgs/RobotMode | -> Should be moved to ur_msgs | ||
joint_mode |
VECTOR6INT32 |
Joint control modes Please see Remote Control Via TCP/IP - 16496 | custom_msg | -> should be established inside ur_msgs | ||
safety_mode |
INT32 |
Safety mode Please see Remote Control Via TCP/IP - 16496 | ur_dashboard_msgs/SafetyMode | -> Should be moved to ur_msgs | ||
safety_status |
INT32 |
Safety ststus | 3.10.0/5.4.0 | custom_msg | -> should be established inside ur_msgs | |
actual_tool_accelerometer |
VECTOR3D |
Tool x, y and z accelerometer values | geometry_msgs/Vector3 | |||
speed_scaling |
DOUBLE |
Speed scaling of the trajectory limiter | std_msgs/Float64 | |||
target_speed_fraction |
DOUBLE |
Target speed fraction | std_msgs/Float64 | |||
actual_momentum |
DOUBLE |
Norm of Cartesian linear momentum | std_msgs/Float64 | |||
actual_main_voltage |
DOUBLE |
Safety Control Board: Main voltage | std_msgs/Float64 | |||
actual_robot_voltage |
DOUBLE |
Safety Control Board: Robot voltage (48V) | std_msgs/Float64 | |||
actual_robot_current |
DOUBLE |
Safety Control Board: Robot current | std_msgs/Float64 | |||
actual_joint_voltage |
VECTOR6D |
Actual joint voltages | custom_msg | rtde_msgs/JointVoltages | ||
actual_digital_output_bits |
UINT64 |
Current state of the digital outputs. 0-7: Standard, 8-15: Configurable, 16-17: Tool | ur_msgs/IOStates | already published | ||
runtime_state |
UINT32 |
Program state | custom_msg | -> should be established inside ur_msgs | ||
elbow_position |
VECTOR3D |
Position of robot elbow in Cartesian Base Coordinates | 3.5.0/5.0.0 | geometry_msgs/Vector3 | ||
elbow_velocity |
VECTOR3D |
Velocity of robot elbow in Cartesian Base Coordinates | 3.5.0/5.0.0 | geometry_msgs/Vector3 | ||
robot_status_bits |
UINT32 |
Bits 0-3: Is power on | Is program running | Is teach button pressed | Is power button pressed | custom_msg | -> should be established inside ur_msgs | ||
safety_status_bits |
UINT32 |
Bits 0-10: Is normal mode | Is reduced mode | | Is protective stopped | Is recovery mode | Is safeguard stopped | Is system emergency stopped | Is robot emergency stopped | Is emergency stopped | Is violation | Is fault | Is stopped due to safety | custom_msg | -> should be established inside ur_msgs | ||
analog_io_types |
UINT32 |
Bits 0-3: analog input 0 | analog input 1 | analog output 0 | analog output 1, {0=current[A], 1=voltage[V]} | ur_msgs/IOStates | already published | ||
standard_analog_input0 |
DOUBLE |
Standard analog input 0 [A or V] | ur_msgs/IOStates | already published | ||
standard_analog_input1 |
DOUBLE |
Standard analog input 1 [A or V] | ur_msgs/IOStates | already published | ||
standard_analog_output0 |
DOUBLE |
Standard analog output 0 [A or V] | ur_msgs/IOStates | already published | ||
standard_analog_output1 |
DOUBLE |
Standard analog output 1 [A or V] | ur_msgs/IOStates | already published | ||
io_current |
DOUBLE |
I/O current [A] | std_msgs/Float64 | |||
euromap67_input_bits |
UINT32 |
Euromap67 input bits | custom_msg | Array of ur_msgs/Digital | Not optimal but merging these into one common message would break the name?factory?msg pipeline | |
euromap67_output_bits |
UINT32 |
Euromap67 output bits | custom_msg | Array of ur_msgs/Digital | ||
euromap67_24V_voltage |
DOUBLE |
Euromap 24V voltage [V] | std_msgs/Float64 | |||
euromap67_24V_current |
DOUBLE |
Euromap 24V current [A] | std_msgs/Float64 | |||
tool_mode |
UINT32 |
Tool mode Please see Remote Control Via TCP/IP - 16496 | ur_msgs/ToolData | already published | ||
tool_analog_input_types |
UINT32 |
Output domain {0=current[A], 1=voltage[V]} Bits 0-1: tool_analog_input_0 | tool_analog_input_1 | ur_msgs/ToolData | already published | ||
tool_analog_input0 |
DOUBLE |
Tool analog input 0 [A or V] | ur_msgs/ToolData | already published | ||
tool_analog_input1 |
DOUBLE |
Tool analog input 1 [A or V] | ur_msgs/ToolData | already published | ||
tool_output_voltage |
INT32 |
Tool output voltage [V] | ur_msgs/ToolData | already published | ||
tool_output_current |
DOUBLE |
Tool current [A] | ur_msgs/ToolData | already published | ||
tool_temperature |
DOUBLE |
Tool temperature in degrees Celsius | ur_msgs/ToolData | already published | ||
tcp_force_scalar |
DOUBLE |
TCP force scalar [N] | std_msgs/Float64 | |||
output_bit_registers0_to_31 |
UINT32 |
General purpose bits | custom_msg | Array of ur_msgs/Digital | Not optimal but merging these into one common message would break the name?factory?msg pipeline | |
output_bit_registers32_to_63 |
UINT32 |
General purpose bits | custom_msg | Array of ur_msgs/Digital | ||
output_bit_register_X |
BOOL |
64 general purpose bits X: [64..127] - The upper range of the boolean output registers can be used by external RTDE clients (i.e URCAPS). | 3.9.0 / 5.3.0 | std_msgs/Bool | ||
output_int_register_X |
INT32 |
48 general purpose integer registers X: [0..23] - The lower range of the integer output registers is reserved for FieldBus/PLC interface usage. X: [24..47] - The upper range of the integer output registers can be used by external RTDE clients (i.e URCAPS). | [0..23] 3.4.0 [24..47] 3.9.0 / 5.3.0 | std_msgs/Int32 | ||
output_double_register_X |
DOUBLE |
48 general purpose double registers X: [0..23] - The lower range of the double output registers is reserved for FieldBus/PLC interface usage. X: [24..47] - The upper range of the double output registers can be used by external RTDE clients (i.e URCAPS). | [0..23] 3.4.0 [24..47] 3.9.0 / 5.3.0 | std_msgs/Float64 | ||
input_bit_registers0_to_31 |
UINT32 |
General purpose bits This range of the boolean output registers is reserved for FieldBus/PLC interface usage. | 3.4.0 | custom_msg | Array of ur_msgs/Digital | Not optimal but merging these into one common message would break the name?factory?msg pipeline |
input_bit_registers32_to_63 |
UINT32 |
General purpose bits This range of the boolean output registers is reserved for FieldBus/PLC interface usage. | 3.4.0 | custom_msg | Array of ur_msgs/Digital | |
input_bit_register_x |
BOOL |
64 general purpose bits X: [64..127] - The upper range of the boolean output registers can be used by external RTDE clients (i.e URCAPS). | 3.9.0 / 5.3.0 | std_msgs/Bool | ||
input_int_register_x[0 .. 48] |
INT32 |
48 general purpose integer registers X: [0..23] - The lower range of the integer input registers is reserved for FieldBus/PLC interface usage. X: [24..47] - The upper range of the integer input registers can be used by external RTDE clients (i.e URCAPS). | [0..23] 3.4.0 [24..47] 3.9.0 / 5.3.0 | std_msgs/Int32 | ||
input_double_register_x[0 .. 48] |
DOUBLE |
48 general purpose double registers X: [0..23] - The lower range of the double input registers is reserved for FieldBus/PLC interface usage. X: [24..47] - The upper range of the double input registers can be used by external RTDE clients (i.e URCAPS). | [0..23] 3.4.0 [24..47] 3.9.0 / 5.3.0 | std_msgs/Float64 | ||
tool_output_mode |
UINT8 |
The current output mode | 5.2.0 | custom_msg | -> should be established inside ur_msgs | |
tool_digital_output0_mode |
UINT8 |
The current mode of digital output 0 | 5.2.0 | custom_msg | -> should be established inside ur_msgs | |
tool_digital_output1_mode |
UINT8 |
The current mode of digital output 1 | 5.2.0 | custom_msg | -> should be established inside ur_msgs | |
input_bit_registers0_to_31 |
UINT32 |
General purpose bits (input read back) | 3.4.0 | custom_msg | Array of ur_msgs/Digital | Not optimal but merging these into one common message would break the name?factory?msg pipeline |
input_bit_registers32_to_63 |
UINT32 |
General purpose bits (input read back) | 3.4.0 | custom_msg | Array of ur_msgs/Digital | |
input_int_register_X |
INT32 |
24 general purpose integer registers (input read back) X: [0..23] | 3.4.0 | custom_msg | Array of ur_msgs/Digital | |
input_double_register_X |
DOUBLE |
24 general purpose double registers (input read back) X: [0..23] | custom_msg | double |
Some first comments:
- publish fields like
target_q,target_qdandtarget_momentin asensor_msgs/JointStateon atarget_joint_statestopic (similar to ros-industrial/ur_modern_driver#341) - same for
actualfields - the
qddandcurrentwould require a custom message unfortunately. - it might be nice to general the "target" fields to all be published inside a
targetnamespace - all
Posepublishers could also be published as TF frames instead. That would make using the data for transforms easier (see also ros-controls/ros_control#372) - re:
joint_temperatures:ur_modern_driveralso publishes these, but uses plainsensor_msgs/Temperature(fixed in ros-industrial/ur_modern_driver#320). RViz can renderTemperaturemessages in-situ if a valid TF frame is set forframe_idin theHeader. Perhaps not using a custom message here would be better. - re:
actual_execution_time: is this not more of a period? I haven't checked the documentation, but if it is, a std_msgs/Duration may be better. An actual "time" time may be published using sensor_msgs/TimeReference. - re:
output_bit_registers0_to_31: not sure I would publish those as arrays ofur_msgs/Digital. That is going to be a lot of elements in that array. Perhaps leaving them asuint32fields? Or auint32[]?
Thank you for your input.
Some first comments:
- publish fields like
target_q,target_qdandtarget_momentin asensor_msgs/JointStateon atarget_joint_statestopic (similar to ros-industrial/ur_modern_driver#341)
From our point of view, this goes against the idea of this PR which is providing an easy interface to request single RTDE fields. Requesting one of the above will require requesting all the others, as well.
- same for
actualfields
The actual fields are already published through the joint_state controller and are thereby planned to be excluded from separate publishing.
- the
qddandcurrentwould require a custom message unfortunately.
Yes, as we suggested. But I guess that comment was mainly referring to 1. and 2.
- it might be nice to general the "target" fields to all be published inside a
targetnamespace
Same reasoning as 1.
- all
Posepublishers could also be published as TF frames instead. That would make using the data for transforms easier (see also ros-controls/ros_control#372)
Yes, we could easily publish TF frames, as well. However, I also like the idea of putting this into a separate ros controller...
- re:
joint_temperatures:ur_modern_driveralso publishes these, but uses plainsensor_msgs/Temperature(fixed in ros-industrial/ur_modern_driver#320). RViz can renderTemperaturemessages in-situ if a valid TF frame is set forframe_idin theHeader. Perhaps not using a custom message here would be better.
I agree, that would be a better solution.
- re:
actual_execution_time: is this not more of a period? I haven't checked the documentation, but if it is, a std_msgs/Duration may be better. An actual "time" time may be published using sensor_msgs/TimeReference.
Both suggestions sound superior. We'll do some more investigation and pick the appropriate one from those.
- re:
output_bit_registers0_to_31: not sure I would publish those as arrays ofur_msgs/Digital. That is going to be a lot of elements in that array. Perhaps leaving them asuint32fields? Or auint32[]?
Not sure, if I understand that correctly. Why would there be a lot of elements? It should be exactly 32. Publishing a plain uint32 seems a bit against the statement from https://github.com/UniversalRobots/Universal_Robots_ROS_Driver/pull/35#issuecomment-553805534, right? Using a uint32[] message also seems a bit counter-intuitive to me, as there are actually boolean values being represented. We could also go for a bool[] message.
Initial rework towards new structure/message types is done, should be critically looked over though - some questions about specific data fields remain and I have added them as comments directly in the code.
A side question: Is this PR related to #67? Are all RTDE field hard wired to some robot parameters? Or can the ur programmer set/modify RTDE values (i.e. in the programming or installation tab) of some fields?
There is a typo in data_field_publisher.cpp (target_movement should be target_moment).
Hi,
- I am missing timestamps in the "data" Topics, e.g. if I get temperatures or Joint angles. I have found the seperate Topic "timestamps" but this does not help. I think the discussion About Heritage from Standard message-types is started and I want only to say that I think it is important to use Standard types to make the timestamps available. My collegue has written a patch for that that I am just testing.
- Is it possible to get the correct timestamps from the UR? It Looks that the data is read without timestamps from the UR. This is really a pity.
best regards Oliver
Hi,
- I am missing timestamps in the "data" Topics, e.g. if I get temperatures or Joint angles. I have found the seperate Topic "timestamps" but this does not help. I think the discussion About Heritage from Standard message-types is started and I want only to say that I think it is important to use Standard types to make the timestamps available. My collegue has written a patch for that that I am just testing.
- Is it possible to get the correct timestamps from the UR? It Looks that the data is read without timestamps from the UR. This is really a pity.
best regards Oliver
This issue is exactly the (main) reason why this isn't merged, yet.
Is this still under development? We want to have the actual TCP position data and this PR seems to be what we want.
I am just reading the TCP via the topic /ur_hardware_interface/rtde_data/target_TCP_pose. I get a standard messagetype with the position vector and the quaternion describing the orientation. This works fine. But there is no timestamp available. I also tried to change the sample rate without luck. Only streaming with 500Hz works for me.
Is this still under development? We want to have the actual TCP position data and this PR seems to be what we want.
The actual TCP pose is already available inside the tf system as as tool0_controller.
And yes, this is still on my ToDo-List, it just always gets too much over-prioritized :-(
Hello everyone and thank you for your contribution. I am new in ROS and currently involved in a project with an UR3e. I have couple of questions I would be super grateful if you´d help me clarify:
-
I would like to know, after installing this branch of the package, How do the RTDE variables can be seen/printed and what are the specific names of the topics to which these variables are being sent or saved to?
-
Also, I would like to know how does this differ from: https://github.com/t-schnell/Universal_Robots_ROS_Driver/blob/master/ur_robot_driver/resources/rtde_output_recipe.txt And how would it be possible to print or access the RTDE information stated in this last .txt?
Thanks so much in advance for your time and help!
Hello everyone and thank you for your contribution. I am new in ROS and currently involved in a project with an UR3e. I have couple of questions I would be super grateful if you´d help me clarify:
- I would like to know, after installing this branch of the package, How do the RTDE variables can be seen/printed and what are the specific names of the topics to which these variables are being sent or saved to?
- Also, I would like to know how does this differ from: https://github.com/t-schnell/Universal_Robots_ROS_Driver/blob/master/ur_robot_driver/resources/rtde_output_recipe.txt And how would it be possible to print or access the RTDE information stated in this last .txt?
Thanks so much in advance for your time and help!
When using this branch adding variables to rtde_output_recipe.txt will automatically publish this data on rtde_data/<variable_name>.
Hello everyone and thank you for your contribution. I am new in ROS and currently involved in a project with an UR3e. I have couple of questions I would be super grateful if you´d help me clarify:
- I would like to know, after installing this branch of the package, How do the RTDE variables can be seen/printed and what are the specific names of the topics to which these variables are being sent or saved to?
- Also, I would like to know how does this differ from: https://github.com/t-schnell/Universal_Robots_ROS_Driver/blob/master/ur_robot_driver/resources/rtde_output_recipe.txt And how would it be possible to print or access the RTDE information stated in this last .txt?
Thanks so much in advance for your time and help!
When using this branch adding variables to
rtde_output_recipe.txtwill automatically publish this data onrtde_data/<variable_name>.
@fmauch Thank you so much for your response. What about the variables that are already specified in rtde_output_recipe.txt inside the official package, Can I access to them somehow (either through topics or by printing them in the terminal) without using this branch? Thanks again!
@RisMmi Most data is available through running controllers. You can try running rosnode info /ur_hardware_interface to see all topics published by the driver.
This PR hasn't made any progress for quite some time and will be closed soon. Please comment if it is still relevant.