February 17, 2019, 07:58:25 AM
Robotforum | Industrial Robots Community

 Newbies looking for expert opinion

Author Topic:  Newbies looking for expert opinion  (Read 1170 times)

0 Members and 1 Guest are viewing this topic.

November 12, 2018, 04:02:17 PM
Read 1170 times
Offline

barely_sane


Me and Mikalaanning are working on a school project. Our code is a modified version of the one from an earlier post, https://www.robot-forum.com/robotforum/kuka-lbr-iiwa/need-help-for-a-school-project/

But in the code which NullReference provided us, we got into a problem with the calculation and movements of the robot. Getting Nullpoint exception in the Frame [][], seems it cant get the values from the array.
We are quite limited in our experience with the robot, so the solution we came to was declaring each frame induvidually.

So there is a few question we need some answers to:
- Is there a better solution then declaring each frame?
- If we decide to declare them induvidually, how should we go about calculating them?
- As of right now, our baseplane got to be defined on each start up, is there a good way to impliment a four point plane to our code?

May our prayers to the robot gods and gurus be heared.
« Last Edit: November 13, 2018, 05:11:42 PM by barely_sane »

Today at 07:58:25 AM
Reply #1

Advertisement

Guest

November 12, 2018, 05:17:42 PM
Reply #1
Offline

NullReference


Did you do a 3 point calibration on the canvas base?

Post your modified code.
« Last Edit: November 12, 2018, 05:49:18 PM by NullReference »

November 12, 2018, 06:43:38 PM
Reply #2
Offline

mikalaanning



Following the code you provided we managed to mark one single point, and then we tried to work from there. but we got a nullpoint exception at the line where we made the frames using the two-dimensional array. We're going to try to work around this by making each point without using an array. Planning to do this tomorrow, and then we'll provide the updated code.

And to answer your question, no. We did not do a 3 point calibration on the canvas base. Only figured out how to mark once. The most optional would be to have points in each of the four corners of the whiteboard making that the canvas. And then just using lin on this frame. Any idea on how we can achieve this?

November 12, 2018, 06:53:56 PM
Reply #3
Offline

NullReference


You must do a 3 point calibration or atleast teach the canvas base. A newly created frame will always generate a nullpointer exception because it contains no teach data.

November 13, 2018, 05:02:09 PM
Reply #4
Offline

barely_sane


Thanks for the fast reply to our previous post.

We updated the code. But now we got error with the task instancing.


How should we go about fixing this? We got no clue, but we think the error is connected to line 25. Which is "Frame canvas = getApplicationData().getFrame("/canvas").copy();"

Another question, handguiding. How can we impliment it? what we have tried havent worked so far. (e.g adding it in safety config)


Code: [Select]
package application;

import javax.inject.Inject;
import javax.inject.Named;
import com.kuka.roboticsAPI.applicationModel.RoboticsAPIApplication;
import static com.kuka.roboticsAPI.motionModel.BasicMotions.*;
import com.kuka.roboticsAPI.deviceModel.LBR;
import com.kuka.roboticsAPI.geometricModel.Frame;
import com.kuka.roboticsAPI.geometricModel.Tool;
import com.kuka.roboticsAPI.motionModel.CIRC;
import com.kuka.roboticsAPI.motionModel.CartesianPTP;
import com.kuka.roboticsAPI.motionModel.LIN;
import com.kuka.roboticsAPI.motionModel.MotionBatch;

