-
Notifications
You must be signed in to change notification settings - Fork 402
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adding reset revolution counter service (#325) #343
base: master
Are you sure you want to change the base?
Conversation
Reset the revolution counter of the robot's wrist_3_link
First of all, thanks for the PR! Given your description the script function is indeed able to be run in a secondary function which would definitely be a good approach. The problem is that the hardware interface sends the current joint command to the robot each control cycle. If that joint happens to be a full revolution off the current command, it will do a full rotation to get to the old configuration. So, in order to prevent this, one could modify the
While the first two problems could probably be mitigated by doing numerous workarounds, the third one would actually remain a problem, but can also be seen as a hint to another possible solution. If we shutdown all controllers actually moving the robot, then reset the counter and then restart the controller that has been running (maybe with a short delay to let the reset command do its job) the system will
The easiest way to achieve this would be to use the already running controller stopper. This could be done by simply publish a message to the However, as a proof of concept, this should work. While the reset is taking place, all "controlling" controllers (All except those) should get stopped temporarily. The |
Thank you for the explanation! I tried the approach that you mentioned, stopping the controllers > sending the script > restarting the controllers. I tested it and it worked. I had to add a delay after sending the script to allow the command to be processed before the controllers were back running. |
OK, great! So now we need to find a way to make this less hacky and prune to errors. My main concern is that this behavior is also controlled by One way around this might be to call this function directly instead of copying the contents and add a mutex to that function. This is necessary, as the service callback will be triggered by the async spinner while the changing program state will be triggered by the Reverse interface watchdog (which runs in a separate thread). Oh, and maybe it's about time to format your code according to the style guidelines :-) We use clang-format in order to to that automatically. I usually use this script to format a complete repo: #!/bin/bash
# This script uses clang-format to format all *.cpp, *.hpp and *.h files recursively
clang_format_exec="clang-format"
find . -name "*.cpp" -exec sh -c "echo 'Formatting {}' && $clang_format_exec -i {}" \;
find . -name "*.hpp" -exec sh -c "echo 'Formatting {}' && $clang_format_exec -i {}" \;
find . -name "*.h" -exec sh -c "echo 'Formatting {}' && $clang_format_exec -i {}" \; |
Thank you for the formatting script! I made the suggested changes, I am not sure if I added the This is the behavior of the function when tested:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
* If the angle of the wrist3 is bigger than 2_PI or less than -2_PI: The wrist3 moves slightly to some position and the revolution counter is reset. Though I am not sure why it moves.
Thanks for that insight, I will try to get it verified
@@ -760,6 +760,10 @@ Setup the mounted payload through a ROS service | |||
|
|||
Calling this service will zero the robot's ftsensor. Note: On e-Series robots this will only work when the robot is in remote-control mode. | |||
|
|||
##### reset_revolution_counter ([std_srvs/Trigger](http://docs.ros.org/api/std_srvs/html/srv/Trigger.html)) | |||
|
|||
Calling this service will reset the revolution counter for the robot's wrist_3_link. Note: On e-Series robots this will only work when the robot is in remote-control mode. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just want to clarify for the future reader that it is only the UR3 that will benefits from this.
Calling this service will reset the revolution counter for the robot's wrist_3_link. Note: On e-Series robots this will only work when the robot is in remote-control mode. | |
The UR3 and UR3e's wrist 3 can do infinite rotations and are therefore not limited to ±2Pi. | |
Calling this service will reset the revolution counter for the robot's wrist_3_link. Note: On e-Series robots this will only work when the robot is in remote-control mode. | |
This is handy to avoid rotating back after e.g. a screwing task, and thereby avoid compensating for this in the program. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might be nice to make this even stronger and have the service fail if the robot is not a UR3.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suppose something like this:
bool HardwareInterface::resetRevolutionCounter(std_srvs::TriggerRequest& req, std_srvs::TriggerResponse& res)
{
if (ur_driver_->getName() == 'UR3e' || ur_driver_->getName() == 'UR3')
{
std::mutex mtx;
handleRobotProgramState(false);
mtx.lock();
res.success = this->ur_driver_->sendScript(R"(sec resetRevolutionCounter():
reset_revolution_counter()
end
)");
mtx.unlock();
handleRobotProgramState(true);
}
else
{
std::stringstream ss;
ss << "Resetting the revolution counter is only available for UR3/e robots. This robot is "
<< ur_driver_->getName();
ROS_ERROR_STREAM(ss.str());
res.message = ss.str();
res.success = false;
}
return true;
}
Though, I don't know where to get the robot's name...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Out of my head I am not sure whether there's something predefined to get the robot model through the API. But that would have been my next point on the list.
Edit: Currently, this is not available through the API. Receiving it through the dashboard client would be a workaround to not further postpone this PR. Alternatively it could be received through the primary interface, but that is currently not implemented.
@gavanderhoorn wrote:
Might be nice to make this even stronger and have the service fail if the robot is not a UR3.
I would even have supposed to advertise it only for UR3(e) robots. But that might be more confusing than simply letting the service fail...
@cambel Just to make sure: Is this independent of using with the ROS driver? |
I am not sure. I've only tested it using the ROS driver. |
Okay, I did some more tests. Using the URScript function Edit: The revolution counter is reset when the wrist3 angle is outside the range [0, 2_PI] The slight motion that I have been observing may be due to the slight delay added to the function The problem is as @fmauch explained above, about the timing of the threads. I tried to implement the I'd appreciate some guidance on this part. |
I'd like to nail things down to the actual problem: Could you add sleeps (as in 1 sec) before [exclusive] or after calling the URScript function? Is the problem that the controllers aren't going down fast enough or coming up too early? The problem with our current setup is that we have a (kind of hacky) fire-and-forget interface to stopping & starting the controllers. If we can nail down the problem, we can think of a more proper solution. |
@fmauch I will do more tests to try to understand how the driver is trying to execute the stopping & starting the controllers. However, last time I did already try adding sleep of 1 second before/after calling the URScript, the result was the spin behavior I mentioned in the first commend of this thread. I even try only stopping the controller and then executing the URScript, but it goes back to working sometimes only when the functions sync properly I guess. After that, the controllers were running again without explicitly starting them again. |
Maybe the best solution to do this is to subtract an angle offset in the driver, instead of trying to make a async. call sync. Or add it to the sync protocol. |
This PR hasn't made any progress for quite some time and will be closed soon. Please comment if it is still relevant. |
Hi,
I am trying to implement the service to reset the revolution counter of the robot's wrist_3_link. However, I am having a problem with the behavior of the script.
If I send the script as a secondary program:
It does not work as intended, the wrist_3_link gives a full rotation at full speed, which is not desirable at all, but on top of that, the counter is not reset.
On the other hand, if I send the script just as:
It does work as intended with the caveat that the driver's program is stopped and has to be reconnected in order to send any new command.
I think that the best solution would be to be able to reset the counter without disconnecting the main driver's program. Similarly to the behavior of the
zero_ftsensor
service.I would appreciate any suggestions on what I may be doing wrong.