Skip to content

Commit

Permalink
Added solver.
Browse files Browse the repository at this point in the history
  • Loading branch information
markmaker committed May 25, 2020
1 parent e3a14a2 commit 4b8f935
Show file tree
Hide file tree
Showing 23 changed files with 2,312 additions and 292 deletions.
12 changes: 11 additions & 1 deletion src/main/java/org/openpnp/machine/neoden4/NeoDen4Driver.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import org.openpnp.model.Configuration;
import org.openpnp.model.Length;
import org.openpnp.model.LengthUnit;
import org.openpnp.model.Motion;
import org.openpnp.model.Named;
import org.openpnp.spi.Axis;
import org.openpnp.spi.ControllerAxis;
Expand Down Expand Up @@ -487,8 +488,17 @@ private void setMoveSpeed(double speed) throws Exception {
}

@Override
public void moveTo(ReferenceHeadMountable hm, AxesLocation location, double speed, MoveToOption... options)
public void moveTo(ReferenceHeadMountable hm, Motion motion, MoveToOption... options)
throws Exception {
AxesLocation location = motion.getVector(Motion.Derivative.Location);
double feedRate = motion.getFeedRatePerSecond(getUnits());
// Reconstruct speed factor from "virtual" feed-rate assuming the default
// 250mm/s axes feedrate.

// TODO: better solution.

double speed = Math.max(0.0, Math.min(1.0, feedRate/250.0));

double x = location.getCoordinate(location.getAxis(this, Axis.Type.X), units);
double y = location.getCoordinate(location.getAxis(this, Axis.Type.Y), units);
double z = location.getCoordinate(location.getAxis(this, Axis.Type.Z), units);
Expand Down
30 changes: 21 additions & 9 deletions src/main/java/org/openpnp/machine/reference/ReferenceDriver.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import java.io.Closeable;

import org.openpnp.model.AxesLocation;
import org.openpnp.model.Motion;
import org.openpnp.spi.Driver;
import org.openpnp.spi.MotionPlanner.CompletionType;
import org.openpnp.spi.Movable.MoveToOption;
Expand All @@ -32,13 +33,18 @@
* Defines the interface for a simple driver that the ReferenceMachine can drive. All methods result
* in machine operations and most methods should block until they are complete or throw an error.
*
* This Driver interface is intended to model a machine with one or more Heads, and each Head having
* one or more Nozzles and zero or more Cameras and Actuators.
* This Driver interface is intended to talk to one controller with Axes and Actuators attached.
*
* In OpenPnP, the Head does not move on it's own. It is moved by the moving of attached objects:
* Nozzles, Cameras, Actuators. For this reason, all movements on the driver are specified as
* movements by one of these objects. This allows the driver to make decisions as to what axes
* should be moved to accomplish a specific task.
* Nozzles, Cameras, Actuators, so-called HeadMountables. The HeadMountables specify with which axes
* they are moved. The axes are in turn assigned to the Driver. When you move a HeadMountable the
* MotionPlanner will determine which axes are involved and call the drivers accordingly.
*
* Drivers should only expose the functionality of the controller in a unified way. They should not add
* any additional logic on top like axis mapping, transformations etc. other than what is needed to make
* the controller behave like any other controller. This is different from previous versions of OpenPnP
* where the driver did much more.
*
*/
public interface ReferenceDriver extends Driver, WizardConfigurable, PropertySheetHolder, Closeable {
/**
Expand All @@ -53,7 +59,7 @@ public interface ReferenceDriver extends Driver, WizardConfigurable, PropertyShe
public void home(ReferenceMachine machine) throws Exception;

/**
* Set the current physical or virtual axis positions to be reinterpreted as the specified coordinates.
* Set the current physical axis positions to be reinterpreted as the specified coordinates.
* Used after visual homing and to reset a rotation angle after it has wrapped around.
*
* In G-Code parlance this is setting a global offset:
Expand All @@ -74,12 +80,11 @@ public interface ReferenceDriver extends Driver, WizardConfigurable, PropertyShe
*
* @param hm The HeadMountable having triggered the move. This is mostly for proprietary machine driver support
* and might only be a stand-in in some motion blending scenarios on the GcodeDriver.
* @param location destination
* @param speed relative speed (0-1) of the move
* @param motion the moveTo Motion to execute, including location, feedrate, acceleration etc. as shaped by the MotionPlanner
* @param options zero to n options from the MoveToOptions enum.
* @throws Exception
*/
public void moveTo(ReferenceHeadMountable hm, AxesLocation axesLocation, double speed, MoveToOption... options) throws Exception;
public void moveTo(ReferenceHeadMountable hm, Motion motion, MoveToOption... options) throws Exception;

/**
* Perform a coordinated wait for completion. This must be issued before capturing camera frames.
Expand Down Expand Up @@ -143,6 +148,13 @@ public default String actuatorRead(ReferenceActuator actuator, double parameter)

public default void createDefaults() throws Exception {}

/**
* Migrates the driver for the new global axes implementation. Is marked a deprecated as it can be removed
* along with the old GcodeDriver Axes implementation, if migration of users is expected to be complete.
*
* @param machine
* @throws Exception
*/
@Deprecated
void migrateDriver(ReferenceMachine machine) throws Exception;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import org.openpnp.model.Length;
import org.openpnp.model.LengthUnit;
import org.openpnp.model.Location;
import org.openpnp.spi.Axis;
import org.openpnp.spi.Movable.LocationOption;
import org.openpnp.spi.base.AbstractControllerAxis;
import org.simpleframework.xml.Attribute;
Expand Down Expand Up @@ -56,9 +57,6 @@ public class ReferenceControllerAxis extends AbstractControllerAxis {
@Element(required = false, data = true)
private String preMoveCommand;

@Element(required = false)
private Length homeCoordinate = new Length(0.0, LengthUnit.Millimeters);

@Element(required = false)
private Length softLimitLow = new Length(0.0, LengthUnit.Millimeters);

Expand Down Expand Up @@ -90,36 +88,25 @@ public class ReferenceControllerAxis extends AbstractControllerAxis {
@Element(required = false)
private double resolution = 0.0001; //

@Override
public Length getHomeCoordinate() {
return homeCoordinate;
}

@Override
public void setHomeCoordinate(Length homeCoordinate) {
Object oldValue = this.homeCoordinate;
this.homeCoordinate = homeCoordinate;
firePropertyChange("homeCoordinate", oldValue, homeCoordinate);
}

public double getResolution() {
if (resolution <= 0.0) {
resolution = 0.0001;
}
return resolution;
}

public void setResolution(double resolution) {
Object oldValue = this.resolution;
if (resolution <= 0.0) {
resolution = 0.0001;
}
this.resolution = resolution;
firePropertyChange("resolution", oldValue, resolution);
}

@Override
public double roundedToResolution(double coordinate) {
if (resolution != 0.0) {
return Math.round(coordinate/resolution)*resolution;
}
else {
return coordinate;
}
protected long getResolutionTicks(double coordinate) {
return Math.round(coordinate/getResolution());
}

public Length getFeedratePerSecond() {
Expand Down Expand Up @@ -218,13 +205,13 @@ public Wizard getConfigurationWizard() {
@Override
public double getMotionLimit(int order) {
if (order == 1) {
return getFeedratePerSecond().convertToUnits(LengthUnit.Millimeters).getValue();
return getFeedratePerSecond().convertToUnits(AxesLocation.getUnits()).getValue();
}
else if (order == 2) {
return getAccelerationPerSecond2().convertToUnits(LengthUnit.Millimeters).getValue();
return getAccelerationPerSecond2().convertToUnits(AxesLocation.getUnits()).getValue();
}
else if (order == 3) {
return getJerkPerSecond3().convertToUnits(LengthUnit.Millimeters).getValue();
return getJerkPerSecond3().convertToUnits(AxesLocation.getUnits()).getValue();
}
return 0;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,86 +26,31 @@
import org.openpnp.model.AxesLocation;
import org.openpnp.model.Length;
import org.openpnp.model.LengthUnit;
import org.openpnp.spi.Axis;
import org.openpnp.spi.CoordinateAxis;
import org.openpnp.spi.Machine;
import org.openpnp.spi.Movable.LocationOption;
import org.openpnp.spi.base.AbstractAxis;
import org.openpnp.spi.base.AbstractCoordinateAxis;
import org.simpleframework.xml.Element;

/**
* The ReferenceVirtualAxis is a pseudo-axis used to track a coordinate virtually i.e. without
* moving a physical axis.
*/
public class ReferenceVirtualAxis extends AbstractAxis implements CoordinateAxis {
@Element(required = false)
private Length homeCoordinate = new Length(0.0, LengthUnit.Millimeters);

/**
* The coordinate stored here is the last commanded coordinate. If this virtual axis is moved along with physical axes,
* there can be motion that is still ongoing.
*/
private double coordinate = 0;
public class ReferenceVirtualAxis extends AbstractCoordinateAxis implements CoordinateAxis {

@Override
public Wizard getConfigurationWizard() {
return new ReferenceVirtualAxisConfigurationWizard(this);
}

@Override
public double getCoordinate() {
return coordinate;
}

@Override
public Length getLengthCoordinate() {
return new Length(coordinate, getUnits());
}

@Override
public void setCoordinate(double coordinate) {
Object oldValue = this.coordinate;
this.coordinate = coordinate;
firePropertyChange("coordinate", oldValue, coordinate);
firePropertyChange("lengthCoordinate", null, getLengthCoordinate());
}

@Override
public void setLengthCoordinate(Length coordinate) {
setCoordinate(coordinate.convertToUnits(getUnits()).getValue());
}

@Override
public LengthUnit getUnits() {
return LengthUnit.Millimeters;
}

@Override
public Length getHomeCoordinate() {
return homeCoordinate;
}

@Override
public void setHomeCoordinate(Length homeCoordinate) {
Object oldValue = this.homeCoordinate;
this.homeCoordinate = homeCoordinate;
firePropertyChange("homeCoordinate", oldValue, homeCoordinate);
}

@Override
public AxesLocation getCoordinateAxes(Machine machine) {
// Yep, we're one.
return new AxesLocation(this);
}

@Override
public AxesLocation toTransformed(AxesLocation location, LocationOption... options) {
// No transformation, obviously
return location;
}

@Override
public AxesLocation toRaw(AxesLocation location, LocationOption... options) {
// No transformation, obviously
return location;
protected long getResolutionTicks(double coordinate) {
return Math.round(coordinate/0.0001);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@
import java.util.ArrayList;
import java.util.List;
import java.util.TreeMap;
import java.util.Map.Entry;

import org.openpnp.ConfigurationListener;
import org.openpnp.machine.reference.ReferenceDriver;
import org.openpnp.machine.reference.ReferenceMachine;
import org.openpnp.machine.reference.axis.ReferenceControllerAxis;
import org.openpnp.machine.reference.axis.ReferenceVirtualAxis;
import org.openpnp.machine.reference.vision.ReferenceBottomVision;
import org.openpnp.model.AxesLocation;
import org.openpnp.model.Configuration;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
import org.openpnp.machine.reference.driver.SerialPortCommunications.Parity;
import org.openpnp.machine.reference.driver.SerialPortCommunications.StopBits;
import org.openpnp.machine.reference.driver.wizards.AbstractReferenceDriverConfigurationWizard;
import org.openpnp.model.Length;
import org.openpnp.model.LengthUnit;
import org.openpnp.spi.base.AbstractDriver;
import org.openpnp.spi.base.AbstractMachine;
import org.pmw.tinylog.Logger;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,14 @@
import java.util.Map;

import org.openpnp.model.AxesLocation;
import org.openpnp.model.AxesLocation.MotionLimits;
import org.openpnp.model.Configuration;
import org.openpnp.model.Length;
import org.openpnp.model.LengthUnit;
import org.openpnp.model.Motion;
import org.openpnp.model.Motion.Derivative;
import org.openpnp.model.Motion.MotionOption;
import org.openpnp.spi.Axis;
import org.openpnp.spi.ControllerAxis;
import org.openpnp.spi.HeadMountable;
import org.openpnp.spi.Movable.MoveToOption;
import org.openpnp.util.NanosecondTime;
Expand All @@ -40,7 +43,6 @@
*/
public abstract class AbstractSimpleMotionPlanner extends AbstractMotionPlanner {


@Override
public void moveToPlanning(HeadMountable hm, AxesLocation axesLocation, double speed, MoveToOption... options)
throws Exception {
Expand Down Expand Up @@ -71,35 +73,20 @@ public void moveToPlanning(HeadMountable hm, AxesLocation axesLocation, double s
}
else {
// No lastMotion, create the previous waypoint from the axes.
// But take all the axes in the machine.
AxesLocation previousLocation = new AxesLocation(Configuration.get().getMachine());
lastMotion = new Motion(startTime,
new AxesLocation [] { previousLocation },
MotionOption.FixedWaypoint, MotionOption.CoordinatedWaypoint);
motionPlan.put(startTime, lastMotion);
}
// Calculate the 1st order kinematics. Note this must include all the axes, not just the ones mapped to
// this moveTo().
AxesLocation lastLocation = lastMotion.getVector(Motion.Derivative.Location);
// Update the given axes (keep the ones not given in this moveTo())
axesLocation = lastLocation.put(axesLocation);
AxesLocation delta = axesLocation
.subtract(lastLocation);
MotionLimits limits = new MotionLimits(delta);
if (limits.getLinearDistance() > 0 || limits.getRotationalDistance() > 0) {
// @see NIST RS274NGC Interpreter - Version 3, Section 2.1.2.5 rule A
double time = Math.max(limits.getLinearDistance()/limits.getLinearLimit(Motion.Derivative.Velocity),
limits.getRotationalDistance()/limits.getRotationalLimit(Motion.Derivative.Velocity))
/Math.max(0.01, speed);
if (!Double.isFinite(time)) {
throw new Exception("Feedrate(s) missing on (some) axes "+axesLocation.getAxes());
}
double endTime = startTime + time;
AxesLocation velocity = time <= 0.0 ? AxesLocation.zero : delta.multiply(1.0/time);
Motion endMotion = new Motion(endTime, new AxesLocation [] { axesLocation, velocity },
MotionOption.FixedWaypoint, MotionOption.CoordinatedWaypoint);
motionPlan.put(endTime, endMotion);
}
// Calculate the 1st order kinematics. Note this must include all the machine axes, not just the ones
// included in this moveTo().
AxesLocation lastLocation =
new AxesLocation(Configuration.get().getMachine())
.put(lastMotion.getVector(Motion.Derivative.Location));

Motion endMotion = Motion.computeWithLimits(startTime, lastLocation, axesLocation, speed, true, false);
motionPlan.put(endMotion.getTime(), endMotion);
}

@Override
Expand Down

0 comments on commit 4b8f935

Please sign in to comment.