No problem! On that note, and to anyone downloads this implementation, I'm really interested to see your modifications or improvements to it; if you wouldn't mind, post them here.
Posts by FlexoWasTaken
-
-
Just adding on a direct answer your question about smoothing...
Smoothing is achieved via the PD (Proportional Derivative) controller algorithm. In simple terms, the algorithm allows each axis to take little steps towards its target, always respecting its current velocity. So, when axis is directed to move from a start point, 0, to a set point, 90, the algorithm determines whether an acceleration of constant value, 0.001 deg/<cycle time>s, needs to be added to or subtracted from to its current velocity, 0 deg/<cycle time>s. On the next iteration, the robot is at 0.001, still needs to get to 90, but is now moving at a rate of 0.001 deg/<cycle time>s; the acceleration is added again to the velocity and the robot increases in speed towards the set-point. Because the acceleration value is small, an axis never appears to jerk, regardless of which direction the robot is told to go; hence smooth motion.
In previous posts, I had said I was looking for washy or surfy motion, wherein the robot is allowed to overshoot set-points (and then try to cycle back) in the interest of keeping motion really fluid and smooth; this is possible. It's also possible -- especially if you play with the D parameter -- to get fine motion that never overshoots and also slows-down nicely as it approaches a set point. To experiment with different motion characteristics, try playing around with the parameters in the USER fold of the SRC file; keep your changes minimal, though, until you understand how their effects.
Good luck, RSI rocks.
-
Hey,
RSI has a sort of steep learning curve and there are few useful, working implementations available online for it; I've attached mine. My lab used this material at Autodesk University (2017) and it works nicely when used with live-input from a virtual reality controller. It's a generalizable implementation, but just note that the parameters I used to tune it are for that application only (we had to account for poor input, such as from shaky-hands). It'll have to be tuned for your application so I highly recommend using it as a starting point only. It should be enough to get started, though.
The code I've provided is fairly well organized and documented. You'll be interested in the files _datagram_to_send.xml, RSI_Ethernet.rsi, and RSI_Ethernet.src. Note that you'll have to modify the contents of RSI_EthernetConfig.xml (or, really, generate your own) to match your setup.
The key to RSI is that you have to build the motion planner itself. In the example I've provided is implemented a fairly standard trapezoidal velocity algorithm which, in effect, chases after the most-recently-received set-point per axis. The constant acceleration parameter is added (a*1) to a velocity parameter; this effect is cumulative, and the robot will, in effect, start speeding up. Acceleration is no longer applied (a*0) once the velocity reaches a set limit (such as an axis or work cell limit); the robot will, in effect, move at a constant rate. Acceleration is negated (a*-1) once the axis is within a certain range of the set point; the robot will, in effect, slow down. The following diagram shows this behavior.
Code
Display MoreAcceleration: __ __| |__ __ |__| Velocity: ____ / \ / \ __/ \__ Position: __ / / / / / __ /
When you open RSI_Ethernet.rsi in the RSI editor, note that I implement at custom PD function for each axis to control their displacements. I don't use many of the internal PID functions provided by RSI; the documentation and support for this material is shockingly poor. The function is the same for each axis, however, you will need to verify and configure a few of the parameters inside -- such as velocity limit and starting position -- yourself. Note that this implementation doesn't care about "how long" it takes to reach a set point by any axis, so each axis will move towards its set point independent of the whole; the algorithm we implemented can, however, be rearranged such that all axes converge synchronously. The bulk of the work -- the motion planner, that is -- is done by this file. I won't copy all the code here, but it is pretty well documented and included in the attachment.
I've also included a Processing sketch called sim.pde which we used to test the motion planner and parameters before running them on the real robot; it's a short program and I recommend running it (using the Processing IDE) to visualize what's going on. It will follow the position of your mouse, the Y position of which corresponding with a displacement that might be to an axis. Again, this is only used to prototype/visualize in low-resolution a few aspects of the motion planner, but was useful nonetheless.
The robot runs the following program. Note that the parameters in the fold RSISYS are store the velocity of each axis during the previous cycle; if any of these would exceed the physical limit of an axis (which may be reduced further by the user parameter $SEN_PREA[8]), acceleration to that axis is, again, multiplied by 0. The parameter $SEN_PREA[9] corresponds with the convergence tolerance, a range around the set point within which the robot can be said to have "reached the position". This code follows what you'll find in the RSI documentation.
Code
Display More&ACCESS RVP &REL 2 &PARAM TEMPLATE = C:\KRC\Roboter\Template\vorgabe &PARAM EDITMASK = * DEF RSI_Ethernet( ) ; Declaration of KRL variables DECL INT ret ; Return value for RSI commands DECL INT CONTID ; ContainerID ;FOLD INI ;FOLD BASISTECH INI GLOBAL INTERRUPT DECL 3 WHEN $STOPMESS==TRUE DO IR_STOPM ( ) INTERRUPT ON 3 BAS (#INITMOV,0 ) ;ENDFOLD (BASISTECH INI) ;FOLD RSISYS INI ;RSI System parameters $SEN_PREA[1] = 0 ; Stored velocity; do not modify! $SEN_PREA[2] = 0 ; Stored velocity; do not modify! $SEN_PREA[3] = 0 ; Stored velocity; do not modify! $SEN_PREA[4] = 0 ; Stored velocity; do not modify! $SEN_PREA[5] = 0 ; Stored velocity; do not modify! $SEN_PREA[6] = 0 ; Stored velocity; do not modify! ;ENDFOLD (RSISYS INI) ;FOLD USER INI ;User parameters $SEN_PREA[7] = 0.001 ; Maximum acceleration $SEN_PREA[8] = 0.330 ; Percentage of full rotational velocity $SEN_PREA[9] = 0.100 ; Convergence tolerance (degrees) $SEN_PREA[10] = -0.200 ; Differential parameter $SEN_PREA[11] = 0.002 ; Proportional parameter $SEN_PREA[12] = 240.0 ; Maximum TCP velocity (mm/s) (unused) ;ENDFOLD (USER INI) ;ENDFOLD (INI) ; Move to start position PTP {A1 0, A2 -90, A3 90, A4 0, A5 45, A6 0} ; Create RSI Context ret = RSI_CREATE("RSI_Ethernet.rsi", CONTID, TRUE) IF (ret <> RSIOK) THEN HALT ENDIF ; Start RSI execution ret = RSI_ON(#RELATIVE) IF (ret <> RSIOK) THEN HALT ENDIF ; Sensor guided movement RSI_MOVECORR() ; Turn off RSI ret = RSI_OFF() IF (ret <> RSIOK) THEN HALT ENDIF ; Move to end position PTP {A1 0, A2 -90, A3 90, A4 0, A5 45, A6 0} END
What I send to the robot, then, is a datagram containing the degree of rotation per axis and a timestamp. Note that I overwrite the value 000.000 with the appropriate degree of rotation and 0000000000 with the timestamp. I was able to send this reliably using both the 4ms and 12ms cycle times. This follows what you'll find in the RSI documentation.
Code<Sen Type="ADSK"> <AKorr A1="000.000" A2="000.000" A3="000.000" A4="000.000" A5="000.000" A6="000.000" /> <IPOC>0000000000</IPOC> </Sen>
I have to get to work, but I hope this helps!
-
I see a lot of views with few replies; anyone else want to talk about this?
-
OK awesome, thanks all for the rapid response! Changes been made reflecting concerns expressed by panic mode, some of the parameters identified by SkyeFire have also been tuned, and the RSI project has been very much redesigned; the updated version is attached for your reference.
Know that we have adequate safeguarding in place and that this is not a video game for us, either. To clarify, we don't plan to have an end-effector or a workpiece so, for our tool (here, the mounting flange), the default maximum load has been applied; I don't see a way of governing loads using RSI. We are also using #ABSOLUTE corrections. Your concerns withstanding, I think that my movements would necessarily exceed those limits. The BCO move puts our robot at [0, -90, 90, 0, 90, 0], so if a series of corrections equal to 0.01 degrees per axis should attempt to bring the robot to [10, -80, 100, 10, 100, 10], then those limits would constrain my corrections not beyond [5, -85, 95, 5, 95, 5]. In the case of #RELATIVE corrections, this makes sense to me and I agree with you. However, I think those limits conflict with the usage of #ABSOLUTE correction. To me, it sounds like an implementation of the Limit object earlier in the program would be better in my case. Please see my changes and correct me if I'm totally wrong and if some part of that logic would still cause unsafe behavior.
For each axis, the new RSI implementation works as follows:
(1) First, the correction is calculated by differencing a target joint-position (via Ethernet) and the current joint-position (via AxisAct).
(2) Next, the correction is multiplied by a gain factor (via P) and limited the result to a certain range (via Limit).
(3) Next, the correction is summed with the adjusted correction and the total absolute correction (via AxisCorrMon)
(4) Finally, the correction is passed to the motion block (via AxisCorr).This implementation is working fairly well. I still see some abrupt motion here and there. SkyeFire, I will post images from the RSI Monitor later. Also, an undesirable result of the solution is that the robot will never actually reach or exceed my targets, getting infinitely close but never achieving them (the magnitude of the displacement decreases exponentially). Does anyone have ideas on how to implement RSI in order to fix this, such as a method of using the PID object instead of the P object?
Thanks,
FlexoWasTakenEdit: The file you will care about in the attachment is called RSI_Ethernet.rsi; open using RSIVisualShell.
-
Hi there,
I'm working with Robot Sensor Interface (RSI) and a KR60 and having trouble producing smooth motion.
For reference, I've attached a directory called "shared.zip" containing a SRC file and two RSI files, one of which connects inputs received via an Ethernet object directly to an AxisCorr object and the other incorporates a PID object. I have tried using P, PD, I, D, and PID with varying parameters in place of that PID object without success, though it's quite likely my implementation of RSI simply isn't correct. Otherwise, I'm using #IPO_FAST (4ms cycle time) and sending corrections in the range 0.001 to 0.01 degrees to any or all of my robot's axes, though I would like to send corrections as large as 0.1 degree. I have a custom C# application (connected upstream to a game controller) on an external PC which transmits datagrams to the Ethernet object.
The robot appears to move abruptly and rapidly, its motors making a terrible noise as it does; corrections are not reached smoothly. I've read a couple of posts here that refer to jagged motion and robots appearing to tear themselves apart using RSI, though I've not seen any actionable solutions (except for modifying the system variable $FILTER at the expense of the robot's warranty). What I'd like to know is how, specifically, do I (a) implement and (b) tune the parameters of RSI such that I can achieve smooth -- think slow or surfy -- corrections of larger size? I'm a programmer and, if possible, I'd really like to see example code. Let me know if I can provide more information.
Thanks a ton for your answers,.
FlexoWasTaken(gratuitous smiley: )