I've tried using the servoj() command at 125 Hz back in 2013, but without much success. I had the same issues as you notice in the video. I discussed the issue with Kelsey Hawkins at Roscon 2013, and his development of the C-API version is a result of this.
I would recommend you take a look at a recent technical paper I’ve made with some students of mine called “UR10 Performance Analysis” (http://orbit.dtu.dk/en/publications/ur10-performance-analysis(0deaebd1-1593-4641-a971-e1ac0234ed88).html ) – despite its name, it is applicable to UR 5 and UR 10 alike, as it focuses on the software side. The paper also looks into some network related issues.
In short, I would recommend you use the speedj() command instead – in my experience, it is the only command that works reliably and consistently at 125 hz (except if you have an very old version of the ur5 with the 1st generation of the controller. In that case, no network control works reliably due to a memory leak in the network buffer. But that doesn’t seem to be your problem).
As joint speed control leads to positional drifting it requires that you make a feedback controller if you need accurate positional control, as the speedj command only takes… -well, joint speeds.
Regards
|
--
You received this message because you are subscribed to the Google Groups "swri-ros-pkg-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to
swri-ros-pkg-d...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
I've tried using the servoj() command at 125 Hz back in 2013, but without much success. I had the same issues as you notice in the video. I discussed the issue with Kelsey Hawkins at Roscon 2013, and his development of the C-API version is a result of this.
I would recommend you take a look at a recent technical paper I’ve made with some students of mine called “UR10 Performance Analysis” (http://orbit.dtu.dk/en/publications/ur10-performance-analysis(0deaebd1-1593-4641-a971-e1ac0234ed88).html ) – despite its name, it is applicable to UR 5 and UR 10 alike, as it focuses on the software side. The paper also looks into some network related issues.
In short, I would recommend you use the speedj() command instead – in my experience, it is the only command that works reliably and consistently at 125 hz (except if you have an very old version of the ur5 with the 1st generation of the controller. In that case, no network control works reliably due to a memory leak in the network buffer. But that doesn’t seem to be your problem).
As joint speed control leads to positional drifting it requires that you make a feedback controller if you need accurate positional control, as the speedj command only takes… -well, joint speeds.
The bandwidth with which one can expect to control the robot is determined by the 24ms round-trip time.
On 19/05/15 10:05, Maarten de Vries wrote:
On 18 May 2015 at 09:59, Thomas Timm Andersen <tt...@elektro.dtu.dk> wrote:
The bandwidth with which one can expect to control the robot is determined
by the 24ms round-trip time.
Do you think it would be possible to reduce the feedback latency by
streaming joint position setpoints to the arm (at hopefully 125 Hz) and
implementing the feedback loop on the arm itself in URScript with speedj
commands?
I would expect that could work, but would need some buffering on the controller itself due to the influences of Nagle on the TCP connection.
Perhaps UR should move to UDP for the 'rt' broadcasts on 30003.
As it is stated in the report, disabling NAGLE on the host computer is sufficient. It is also mentioned, although not very clearly, that replying to every messages will force the robot controller to stream data at 125 hz and not buffer anything. Just replying with a “\n” is sufficient.
I’ve submitted at paper for IROS on measuring delay on robot manipulators. As it is still being reviewed, I can’t disclose the results yet, but one thing is clear on the UR: The time from a motion is carried out, until this is reflected in the data the robot transmit, is less than 8 ms. That is, the joint angles seems to be sampled very close ( < 2ms) to the time the values are transmitted. (Surprisingly, this is not the case for all robots)
Maarten: Implementing the feedback in URScript on the controller is not a bad idea, but I am not sure if it is doable.
At first, let me explain why we have this “big” delay. It took me some month to realize, but it is actually difficult to make it much faster.
At t=0, the robot controller transmit its current status (position, speed, target etc.).
This is read by the host computer shortly after, let’s assume at t=1 ms
According to the report, you now have up to 6 ms to do your control stuff and transmit a new instruction. Let’s assume you are a bit faster than this and transmit a new target at t=4ms
At t=8ms, the robot reads this, and transmit a new status. In this status, it tells us it has a certain target. So it would have to move towards that target in the control period in the time span, t=8ms to t=16ms.
At t=16ms, the robot transmit yet another status. In this status, the target is whatever we transmitted at t=4ms.
The robot then starts actually executing whatever we transmitted, and in the status package transmitted at t=24ms the position is now what we commanded at t=4ms (Giving that it can be reached in 8ms).
It should be noted that since we don’t have access to the firmware, determining when one control cycle ends and another begins is purely guesswork, although looking at the C-API can give a hint. Any function that actually commands the joint servos is said to be blocking for the rest of the control cycle. But obviously the servos are already doing something, so what actually must happen is that a call to these functions will block, and then at the start of the next control cycle (when the C program and the thread that controls the servos synchronize) these values are written to the servo controller.
My guess is that pseudo-code for the controller is
Set joint vel to 0
Read internal state of joints
Send joint vel to servo controller
While (1) {
Transmit internal state, and current target being pursued, to network socket
Sleep(xx) to minimize blocking time
Read instruction from network socket
Parse instruction
Read internal state of joints for position controller
Calculate new joint vel
Send new joint vel to servo controller and block
}
Where xx is a low value, like 0.5-1 ms. This would explain why sometimes transmitting a new instruction as soon as we received a status only yields an 8ms delay instead of the usual 16ms (The mentioned best-case scenario in section 2.3). We would have liked that delay to be a bit higher so we could reliably see an 8ms delay, but as there might be several instructions to parse (I/O, Modbus, configuration, etc.), I don’t blame the folks at UR for choosing this value conservatively. In the above timing explanation, I’ve assumed xx to be zero for simplicity.
The reason I doubt that it is possible to do it faster in URScript is because some of the functions must be blocking as well: I.e. how does the “t” parameter in the speedj-command work, how about reading from a socket (which would be in a separate thread) and reading the internal values. All these unknown makes it difficult to optimize the current solution, and the benefit will at most be 8 ms. Also remember that the 24 ms is the round-trip time. It only takes 16 ms from a command is sent until the robot start to execute it.
Thomas
--
1) Yes, I have heard that Universal should have fixed the firmware so that TCP_NODELAY isn’t necessary any more. Note, though, that this is something handled at a pretty low level in the hardware stack and handling is probably driver dependent. Therefore I would always recommend using the TCP_NODELAY for timing critical applications.
2) I’m not sure what you mean by sleeping? The robot doesn’t buffer its messages, they are still being sent. If you don’t read on your socket connecting the messages are buffered on the receiving computer (Try to use Wireshark to monitor the network, the robot will always send data when it has a connection to port 30003. If not, I would like to know how you made it sleep)
3) That is strange – like I’ve tried to explain earlier, the delay shouldn’t be more than ~24ms. I am pretty sure that it is not due to delay between the controller and the robot, as the controller (which sends the data) is well aware of the target speed.
Your figures are a bit difficult to interpret. Axis labeling and legends would help a lot!
It is still not clear to me what you want to achieve, except “real time control”. But why do you need it, and do you mean “real time” in classical CS sense (guaranteed deterministic periods) or “real time” in a more practical way as “real time” is often used in robotics (really fast reaction to changes).
I usually use speedj with a ‘t’ parameter of 0.02, but still send speedj commands at 125 Hz. If you do this without synchronizing with the robot, you would still get smooth execution, even if you have late packages.
I would guess that the reason you sometimes gets late packages is because you don’t use TCP_NODELAY?
/Thomas
From: jorri...@gmail.com [mailto:jorri...@gmail.com]
Sent: 25. oktober 2015 22:54
To: swri-ros-pkg-dev
Cc: Thomas Timm Andersen; jorri...@gmail.com
Subject: Re: [ROS-Industrial] Re: universal robots package, servoj() at 125Hz
1) with or without using TCPNODELAY, i get a package from the robot every 8ms