ISRA has a pretty good system in their Mono3D, but it requires that the "nominal" positions of all 4 corners be known first. That is, if you put your reactangular(?) target in front of the camera, it will measure the difference between the target's 6DOF position and the "nominal" position you originally set it up to. But if the rectangular(?) target changes shape --for example, becomes less rectangular and more trapezoidal-- then the measurement becomes less reliable. So in part it will depend on whether the 4 corners you're trying to measure are on a part whose shape never changes (only position/orientation), or whether you're trying something more like locating the centroid of roughly-rectangular objects of varying size.
Posts by SkyeFire
-
-
30-50 um? That's microns, correct? That's... a very small distinction to make. Many sensors don't have that degree of resolution. Heck, the robot often can't even move that finely!
By way of comparison, 30-50 microns is a fairly average thickness of a human hair. 50 microns is the thickness of an average sheet of paper.
You're probably going to need some kind of high-precision laser or visual sensor. A normal proximity switch or mechanical contact sensor is not going to reliably detect offsets that small.
-
Hmmm.... is your TCP colinear with the A6 axis? Or close to it? It would be a bit of a mathematical chore, but you could introduce a somewhat-constant A6 rotation by constantly adding a Tool A rotation to each point (assuming your TCP ABC values are 0,0,0).
Mm... now I can't stop thinking about it. This is just spitballing, so take it for what it's worth, but... assuming a TCP of {X 0,Y 0, Z 500, A 0,B 0,C 0}, and porgramming a start point directly over the flame with the Z+ axis of the tool pointing straight down (directly opposing World Z+, in other words) and the Tool X axis aligned with World X....
Code
Display MoreDECL INT _nXRotation DECL FRAME _fPosArray[180] DECL INT _nArrayIndex DECL FRAME _fShiftFrame DECL REAL _rA6Rotation DECL INT _nLoops DECL INT _nLoopIndex DECL E6AXIS _aAxisPos _nA6Rotation = ($SOFTP_END[6] - $SOFTN_END[6] - 5)/180; max degs A6 rotation per 1deg of World rotation, with a 5deg cushion _nLoops = 10 ; number of times to perform full-arc-and-back PTP StartPosition ; starting position, Tool Z+ pointing straight down at flame WAIT SEC 0 ; break advance pointer _aAxisPos = $AXIS_ACT _aAxisPos.A6 = $SOFTN_END[6] + 2.5 PTP _aAxisPos ; move to first point of arc _fPosArray[1] = $POS_ACT ; store first position of arc _nArrayIndex = 2 FOR _nXRotation = -90 to 90 ; 180 degree rotation around World X _fShiftFrame = $NULLFRAME _fShiftFrame.X = _nXRotation _fPosArray[_nArrayIndex] = _nXRotation : _fPosArray[1] ; rotate around World X by ? degrees _fShiftFrame = $NULLFRAME _fShiftFrame.Z = _rA6Rotation * (_nArrayIndex-1) _fPosArray[_nArrayIndex] = _fPosArray[_nArrayIndex] : _fShiftArray ; rotate around Tool Z axis (A6) by ? degrees per step ENDFOR ; start the flame here WAIT FOR (user input or start button or whatever) FOR _nLoopIndex = 1 TO _nLoops ; Clockwise 180deg arc FOR _nArrayIndex = 1 TO 180 LIN _fPosArray[_nArrayIndex] C_VEL ENDFOR ; Counterclockwise 180deg arc FOR _nArrayIndex = 179 TO 1 STEP -1 LIN _fPosArray[_nArrayIndex] C_VEL ENDFOR ENDFOR
Just off-the-cuff, but what it should do is rotate the TCP around the World X axis through 180deg (and back again) while also rotating A6 just about its maximum possible amount across the total arc. It's vulnerable to axis limits, and there'll be a "slow spot" at each end while the robot reverses direction.
-
If you want to set the velocity of each axis yourself, then don't call BAS afterwards. Several (but not all) of the BAS subroutines will re-set $VEL_AXIS to either all the same value, the default value for each axis, or the values in PDAT_ACT or LDAT_ACT.
In KRL, whatever the last change made to a system variable is, is retained until another command makes another change.
Also, $VEL_AXIS is not a "max" speed -- it's an actual speed command value for individual axes. Usually it is only directly manipulated if you're going to move one axis in isolation. Any normal robot motion involving multiple axes will be time-synchronized by the motion planner -- if one axis will take 5sec to make the move, and another will only need 1sec, the faster axis will be slowed down so that it's beginning and end of motion is time synchronized with the slowest axis.
-
So, I've made more success on this front. My last remaining issue is quite an odd one.
Basically, I've successfully used the Cognex Output Buffer to send whatever data I want to the robot. Since Cognex uses Siemens byte ordering, I have to use the Byte Swapping option in WorkVisual for any multi-byte mappings, but it works fine. I can use UINT, INT, and even Float (if I use my IEEE-754 converter in the robot).
The Cognex Input Buffer also works. However... the Byte Swapping in WorkVisual doesn't. Literally, it has no effect. After my success with the robot inputs, I followed the same process for the robot outputs. Set up a 16-bit or 32-bit word in the Cognex, mapped it to an Output block in WorkVisual, and ran my test program.
My test program has a SIGNAL declaration for the 16- or 32-bit word, and I simply increment its value while watching what the Cognex receives. And what I get (for a 32-bit allocation) is this:
Robot output 1 -> Cognex receives 16777216
2 -> 33554432
4-> 67108864Basically, the lowest bit of the lowest byte on the robot outputs is being mapped to the lowest bit of the highest byte in the Cognex inputs. If I increment the robot's output value by powers of 2, I can watch the active bit march upwards, one bit at a time, through the highest byte in the Cognex, then jump to the lowest bit of the 2nd-highest byte, then from the highest bit of that byte to the lowest bit of the 3rd-highest byte, and so on. Until, when the robot sends 16777216, the Cognex receives a 1.
Obviously, I need to swap my bytes, yes? But here's the kicker: swapping the bytes in WV does nothing. Literally -- If I go into WV, swap the bytes, deploy the project, then re-run my test program, literally nothing changes in what the Cognex receives.
I also tried changing the mapping in WorkVisual between I/O, Signed, and Unsigned. No change. Un-swapped the bytes. No change. Swapped the bytes again (did this about 6 times). No change.Now, keep in mind that, on the robot inputs, I can clearly see the WV byte-swap work. If I un-swap the bytes in WV, what the robot receives from the Cognex looks just like what I outlined above. If I swap the bytes, the robot receives exactly what the Cognex sends. But the WV byte-swapping on the outputs[/] not only does not work, but makes [b]no difference at all. I've also tried firing the $OUTs in the robot one at a time directly, rather than assigning integers values to the SIGNAL variable -- no difference.
I can't really believe that this is a Cognex-side issue. Even if it was, swapping and un-swapping the bytes in WorkVisual should make some visible difference in what the Cognex receives. Instead, it's almost as if the WV byte-swapping simply isn't doing anything for the outputs, only for the inputs.
I'm using WV 4.0.19, and my OfficePC is running KSS 8.3.28. I haven't had this kind of problem with WorkVisual before, connecting to Siemens PLCs (which also require byte-swapping). Has anyone ever run into anything similar? I've got feelers out to both Cognex and KUKA tech support, but so far nothing's come back.
-
The key thing to understand here is that, unlike system variables (which are indicated by a $ prefix), the xDAT_ACT variables, and the BAS moduleare, in effect, factory default add-ons. Particularly, to support menu-based (officially, "Inline Forms") programming from the teach pendant. They are not critical to the robot's core functionality(1), or to writing functional programs in KRL.
As such, they've gone through decades of "compatibility barnacle" accumulation, and show a lot of vestigial elements.
For instance, BAS(#PTP_PARAMS, 75) uses the numerical argument to set the motion speed, rather than the value stored in PDAT_ACT. However, BAS has many other functions -- you can look at it's raw source code in the /R1/System directory. And some of those other functions (called using different #Enumerated values in the first call argument) do use the PDAT_ACT.VEL value.As for the sturctures, briefly:
PDAT variables control factors for PTP motion: Velocity, Acceleration, Approximation radius (and, for other KSS versions, things like APO_JERK are also added)
LDAT variables do the same for LIN motions, but the Velocity value is in m/s rather than %max, and Approximation is in mm rather than %distance
FDAT variables contain the settings for the values for $TOOL_ACT, $BASE_ACT, whether the tool is fixed or robot-mounted (IPO_FRAME) -- basically, parameters that influence how a Cartesian point is positioned in space.(1)KUKA's design paradigm appears to differ from most of the competition -- where most industrial robot manufacturers treat teach-pendant programming as a core function, KUKA treats it as an add-on. As such, the "magic" that makes the inline-form programming work is not in the robot's OS, but in the user interface layer. All those ;FOLD/;ENDFOLD structures created by the inline forms are treated by the compiler as simple comments -- only the user interface treats them as a sort of executable scripting code. Mostly invisible to the user, this system actually writes "raw" KRL code directly into the program, concealed inside the inline-form Folds, and formatted in specific ways to enable the user interface to adjust that KRL code when someone hits the Change button on the pendant.
-
It's been done on KRC1s and KRC2s, but I have not been able to find any means of doing it on a KRC4. The big issue appears to not be the physical RAM, of which there is plenty, but some kind of internal limitation on the VxWorks virtual machine where all the robot's OS and applications reside. From what I've been told, the /R1 directory tree has a maximum capacity of 8-9MB. Which is ridiculously tiny for a modern piece of machinery, but it is what it is. Increasing the physical installed RAM won't affect this limit. There were some hacks to modify these limits on the earlier KRCs, but I'm fairly sure these don't work on the KRC4s.
If you don't need all those points in the robot at the same time, you could perhaps use the DirLoader application.
There's EKI, which some posters have used to load positions from a remote server on demand. I've also had some luck loading points from a text file, which could be as large as you like -- the UserFiles directory has several GBs of free space. Both of these require some careful programming to get the timing right and avoid stop&go motions, but it's been done.
-
Are you trying to control the clamp from the robot, or just sense it's condition (empty/full, closed/open)? Exactly how many sensors and/or actuators do you require? Digital or analog? Rotary or linear? Pneumatic or electric?
I'm not familiar with the Fanuc I/O setup, but you need to determine exactly what I/O your robot controller currently has that you could use for this purpose. It may not have any -- a lot of robot controllers these days don't have any "hard" I/O, in favor of having flexible support for multiple FieldBus options. But FieldBus often requires adding an option package to the robot (seldom cheap), and buying external FieldBus hardware (also seldom cheap).
-
There's a difference between an SPL block and an SPL motion. I'm only familiar with the former, since the latter wasn't an option on KSS 5 at the time. An SPL block is entirely pre-computed before the robot even begins the first SPL point in the block. The SPL motions are affected by the previous and following motions, but also by the motions further away. The robot pre-computes a motion path that smoothly moves through every point in the Spline block at a fixed speed, and then executes that path (probably by auto-generating an enormous number of very tiny approximated LIN motions, but that's a guess).
The problem is, there's probably more than one valid way to compute a spline motion. So the points you select from your SVG file may not produce the same path through those points as the curve in the SVG file the selected points came from. Greater point density can reduce that problem, but can run into memory limits and possible issues with the robot's ability to handle massive numbers of close-coupled SPL motions. As I said, my knowledge is rather outdated, so I'm not sure exactly what those limits are.
The last time I used Spline blocks, I had to drive my end mill into the stock to full depth using a normal, non-Spline motion, then start the Spline block (with a brief motion halt) to carry out the cut path, then halt and use a non-Spline motion to withdraw the cutter. The issue was that if the "plunge" motions were part of the Spline block, the cut depth would behave in very strange ways as the robot tried to make a smooth path that included a large number of points in a 2-D plane, and one or two points at the ends that were far out of plane. It could result in paths that plunged far too deeply and then started "bobbing" vertically.
The modern implementation of Spline motions under KSS 8 appears to be more advanced, but I have yet to do any work with it.
-
The error message suggests that the XML sent to the robot does not match the format of the XML template defined in the robot. The XML schema must match on both ends.
-
If you can quantify the error in the circle, you could try using my ellipsoidal generator and adjust the parameters to "tune out" the errors.
http://kuka.skyefire.org/, use the GeneralEllipsoid module. Read the comments, they explain how the program works.Also, the robot does not have anything like the rigidity of a CNC machine, so performing good milling with a robot, even if the programmed path is perfect, requires low speeds. The robot will flex under even small recoil loads from the milling head.
-
It should be a quite simple programming task in C, Java, Python, etc. Simply create a host "listening" on a port, then respond to any incoming requests with XML-formatted ASCII text strings.
The older versions of EKI, for the KRC2s, used to include this file as an example of the server-side source code.
Code
Display More////////////////////////////////////////////////////////////////////////////// ///KUKA Roboter GmbH ///Bluecherstr. 144 ///86165 Augsburg ///Germany /// ///Topic: C# Code: Server-apllication with Ethernet.KRL.XML /// Best effort: Microsoft Windows System and Console Application Projekt. ///Date: 10. March 2006 ///Developer: Rajko Rolke ////////////////////////////////////////////////////////////////////////////// private static void anyfunction() { // starting communication by separate process System.Threading.Thread secondThread; secondThread = new System.Threading.Thread(new System.Threading.ThreadStart(StartListening)); secondThread.Start(); } // second thread private static void StartListening() { uint Port = 6008; // port number TCP/IP uint AddressListIdx = 0; // network card index System.Xml.XmlDocument SendXML = new System.Xml.XmlDocument(); // XmlDocument pattern System.Net.Sockets.Socket listener; // create system socket System.Net.Sockets.Socket handler; // create system socket // Data buffer for incoming data. byte[] bytes = new Byte[1024]; // Establish the local endpoint for the socket. // Dns.GetHostName returns the name of the // host running the application. System.Net.IPHostEntry ipHostInfo = System.Net.Dns.Resolve(System.Net.Dns.GetHostName()); System.Net.IPAddress ipAddress = ipHostInfo.AddressList[AddressListIdx]; System.Net.IPEndPoint localEndPoint = new System.Net.IPEndPoint(ipAddress, (int)Port); // Create a TCP/IP socket. listener = new System.Net.Sockets.Socket(System.Net.Sockets.AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp); // open Socket and listen on network listener.Bind(localEndPoint); listener.Listen(1); // Program is suspended while waiting for an incoming connection. // bind the first request handler = listener.Accept(); // no connections are income listener.Close(); // string members for incoming and outgoing data String strReceive = null; String strSend = null; // load sending data by external file SendXML.PreserveWhitespace = true; SendXML.Load("ExternalData.xml"); while(true) { // wait for data and receive bytes int bytesRec = handler.Receive(bytes); if (bytesRec == 0) { break; // Client closed Socket } // convert bytes to string strReceive = String.Concat(strReceive,System.Text.Encoding.ASCII.GetString(bytes,0,bytesRec)); // take a look to the end of data if ((strReceive.LastIndexOf("....write here the endtag of KRC xml structure.....</xx>..")) == -1) { continue; } else { strSend = SendXML.InnerXml; // send data as requested byte[] msg = System.Text.Encoding.ASCII.GetBytes(strSend); handler.Send(msg,0,msg.Length,System.Net.Sockets.SocketFlags.None); } strReceive = null; } }
-
To tie a logic or signal operation directly to a particular motion point, and guarantee that the Advance pointer does not cause unanticipated issues, the usual technique is to use TRIGGER commands. There's a few ways to do this. My preferred option is to use a subroutine that "packages" any and all logic I want carried out.
Code
Display MoreLIN P1 C_DIS TRIGGER WHEN DISTANCE=1 DELAY=0 DO CheckSensor() LIN P2 C_DIS LIN P3 C_DIS ..... END DEF CheckSensor() CONTINUE IF NOT diPartExist THEN WAIT FOR diPartExist ENDIF END
The DISTANCE and/or DELAY values may need fine-tuning to achieve the precise performance you desire. Or, for LIN moves, you might find PATH-style Triggers better suited for what you're trying to accomplish. The manual goes into quite a bit of depth about how TRIGGER commands interact with approximated motions.
-
While you did not state your KUKA arm model or controller model, most KUKAbots are designed to have the drive shafts or belts "slip" before the arm takes physical damage (like bending the arm). Axis slippage can be correct by re-mastering, but bending the arm so it does not match the kinematic model does not.
Check the TCP by installing a sharp pointed cutter and rotating around a fixed sharp pointer. If the robot drifts a lot, you may have damaged the robot or the tool mounting.
Assuming the arm isn't bent, the next thing to check is the mounting of the tool to the robot A6 flange -- you may want to remove the tool and check the dowel pins in the adapter plate. I've seen cases where a tool that looked fine had actually had the dowel pins snapped by such an impact, and the clearance holes for the mounting bolts had enough play to make the working end of the tool drift off substantially.
Also, if the TCP checks out fine, check the mounting of the robot to the floor. I've had some nasty surprises that way. And old concrete anchors can slip without looking like they have.
If those both check out, make an Archive of the robot, re-teach the TCP, and test it. Compare the old TCP values to the new ones to see what's changed.
-
First, that program will not perform approximated motion. You don't have any C_DIS or other approximation suffixes on any of your motion commands.
Second, with an $ADVANCE value of 1, the WAIT FOR check will be performed at the beginning of the LIN P2 motion. If the boolean result is False at that moment, the robot will come to a complete stop at P2, even if the boolean condition has become True while the robot was en route from P1 to P2.
-
What controller model? What KSS version?
Define "OK" -- how did you test the batteries? Did you test their output voltage with the main power off? Have you load-tested them? How long has it been since they were replaced? What voltage is across the battery terminals when the main power is on and the charging circuit is active?
-
Nice! (and tasty )
(we need an "eating" emoticon to go with the "drinking" one).Yeah, I'm pretty sure normal cleaning isn't food-grade. Um... is the metal of the mold stainless steel, or something else? I'm not sure if there are any "safety" issues with most metals touching food, but I know from experience that normally anything that touches food has to be stainless.
I also suspect you'll need some food-grade mold release.Still, though, looks like fun. And the chocolate can probably tolerate a less-than-optimum motion pattern than what you usually cast (QC for chocolate is usually less stringent ) Good luck! Let us know how it works out.
-
What exactly are you trying to accomplish?
(caveat: the last time I used Spline motions was on KRC2s under KSS 5.6, and I know improvements have been made, so some of my knowledge is out of date).
Normal robot motions, with approximation enabled, calculate the smoothest/shortest motion through the approximated points, using the approximation radii set by for those points to define the start/stop of the approximation (the manual describes this in detail). One effect is that the robot never passes through those points, just near them. This results in hand-programmed paths for things like glue application that have to have their "corner" points programmed well out from the actual path, and act like "handles" that "pull" the path towards them, necessitating a great deal of trial-and-error tweaking to fine tune the path.
Spline motions are intended to accomplish the same sort of thing, but forcing the robot to pass through each programmed point, instead of passing near them. This is a more recent addition to most robots, since it it much more computationally intensive. An SPL block usually has to be completely pre-calculated, and has many more limitations on it than "normal" motions. It also, IIRC, avoids speed changes along the path, unlike "classical" approximated robot motion.
Obviously, any transition between the two motion modes is... complex. It used to be that any such transition had to bring the robot to a complete momentary halt -- it simply wasn't possible to make a smooth on-the-fly transition. According to my glance at the KSS 8.x manuals, it looks like this has been improved, but that transition path is still going to be a bit unpredictable.
-
What do you mean, "square openings"?
The holes in your photo look pretty good, to the naked eye. Please provide details. -
It should be possible. But the math would be rather more complex.
To make such an arrangement work using the standard 4-pt method, for example, it would only work if you could guarantee that the same point on the surface of the probe was what made contact with the target sphere at each of the 4 points. Otherwise the circular fit would fail, since it is designed for touching two points (think spheres with radius of 0) to each other. Then you would have to remove the radius of the target sphere (and possibly the radius of the probe sphere) from the resulting tool measurement.
Someone who had the math skills could probably create an algorithm that could do the calibration using many points of contact (probably would need to be automated), if the radii of both the target sphere and the probe sphere were known with high accuracy. Theoretically, reverse-engineering the sphere radii would be possible, but given the robot's inherent accuracy issues, that would likely be self-defeating.
If I started with knowledge of both radii, and had a rough idea of the TCP dimensions to start from, I think I could brute-force a program to iteratively fine-tune the TCP using this method. But it would take some serious work. Getting a professional mathematician's input would be valuable, I think.