public class TicTacToe extends RoboticsAPIApplication
{
@Inject
Tool tool;
LBR robot;
// Get the canvas base.
Frame canvas = getApplicationData().getFrame("/canvas").copy();

// Contains the points of all 9 squares and the playGround.
Frame square1 = new Frame(canvas);
Frame square2 = new Frame(canvas);
Frame square3 = new Frame(canvas);
Frame square4 = new Frame(canvas);
Frame square5 = new Frame(canvas);
Frame square6 = new Frame(canvas);
Frame square7 = new Frame(canvas);
Frame square8 = new Frame(canvas);
Frame square9 = new Frame(canvas);
Frame playGround = new Frame(canvas);

// Contains the corners in the drawCross method.
Frame corner1 = new Frame();
Frame corner2 = new Frame();
Frame corner3 = new Frame();
Frame corner4 = new Frame();

// Contains the two points of the circle in the drawCircle method.
Frame auxiliarry = new Frame();
Frame StartEnd = new Frame();

private double canvasWidthHeight = 300;
double squareWidthHeight = canvasWidthHeight / 3;

@Override
public void initialize()
{
tool.attachTo(robot.getFlange());
square1.setX(squareWidthHeight / 2);
square1.setY(squareWidthHeight / 2);

square2.setX(squareWidthHeight / 2 + squareWidthHeight);
square2.setY(squareWidthHeight / 2);

square3.setX(squareWidthHeight / 2 + squareWidthHeight * 2);
square3.setY(squareWidthHeight / 2);

square4.setX(squareWidthHeight / 2);
square4.setY(squareWidthHeight / 2 + squareWidthHeight);

square5.setX(squareWidthHeight / 2 + squareWidthHeight);
square5.setY(squareWidthHeight / 2 + squareWidthHeight);

square6.setX(squareWidthHeight / 2 + squareWidthHeight * 2);
square6.setY(squareWidthHeight / 2 + squareWidthHeight);

square7.setX(squareWidthHeight / 2);
square7.setY(squareWidthHeight / 2 + squareWidthHeight * 2);

square8.setX(squareWidthHeight / 2 + squareWidthHeight);
square8.setY(squareWidthHeight / 2 + squareWidthHeight * 2);

square9.setX(squareWidthHeight / 2 + squareWidthHeight * 2);
square9.setY(squareWidthHeight / 2 + squareWidthHeight * 2);
}

@Override
public void run()
{
drawPlayGround();
drawCross(1);
drawCircle(2);
}

private void drawPlayGround()
{
playGround.setX(0);
playGround.setY(0);

Frame point1 = playGround;
Frame point2 = playGround;
Frame point3 = playGround;
Frame point4 = playGround;
Frame point5 = playGround;
Frame point6 = playGround;
Frame point7 = playGround;
Frame point8 = playGround;

point1.setX(point1.getX() + squareWidthHeight); // Y = 0
point2.setX(point2.getX() + squareWidthHeight*2); // Y = 0
point3.setX(point3.getX() + canvasWidthHeight);
point3.setY(point3.getY() + squareWidthHeight);
point4.setX(point4.getX() + canvasWidthHeight);
point4.setY(point4.getY() + squareWidthHeight*2);
point5.setX(point5.getX() + squareWidthHeight*2);
point5.setY(point5.getY() + canvasWidthHeight);
point6.setX(point6.getX() + squareWidthHeight);
point6.setY(point6.getY() + canvasWidthHeight);
point7.setY(point7.getY() + squareWidthHeight*2); // X = 0
point8.setY(point8.getY() + squareWidthHeight); // X = 0

// Create all the motions and send them as a batch to the controller
CartesianPTP toPrePosition = ptp(point1.setZ(50));
LIN toPoint1 = lin((point1).setZ(50));
LIN toDrawPoint1 = lin(point1.copy().setZ(30));
LIN toDrawPoint6 = lin(point6.copy().setZ(30));
LIN toPoint6 = lin((point6).setZ(50));
LIN toPoint5 = lin((point5).setZ(50));
LIN toDrawPoint5 = lin(point5.copy().setZ(30));
LIN toDrawPoint2 = lin(point2.copy().setZ(30));
LIN toPoint2 = lin((point2).setZ(50));
LIN toPoint3 = lin((point3).setZ(50));
LIN toDrawPoint3 = lin(point3.copy().setZ(30));
LIN toDrawPoint8 = lin(point8.copy().setZ(30));
LIN toPoint8 = lin((point8).setZ(50));
LIN toPoint7 = lin((point7).setZ(50));
LIN toDrawPoint7 = lin(point7.copy().setZ(30));
LIN toDrawPoint4 = lin(point4.copy().setZ(30));
LIN toPoint4 = lin((point4).setZ(50));

// Move the tool to a start position so we know it can plan the motions
robot.move(ptp(getApplicationData().getFrame("/HomePosition")).setJointVelocityRel(0.3));

MotionBatch batch = new MotionBatch(toPrePosition,
toPoint1, toDrawPoint1, toDrawPoint6, toPoint6,
toPoint5, toDrawPoint5, toDrawPoint2, toPoint2,
toPoint3, toDrawPoint3, toDrawPoint8, toPoint8,
toPoint7, toDrawPoint7, toDrawPoint4, toPoint4);

batch.setJointVelocityRel(0.3);
tool.move(batch);

// Return to the start position
robot.move(ptp(getApplicationData().getFrame("/HomePosition")).setJointVelocityRel(0.3));
}

private void drawCross(int square)
{
if (square == 1)
{
corner1 = square1.copy();
corner2 = square1.copy();
corner3 = square1.copy();
corner4 = square1.copy();
}
else if (square == 2)
{
corner1 = square2.copy();
corner2 = square2.copy();
corner3 = square2.copy();
corner4 = square2.copy();
}
else if (square == 3)
{
corner1 = square3.copy();
corner2 = square3.copy();
corner3 = square3.copy();
corner4 = square3.copy();
}
else if (square == 4)
{
corner1 = square4.copy();
corner2 = square4.copy();
corner3 = square4.copy();
corner4 = square4.copy();
}
else if (square == 5)
{
corner1 = square5.copy();
corner2 = square5.copy();
corner3 = square5.copy();
corner4 = square5.copy();
}
else if (square == 6)
{
corner1 = square6.copy();
corner2 = square6.copy();
corner3 = square6.copy();
corner4 = square6.copy();
}
else if (square == 7)
{
corner1 = square7.copy();
corner2 = square7.copy();
corner3 = square7.copy();
corner4 = square7.copy();
}
else if (square == 8)
{
corner1 = square8.copy();
corner2 = square8.copy();
corner3 = square8.copy();
corner4 = square8.copy();
}
else if (square == 9)
{
corner1 = square9.copy();
corner2 = square9.copy();
corner3 = square9.copy();
corner4 = square9.copy();
}

corner1.setX(corner1.getX() + squareWidthHeight / 2);
corner1.setY(corner1.getY() + squareWidthHeight / 2);
corner2.setX(corner2.getX() - squareWidthHeight / 2);
corner2.setY(corner2.getY() - squareWidthHeight / 2);
corner3.setX(corner3.getX() - squareWidthHeight / 2);
corner3.setY(corner3.getY() + squareWidthHeight / 2);
corner4.setX(corner4.getX() + squareWidthHeight / 2);
corner4.setY(corner4.getY() - squareWidthHeight / 2);

// Create all the motions and send them as a batch to the controller
CartesianPTP toPrePosition = ptp(corner1.setZ(50));
LIN toCorner1 = lin((corner1).setZ(50));
LIN toDrawCorner1 = lin(corner1.copy().setZ(30));
LIN toDrawCorner2 = lin(corner2.copy().setZ(30));
LIN toCorner2 = lin((corner2).setZ(50));
LIN toCorner3 = lin((corner3).setZ(50));
LIN toDrawCorner3 = lin((corner3.copy()).setZ(30));
LIN toDrawCorner4 = lin((corner4.copy()).setZ(30));
LIN toCorner4 = lin((corner4).setZ(50));

// Move the tool to a start position so we know it can plan the motions
robot.move(ptp(getApplicationData().getFrame("/HomePosition")).setJointVelocityRel(0.3));

MotionBatch batch = new MotionBatch(toPrePosition,
toCorner1, toDrawCorner1,
toDrawCorner2, toCorner2,
toCorner3, toDrawCorner3,
toDrawCorner4, toCorner4);

batch.setJointVelocityRel(0.3);
tool.move(batch);

// Return to the start position
robot.move(ptp(getApplicationData().getFrame("/HomePosition")).setJointVelocityRel(0.3));
}

private void drawCircle(int square)
{
if (square == 1)
{
auxiliarry = square1.copy();
StartEnd = square1.copy();
}
else if (square == 2)
{
auxiliarry = square2.copy();
StartEnd = square2.copy();
}

StartEnd.setX(StartEnd.getX() - ((squareWidthHeight / 2) - (squareWidthHeight / 10)));
auxiliarry.setX(auxiliarry.getX() + ((squareWidthHeight / 2) - (squareWidthHeight / 10)));

// Move the tool to a start position so we know it can plan the motions
robot.move(ptp(getApplicationData().getFrame("/HomePosition")).setJointVelocityRel(0.3));

// Create all the motions and send them as a batch to the controller
CartesianPTP toPrePosition = ptp(StartEnd.copy().setZ(50));
LIN toStartCircle = lin((StartEnd).setZ(30));
CIRC drawCircle = circ(auxiliarry, StartEnd);
LIN toEndCircle = lin((StartEnd).setZ(50));

MotionBatch batch = new MotionBatch(toPrePosition, toStartCircle, drawCircle, toEndCircle);

batch.setJointVelocityRel(0.3);
tool.move(batch);

// Return to the start position
robot.move(ptp(getApplicationData().getFrame("/HomePosition")).setJointVelocityRel(0.3));
}
}

