Greetings to the UR community!
I am currently writing a URCap that needs to access the Gripper for open/close actions in a generic way. Basically i created a node similar to the example pick and place application.
So I tried to use the GripperManager to get a list of available devices, but i do not get any grippers in the result list.
I am currently using a Robotiq 2-Finger Gripper connected to the robot via the TCP (RS485?) connector which is working fine via the URScript API. I also tried to refresh the list after gripper activation but no success yet.
Also one additional Question: Is it possible to execute some Gripper Commands during the programming steps, like it is possible with the Robot to set a specific position for e.g. waypoints? Or is it only possible to use the gripper nodes for this purpose?
Best regards
it seems that the robotiq urcap does not at all implement the GripperContribution interface of UR. So that’s why.
Perhaps a more general question. Is it common for grippers to ignore the UR GripperContribution interface or is this Robotiq just an exception?
Best regards
Compared to the age of a lot of grippers on the market, the gripper ineterface is relatively new, so if some grippers had URCaps build before the gripper interface was released, they may not implement it. I couldn’t speak for which grippers this might concern, though I suspect this is the reason.
Hi Sam,
thanks for your response!
I would like to find some generic way to communicate with a gripper connected to the robot. I first tried the gripper interface, but that didn’t seem to work. Is there any other way to send commands like open and close to a gripper in a generic way?
I tried to use some kind of script input field to let the user place urscript commands there for opening or closing and then create the script with these commands. But this only works during URScript runtime. When I try to use these commands (e.g. rq_close_and_wait())) via the ScriptCommunicator (GitHub - EbbeFuglsang/URCap-ScriptCommunicator: Exemplification of how to communicate with URControl from a URCap) they seem to break the script. Possibly because they are interpreted by the polyscope plugin and the robot doesn’t know nothing about these special gripper commands?
I would really appreciate any hints on how to achieve a generic gripper movement via my urcap that works for any gripper.
Thanks in advance and best regards
Jan
I suspect that you will have to mimic Robotiq’s URScript control of the grippers in order to enable script control. Usually a URCap’s installation file will generate some script functions which will then be gcalled in the generateScript()
method of a program node. I suspect that your best option is to inspect the script generated by Robotiq’s URCap and implement the same script functions in your own program node’s generateScript()
.
Also in response to your additional question, you will need threads to perform gripper commands mid way through motion. Just make sure that you don’t overlap gripper control between the main program and the thread controlling the gripper.
Actually I did not try to move the Gripper during robot movement. Only after a completed movel command. But the Script seems to be ignored entirely as soon as i have any robotiq commands added. Still the same script seems to work when fed into the generateScript method of my contribution.
Ok, I think i found the scripts the robotiq gripper uses to initialize. BUT actually this throws me back to the beginning, because then I still have to add some special code for every gripper because I cannot reuse the existing initialization steps already done inside the gripper URCaps InstallationContribution.
Isn’t there any way to just extract the initialization scripts from all existing URCaps to reuse them programatically?
Isn’t there any way to just extract the initialization scripts from all existing URCaps to reuse them programatically?
It depends if the initialisation code is wrapped up inside a function defined by the installation file. If it is, you can just call that function with any required argments, if not then you will have to copy and paste the code into your URCap. It’s not really an ideal solution but it might babout all you can do.
The advantage of copying the installation file’s code is it will mean you may be able to uninstall the separate URCaps for the various grippers if you are usign he script to control them (though there may be other things the URCap does such as initialising the grippers that are not done in the installation file script which may mean you still require the URCap). If you are just calling functions defined in the installation file, you will obviously require the URCap to define the various functions.
But how do i get a List of references to all known InstallationNodeContributions installed inside polyscope?
If I whould be able to get that list, i could try to call all generateScript methods of them with my own ScriptWriter implementation to get the vast majority of initialization code. Then it should be possible to use their URScript commands inside my Secondary Client assuming that if i make sure that the installed URCaps are initialized correctly (Like running deamons and other stuff).
Is there anithing like polyscopeapi.getAllRegisteredInstallationNodeContributions()?
I’m afraid I dont think such a function exists, I couldn’t find one in a brief check of the API, though I could still be wrong. You might have to implement a more crude solution of a selection of tickboxes in the installation file which decide which script to generate. Not an ideal solution but does allow you more direct control over which gripper types are supported.
If someone else stumbles across this. This is a (hacky) way to get the correctly configured preamble scripts from the robotiq installation. Might also be suitable to communicate with other cooperative service bundles:
public class Activator implements BundleActivator {
private final static Logger LOG = LogManager.getLogger();
public static BundleContext context;
private static Method mGenerateScript;
private static Object installationScriptWriter;
public static Bundle getGripperBundle() {
for (Bundle b : context.getBundles()) {
if (b.getSymbolicName().equals("com.robotiq.urcap.gripper")) {
return b;
}
}
throw new RuntimeException("Gripper bundle not found");
}
public static Object getGripperService(){
Bundle b = getGripperBundle();
if(b.getRegisteredServices() == null) {
throw new RuntimeException("Missing gripper bundle services");
}
for (ServiceReference s : b.getRegisteredServices()) {
Object svc = context.getService(s);
if (svc.getClass().getName().equals("com.ur.robotiq.urcap.gripper.impl.GripperInstallationNodeService")) {
return svc;
}
}
throw new RuntimeException("Robotiq GripperInstallationNodeService not found");
}
public static void generateGripperInstallationScript(ScriptWriter script) {
try {
if(mGenerateScript == null) {
Object svc = getGripperService();
Field fScriptWriter = svc.getClass().getDeclaredField("_gripperInstallationScriptWriter");
fScriptWriter.setAccessible(true);
installationScriptWriter = fScriptWriter.get(svc);
mGenerateScript = installationScriptWriter.getClass().getDeclaredMethod("generateScript", ScriptWriter.class);
mGenerateScript.setAccessible(true);
}
mGenerateScript.invoke(installationScriptWriter, script);
} catch (Exception e) {
LOG.error("Unable to extract installation script", e);
throw new RuntimeException("No Gripper installation found", e);
}
}
@Override
public void start(final BundleContext context) {
Activator.context = context;
}
@Override
public void stop(BundleContext context) {
Activator.context = null;
Activator.mGenerateScript = null;
Activator.installationScriptWriter = null;
}
}