FEEL I código fonte
Category : Código, Investigação
Num artigo anterior, partilhei a lógica e a inspiração para a aplicação FEEL que desenvolvemos (eu e o João Pedro Sousa) para a KUKA iiwa 7 executar durante o FISTA 2019 no ISCTE-IUL. Atrás da cortina, o braço robótico está a correr uma aplicação simples escrita em JAVA, desenvolvida especificamente para este propósito. Especificamente, a aplicação é corrida por um computador que comanda o braço e o “vigia” para garantir que este cumpre as regras de segurança que garantem o ambiente colaborativo. No entanto, o braço é tão colaborativo quanto a aplicação que corre. É a responsabilidade do programador e do operador garantir que todas as medidas de segurança estão em vigor. Terminado o sermão segue-se a aplicação:
package application;
import java.util.ArrayList;
import java.util.List;
import com.kuka.generated.ioAccess.GripperIOGroup;
import com.kuka.roboticsAPI.applicationModel.RoboticsAPIApplication;
import com.kuka.roboticsAPI.conditionModel.ForceCondition;
import com.kuka.roboticsAPI.conditionModel.ICondition;
import com.kuka.roboticsAPI.deviceModel.LBR;
import com.kuka.roboticsAPI.geometricModel.Frame;
import com.kuka.roboticsAPI.geometricModel.Tool;
import com.kuka.roboticsAPI.geometricModel.World;
import com.kuka.roboticsAPI.geometricModel.math.CoordinateAxis;
import com.kuka.roboticsAPI.geometricModel.math.Transformation;
import com.kuka.roboticsAPI.motionModel.BasicMotions;
import com.kuka.roboticsAPI.motionModel.IMotionContainer;
public class PickAndPlace_Fista extends RoboticsAPIApplication {
private LBR _lbr;
private Tool _gripper;
private GripperIOGroup _iogroup;
private Frame _pt;
private List<Frame> _listPt = new ArrayList<Frame>();
private List<Boolean> _rotation = new ArrayList<Boolean>();
@Override
public void initialize() {
_lbr = getContext().getDeviceFromType(LBR.class);
_gripper = (Tool) createFromTemplate("MyVirtualGripper");
_gripper.attachTo(_lbr.getFlange());
_iogroup = new GripperIOGroup(_lbr.getController());
}
public void run() throws Exception {
double cellXY = 63.0;
double cellZ = 20.0;
int numCellX = 5;
int numCellY = 5;
int numCellZ = 4;
int count = 0;
double tol = 3.0;
double vel1 = 20; // cartesian slow
double vel2 = 90; // cartesian fast
double jointVel1 = 0.07; // joint slow
double jointVel2 = 0.18; // joint fast
double breakForce = 5;
_pt = getFrame("/baseFista/P2").copy();
//generate all the positions that the robot will visit
for (int i = 0; i < numCellZ; i++) {
for (int j = 0; j < numCellX; j++) {
for (int k = 0; k < numCellY; k++) {
Frame tempPt = _pt.copy();
tempPt.setZ(_pt.getZ() + cellZ * i + cellZ / 2);
tempPt.setX(_pt.getX() + cellXY * j);
tempPt.setY(_pt.getY() + cellXY * k);
count = i + j + k;
if (count % 2 < 1) {//now rotate the gripper
_rotation.add(false);
} else {
_rotation.add(true);
tempPt.setAlphaRad(tempPt.getAlphaRad() + Math.PI / 2);
}
// we don't really need to add the points to a list because the robot will visit each position as it's created
_listPt.add(tempPt);
// Ensure that the gripper is open before we try to pick something
_iogroup.setOut_Close(false);
_iogroup.setOut_Open(true);
// now move to the station (P1 is a point 20mm above the piece we want to pick)
_gripper.move(BasicMotions.ptp(getFrame("/baseFista/P1").copy().transform(Transformation.ofTranslation(0, 0, -30))).setJointVelocityRel(jointVel2));
_gripper.move(BasicMotions.lin(
getFrame("/baseFista/P1").copy().transform(
Transformation.ofTranslation(0, 0, -10)))
.setCartVelocity(vel1));
// Now we pick the piece
_iogroup.setOut_Open(false);
_iogroup.setOut_Close(true);
// We step back from the station to a safe point
_gripper.move(BasicMotions.lin(
getFrame("/baseFista/P1").copy().transform(
Transformation.ofTranslation(0, 0, -100)))
.setJointVelocityRel(jointVel2));
// first move to a position a little bit above the desired position.
_gripper.move(BasicMotions.ptp(
tempPt.copy().transform(
Transformation.ofTranslation(0, 0, - cellZ * (numCellZ + 3))))
.setJointVelocityRel(jointVel2));
// Create the condition that if broken will cause the robot to react
ICondition cond = ForceCondition
.createNormalForceCondition(
_gripper.getDefaultMotionFrame(),
CoordinateAxis.Z, breakForce);
Frame fr = _lbr.getCurrentCartesianPosition(_gripper.getDefaultMotionFrame());
IMotionContainer container = _lbr.move(BasicMotions
.linRel(0, 0, - cellZ * (numCellZ + 2) - tol)
.setReferenceFrame(World.Current.getRootFrame())
.setJointVelocityRel(jointVel1).breakWhen(cond));
if (container.getFiredBreakConditionInfo() != null) {
// if the condition is broken before reaching the desired position; determine the distance to the desired position and divide it by cellZ
// if the remainder of the division by two is 1, change the boolean
// place the object at the new location
double x = _lbr.getCurrentCartesianPosition(
_gripper.getDefaultMotionFrame())
.distanceTo(fr.copy());
double y = (cellZ * (numCellZ + 2) - x - tol) / cellZ;
getLogger().info("x:" + x);
getLogger().info("y:" + y);
_lbr.move(BasicMotions
.linRel(0, 0, cellZ*4)
.setReferenceFrame(World.Current.getRootFrame())
.setCartVelocity(vel2)); // move back a bit
if (y % 2 < 1) {
_gripper.move(BasicMotions.linRel(0,0,0, Math.PI / 2 , 0,0));
}
_gripper.move(BasicMotions.linRel(0, 0, cellZ * 4)
.setCartVelocity(vel1).breakWhen(cond)); // this motion is using the TCP of the gripper
_iogroup.setOut_Close(false);
_iogroup.setOut_Open(true);
_gripper.move(BasicMotions.linRel(0, 0, -(cellZ * 3 + y))
.setCartVelocity(vel2)); // this motion is using the TCP of the gripper
continue;
}
//we have come most of the way to where we wanted to be and still there is nothing in the way
// now move to a position that is a little bellow the desired position
// if you feel something in the way place the object in the desired position
container = _lbr.move(BasicMotions.linRel(0, 0, -cellZ)
.setReferenceFrame(World.Current.getRootFrame())
.setJointVelocityRel(jointVel1)
.breakWhen(cond));
if (container.getFiredBreakConditionInfo() != null) {
_iogroup.setOut_Close(false);
_iogroup.setOut_Open(true);
_gripper.move(BasicMotions.linRel(0, 0, -(cellZ * (numCellZ + 3)))
.setCartVelocity(vel2));
continue;
}
//Wait! There is no support for the piece the robot is carrying!
// now move until you touch something (up to the base plane)
container = _lbr.move(BasicMotions
.linRel(0, 0, -cellZ * numCellZ)
.setReferenceFrame(World.Current.getRootFrame())
.setJointVelocityRel(jointVel1)
.breakWhen(cond));
if (container.getFiredBreakConditionInfo() != null) {
double x = _lbr.getCurrentCartesianPosition(
_gripper.getDefaultMotionFrame())
.distanceTo(fr.copy());
double y = (x + tol - cellZ * (numCellZ + 3)) / cellZ;
_lbr.move(BasicMotions
.linRel(0, 0, cellZ*4)
.setReferenceFrame(World.Current.getRootFrame())
.setCartVelocity(vel2)); // move back a bit
if (!(y % 2 < 1)) {
_gripper.move(BasicMotions.linRel(0,0,0, Math.PI / 2 , 0,0));
}
_gripper.move(BasicMotions.linRel(0, 0, cellZ * 4)
.setCartVelocity(vel1)
.breakWhen(cond));// this motion is using the TCP of the gripper
_iogroup.setOut_Close(false);
_iogroup.setOut_Open(true);
_gripper.move(BasicMotions.linRel(0, 0, -(cellZ * 4 + y))
.setCartVelocity(vel2));// this motion is using the TCP of the gripper
}
}
}
}
}
@Override
public void dispose() {
// TODO Auto-generated method stub
super.dispose();
}
}
English
Português