November 13, 2018, 06:14:00 PM
Reply #5
Offline

NullReference


This method "getApplicationData().getFrame("/canvas").copy();" exists in the superclass "RoboticsAPIApplication". Line 22 gets executed when the class is being constructed and before this child class inherits anything from the superclass. That means when you call the method getFrame() which exists in the context of the super class it won't exist in your class context (yet). You can fix this by calling this method in your initialize method instead.

If you want handguiding in manual mode you need the white enabling switch on the flange.

November 13, 2018, 06:37:28 PM
Reply #6
Offline

razzo


I will try to get ride of your error which causes this exception which you posted (screenshot).

1. You try to inject your tool, which is good idea. I hope you have already created a tool template otherwise you cannot injected it.
2. If you have a tool template you have to inject it by name. Take a closer look in the manual chapter 15.10
Code: [Select]
@Inject
@Named("NameOfYourToolTemplate")
private Tool gripper;
3. You have a field robot of the class LBR. The easiest way to get your instance of this object is to inject it.
Code: [Select]
@Inject
private LBR robot;

So you should be able to execute xour application at least until 'initialize'.

Today at 07:58:25 AM
Reply #7

Advertisement

Guest

November 13, 2018, 06:58:11 PM
Reply #7
Offline

mikalaanning



Ahh! That explains why it wouldn’t work! I’ll move it back into initialize as you suggested! When it comes to the handguiding it worked before we started our project, we could push the white button and than guide the arm around.. but recently it haven’t worked.. this may be because we have done some work in the safety configuration ect.. do we need to implement a package or something with the handguiding software? Any help here would be usefull.

@Inject
@Named("NameOfYourToolTemplate")
private Tool gripper;[/code]
3. You have a field robot of the class LBR. The easiest way to get your instance of this object is to inject it.
Code: [Select]
@Inject
private LBR robot;

So you should be able to execute xour application at least until 'initialize'.
Yeah, we have initialized the tool in the template and have given that a TCP in the program which we initialized using the 4point.

When it comes to the calibration of both the canvas and the tool, is there any way we gan do this once and then save it in the program? So much hassle to do it every time we upload the code to the robot.

Thanks again guys.

November 13, 2018, 07:17:23 PM
Reply #8
Offline

NullReference



Download the latest program to the controller. Do your calibrations, upload the program to your PC. All processdata, frames and bases are saved in the applicationdata xml file. When you download to the controller you overwrite this xml file and thus all data in the controller is lost.

This method "getApplicationData().getFrame("/canvas").copy();" exists in the superclass "RoboticsAPIApplication". Line 22 gets executed when the class is being constructed and before this child class inherits anything from the superclass. That means when you call the method getFrame() which exists in the context of the super class it won't exist in your class context (yet). You can fix this by calling this method in your initialize method instead.

If you want handguiding in manual mode you need the white enabling switch on the flange.

Ahh! That explains why it wouldn’t work! I’ll move it back into initialize as you suggested! When it comes to the handguiding it worked before we started our project, we could push the white button and than guide the arm around.. but recently it haven’t worked.. this may be because we have done some work in the safety configuration ect.. do we need to implement a package or something with the handguiding software? Any help here would be usefull.

Sounds like you should back trace whatever changes you made to the safety configuration and figure it out yourselves.
« Last Edit: November 13, 2018, 07:20:14 PM by NullReference »

November 13, 2018, 07:30:44 PM
Reply #9
Offline

razzo


You are obviously not very experienced in computer programming especially object based programming.
To give you an idea how comfortable this kind of programming can be I try to show you how to draw square quite easiely (if everything is working - I cannot try it at home  :bawling:).

Your robot programm could look like this:
Code: [Select]
package application;

import javax.inject.Inject;
import javax.inject.Named;

import com.kuka.roboticsAPI.applicationModel.RoboticsAPIApplication;
import static com.kuka.roboticsAPI.motionModel.BasicMotions.*;
import com.kuka.roboticsAPI.deviceModel.LBR;
import com.kuka.roboticsAPI.geometricModel.Frame;
import com.kuka.roboticsAPI.geometricModel.ObjectFrame;
import com.kuka.roboticsAPI.geometricModel.Tool;

public class RobotApplication extends RoboticsAPIApplication {
@Inject
@Named("MyToolTemplate")
private Tool myTool;

@Inject
private LBR robot;

private ObjectFrame squareOrigin = getApplicationData().getFrame("MyFrame");

@Override
public void initialize() {
myTool.attachTo(robot.getFlange());
}

@Override
public void run() {
Square mySquare = new Square(squareOrigin, 20, 30);
mySquare.draw(robot);
}
}

But therefor you have to write another class which contains some information and actions. This could look e.g. like this:
Code: [Select]
package application;

import static com.kuka.roboticsAPI.motionModel.BasicMotions.lin;
import static com.kuka.roboticsAPI.motionModel.BasicMotions.ptp;

import com.kuka.roboticsAPI.deviceModel.Robot;
import com.kuka.roboticsAPI.geometricModel.Frame;
import com.kuka.roboticsAPI.geometricModel.ObjectFrame;

public class Square {
private Frame origin;
private Frame upperLeftCorner;
private Frame lowerLeftCorner;
private Frame upperRightCorner;
private Frame lowerRightCorner;
private double length = 0;
private double height = 0;

public Square(final ObjectFrame origin) {
initFrames(origin);
}

private void initFrames(final ObjectFrame squareOrigin) {
this.origin = new Frame(squareOrigin);
upperLeftCorner = new Frame(squareOrigin);
lowerLeftCorner = new Frame(squareOrigin);
upperRightCorner = new Frame(squareOrigin);
lowerRightCorner = new Frame(squareOrigin);
}

public Square(final ObjectFrame squareOrigin, final double length, final double height) {
initFrames(squareOrigin);
setLength(length);
setHeight(height);
}

public void setLength(final double length) {
this.length = length;
upperLeftCorner.setX(upperLeftCorner.getX() - length / 2);
lowerLeftCorner.setX(lowerLeftCorner.getX() - length / 2);
upperRightCorner.setX(upperRightCorner.getX() + length / 2);
lowerRightCorner.setX(lowerRightCorner.getX() + length / 2);
}

public void setHeight(final double height) {
this.height = height;
upperLeftCorner.setY(upperLeftCorner.getY() - height / 2);
lowerLeftCorner.setY(lowerLeftCorner.getY() - height / 2);
lowerLeftCorner.setY(lowerLeftCorner.getY() + height / 2);
lowerRightCorner.setY(lowerRightCorner.getY() + height / 2);
}

public void setOrigin(final Frame origin) {
upperLeftCorner = origin;
}

public void draw(final Robot robot) {
robot.move(ptp(getApprochFrame(upperLeftCorner, 50)));

robot.move(lin(upperLeftCorner));
robot.move(lin(lowerLeftCorner));
robot.move(lin(upperRightCorner));
robot.move(lin(lowerRightCorner));
robot.move(lin(upperLeftCorner));

robot.move(lin(getApprochFrame(upperLeftCorner, 50)));
}

private Frame getApprochFrame(final Frame frame, final int distance) {
return frame.copyWithRedundancy().setZ(frame.getZ() + distance);
}

public Frame getOrigin() {
return origin;
}

public double getLength() {
return length;
}

public double getHeight() {
return height;
}
}

Another advice for good Java programming, try to avoid somethink like this:
Code: [Select]
if (square == 1)
{
corner1 = square1.copy();
}
else if (square == 2)
{
corner1 = square2.copy();
}
else if (square == 3)
{
corner1 = square3.copy();
}
else if (square == 4)
....

use instead:
Code: [Select]
switch (square) {
case 1:
corner1 = square1.copy();
break;
case 2:
corner1 = square2.copy();
break;
case 3:
corner1 = square3.copy();
break;
case 4:
corner1 = square4.copy();
break;
default:
getLogger().error("This square is not supported: " + square);
break;
}

I hope, this is not too much code  :icon_smile:

November 13, 2018, 09:33:02 PM
Reply #10
Offline

barely_sane


Mikal kinda wrote it wrong. We havnt gotten the handguiding to work with our program. But it did work back before we replaced it with our own. As for the safety config we did was just adding an Output for the handguiding (inactive in AMF1 and active in AMF2) on Output CIB_SR. 12.

But we found some stuff in the sunrise workbench pdf how to impliment it. So we may make it with that.


Is it that appearent?  :icon_redface:

Well the deal is that we are 2 courses on this subject. The one im a part of, havent had much programming outside of the first semester. And to boot it have been in Arduino. The other course (which Mikal is a part of) have had Java in addition to Arduino, so they are bit better equipped for the task. But the biggest problem we have had with this whole thing is that, until this project which is tied to our exam, never had much relation to the robot. We where until week 42 only working with PLCs in e!Cockpit. And there isnt much help from those employed by the school, tho we get help from the students that had this project last year at times.

So im sorry if we are being a bother, but we have been wrecking heads for a while and this have been some kind of a last resort.

And again, we are greatful to you and NullReference for helping us getting it as far as it has.  :respect:

November 15, 2018, 11:45:16 AM
Reply #11
Offline

barely_sane


Code: [Select]
package application;

import javax.inject.Inject;
import com.kuka.roboticsAPI.applicationModel.RoboticsAPIApplication;
import static com.kuka.roboticsAPI.motionModel.BasicMotions.*;
import com.kuka.roboticsAPI.deviceModel.LBR;
import com.kuka.roboticsAPI.geometricModel.Frame;
import com.kuka.roboticsAPI.geometricModel.Tool;
import com.kuka.roboticsAPI.motionModel.CIRC;
import com.kuka.roboticsAPI.motionModel.CartesianPTP;
import com.kuka.roboticsAPI.motionModel.LIN;
import com.kuka.roboticsAPI.motionModel.MotionBatch;

public class TicTacToe extends RoboticsAPIApplication
{
@Inject
Tool tool;
LBR robot;

Frame canvas = new Frame();
Frame homePosition = new Frame();

// Contains the corners in the drawCross method.
Frame corner1 = new Frame();
Frame corner2 = new Frame();
Frame corner3 = new Frame();
Frame corner4 = new Frame();

Frame square1 = new Frame(canvas);
Frame square2 = new Frame(canvas);
Frame square3 = new Frame(canvas);
Frame square4 = new Frame(canvas);
Frame square5 = new Frame(canvas);
Frame square6 = new Frame(canvas);
Frame square7 = new Frame(canvas);
Frame square8 = new Frame(canvas);
Frame square9 = new Frame(canvas);
Frame playGround = new Frame(canvas);

// Contains the two points of the circle in the drawCircle method.
Frame auxiliarry = new Frame();
Frame StartEnd = new Frame();

private double canvasWidthHeight = 300;
double squareWidthHeight = canvasWidthHeight / 3;

@Override
public void initialize()
{
robot = getContext().getDeviceFromType(LBR.class);
tool = getApplicationData().createFromTemplate("tool"); 

// Get the canvas base.
this.canvas = getApplicationData().getFrame("/canvas").copy();
this.homePosition = getApplicationData().getFrame("/homePosition").copy();

tool.attachTo(robot.getFlange());

square1.setX(squareWidthHeight / 2);
square1.setY(squareWidthHeight / 2);

square2.setX(squareWidthHeight / 2 + squareWidthHeight);
square2.setY(squareWidthHeight / 2);

square3.setX(squareWidthHeight / 2 + squareWidthHeight * 2);
square3.setY(squareWidthHeight / 2);

square4.setX(squareWidthHeight / 2);
square4.setY(squareWidthHeight / 2 + squareWidthHeight);

square5.setX(squareWidthHeight / 2 + squareWidthHeight);
square5.setY(squareWidthHeight / 2 + squareWidthHeight);

square6.setX(squareWidthHeight / 2 + squareWidthHeight * 2);
square6.setY(squareWidthHeight / 2 + squareWidthHeight);

square7.setX(squareWidthHeight / 2);
square7.setY(squareWidthHeight / 2 + squareWidthHeight * 2);

square8.setX(squareWidthHeight / 2 + squareWidthHeight);
square8.setY(squareWidthHeight / 2 + squareWidthHeight * 2);

square9.setX(squareWidthHeight / 2 + squareWidthHeight * 2);
square9.setY(squareWidthHeight / 2 + squareWidthHeight * 2);
}


@Override
public void run()
{
drawPlayGround();
drawCross(1);
    drawCircle(2);
}

private void drawPlayGround()
{
Frame point1 = playGround;
Frame point2 = playGround;
Frame point3 = playGround;
Frame point4 = playGround;
Frame point5 = playGround;
Frame point6 = playGround;
Frame point7 = playGround;
Frame point8 = playGround;

point1.setX(point1.getX() + squareWidthHeight); // Y = 0
point2.setX(point2.getX() + squareWidthHeight*2); // Y = 0
point3.setX(point3.getX() + canvasWidthHeight);
point3.setY(point3.getY() + squareWidthHeight);
point4.setX(point4.getX() + canvasWidthHeight);
point4.setY(point4.getY() + squareWidthHeight*2);
point5.setX(point5.getX() + squareWidthHeight*2);
point5.setY(point5.getY() + canvasWidthHeight);
point6.setX(point6.getX() + squareWidthHeight);
point6.setY(point6.getY() + canvasWidthHeight);
point7.setY(point7.getY() + squareWidthHeight*2); // X = 0
point8.setY(point8.getY() + squareWidthHeight); // X = 0

// Create all the motions and send them as a batch to the controller
CartesianPTP toPrePosition = ptp(point1.setZ(50));
LIN toPoint1 = lin((point1).setZ(50));
LIN toDrawPoint1 = lin(point1.copy().setZ(30));
LIN toDrawPoint6 = lin(point6.copy().setZ(30));
LIN toPoint6 = lin((point6).setZ(50));
LIN toPoint5 = lin((point5).setZ(50));
LIN toDrawPoint5 = lin(point5.copy().setZ(30));
LIN toDrawPoint2 = lin(point2.copy().setZ(30));
LIN toPoint2 = lin((point2).setZ(50));
LIN toPoint3 = lin((point3).setZ(50));
LIN toDrawPoint3 = lin(point3.copy().setZ(30));
LIN toDrawPoint8 = lin(point8.copy().setZ(30));
LIN toPoint8 = lin((point8).setZ(50));
LIN toPoint7 = lin((point7).setZ(50));
LIN toDrawPoint7 = lin(point7.copy().setZ(30));
LIN toDrawPoint4 = lin(point4.copy().setZ(30));
LIN toPoint4 = lin((point4).setZ(50));

// Move the tool to a start position so we know it can plan the motions
robot.move(ptp(homePosition).setJointVelocityRel(0.3));

MotionBatch batch = new MotionBatch(toPrePosition,
toPoint1, toDrawPoint1, toDrawPoint6, toPoint6,
toPoint5, toDrawPoint5, toDrawPoint2, toPoint2,
toPoint3, toDrawPoint3, toDrawPoint8, toPoint8,
toPoint7, toDrawPoint7, toDrawPoint4, toPoint4);

batch.setJointVelocityRel(0.3);
tool.move(batch);

// Return to the start position
robot.move(ptp(homePosition).setJointVelocityRel(0.3));
}

private void drawCross(int square)
{
switch (square)
{
case 1:
corner1 = square1.copy();
corner2 = square1.copy();
corner3 = square1.copy();
corner4 = square1.copy();
break;
case 2:
corner1 = square2.copy();
corner2 = square2.copy();
corner3 = square2.copy();
corner4 = square2.copy();
break;
case 3:
corner1 = square3.copy();
corner2 = square3.copy();
corner3 = square3.copy();
corner4 = square3.copy();
break;
case 4:
corner1 = square4.copy();
corner2 = square4.copy();
corner3 = square4.copy();
corner4 = square4.copy();
break;
case 5:
corner1 = square5.copy();
corner2 = square5.copy();
corner3 = square5.copy();
corner4 = square5.copy();
break;
case 6:
corner1 = square6.copy();
corner2 = square6.copy();
corner3 = square6.copy();
corner4 = square6.copy();
break;
case 7:
corner1 = square7.copy();
corner2 = square7.copy();
corner3 = square7.copy();
corner4 = square7.copy();
break;
case 8:
corner1 = square8.copy();
corner2 = square8.copy();
corner3 = square8.copy();
corner4 = square8.copy();
break;
case 9:
corner1 = square9.copy();
corner2 = square9.copy();
corner3 = square9.copy();
corner4 = square9.copy();
break;
default:
getLogger().error("This square is not supported: " + square);
break;
}

corner1.setX(corner1.getX() + squareWidthHeight / 2);
corner1.setY(corner1.getY() + squareWidthHeight / 2);
corner2.setX(corner2.getX() - squareWidthHeight / 2);
corner2.setY(corner2.getY() - squareWidthHeight / 2);
corner3.setX(corner3.getX() - squareWidthHeight / 2);
corner3.setY(corner3.getY() + squareWidthHeight / 2);
corner4.setX(corner4.getX() + squareWidthHeight / 2);
corner4.setY(corner4.getY() - squareWidthHeight / 2);

// Create all the motions and send them as a batch to the controller
CartesianPTP toPrePosition = ptp((corner1).setZ(50));
LIN toCorner1 = lin((corner1).setZ(50));
LIN toDrawCorner1 = lin(corner1.copy().setZ(30));
LIN toDrawCorner2 = lin(corner2.copy().setZ(30));
LIN toCorner2 = lin((corner2).setZ(50));
LIN toCorner3 = lin((corner3).setZ(50));
LIN toDrawCorner3 = lin((corner3.copy()).setZ(30));
LIN toDrawCorner4 = lin((corner4.copy()).setZ(30));
LIN toCorner4 = lin((corner4).setZ(50));

// Move the tool to a start position so we know it can plan the motions
robot.move(ptp(homePosition).setJointVelocityRel(0.3));

MotionBatch batch = new MotionBatch(toPrePosition,
toCorner1, toDrawCorner1,
toDrawCorner2, toCorner2,
toCorner3, toDrawCorner3,
toDrawCorner4, toCorner4);

batch.setJointVelocityRel(0.3);
tool.move(batch);

// Return to the start position
robot.move(ptp(homePosition).setJointVelocityRel(0.3));
}

private void drawCircle(int square)
{
switch (square)
{
case 1:
auxiliarry = square1.copy();
StartEnd = square1.copy();
break;
case 2:
auxiliarry = square2.copy();
StartEnd = square2.copy();
break;
case 3:
auxiliarry = square3.copy();
StartEnd = square3.copy();
break;
case 4:
auxiliarry = square4.copy();
StartEnd = square4.copy();
break;
case 5:
auxiliarry = square5.copy();
StartEnd = square5.copy();
break;
case 6:
auxiliarry = square6.copy();
StartEnd = square6.copy();
break;
case 7:
auxiliarry = square7.copy();
StartEnd = square7.copy();
break;
case 8:
auxiliarry = square8.copy();
StartEnd = square8.copy();
break;
case 9:
auxiliarry = square9.copy();
StartEnd = square9.copy();
break;
default:
getLogger().error("This square is not supported: " + square);
break;
}

StartEnd.setX(StartEnd.getX() - ((squareWidthHeight / 2) - (squareWidthHeight / 10)));
auxiliarry.setX(auxiliarry.getX() + ((squareWidthHeight / 2) - (squareWidthHeight / 10)));

// Move the tool to a start position so we know it can plan the motions
robot.move(ptp(homePosition).setJointVelocityRel(0.3));

// Create all the motions and send them as a batch to the controller
CartesianPTP toPrePosition = ptp(StartEnd.copy().setZ(50));
LIN toStartCircle = lin((StartEnd).setZ(30));
CIRC drawCircle = circ(auxiliarry, StartEnd);
LIN toEndCircle = lin((StartEnd).setZ(50));

MotionBatch batch = new MotionBatch(toPrePosition, toStartCircle, drawCircle, toEndCircle);

batch.setJointVelocityRel(0.3);
tool.move(batch);

// Return to the start position
robot.move(ptp(homePosition).setJointVelocityRel(0.3));
}
}

We have now modified the code according to what you suggested, as well as declaring the robot and the tool. Now we are able to make the robot move to home position, which is located 500mm above the canvas, but now we get the error shown below.



What should we do to solve this? We cant locate the culprint.

November 15, 2018, 03:06:56 PM
Reply #12
Offline

DrG


Hi barely_sane,

from a quick glance on your code,
Code: [Select]
@Inject
Tool tool;
LBR robot;

I would expect, that the Nullpointer exception stems from a missing "@Inject"

Code: [Select]
@Inject
Tool tool;
@Inject  /// <<<< Missing Inject? In this case, the Robot is not initialized, which might lead to the reported Null-Pointer exception
LBR robot;


Greetings,
DrG

November 15, 2018, 03:22:22 PM
Reply #13
Offline

mikalaanning


@Inject
   Tool tool;
   LBR robot;
[/code]

I would expect, that the Nullpointer exception stems from a missing "@Inject"

Code: [Select]
@Inject
Tool tool;
@Inject  /// <<<< Missing Inject? In this case, the Robot is not initialized, which might lead to the reported Null-Pointer exception
LBR robot;


Greetings,
DrG

Forgot to mention this, we have initialized the robot and managed to move the robot down to a point we calibrated in the origo, but when using the movement in the motion batch the robot just stops and gives us the Error code showed. We belive this to be because we have made points out of the canvas frame.. read this another place saying that it were something with different parameters ect.. but couldnt find an solution..

Today at 07:58:25 AM
Reply #14

Advertisement

Guest

November 15, 2018, 04:30:12 PM
Reply #14
Offline

NullReference


Debug your program with the eclipse debugger. Put a breakpoint one line before the code that generates the NPE. When the breakpoint is hit check all objects that might be null by hovering over them with the mouse.

November 15, 2018, 05:24:47 PM
Reply #15
Offline

razzo


I guess you have problems with the redundancy of the robot position. This is a really ugly problem with the LBR iiwa which cannot be solved so easily. We cannot see in which line the problem actually occurs.
This redundancy problem is no LBR iiwa specific problem, but here it is more difficult because of the 7 joints and the special joint configuration.
The manual provides some information about this in chapter 14.10 'Redundancy information'.

So you can drive to your 'homePosition'?
But not to the next position 'toPrePosition = ptp(point1.setZ(50))'?
==> The problem could be that you initialize the 'playGround' in you field declation with an Frame which is at this time empty or 'null'.
Code: [Select]
Frame canvas = new Frame();
Frame playGround = new Frame(canvas);
==> Initialize 'playGround' in your initialize(), below:
Code: [Select]
this.canvas = getApplicationData().getFrame("/canvas"); // .copy() is not neccessary or even worth, it leads to an error.
This could probably help you. For now.

November 16, 2018, 01:41:38 PM
Reply #16
Offline

mikalaanning


Hello! We have done some more changes to the code, among others we realized that our implementation of the frame "playGround" had its flaws since it didn't have "canvas" as its parent. We then realized that when we put "canvas" as a parent to "playGround" and the points used in "drawPlayGround" had "playGround" as a parent, we could cut out a generation of parents and make "canvas" the parent of the points. We then hit another wall.

The issue we have now may be simple to fix, but we can't get our heads around it.  :wallbash:

Here you see the motion when our robot moves to its home position, this works without any issue.


Here you see the motion of the batch drawing the playground. The coordinates showing are the right calculated one based on the canvas itself.


And here you see the "Canvas" Base.


So our question now is;
How can we make the robot draw from the points calculated on another frame that is set as a base?
Are we on the right track? If not, could you show us the way?
    :help:

This is the error we're getting.


Thanks a lot again!  :dance2:
« Last Edit: November 16, 2018, 02:09:32 PM by mikalaanning »

November 16, 2018, 03:07:05 PM
Reply #17
Offline

razzo


The ExecutionException says that you want to move to a position which is X=100 and everything else 0. This will not work, because the robot cannot move to this position. The robot is not that flexiable :(
Does this Frame you want to move to have redundancy information?! If not, the robot cannot move to this position. And if the frame has redundancy information and they are wrong, the robot cannot move to this position ...
For further information read previous posts ...

November 16, 2018, 07:24:10 PM
Reply #18
Offline

NullReference


Well, that's a very unhelpful exception. Try copying the base with copyWithRedundancy();

Also move the robot with tool.move(). robot.move() plans the motions with the flange.

Debug again and post a picture of the motion that throws this exception. Hover your mouse over the motion and expand all fields. Something is null and it shouldn't be.

November 23, 2018, 02:16:09 AM
Reply #19
Offline

Seulki


Hi guys,

Think it might be a very late answer, but anyways by the brief look of your code, the error you're having might still be caused by initializing issue,
Code: [Select]
Frame canvas = new Frame();
Frame playGround = new Frame(canvas);
this.canvas = getApplicationData().getFrame("/canvas").copy();
Frame point1 = playGround;
Your former code above,
doing it in this sequence will never give you desired values to your 'playGround' and 'point1' variables.
because you passed an instance of canvas to playGround before it actually have some values. -> java is pass by value not pass by reference
And this is why we are not suggested to initialize field variables(class variables) at the same time we declare it.
simply, it should be like this,
Code: [Select]
// field variables
Frame canvas;
Frame playGround;
public void initialize() {
this.canvas = getApplicationData().getFrame("/canvas").copyWithRedundancy();
// I highly recommend you to use copyWithRedundancy() insteady of copy(). Former one copies transformation including redundancy information while later one only copies transformation.
playGround = new Frame(canvas);
}
I do not know how you fixed it, but if you're seeing the error message saying 'cannot map the command...',
your target frame is not having a path from the only genuine static frame that is World.
By the code 'new Frame(AbstractFrame parent)', the frame should have path to the parent frame unless your parent itself is also not having a correct path to World.
I'm just saying because this is the reason for your former code, and I do not know your revised code.

Just in case, for you to patch it up, .setParent(canvas) right before you modify transformation values might be a way also.

And few more tips you might want to know,
1. Use ObjectFrame for taught frames(points you actually taught), and use Frame for the ones you made in a program.
2. Use .copyWithRedundancy() to convert your ObjectFrame to a Frame.
3. Using setX/setY/setZ... will change your frame's value only relatively to the frame itself(which is relative to its parent's transformation/orientation) which means every frames must be set as a child of a frame which you want to use as a base; in your case I think it's Canvas.
   When it comes that you need to transform your frame relatively to other frame or to World frame, refer to the code below instead,
Code: [Select]
point1.transform( World.Current.getRootFrame(), Transformation.ofTranslation( x, y, z ) )
  // point1 will be transformed x/y/z relative to World
4. Try use arrays(if the number is set) or List(if the number varies) to make your code compact and iterable.
« Last Edit: November 23, 2018, 02:23:21 AM by Seulki »

November 24, 2018, 09:02:45 AM
Reply #20
Offline

NullReference


point1.transform( World.Current.getRootFrame(), Transformation.ofTranslation( x, y, z ) )
  // point1 will be transformed x/y/z relative to World [/code]

I just encountered this yesterday. If I understood correctly, modifying the translation of  the frame directly is like modifying the frame relative to a parent that has the exact same transformation of the frame you are modifying. If that's right then that's so stupid. If you want to modify a frame relative to the closest parent (which most of the time is what is preferred) then you have to get or create the parent also so you can transform from the parents coordinate system.

Today at 07:58:25 AM
Reply #21

Advertisement

Guest

November 26, 2018, 02:37:57 AM
Reply #21
Offline

Seulki


I'm not really sure if I understood what you mean either. I was thinking about the opposite situation. 'If I want to modify a frame relative to other frames than its parent'
What I was suggesting is that it might be better to use transformation() method instead of setX/Y/Z/A/B/C() methods.
using set...() has only capability to transform itself with referring to it's own(parent's) orientation.
while transformation() has capability to take other frame as its orientation reference.
-> You can't 'simply; yes it's still possible with setParent()' modify your frame to be placed 50mm upward from its ground(World +z) when its parent is not having an aligned orientation to the world.
Code: [Select]
// to transform 'corner1' 50mm regarding canvas Z+
corner1.transform( canvas, Transformation.ofTranslation( 0, 0, 50 ) );
// or
AbstractFrame formerParent = corner1.getParent();
corner1.setParent( canvas, true );
corner1.setZ( corner1.getZ() + 50  );
corner1.setParent( formerParent, true );

Of course we can simply use set...() methods when a reference frame is not needed. But in that case as well, I'd personally prefer use transformation().
With respect, enlighten me if I'm trapped in my way. :)
« Last Edit: November 26, 2018, 04:15:47 AM by Seulki »

November 26, 2018, 06:13:48 PM
Reply #22
Offline

NullReference


If you want to modify a frame relative to the closest parent (which most of the time is what is preferred) then you have to get or create the parent also so you can transform from the parents coordinate system.
I'm not really sure if I understood what you mean either. I was thinking about the opposite situation. 'If I want to modify a frame relative to other frames than its parent'
What I was suggesting is that it might be better to use transformation() method instead of setX/Y/Z/A/B/C() methods.
using set...() has only capability to transform itself with referring to it's own(parent's) orientation.
while transformation() has capability to take other frame as its orientation reference.
-> You can't 'simply; yes it's still possible with setParent()' modify your frame to be placed 50mm upward from its ground(World +z) when its parent is not having an aligned orientation to the world.
Code: [Select]
// to transform 'corner1' 50mm regarding canvas Z+
corner1.transform( canvas, Transformation.ofTranslation( 0, 0, 50 ) );
// or
AbstractFrame formerParent = corner1.getParent();
corner1.setParent( canvas, true );
corner1.setZ( corner1.getZ() + 50  );
corner1.setParent( formerParent, true );

Of course we can simply use set...() methods when a reference frame is not needed. But in that case as well, I'd personally prefer use transformation().
With respect, enlighten me if I'm trapped in my way. :)
[/quote]

I had a frame defined within a base. Getting the frame from getApplicationData() and then increasing z by 10mm  transformed the frame not in the positive z-direction of the parent frame but in the z-direction of the frame itself. I had to fetch the parent frame (base) and set the base as a parent to the frame I wanted to transform. After setting the parent my transformation started behaving as it should.  I used the debugger to check if the frame had a parent prior to setting its parent programatically and sure enough it already had a reference to the parent frame.

Going by your comment this is not how a simple transformation  should behave in this API so I must have done something wrong while transforming.

I agree that transform() is more capable however most of the time I just want to transform relative to the closest parent and just transform 1 coordinate axis.
« Last Edit: November 26, 2018, 06:17:03 PM by NullReference »


Share via facebook Share via linkedin Share via pinterest Share via reddit Share via twitter

xx
Expert opinion needed

Started by jibesh on KUKA Robot Forum

6 Replies
3829 Views
Last post August 06, 2014, 08:14:53 AM
by BogdanRentea
xx
Vim Users: I want your opinion on krl-for-vim and rapid-for-vim

Started by KnoP on General Discussion of Industrial Robots Only

2 Replies
1095 Views
Last post February 02, 2018, 07:21:27 PM
by KnoP
clip
Crash Log Report -Second Opinion

Started by camae on KUKA Robot Forum

4 Replies
2535 Views
Last post April 24, 2013, 01:58:18 AM
by camae
xx
Expert Mode

Started by danielisrael on Nachi Robots

3 Replies
1138 Views
Last post May 18, 2018, 06:05:05 AM
by danielisrael