-
Notifications
You must be signed in to change notification settings - Fork 223
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
eki_hw_interface: An EKI-based hardware interface. #110
eki_hw_interface: An EKI-based hardware interface. #110
Conversation
Unfortunately I have no way of testing this, as I don't have any hw that has this interface. My first question would be: any guestimate as to what sort of performance we can expect from this? You mention that you believe it will/might not be full performance, but can you put any nrs on it? I can imagine that it would be quite important to get a feeling for any performance differences when trying to use this for continuous processes that require specifiek (EEF) velocities fi. |
@durovsky @simonschmeisser and @ivareri, you might also be interested in this. |
thanks for the hint @gavanderhoorn Unfortunately we currently don't have access to any kuka and they were not cooperative wrt licencing a simulation |
I plan to measure this. The robot I want to use is getting moved, so probably next week or the week after. A single sent point via the interface (i.e., not using the That said, the performance should be better than any of the
Indeed. The data will help understand what people are getting. A trajectory downloading version/mode would also be a relatively easy extension. I am also entertaining the idea of a hybrid extension that can take streamed trajectories but also invoke internal KRL commands (similar to sending ur_script commands via socket) when necessary/desirable. This would get you nice reactionary MoveIt/ |
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.
Thanks for the PR 👍. This is a welcome addition to this repository.
I added a lot of comments, but I was just commenting on everything I saw, so don't take it as there being many things that need changes.
The RSI hw iface could use some TLC, so I also looked for things that we could avoid with the EKI iface in this PR.
kuka_eki_hw_interface/CMakeLists.txt
Outdated
cmake_minimum_required(VERSION 2.8.3) | ||
project(kuka_eki_hw_interface) | ||
|
||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") |
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.
We should probably use add_compile_options(-std=c++11)
here instead.
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.
Agreed; copypasta from the rsi_hw_interface...
/* | ||
* Software License Agreement (BSD License) | ||
* | ||
* Copyright (c) 2018, Brett Hemes (3M) |
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.
You probably already checked, but is the copyright yours, or 3M's?
You're always the author of course.
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.
Interesting 😄 3M didn't catch this but yes, this should be changed
{ | ||
|
||
private: | ||
|
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.
empty line seems redundant (same on line 56)
~KukaEkiHardwareInterface(); | ||
|
||
void start(); | ||
void configure(); |
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.
There is a RobotHW::init(..)
in kinetic-devel
. Wondering if we can somehow already start using that, to facilitate porting later on (although introducing our own init()
here will shadow the one in RobotHW
under Kinetic).
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.
Can you elaborate here?
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.
The kinetic-devel
version of RobotHW
in ros_control
defines an init(..)
method that should be used to perform any initialisation actions the hw iface may need. As there was nothing in Indigo, we have a custom configure()
.
I was wondering whether it would be an idea to instead of keeping our configure()
, start using init(..)
already, so when we migrate to kinetic-devel
of ros_control
with this repository we are already up-to-date.
void start(); | ||
void configure(); | ||
bool read(const ros::Time time, const ros::Duration period); | ||
bool write(const ros::Time time, const ros::Duration period); |
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.
Can we make these references?
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 was going to originally but the rsi_hw_interface and Adolfo's examples are by value so I did the same.
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.
Do you mean Dave's boilerplate? His code does use references.
Upstream kinetic-devel
also has read(..)
and write(..)
and those also use references (here). I cannot really come up with a reason not to use them here tbh.
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 guess I was looking at some old wiki examples? I don't remember. Maybe here: https://github.com/ros-controls/ros_control/wiki/joint_limits_interface
Aside, but I also have a bad habit of not always realizing I am on an older distributions API documentation page 🙄
By reference is the right answer here. Thanks for the links.
TiXmlDocument xml_out; | ||
TiXmlElement* robot_command = new TiXmlElement("RobotCommand"); | ||
TiXmlText* empty_text = new TiXmlText(""); | ||
robot_command->LinkEndChild(empty_text); // force <RobotCommand></RobotCommand> format (vs <RobotCommand />) |
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.
The construction of this XML document seems to be always the same. Would it make sense to move that to either the ctor or some other initialisation method and store xml_out
(maybe member variable)?
Same for TiXmlPrinter
below.
{ | ||
ROS_INFO_NAMED("kuka_eki_hw_interface", "Starting Kuka EKI hardware interface..."); | ||
// TODO(BrettHemes): Error handling? | ||
// TODO(BrettHemes): Do these block? Look into implementing non-blocking receives |
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.
See earlier comment about TODO
s.
command_server_port_}); | ||
|
||
// Initialize joint_position_command_ from initial robot state (avoid bad (null) commands before controllers come up) | ||
while (!socket_read_state(joint_position_command_)); |
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 don't know whether it can happen, but perhaps we should add some timeout or maximum retry mechanism here to avoid infinite waits.
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.
Yeah, I will look into this.
else | ||
{ | ||
ROS_ERROR("Failed to get EKI addresses/ports from parameter server!"); | ||
throw std::runtime_error("Failed to get EKI addresses/ports parameter server."); |
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.
Suggestion: mention which parameters we're looking for here (ref #106).
{ | ||
ros::init(argc, argv, "kuka_eki_hw_interface"); | ||
|
||
ros::AsyncSpinner spinner(1); |
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.
Should this be 2
? I remember several implementations using 2 threads to avoid (ROS event) operations from blocking the control loop (Dave's ros_control_boilerplate
fi (here).
🛎️ ? |
Yes yes! I am still here. I got sick and then was on travel. I will followup this week 😃 |
@gavanderhoorn wonderful comments; thank you very much! There are some that I need a bit more help with please. I have begun addressing the rest and will update the PR as I knock them off. |
I've replied to some of your questions @BrettHemes. Thanks for taking care of my comments. |
kuka_eki_hw_interface/CMakeLists.txt
Outdated
@@ -9,6 +9,7 @@ find_package(catkin REQUIRED COMPONENTS | |||
hardware_interface | |||
joint_limits_interface | |||
roscpp | |||
angles |
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.
Could you move angles
to the top? Let's keep these COMPONENTS
sorted alphabetically.
kuka_eki_hw_interface/CMakeLists.txt
Outdated
@@ -25,6 +26,7 @@ catkin_package( | |||
hardware_interface | |||
joint_limits_interface | |||
roscpp | |||
angles |
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.
Same here.
kuka_eki_hw_interface/package.xml
Outdated
@@ -20,4 +20,5 @@ | |||
<depend>hardware_interface</depend> | |||
<depend>joint_limits_interface</depend> | |||
<depend>roscpp</depend> | |||
<depend>angles</depend> |
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.
Sorting here again.
And angles
is a header only library, so no need to make it a depend
.
9fea295
to
2eb02d9
Compare
603ef7d
to
0e21dc8
Compare
08e6f79
to
93f6eb2
Compare
Note: velocty and effort value population in the krl interrupt currently disabled due to it inducing stuttering. Interrupt service needs to be shorter... could re-add possibly after some optimization and further testing...
OK I think I got most of @gavanderhoorn's suggestions addressed and the code is all the better for it. Some things I did not fix / remaining nuances:
@gavanderhoorn Would you mind giving the code another once over at this point? |
@BrettHemes wrote:
Repeated construction of these TinyXML objects probably does not incur a very large overhead. Let's leave this as it is for now.
hm, unfortunate. But as you say: let's save this for a later PR.
Other than "holy ****"? :) Minor suggestion: we could make this time-out perhaps configurable using a ROS parameter.
Ok. It sounds like this is sufficiently covered then. |
@gavanderhoorn OK, what are your thoughts? I added the ability to set the socket read timeout via parameter and I think we are getting close to being mergable. Also, extrapolating from previous discussions, I assume all of the tweaks since the original PR should get squashed into the "initial commit" commit when it comes time to merge? Am I correct here? |
@BrettHemes wrote:
yes, I think this is quite ok like this. re: merge: I was hoping to get some time on an Agilus with EKI (which we apparently have) to test this out on real hw. Not that I don't trust you, but I just like to do that. That appears more difficult than I anticipated, so it doesn't make sense to hold off merging.
Yes, I typically like to do that, unless you absolutely want to keep the history of those changes. As they are all fixups though, I never really see the value. In a way, the end result is what the PR "should ideally have been". |
What time frame are you looking at? A second hw test would be nice...
Agreed |
@BrettHemes wrote:
I've just sent the lab with the agilus with EKI an email. If I don't get a response early next week, I'll merge without testing myself. |
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.
Robot is too busy, and I don't want to hold this up too long. It's been quite some time already.
Thanks for the contribution @BrettHemes, this is a very nice addition to this repository.
👍 🍔 🍻
An EKI-based Kuka driver targeted at use with ros_control. Based off of existing kuka_rsi_hw_interface but with a "soft" real-time Ethernet UDP/IP interface. Streaming happens at ~50 Hz (vs the RSI interface's 250Hz) with all commanded setpoints executed as fast as possible on the KRC. In this configuration, any significant latency from the ROS side simply results in the robot safely decelerating while keeping the server running (i.e., no faults or program stops). 50 Hz streaming from the ROS PC (or really enough to prevent the advanced run from triggering a stop) results in smooth motion and no stutters.
Depending on the displacement of the commanded waypoints, I imagine that full joint speeds will not be reachable due to the 5-step look-ahead limit of the advance run on the controller (further testing and performance graphs planned to confirm this). Despite this, however, I believe that this is totally usable when less-than-maximum performance is required (use RSI in that case...) and will fill the use-case gap identified in #77. In fact the observed performance exceeded my original expectations of the approach. In my limited testing thus far the motion was significantly smooth and correct using MoveIt! RViz generated trajectories (using RRTkConfigDefault) on a real Kuka Agilus robot. Was using ros_control in Ubuntu 16.04 with the default (i.e., non-low-latency) kernel.