import java.io.File;
import java.util.LinkedList;
import java.util.Queue;
import org.apache.commons.io.FileUtils;
import org.junit.Test;
import org.openpnp.machine.reference.ReferenceActuator;
import org.openpnp.machine.reference.ReferenceHeadMountable;
import org.openpnp.machine.reference.ReferenceMachine;
import org.openpnp.machine.reference.ReferenceNozzle;
import org.openpnp.machine.reference.driver.test.TestDriver;
import org.openpnp.machine.reference.driver.test.TestDriver.TestDriverDelegate;
import org.openpnp.model.Board;
import org.openpnp.model.Board.Side;
import org.openpnp.model.BoardLocation;
import org.openpnp.model.Configuration;
import org.openpnp.model.Job;
import org.openpnp.model.LengthUnit;
import org.openpnp.model.Location;
import org.openpnp.model.Placement;
import org.openpnp.spi.Head;
import org.openpnp.spi.HeadMountable;
import org.openpnp.spi.JobProcessor;
import org.openpnp.spi.Machine;
import org.openpnp.spi.Nozzle;
import com.google.common.io.Files;
public class BasicJobTest {
/**
* Creates a basic job in memory and attempts to run it. The Driver is monitored to make sure it
* performs a pre-defined set of expected moves. This test is intended to test the primary
* motions and operation of the entire system, including feeding, picking, placing and basic job
* processing.
*
* TODO: Don't ignore additional movements after the expected movements complete. This should
* cause the test to fail and it does not currently.
*
* @throws Exception
*/
@Test
public void testSimpleJob() throws Exception {
File workingDirectory = Files.createTempDir();
workingDirectory = new File(workingDirectory, ".openpnp");
System.out.println("Configuration directory: " + workingDirectory);
// Copy the required configuration files over to the new configuration
// directory.
FileUtils.copyURLToFile(ClassLoader.getSystemResource("config/BasicJobTest/machine.xml"),
new File(workingDirectory, "machine.xml"));
FileUtils.copyURLToFile(ClassLoader.getSystemResource("config/BasicJobTest/packages.xml"),
new File(workingDirectory, "packages.xml"));
FileUtils.copyURLToFile(ClassLoader.getSystemResource("config/BasicJobTest/parts.xml"),
new File(workingDirectory, "parts.xml"));
Configuration.initialize(workingDirectory);
Configuration.get().load();
Machine machine = Configuration.get().getMachine();
ReferenceMachine referenceMachine = (ReferenceMachine) machine;
TestDriver testDriver = (TestDriver) referenceMachine.getDriver();
BasicJobTestDriverDelegate delegate = new BasicJobTestDriverDelegate();
testDriver.setDelegate(delegate);
Job job = createSimpleJob();
Head h1 = machine.getHead("H1");
Nozzle n1 = h1.getNozzle("N1");
Nozzle n2 = h1.getNozzle("N2");
delegate.expectMove("Move N1 Nozzle Change Unload", n1,
new Location(LengthUnit.Millimeters, 40, 0, 0, 0), 1.0);
delegate.expectMove("Move N1 Nozzle Change Load", n1,
new Location(LengthUnit.Millimeters, 50, 0, 0, 0), 1.0);
delegate.expectMove("Move N1 to F1", n1, new Location(LengthUnit.Millimeters, -10, 0, 0, 0),
1.0);
delegate.expectPick(n1);
delegate.expectMove("Move N2 to F1", n2, new Location(LengthUnit.Millimeters, -20, 0, 0, 0),
1.0);
delegate.expectPick(n2);
delegate.expectMove("Move N1 to R1, Safe-Z", n1,
new Location(LengthUnit.Millimeters, 0, 10, 0, 45), 1.0);
delegate.expectMove("Move N1 to R1, Z", n1,
new Location(LengthUnit.Millimeters, 0, 10, 0.825500, 45), 1.0);
delegate.expectPlace(n1);
delegate.expectMove("Move N1 to R1, Safe-Z", n1,
new Location(LengthUnit.Millimeters, 0, 10, 0, 45), 1.0);
delegate.expectMove("Move N2 to R2, Safe-Z", n2,
new Location(LengthUnit.Millimeters, 00, 20, 0, 90), 1.0);
delegate.expectMove("Move N2 to R2, Z", n2,
new Location(LengthUnit.Millimeters, 00, 20, 0.825500, 90), 1.0);
delegate.expectPlace(n2);
delegate.expectMove("Move N2 to R2, Safe-Z", n2,
new Location(LengthUnit.Millimeters, 00, 20, 0, 90), 1.0);
JobProcessor jobProcessor = machine.getPnpJobProcessor();
machine.setEnabled(true);
jobProcessor.initialize(job);
while (jobProcessor.next());
}
private Job createSimpleJob() {
Job job = new Job();
Board board = new Board();
board.setName("test");
board.addPlacement(createPlacement("R1", "R-0805-10K", 10, 10, 0, 45, Side.Top));
board.addPlacement(createPlacement("R2", "R-0805-10K", 20, 20, 0, 90, Side.Top));
BoardLocation boardLocation = new BoardLocation(board);
boardLocation.setLocation(new Location(LengthUnit.Millimeters, 0, 0, 0, 0));
boardLocation.setSide(Side.Top);
job.addBoardLocation(boardLocation);
return job;
}
public static Placement createPlacement(String id, String partId, double x, double y, double z,
double rotation, Side side) {
Placement placement = new Placement(id);
placement.setPart(Configuration.get().getPart(partId));
placement.setLocation(new Location(LengthUnit.Millimeters, x, y, z, rotation));
placement.setSide(side);
return placement;
}
/**
* TODO: Allow passing of null for the expect methods to ignore a particular field.
*/
public static class BasicJobTestDriverDelegate extends TestDriverDelegate {
private Queue<ExpectedOp> expectedOps = new LinkedList<>();
public void expectMove(String description, HeadMountable hm, Location location,
double speed) {
ExpectedMove o = new ExpectedMove(description, hm, location, speed);
expectedOps.add(o);
}
public void expectPick(Nozzle nozzle) {
expectedOps.add(new ExpectedPick(nozzle));
}
public void expectPlace(Nozzle nozzle) {
expectedOps.add(new ExpectedPlace(nozzle));
}
public void expectedActuate() {
expectedOps.add(new ExpectedActuate());
}
@Override
public void moveTo(ReferenceHeadMountable hm, Location location, double speed)
throws Exception {
if (expectedOps.isEmpty()) {
throw new Exception("Unexpected Move " + location + ".");
}
else {
ExpectedOp op = expectedOps.remove();
if (!(op instanceof ExpectedMove)) {
throw new Exception("Unexpected Move " + location + ". Expected " + op);
}
ExpectedMove move = (ExpectedMove) op;
if (!move.location.equals(location) || hm != move.headMountable) {
throw new Exception("Unexpected Move " + location + ". Expected " + op);
}
}
}
@Override
public void pick(ReferenceNozzle nozzle) throws Exception {
if (expectedOps.isEmpty()) {
throw new Exception("Unexpected Pick " + nozzle + ".");
}
else {
ExpectedOp op = expectedOps.remove();
if (!(op instanceof ExpectedPick)) {
throw new Exception("Unexpected Pick " + nozzle + ". Expected " + op);
}
ExpectedPick pick = (ExpectedPick) op;
if (pick.nozzle != nozzle) {
throw new Exception("Unexpected Pick " + nozzle + ". Expected " + op);
}
}
}
@Override
public void place(ReferenceNozzle nozzle) throws Exception {
if (expectedOps.isEmpty()) {
throw new Exception("Unexpected Place " + nozzle + ".");
}
else {
ExpectedOp op = expectedOps.remove();
if (!(op instanceof ExpectedPlace)) {
throw new Exception("Unexpected Place " + nozzle + ". Expected " + op);
}
ExpectedPlace place = (ExpectedPlace) op;
if (place.nozzle != nozzle) {
throw new Exception("Unexpected Place " + nozzle + ". Expected " + op);
}
}
}
@Override
public void actuate(ReferenceActuator actuator, boolean on) throws Exception {
// TODO Auto-generated method stub
super.actuate(actuator, on);
}
@Override
public void actuate(ReferenceActuator actuator, double value) throws Exception {
// TODO Auto-generated method stub
super.actuate(actuator, value);
}
class ExpectedOp {
}
class ExpectedPick extends ExpectedOp {
public Nozzle nozzle;
public ExpectedPick(Nozzle nozzle) {
this.nozzle = nozzle;
}
@Override
public String toString() {
return "Pick " + nozzle + " " + nozzle.getNozzleTip().getName();
}
}
class ExpectedPlace extends ExpectedOp {
public Nozzle nozzle;
public ExpectedPlace(Nozzle nozzle) {
this.nozzle = nozzle;
}
@Override
public String toString() {
return "Place " + nozzle + " " + nozzle.getNozzleTip().getName();
}
}
class ExpectedActuate extends ExpectedOp {
@Override
public String toString() {
return "Actuate";
}
}
class ExpectedMove extends ExpectedOp {
public HeadMountable headMountable;
public Location location;
public double speed;
public String description;
public ExpectedMove(String description, HeadMountable headMountable, Location location,
double speed) {
this.headMountable = headMountable;
this.location = location;
this.speed = speed;
this.description = description;
}
@Override
public String toString() {
return "Move (" + description + ") " + headMountable + " " + location.toString();
}
}
}
}