Universal Robots+

Display global URScipt variable in Program Node

I want to represent a couple of values (e.g. X, Y, Z forces) in the program node. How do you implement this?

How to return the values of global variables in the generateScript(ScriptWriter writer) function block to display in the ProgramNode of a given URCap?

Thanks in advance for help!

LZ

In addition, I attach the mentioned code. Thanks in advance for your help!

The ProgramNodeContribution code:

package com.ProCobot.ForceMonitoring.impl;

import java.awt.EventQueue;
import java.util.Collection;
import java.util.Timer;
import java.util.TimerTask;

import com.ur.urcap.api.contribution.ProgramNodeContribution;
import com.ur.urcap.api.contribution.program.ProgramAPIProvider;
import com.ur.urcap.api.domain.ProgramAPI;
import com.ur.urcap.api.domain.data.DataModel;
import com.ur.urcap.api.domain.variable.GlobalVariable;
import com.ur.urcap.api.domain.variable.Variable;
import com.ur.urcap.api.domain.variable.VariableModel;
import com.ur.urcap.api.domain.variable.VariableException;
import com.ur.urcap.api.domain.variable.VariableFactory;
import com.ur.urcap.api.domain.variable.VariableFilterFactory;
import com.ur.urcap.api.domain.value.expression.InvalidExpressionException;
import com.ur.urcap.api.domain.undoredo.UndoRedoManager;
import com.ur.urcap.api.domain.undoredo.UndoableChanges;
import com.ur.urcap.api.domain.util.Filter;
import com.ur.urcap.api.domain.script.ScriptWriter;

	
public class ForceMonitoringProgramNodeContribution implements ProgramNodeContribution{
	
	private final ProgramAPIProvider apiProvider;
	private final ProgramAPI programAPI;
	
	private final ForceMonitoringProgramNodeView view;
	private final DataModel model;
	
	private final VariableModel variableModel;
	private final VariableFactory variableFactory;
	private final UndoRedoManager undoRedoManager;
	
	private Timer uiTimer;
	
	private static final String FORCE_TCP_XVALUE_KEY = "force@TCP X";
	private static final String FORCE_TCP_YVALUE_KEY = "force@TCP Y";
	private static final String FORCE_TCP_ZVALUE_KEY = "force@TCP Z";
	
	private static final String DEFAULT_FORCE_TCP_XVALUE = "NaN";
	private static final String DEFAULT_FORCE_TCP_YVALUE = "NaN";
	private static final String DEFAULT_FORCE_TCP_ZVALUE = "NaN";
	
	GlobalVariable tcpForceTorqueVar = null;
	GlobalVariable tcpForceXVar = null;
	GlobalVariable tcpForceYVar = null;
	GlobalVariable tcpForceZVar = null;
	
	
	public ForceMonitoringProgramNodeContribution(ProgramAPIProvider apiProvider, ForceMonitoringProgramNodeView view, 
			DataModel model) {
	
		this.apiProvider = apiProvider;
		this.programAPI = apiProvider.getProgramAPI();
		this.view = view;
		this.model = model;
		this.variableModel = apiProvider.getProgramAPI().getVariableModel();
		this.variableFactory = apiProvider.getProgramAPI().getVariableModel().getVariableFactory();
		this.undoRedoManager = apiProvider.getProgramAPI().getUndoRedoManager();
		
		try {
			tcpForceTorqueVar = variableFactory.createGlobalVariable("tcpForceTorque", 
					programAPI.getValueFactoryProvider().createExpressionBuilder().append("0").build());
			tcpForceXVar = variableFactory.createGlobalVariable("tcpForceX", 
					programAPI.getValueFactoryProvider().createExpressionBuilder().append("0").build());
			tcpForceYVar = variableFactory.createGlobalVariable("tcpForceY", 
					programAPI.getValueFactoryProvider().createExpressionBuilder().append("0").build());
			tcpForceZVar = variableFactory.createGlobalVariable("tcpForceZ", 
					programAPI.getValueFactoryProvider().createExpressionBuilder().append("0").build());
		} 
		catch (VariableException e) {
			view.setError(e.getLocalizedMessage());
			e.printStackTrace();
		} 
		catch (InvalidExpressionException e) {
			view.setError(e.getLocalizedMessage());
			e.printStackTrace();
		}
		
	}
	
	private String getForceXVal() {
		return model.get(FORCE_TCP_XVALUE_KEY, DEFAULT_FORCE_TCP_XVALUE);
	}
	
	private String getForceYVal() {
		return model.get(FORCE_TCP_YVALUE_KEY, DEFAULT_FORCE_TCP_YVALUE);
	}
	
	private String getForceZVal() {
		return model.get(FORCE_TCP_ZVALUE_KEY, DEFAULT_FORCE_TCP_ZVALUE);
	}
	
	private void setForceXVal(final String xVal) {
		undoRedoManager.recordChanges(new UndoableChanges() {
			@Override
			public void executeChanges() {
				model.set(FORCE_TCP_XVALUE_KEY, xVal);
			}
		});
	}
	
	private void setForceYVal(final String yVal) {
		undoRedoManager.recordChanges(new UndoableChanges() {
			@Override
			public void executeChanges() {
				model.set(FORCE_TCP_YVALUE_KEY, yVal);
			}
		});
	}
	
	private void setForceZVal(final String zVal) {
		undoRedoManager.recordChanges(new UndoableChanges() {
			@Override
			public void executeChanges() {
				model.set(FORCE_TCP_ZVALUE_KEY, zVal);
			}
		});
	}
	
	@Override
	public void openView() {
		
		view.setForceXValLabel(getForceXVal());
		view.setForceYValLabel(getForceYVal());
		view.setForceZValLabel(getForceZVal());
		
		//UI updates from non-GUI threads must use EventQueue.invokeLater (or SwingUtilities.invokeLater)
		uiTimer = new Timer(true);
		uiTimer.schedule(new TimerTask() {
			@Override
			public void run() {
				EventQueue.invokeLater(new Runnable() {
					@Override
					public void run() {	
						updateTCPForce();
					}
				});
			}
		}, 0, 1000);
	
	}
	
	@Override
	public void closeView() {
	
	}
	
	@Override
	public String getTitle() {
	
		return "ForceMonitoring: ["+getForceXVal()+","+getForceYVal()+","+getForceZVal()+"]";
	
	}
	
	@Override
	public boolean isDefined() {
	
		return true;	
	}
	
	@Override
	public void generateScript(ScriptWriter writer) {
		
		writer.appendLine(tcpForceTorqueVar + "=" + "get_tcp_force()");
		writer.appendLine("textmsg(tcpForceTorque)");
		
		writer.appendLine(tcpForceXVar + "=" + "tcpForceTorque[0]");
		writer.appendLine("textmsg(tcpForceX)");
		
		writer.appendLine(tcpForceYVar + "=" + "tcpForceTorque[1]");
		writer.appendLine("textmsg(tcpForceY)");
		
		writer.appendLine(tcpForceZVar + "=" + "tcpForceTorque[2]");
		writer.appendLine("textmsg(tcpForceZ)");
	
	}
	
	private void updateTCPForce() {		
		
		Collection<Variable> vars;
		Object[] objects;
		String tcpForceInXaxis = "0.0";
		String tcpForceInYaxis = "0.0";
		String tcpForceInZaxis = "0.0";
		
		try {
			// Update the TCP force				
			vars = getGlobalVariables();
			objects = vars.toArray();
			
			System.out.println("Contents of the array: ");
			System.out.println(objects);
			System.out.println("---xxx---");
			
			for (int i = 0; i < objects.length; i++) {		
				
				if (objects[i].toString() == "tcpForceX") {		
					tcpForceInXaxis = objects[i].toString();			
					setForceXVal(tcpForceInXaxis);
					System.out.println(tcpForceInXaxis);
					
				}
				else if (objects[i].toString() == "tcpForceY") {		
					tcpForceInYaxis = objects[i].toString();			
					setForceYVal(tcpForceInYaxis);
					System.out.println(tcpForceInYaxis);
					
				}
				else if (objects[i].toString() == "tcpForceZ") {	
					tcpForceInZaxis = objects[i].toString();					
					setForceZVal(tcpForceInZaxis);
					System.out.println(tcpForceInZaxis);
					
				}
			}
			
		} catch (Exception e) {
			System.err.println("Could not retrieve essential data for the program node.");
			tcpForceInXaxis = "<Failed to retrieve TCP force in x-axis>";
			tcpForceInYaxis = "<Failed to retrieve TCP force in y-axis>";
			tcpForceInZaxis = "<Failed to retrieve TCP force in z-axis>";
		}
		
		view.setForceXValLabel(tcpForceInXaxis);
		view.setForceYValLabel(tcpForceInYaxis);
		view.setForceZValLabel(tcpForceInZaxis);
	}

	public void setVariable(final String key, final Variable variable) {
		undoRedoManager.recordChanges(new UndoableChanges() {
			@Override
			public void executeChanges() {
				model.set(key, variable);
			}
		});
	}

	public Collection<Variable> getGlobalVariables() {
		return variableModel.get(new Filter<Variable>() {
			@Override
			public boolean accept(Variable element) {
				return element.getType().equals(Variable.Type.GLOBAL) || element.getType().equals(Variable.Type.VALUE_PERSISTED);
			}
		});
	}
	
}

The ProgramNodeService code:

package com.ProCobot.ForceMonitoring.impl;

import com.ur.urcap.api.contribution.ViewAPIProvider;	
import com.ur.urcap.api.contribution.program.ContributionConfiguration;	
import com.ur.urcap.api.contribution.program.CreationContext;	
import com.ur.urcap.api.contribution.program.ProgramAPIProvider;	
import com.ur.urcap.api.contribution.program.swing.SwingProgramNodeService;	
import com.ur.urcap.api.domain.data.DataModel;

import java.util.Locale;

public class ForceMonitoringProgramNodeService implements SwingProgramNodeService<ForceMonitoringProgramNodeContribution, ForceMonitoringProgramNodeView>{
	
	
	@Override
	public String getId() {
	
		return "ForceMonitoringNode";
	
	}
	
	@Override
	public void configureContribution(ContributionConfiguration configuration) {
	
		configuration.setChildrenAllowed(false);
	
	}
	
	@Override
	public String getTitle(Locale locale) {
	
		return "Force Monitoring";
	
	}
	
	@Override
	public ForceMonitoringProgramNodeView createView(ViewAPIProvider apiProvider) {
	
		return new ForceMonitoringProgramNodeView(apiProvider);
	
	}
	
	@Override
	public ForceMonitoringProgramNodeContribution createNode(ProgramAPIProvider apiProvider, ForceMonitoringProgramNodeView view,
	
			DataModel model, CreationContext context) {
	
		return new ForceMonitoringProgramNodeContribution(apiProvider, view, model);
	
	}
	
}

The ProgramNodeView code:

package com.ProCobot.ForceMonitoring.impl;

import java.util.Locale;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;

import com.ur.urcap.api.contribution.ContributionProvider;	
import com.ur.urcap.api.contribution.ViewAPIProvider;	
import com.ur.urcap.api.contribution.program.swing.SwingProgramNodeView;	
 
	
public class ForceMonitoringProgramNodeView implements SwingProgramNodeView<ForceMonitoringProgramNodeContribution>{	
 
	private static final int HORIZONTAL_SPACE = 10;
	private static final int VERTICAL_SPACE = 10;

	private final ViewAPIProvider apiProvider;	
	private final ImageIcon errorIcon;
	public ForceMonitoringProgramNodeView(ViewAPIProvider apiProvider) {
	
		this.apiProvider = apiProvider;
		this.errorIcon = getErrorImage();
	}	
	
	private JLabel forceXValLabel;
	private JLabel forceYValLabel;
	private JLabel forceZValLabel;
	private JLabel errorLabel = new JLabel();
	
	@Override
	public void buildUI(JPanel panel, ContributionProvider<ForceMonitoringProgramNodeContribution> provider) {
	
		panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
		
		panel.add(createInfo());
		panel.add(createVerticalSpace());
		
//		panel.add(createXYZInfoBox("Force X:", forceXValLabel));
//		panel.add(createVerticalSpace());
//		panel.add(createXYZInfoBox("Force Y:", forceYValLabel));
//		panel.add(createVerticalSpace());
//		panel.add(createXYZInfoBox("Force Z:", forceZValLabel));
//		panel.add(createVerticalSpace());
		
		panel.add(createForceXInfoBox("Force@TCP X:"));
		panel.add(createVerticalSpace());
		panel.add(createForceYInfoBox("Force@TCP Y:"));
		panel.add(createVerticalSpace());
		panel.add(createForceZInfoBox("Force@TCP Z:"));
		panel.add(createVerticalSpace());
		panel.add(createErrorLabel());
	
	}
	
	private Box createInfo() {
		Box infoBox = Box.createVerticalBox();
		infoBox.setAlignmentX(Component.CENTER_ALIGNMENT);
		JLabel pane1 = new JLabel();
		pane1.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
		pane1.setText("<HTML>This is ProCobot's Force Monitoring node that shows the X, Y, Z forces below.</HTML>");
		pane1.setBackground(infoBox.getBackground());
		infoBox.add(pane1);

		JLabel panel2 = new JLabel();
		Locale locale = apiProvider.getSystemAPI().getSystemSettings().getLocalization().getLocale();
		panel2.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
		panel2.setText("<HTML>Currently, the robot is configured to use the Locale: " + locale.getDisplayName() + "</HTML>");
		infoBox.add(panel2);


		return infoBox;
	}
	
	private Box createXYZInfoBox(String description, 
			JLabel textLabel) {
		
		Box box = Box.createHorizontalBox();
		box.setAlignmentX(Component.LEFT_ALIGNMENT);

		
		JLabel label = new JLabel(description + "   ");
		label.setFont(label.getFont().deriveFont(Font.BOLD));		
		
		box.add(label);
		box.add(createHorizontalSpace());
		
		textLabel = new JLabel();
		box.add(textLabel);
		
		return box;
		
	}
	
	private Box createForceXInfoBox(String description) {
		
		Box box = Box.createHorizontalBox();
		box.setAlignmentX(Component.LEFT_ALIGNMENT);

		
		JLabel label = new JLabel(description + "   ");
		label.setFont(label.getFont().deriveFont(Font.BOLD));		
		
		box.add(label);
		box.add(createHorizontalSpace());
		
		forceXValLabel = new JLabel();
		box.add(forceXValLabel);
		
		return box;
		
	}
	
	private Box createForceYInfoBox(String description) {
		
		Box box = Box.createHorizontalBox();
		box.setAlignmentX(Component.LEFT_ALIGNMENT);

		
		JLabel label = new JLabel(description + "   ");
		label.setFont(label.getFont().deriveFont(Font.BOLD));		
		
		box.add(label);
		box.add(createHorizontalSpace());
		
		forceYValLabel = new JLabel();
		box.add(forceYValLabel);
		
		return box;
		
	}
	
	private Box createForceZInfoBox(String description) {
		
		Box box = Box.createHorizontalBox();
		box.setAlignmentX(Component.LEFT_ALIGNMENT);

		
		JLabel label = new JLabel(description + "   ");
		label.setFont(label.getFont().deriveFont(Font.BOLD));		
		
		box.add(label);
		box.add(createHorizontalSpace());
		
		forceZValLabel = new JLabel();
		box.add(forceZValLabel);
		
		return box;
		
	}
	
	private Component createHorizontalSpace() {
		return Box.createRigidArea(new Dimension(HORIZONTAL_SPACE, 0));
	}
	
	private Component createVerticalSpace() {
		return Box.createRigidArea(new Dimension(0, VERTICAL_SPACE));
	}

	public void setForceXValLabel(String xVal) {
		forceXValLabel.setText(xVal);		
	}

	public void setForceYValLabel(String yVal) {
		forceYValLabel.setText(yVal);		
	}

	public void setForceZValLabel(String zVal) {
		forceZValLabel.setText(zVal);		
	}

	private Box createErrorLabel() {
		Box infoBox = Box.createHorizontalBox();
		infoBox.setAlignmentX(Component.LEFT_ALIGNMENT);
		errorLabel.setVisible(false);
		infoBox.add(errorLabel);
		return infoBox;
	}

	private ImageIcon getErrorImage() {
		try {
			BufferedImage image = ImageIO.read(getClass().getResource("/icons/warning-bigger.png"));
			return new ImageIcon(image);
		} catch (IOException e) {
			// Should not happen.
			throw new RuntimeException("Unexpected exception while loading icon.", e);
		}
	}

	public void setError(final String message) {
		errorLabel.setText("<html>Error: Could not create variable<br>" + message + "</html>");
		errorLabel.setIcon(errorIcon);
		errorLabel.setVisible(true);
	}

	private void clearErrors() {
		errorLabel.setVisible(false);
	}
	
}

Maybe it is not possible to display the global value on program node.
So it is recommended to get force value by RTDE.
Did you see sky-net topic?
There is hints how to use RTDE.

Best regards

Would be lovely if a developer that knows it for sure - clarifies it, whether it can be done with global variables or cannot.

Any tips on how to manage to fix this problem?

It is possible to exchange the value of global variable between robot program and urcaps by using socket connection.
If the forces value be obtained by script, server built in urcap can recieve them.

Please see my sample “Dialog Script URCap” uploaded recently.

Hi @lukasz.ziegler,
In theory it’s possible, because Polyscope can also display the values of global variables in the Variables tab.
Look for the structures GlobalVariablesSetupMessage (Primary client only) and GlobalVariablesUpdateMessage (Primary client only) in this document:
https://s3-eu-west-1.amazonaws.com/ur-support-site/16496/Client_Interface_V3.13andV5.8.xlsx

1 Like