Roles Founding Pro, Tactile Sensor Beta Testers
Full Name Matthew Bush
Job Title COO/Cofounder
Country US - United States
Company (optional) Hirebotics, LLC
I thought that we might want a single thread where everyone can post up any handy little helper functions that they have developed over time that make programming and using the UR robots easier. If you have any functions that you are willing to share please post the code below along with an example of how to use the code. If you have any questions about how to use something please feel free to reach out to the author or post a question on here so that everyone can learn from each other.
This function allows you to easily change the speed of the running robot by changing the current value of the speed slider programmatically.
This function takes a float between 0 and 1 as an argument, one thing to note is if you actually send 0 it pauses the program but I have not found a way to easily recover from this so I am using the if statement to verify that the speed is not 0, if so it sets it to 0.001 which basically stops motion but allows the robot program to continue to run.
def runSlow(speed): if speed == 0: speed = 0.001 end socket_open("127.0.0.1",30003) socket_send_string("set speed") socket_send_string(speed) socket_send_byte(10) socket_close() end
Usage in a program would be
Another example is how to have a popup message that only has an OK button and is non-blocking, this allows you to have informational messages that do not stop the program execution and that the operator cannot stop program execution from either. An example of where we use this is during programs that have a long start-up time during the before start portion of the program. We will pop up a message to tell the user that the program is in the process of starting so that they don't hit the play button repeatedly.
The way that you would use this is
def infoPopup(msg): socket_open("127.0.0.1", 29999, "popup") socket_send_string("popup ", "popup") socket_send_string(msg, "popup") socket_send_byte(10, "popup") socket_close("popup") end
infoPopup("Some Message Here")
One last one is to programmatically close the popup, now, the caveat to this is it will close ANY open popup, it actually doesn't know what it is closing, just that popups will be closed. So you want to make sure you are only using this when there is no chance that you are closing something that should be blocking operation, user be warned.
def closeInfoPopup(): socket_open("127.0.0.1", 29999, "close") socket_send_string("close popup", "close") socket_send_byte(10, "close") socket_close("close") end
Simply use it by calling the function in your program
That looks really good!
Now for the silly question, which manufacturers dress pack is that on the robot? And how is it working for you?
@abeachy_HG24 that's pretty straightforward to do in a background thread. Use a flag variable to turn it on and off when you want to record max value. You might want to play around with some filtering but you can do something like this
if measureMax == True:
If Fx > previousMax:
maxValue = Fx
previousMax = Fx
maxValue = 0
Let me know if that does what you're looking for. Depending on how much your signal is fluctuating you might want to do some signal filtering using time averaging.
Which version of the software are you running @Student?
**Edit** Nevermind, I thought that they had changed it to where you could use subprograms within subprograms but that's not the case.
Because of this issue, I stopped using subprograms a long time ago, also found they seemed to add time to the program anyways. Simply moving the call to URScript will not be enough as that is what the program does when it compiles at runtime anyways. The way that we have gotten around this and use it every day in production is two-fold.
Anything that we call repetitively and can write in URscript we do, such as commands for opening and closing grippers or the Robotiq script commands for the gripper versus using the subprogram commands. This allows me to write once and then use anywhere plus similar to using subprograms it's quick to make changes to the command and have it applied everywhere.The other is a bit more "confusing" at first but once you have done it a couple of times it's not bad. We break the code up into chunks and then wrap each chunk inside of an if statement with a code. Then at the top of the program is our logic and that logic calls the code that is to run next so something like this:
Before Start Section codeblock = 0 Program Section whatStepToDo = "Get User Input as to what step needs to be done" if codeblock == 0: switch whatStepToDo: case 1: codeblock = 100 case 2: codeblock = 200 case 3: codeblock = 300 default: codeblock = 0 end end if codeblock == 100: Do whatever unique thing you want to do here codeblock = 400 end if codeblock == 200: Do some other unique thing here end if codeblock == 300: Do something even more unique here end if codeblock == 400: This is somehting that can be called from anywhere so needs to be at the end of the program, this could even call another subroutine so long as it appears below this one in the program end
The biggest challenge with this style is that you have your logic at the top of the program and then all of your subroutines below that both physically and numerically. There is no goto in the UR language so you can't jump back up to the top for instance and go from code block 200 to 100 unless you control how you reset going back to your starting logic blocks.
The part that we really like about this is it provides for a lot of reusability in our code. We have program templates that we use for our deployments that already have defined a number of code blocks that get used in every deployment. Also, once we solve a problem it's really easy to copy and paste it into another program for use there such as a block that takes in the current location and then does a spiral or helix move from that location. Another big advantage is that it makes it easy to do testing of the code, we can make the robot just use one code block for instance so that we can check all of the motion and verify that it is doing exactly what we want it to do.
I have obviously oversimplified the starting logic as there is only one thing that it is doing and it's asking a user for it. We have a round robin testing scenario where the robot is using up to 3 testers at the end of the line to test product and is keeping track of which tester to service when as well as determining if the part that was just tested needs to be retested on another tester, discarded down the reject chute or placed on the outbound conveyor to go to packaging. All of this logic is being handled in 3 logic steps at the top of the program and then calling all the required move steps based on what the logic tells it to do.
This is how we have gotten around using subprograms and it has created a scenario where it is much easier to test the code, start from multiple places based on user input during the start-up sequence so that we can resume operation where we left off, reuse code in other programs and create templates that provide core functionality without us needing to do that everytime.