Skip to content
This repository has been archived by the owner on Jan 16, 2019. It is now read-only.

Publish industrial_msgs::RobotStatus #5

Merged
merged 4 commits into from
Jan 2, 2018
Merged

Publish industrial_msgs::RobotStatus #5

merged 4 commits into from
Jan 2, 2018

Conversation

simonschmeisser
Copy link

This adds a publisher for industrial_msgs::RobotStatus

the mapping is not quite unique and might need to be discussed some more. Especially protective_stopped is currently mapped to in_error. There are probably other error states that should lead to in_error as well and be assigned an unique error_code. @gavanderhoorn Do we have a generic list of such error_codes somewhere or are these "vendor specific" and if so where would I place an enum/message description?

the mapping is not quite simple and might need to be discussed some more
@gavanderhoorn
Copy link
Collaborator

Is this a forward-port of ros-industrial-attic#143?

@simonschmeisser
Copy link
Author

more of a rewrite as the code changed significantly, but yes I meant to reference that PR

@gavanderhoorn
Copy link
Collaborator

gavanderhoorn commented Nov 15, 2017

@simonschmeisser wrote:

Do we have a generic list of such error_codes somewhere or are these "vendor specific" and if so where would I place an enum/message description?

The message docs say this:

Error code: Vendor specific error code (non zero indicates error)

For UR we could maybe see whether we could use some of the status codes that are sometimes printed in the log (on the TP) for certain events. But I wouldn't know where to find those.

@gavanderhoorn
Copy link
Collaborator

@simonschmeisser wrote:

more of a rewrite as the code changed significantly, but yes I meant to reference that PR

ok. Well that PR includes some more logic for when in_error should be set. Did you not include that on purpose?

@simonschmeisser
Copy link
Author

I couldn't really follow that logic, so yes, I did not copy that on purpose.

msg.e_stopped.val = data.emergency_stopped;
msg.in_motion.val = data.program_running;
msg.in_error.val = data.protective_stopped;
msg.motion_possible.val = (robot_mode_V3_X::RUNNING == data.robot_mode) ? industrial_msgs::TriState::ON : industrial_msgs::TriState::OFF;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpicking but data.robot_mode == robot_mode_V3_X::RUNNING (reverse ordering) is probably preferred as this is the style used elsewhere.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah, yes, sorry, I was experimenting if I could get this away:

ur_modern_driver/src/ros/mb_publisher.cpp:41: Warnung: enumeral mismatch in conditional expression: ‘industrial_msgs::TriState_<std::allocator<void> >::<anonymous enum>’ vs ‘industrial_msgs::TriState_<std::allocator<void> >::<anonymous enum>’ [-Wenum-compare]
  msg.motion_possible.val = (data.robot_mode == robot_mode_V3_X::RUNNING) ? industrial_msgs::TriState::ON : industrial_msgs::TriState::OFF;
                                                                       ^

@Zagitta
Copy link
Owner

Zagitta commented Nov 15, 2017

Thank you very much for the PR @simonschmeisser, looks very good to me, my only comment is the above nitpick and I'd be more than happy to merge your contribution 😄


msg.drives_powered.val = data.robot_power_on;
msg.e_stopped.val = data.emergency_stopped;
msg.in_motion.val = data.program_running;
Copy link
Collaborator

@gavanderhoorn gavanderhoorn Nov 15, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't believe in_motion is the same as program_running, is it?

Not sure whether there is a way to determine the robot is in motion without a program, or whether that is even possible actually.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can secondary programs contain motion commands? And do they then update program_running?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is if but not iff, ie there will always be a program running when it moves but having a program running does not signify that it will actually move. At least that's my understanding

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok. But then this expression doesn't currently accurately encode the state of the robot, right?

It could be executing a program without any motion?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

industrial_msgs::TriState::Unknown then?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we don't use this field except for decorative purposes, so I don't care from a consumer point of view

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we don't use this field except for decorative purposes, so I don't care from a consumer point of view

That's great, but if we add this (RobotStatus) it should accurately encode the status of the robot.

If we can't derive something from what the robot provides us, then yes, I believe using TriState::Unknown for now would be better.

msg.drives_powered.val = data.robot_power_on;
msg.e_stopped.val = data.emergency_stopped;
msg.in_motion.val = data.program_running;
msg.in_error.val = data.protective_stopped;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is protective_stopped high for all errors that can occur?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there does not seem to be another way to be informed about errors looking at the format in robot_mode.h

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about emergency_stopped? That would definitely be an 'in_error' situation, but that's not captured here at the moment. ros-industrial-attic#143 makes in_error the union of protective_stopped and emergency_stopped.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah okay, I thought of e-stopped more like a state and the error would appear separately once you try moving despite it being in e-stopped mode. But I can change it to said union. This would again ask for a place to define the "vendor specific" error codes and then setting error_code to differentiate protective_stopped

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Vendor specific" means that the error codes are defined by the vendor. Not by us, for every vendor.

This field is typically populated by copying the error code that the robot controller gives you for different errors. On Fanucs fi you would be copying the code returned by the ERR_DATA(..) Karel function (which is typically a 5 or 6 digit number).

Those codes are defined by Fanuc. We don't make them up ourselves.

UR has similar codes I believe (just take a look at the log on the TP), but I'm not sure we can retrieve those from somewhere.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought of e-stopped more like a state and the error would appear separately once you try moving despite it being in e-stopped mode.

That could definitely be a way to implement it, but we would need a way to reliably determine which of the two it is. I don't have a scripting manual with me right now, but if there is a get_last_error_code() function that we can use, then we can definitely do what you propose.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're correct. e_stopped is the state, and in_error should follow from whether the robot controller defines this as an error.

