How to add a node via external buttons

I’ve got some custom nodes, and I’m wondering how people are able to create nodes with external inputs, such as buttons mounted near the tool flange, and using the Tool IO. Is there a thread that is constantly monitoring the state of the Tool IO or something? Likewise, how would you go about capturing waypoint data with a press of a button instead of using the getRobotMovementCallback()s?

Hi,

Maybe I think that it can be realized by using RTDE.

  1. watching the values of tcp pose and values of tool IO.
  2. set tcp pose into new waypoint node when detecting on of the IO.

Please see my github repositories how to monitor of IOs.

Hi!

I am facing the same problem.

Is there a way, in your opinion, to achieve this result via XMLRPC?

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: