Costum movenode

hello,

Can anyone tell me how to create a MoveP / MoveJ node with my own layout? Or tips that help me on my way. I can’t find it in any of the examples.

Greetings Zoë

Zoe,

UR+ portail is full of tutorials and examples on how to create your own URCap nodes. I would suggest you start looking at the section ‘My Fisrt URCap’ here. There are many example I am sure will help you get started !

Julien

Hi @jsthilaire ,

Thank you for your response

I know how to make a normal program node but i ran into the fact that a move node works a little differently. Meanwhile I have started to look at it from a different angle and I don’t think it needs to be very different from another node.

However, I am now stuck that the following code doesn’t seem to retrieve the position of the robot that I need for my waypoint

UserInterfaceAPI uiapi = apiProvider.getUserInterfaceAPI();
uiapi.getUserInteraction().getUserDefinedRobotPosition(new RobotPositionCallback2() {
@Override
public void onOk(PositionParameters positionParameters) {
model.set(POSITION_WAYPOINT, positionParameters.getPose());
System.out.println(positionParameters.getPose());
}

		public void onCancel(){
		
		}

Any ideas on how to fix this?

regards, Zoe

Zoe,

everytime you are saving data to the data model you must use the undoRedoManager in order for that value to be persistent.

Try this :

final UndoRedoManager undoRedoManager = apiProvider.getProgramAPI().getUndoRedoManager();

apiProvider.getUserInterfaceAPI().getUserInteraction().getUserDefinedRobotPosition(new RobotPositionCallback2() {
					@Override
					public void onOk(final PositionParameters parameters) {
						undoRedoManager.recordChanges(new UndoableChanges() {
							@Override
							public void executeChanges() {
                               model.set(POSITION_WAYPOINT, parameters.getPose());
                            }
                         }
                     }

                 });

to query the data, the undoRedoManager is not required :

Pose userPose = model.get(POSITION_WAYPOINT, null)

@jsthilaire

If i use this code, i get the following message…

@jsthilaire
I found the mistake. It was in making the variable. Thank you so much for your help!

One thing I’ll point out so you don’t make the same mistake I did. If you are capturing only the Pose with “parameters.getPose()” and decide to allow the user to select Joint Move later on (like in a future update) you’ll need to be able to pass it a Joint Positions. This will be incompatible with existing programs whose waypoints were created before capturing the Joint Positions.

To really mimic a built-in UR move, you may want to also just capture and store the Joint Positions so they are there if you need them. Of course, if you’re just doing a MoveP type move, then they can only be linear anyway. Just a thought.

@eric.feldmann good point, we also usually save all 3 PositionParameters outputs to the data model :

parameters.getPose()
parameters.getJointPositions()
parameters.getTCPOffset()

@eric.feldmann @jsthilaire

Thank you guys for the great advice, I will take it with me by creating the moveNode.

I actually had one more question, do you guys happen to know if it is possible to make a dropdown menu with java swing with the features?

kind regards,
Zoë Hermans

Yes you can do this.

The view:

public void setFeatureSelectionItems(final Feature[] items) {
	featureSelectionBox.removeAllItems();
	featureSelectionBox.setModel(new DefaultComboBoxModel<>(items));
}

The contribution function that generates the input parameter to the above view function:

private Feature[] getFeatures() {
		final Filter<Feature> filter = element -> {
			if (element.getClass().equals(FeaturePlane.class)) {
				return false;
			} else {
				if (!element.isDefined()) {
					return false;
				} else if (!element.isResolvable()) {
					return false;
				}
			}

			return true;
		};

		final Collection<Feature> features = new ArrayList<>();
		features.add(programAPI.getFeatureModel().getBaseFeature());
		features.addAll(programAPI.getFeatureModel().getGeomFeatures(filter));

		return features.toArray(new Feature[0]);
	}

Just be warned, when using the Features, you have to make sure that all your custom moves now check which Feature is active and convert all your saved poses/joint positions to that frame. I’ve spent many many hours troubleshooting issues resulting from moves not behaving correctly when selecting a Feature.

@eric.feldmann

i was thinking about converting the waypoints the way you said here:

Thankyou so much for helping me and thinking with me.

kind regards

Hi @eric.feldmann,

I am trying to use the features from the combobox now, but it constanly says that my base is not defined if i select the baseFeature. it also doensn’t want to be the default selected item… i tried getPose, setSelectedIndex, and tried to fill in the kind of arraylist. But this also doesn’t seem to work. The rest of the features are working perfectly.

Do you know the solution maybe?

Hmm not sure about why it would be undefined as long as you’re using the built-in programAPI.getFeatureModel().getBaseFeature() to capture it. This is what I’m doing in the “getFeatures()” function in the above reply.

As for having it selected to Base by default, I use this:

public void setFeatureSelected(final Feature item) {
		featureSelectionBox.setSelectedItem(item);
	}

And I pass it the Feature that I’m storing as the Active Feature in my datamodel. I do this because I allow the user to select a Default Feature if they want, so any moves they add automatically come in with THAT feature instead. Like this:

public Feature getDefaultFeature() {
		return model.get(Position.ACTIVE_FEATURE, apiProvider.getInstallationAPI().getFeatureModel().getBaseFeature());
	}

So if they haven’t set a Feature themselves, the model.get() will return the Base Feature by default.

It seems like the position is not being read. In fact, I get back the following:

What I find strange because the other features he reads well.

I also tried the default in the combobox in the same way, but that does not work.

@eric.feldmann Sorry I see I forgot to tag you

Where exactly does it say the error is coming from? What code are you using to access the Base Feature? I’m on vacation today, so I don’t have my laptop, but I’m pretty sure there’s some other CAP examples that also show how to get/use features.

Regarding the passing of the feature, I found the following.

The value of the feature is passed to the child node properly. If I println() the value, it will also contain the value Base. But when I try to throw this into an if-statement in these ways:

if(getFeature() == programAPI.getFeatureModel().getBaseFeature() {}
if(getFeature().getName == “Base”){}
if(getFeature().getName() == programAPI.getFeatureModel().getBaseFeature().getName() ){}
if(getFeature().getPose() == programAPI.getFeatureModel().getBaseFeature().getPose() ){}

Then this is always False and it goes on to the else statement. Even if I print the two values in a row they are the same but I still get the message:
“Compile errorL name ‘Base’ is not defined” when using the value of Base in moveJ.
(the intention is that I use the if-statement to prevent it from going into moveJ)

kind regards,
Zoë

So it’s totally an aside, but I’ve seen Java have a hard time using == to compare strings. You may find success with your if() statements by using .equals() as the comparison.

We use the Features in our welding CAP, and it ends up writing script that looks like this:

movep(pose_trans(Base, pose_trans(pose_inv(p[0.0,0.0,0.0,0.0,0.0,0.0]), p[-0.18963153690184714,-0.639468548254798,0.26097114845197156,-0.0012213596815951828,3.116276528481966,0.03889191563689264])), a = 0.5, v = weld_speed, r = 0.0017779999882652003)

Can you verify that your script is writing “Base” exactly like that? No additional spaces, capital B? You’ll also see the argument for the pose_inv() command is the POSE for the Feature, (Base being all 0s) so make sure you’re not putting the String “Base” in where it expects a pose.

1 Like

Hello Eric

Using .equals turned out to be the solution. Good to know that == in java therefore does not always have the desired effect. So I’m going to do that differently from now on.

Thanks again for your help!

Kind regards,

Zoë Hermans