Let's keep what you have for now.

Sorry for the noise.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

re: vendor specific codes: looking at a UR we have here I keep seeing C100A5 in the log whenever the robot is Robot changed mode: EMERGENCY STOPPED.

Those are the codes that would go into error_code.

void MBPublisher::publishRobotStatus(SharedRobotModeData& data)
{
industrial_msgs::RobotStatus msg;
msg.drives_powered.val = data.robot_power_on;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can robot_power_on ever be true if real_robot_enabled is false? Perhaps in ur-sim?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

testing with ursim I get the following output in Poly:
0000d05h41m35.184s RobotInterface C102A0: Real Robot not connected - Simulating Robot

meanwhile the robot mode contains the following data:

when I turn off the robot:
robot_power_on: 0 physical robot: 0 real_robot: 1 mode: 3 (POWER_OFF)

when I turn on the robot but do not yet release the brakes (ON but not START):
robot_power_on: 1 physical robot: 0 real_robot: 1 mode: 5 (IDLE)

when I release the brakes:
robot_power_on: 1 physical robot: 0 real_robot: 1 mode: 7 (RUNNING)

so I'm not sure what real_robot_enabled is supposed to tell us, maybe there is a way to switch to moving a simulated robot on the actual controller?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so I'm not sure what real_robot_enabled is supposed to tell us, maybe there is a way to switch to moving a simulated robot on the actual controller?

There is a two-option selection bullet list at the bottom right or left (don't remember) that contains those two options. I've never used it, but IIRC you can use it to switch to a virtual robot.

Copy link
Collaborator

@gavanderhoorn gavanderhoorn Nov 15, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The difference between IDLE and RUNNING may indicate that RUNNING would be better indicator of drives_powered?

Edit: hm, no. That makes no sense.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, found that (for the reference: it is in 'Program Robot' -> 'Move' or 'I/O' but I can only change it to simulated in IO), real_robot_enabled then does turn to false. But this doesn't map to any of the industrial_msgs::RobotStatus fields does it?

Copy link
Author

@simonschmeisser simonschmeisser Nov 15, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

# Drive power status: True if drives are powered.  Motion commands will 
# automatically enable the drives if required.  Drive power is not requred
# for possible motion
industrial_msgs/TriState drives_powered

So yes, maybe drives powered should be obtained from Mode == RUNNING as in that halfway on mode (breakes still on) it does not automatically start moving. But then drives_powered would be the same as motion_possible. And as far as I understand motion_possible is authorative?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think drives_powered should reflect the status of the drives (ie: robot_power_on.

RUNNING could then be used in the predicate for motion_possible (ie: mode != RUNNING -> motion_possible = false.

@gavanderhoorn
Copy link
Collaborator

I think if you can add some comments (fi, why in_motion is Unknown at the moment), this would be ok to merge.

this allows to extract motion_possible and mode as well

added comments for everything non obvious or disputable
@simonschmeisser
Copy link
Author

Switching to using either version 1 or 3 of the data package instead of using the default type allows publishing some more info. I also commented everything and added const correctness.

@simonschmeisser
Copy link
Author

@Zagitta @gavanderhoorn anything else you would like me to modify?

@Zagitta
Copy link
Owner

Zagitta commented Nov 23, 2017

It looks good to me but since I'm not really involved in anything related to UR anymore I'll let @gavanderhoorn have the final say 😃


public:
MBPublisher() : io_pub_(nh_.advertise<ur_msgs::IOStates>("ur_driver/io_states", 1))
, status_pub_(nh_.advertise<industrial_msgs::RobotStatus>("robot_status", 1))
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this perhaps be published at "ur_driver/robot_status"?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could, but that would make it non-compliant with other ros-i robot drivers.

A remap can fix that though.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alright yes that makes perfect sense, let's keep it as it is here then.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well .. let's actually not.

All topics for the ur_driver are below a ur_driver namespace already, so having this one outside it breaks that.

If/when we need to make this driver ros-i compliant, we can either blanketly remap everything or update the topics.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So I'll add the prefix for consistencies sake?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe that makes the most sense for now, yes.

Otherwise users would find all topics of the driver under the ur_driver namespace, but a lone (and seemingly unrelated) /robot_status topic in the global one.

@gavanderhoorn
Copy link
Collaborator

I would be ok with merging this. My only question would be whether the duplication between publishRobotStatus(const RobotModeData_V1_X&) and publishRobotStatus(const RobotModeData_V3_0__1&) is needed.

@simonschmeisser: would it make sense to introduce a separate function that sets up and publishes the message that gets called from those two callbacks?

@simonschmeisser
Copy link
Author

@gavanderhoorn yes, I can add a generic publishRobotStatus(industrial_msgs::RobotStatus) that gets called after setting the version-specific fields. Will do so later

@gavanderhoorn
Copy link
Collaborator

If the version-specific fields are just regular primitive types, you could potentially create a publishRobotStatus(int robot_mode, .. etc) that gets called.

@Zagitta
Copy link
Owner

Zagitta commented Dec 8, 2017

I suggest following the approach here to keep things consistent 😃

@simonschmeisser
Copy link
Author

@gavanderhoorn @Zagitta are you fine with the current state or should I change anything else?

@Zagitta Zagitta merged commit 24eef75 into Zagitta:master Jan 2, 2018
@Zagitta
Copy link
Owner

Zagitta commented Jan 2, 2018

Thank you very much for your contribution 🎉

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants