Possibly, I don’t know. I ended up going with my initial thought (using a thread in Java to monitor the state of a Tool IO). Right or wrong, it works. Had to go down a lot of rabbit holes to get it functioning, but it got there in the end.
import java.util.Collection;
import java.util.Iterator;
import com.ur.urcap.api.domain.io.DigitalIO;
import com.ur.urcap.api.domain.io.IO;
import com.ur.urcap.api.domain.io.IOModel;
import com.ur.urcap.api.domain.io.ModbusIO;
public class IOHelper {
private final IOModel ioModel;
public IOHelper(final IOModel ioModel) {
this.ioModel = ioModel;
}
public DigitalIO[] getDigitalInputs() {
final Collection<DigitalIO> ioCollection = ioModel.getIOs(DigitalIO.class);
ioCollection.removeIf(n -> !n.isInput());
final int inputSize = ioCollection.size();
final Iterator<DigitalIO> itr = ioCollection.iterator();
final DigitalIO[] inputList = new DigitalIO[inputSize];
for (int i = 0; i < inputSize; i++) {
inputList[i] = itr.next();
}
return inputList;
}
public DigitalIO[] getDigitalOutputs() {
final Collection<DigitalIO> ioCollection = ioModel.getIOs(DigitalIO.class);
ioCollection.removeIf(DigitalIO::isInput);
final int outputSize = ioCollection.size();
final Iterator<DigitalIO> itr = ioCollection.iterator();
final DigitalIO[] outputList = new DigitalIO[outputSize];
for (int i = 0; i < outputSize; i++) {
outputList[i] = itr.next();
}
return outputList;
}
public ModbusIO[] getModBusInputs() {
final Collection<ModbusIO> ioCollection = ioModel.getIOs(ModbusIO.class);
ioCollection.removeIf(n -> !n.isInput());
final int inputSize = ioCollection.size();
final Iterator<ModbusIO> itr = ioCollection.iterator();
final ModbusIO[] inputList = new ModbusIO[inputSize];
for (int i = 0; i < inputSize; i++) {
inputList[i] = itr.next();
}
return inputList;
}
public ModbusIO[] getModBusOutputs() {
final Collection<ModbusIO> ioCollection = ioModel.getIOs(ModbusIO.class);
ioCollection.removeIf(ModbusIO::isInput);
final int outputSize = ioCollection.size();
final Iterator<ModbusIO> itr = ioCollection.iterator();
final ModbusIO[] outputList = new ModbusIO[outputSize];
for (int i = 0; i < outputSize; i++) {
outputList[i] = itr.next();
}
return outputList;
}
public DigitalIO getSpecificDigitalIO(final String defaultName) {
final Collection<DigitalIO> ioCollection = ioModel.getIOs(DigitalIO.class);
final int ioCount = ioCollection.size();
if (ioCount > 0) {
final Iterator<DigitalIO> ioItr = ioCollection.iterator();
while (ioItr.hasNext()) {
final DigitalIO thisIO = ioItr.next();
final String thisDefaultName = thisIO.getDefaultName();
if (thisDefaultName.equals(defaultName)) {
return thisIO;
}
}
}
return null;
}
public IO getSpecificGPIO(final String defaultName) {
final Collection<IO> ioCollection = ioModel.getIOs();
final int ioCount = ioCollection.size();
if (ioCount > 0) {
final Iterator<IO> ioItr = ioCollection.iterator();
while (ioItr.hasNext()) {
final IO thisIO = ioItr.next();
final String thisDefaultName = thisIO.getDefaultName();
if (thisDefaultName.equals(defaultName)) {
return thisIO;
}
}
}
return null;
}
public ModbusIO getSpecificModBusIO(final String signalName) {
final Collection<ModbusIO> ioCollection = ioModel.getIOs(ModbusIO.class);
final int ioCount = ioCollection.size();
if (ioCount > 0) {
final Iterator<ModbusIO> ioItr = ioCollection.iterator();
while (ioItr.hasNext()) {
final ModbusIO thisIO = ioItr.next();
final String thisSignalAddress = thisIO.getName();
if (thisSignalAddress.equals(signalName)) {
return thisIO;
}
}
}
return null;
}
}
Here’s a class file that can get you access to the IO from within Java. I used this function to grab the tool io:
getSpecificDigitalIO("tool_out[0]")
You’ll notice in this case I used the OUTPUT, instead of the input. That’s just so I can easily trigger it in my simulator. On the real robot, I would change this to tool_in[0].
Then I just put a Timer that rolls over ever 100ms that checks for changes of that output and reacts accordingly.
You’ll have to use java.awt.EventQueue.invokeLater() in order to set anything in the DataModel, since the Thread does not count as a UI, so Polyscope will throw a fit if you try to edit the datamodel or program tree from inside it.
You’ll have to send a script command via socket to the robot using “get_actual_tcp_pose()” and get the result back to store into the datamodel. You can download the script communication classes here: