Skip to content

Commit

Permalink
Fixed cornering
Browse files Browse the repository at this point in the history
  • Loading branch information
dren-dk committed Jun 28, 2016
1 parent 0b6ea53 commit 697d31b
Show file tree
Hide file tree
Showing 6 changed files with 238 additions and 89 deletions.
6 changes: 3 additions & 3 deletions host/shiver/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -36,23 +36,23 @@ machine:
acceleration: 5000
maxSpeed: 1500
minSpeed: 20
maxJerk: 2
maxJerk: 10
mmPerStep: 0.0375
coilCurrent: 1800
microSteppingMode: 3
y:
acceleration: 500
maxSpeed: 1500
minSpeed: 20
maxJerk: 2
maxJerk: 10
mmPerStep: 0.0375
coilCurrent: 1800
microSteppingMode: 3
z:
acceleration: 0.1
maxSpeed: 10
minSpeed: 0.2
maxJerk: 0.2
maxJerk: 100
mmPerStep: 0.003125
coilCurrent: 1500
microSteppingMode: 3
Expand Down
140 changes: 140 additions & 0 deletions host/shiver/src/main/java/dk/osaa/psaw/core/BrokenCornering.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
package dk.osaa.psaw.core;

import dk.osaa.psaw.config.AxisConstraints;
import dk.osaa.psaw.config.PhotonSawMachineConfig;
import dk.osaa.psaw.machine.Move;
import dk.osaa.psaw.machine.MoveVector;
import lombok.Getter;
import lombok.extern.java.Log;

import java.util.ArrayList;
import java.util.List;

/**
* This class wraps up the algorithm needed to change direction without stopping.
*
* @author Flemming Frandsen <dren.dk@gmail.com> <http://dren.dk>
*/
@Log
public class BrokenCornering {

private final List<Double> maxJerks;
/**
* The speed along the exit vector after the corner.
*/
@Getter
double exitSpeed;

@Getter
MoveVector jerks;

@Getter
MoveVector exitSpeeds;

static int id = 0;

/**
* Calculates the cornering parameters
*
* @param cfg The movement constraints that govern the mechanical system that this drives
* @param entryVector The direction of the system before the corner
* @param entrySpeed The speed of the system before the corner
* @param exitVector The direction of the system after the corner
* @param maxExitSpeed The absolute maximum exit speed to target
*/
public BrokenCornering corner(PhotonSawMachineConfig cfg, MoveVector entryVector, double entrySpeed, MoveVector exitVector, double maxExitSpeed) {
List<Double> maxJerks = new ArrayList<>();
for (AxisConstraints ac : cfg.getAxes().getArray()) {
maxJerks.add(ac.getMaxJerk());
}

return new BrokenCornering(maxJerks, entryVector, entrySpeed, exitVector, maxExitSpeed);
}

/**
* Calculates the cornering parameters
*
* @param maxJerks The max jerk limits for all the axes that govern the mechanical system that this drives
* @param entryVector The direction of the system before the corner
* @param entrySpeed The speed of the system before the corner
* @param exitVector The direction of the system after the corner
* @param maxExitSpeed The absolute maximum exit speed to target
*/
public BrokenCornering(List<Double> maxJerks, MoveVector entryVector, double entrySpeed, MoveVector exitVector, double maxExitSpeed) {
this.maxJerks = maxJerks;

id++;

boolean done = false;
while (!done) {
MoveVector entrySpeeds = entryVector.mul(entrySpeed);
double overSpeed = -1;
exitSpeed = maxExitSpeed;
MoveVector maxExitSpeeds = exitVector.mul(maxExitSpeed);

/*
* Find the speed limit for each axis,
* then compare that to the entry speed
* and pick the axis that is going to constrain the corner
*/
for (int ax=0;ax<Move.AXES;ax++) {

double max;
if (Math.signum(exitVector.getAxis(ax)) == Math.signum(entryVector.getAxis(ax))) { // Continuing along in the same direction.
max = maxJerks.get(ax) + Math.abs(entrySpeeds.getAxis(ax));

} else { // Direction change or starting from a standstill
max = maxJerks.get(ax)/2;
}

// This limits the exit speed under the assumption that entry speed is low enough to be able to corner within the mc.
double os = Math.abs(maxExitSpeeds.getAxis(ax))/max;
if (os > 1 && os > overSpeed) {
overSpeed = os;
}
}

if (overSpeed > 1) {
exitSpeed = exitSpeed/overSpeed;
}

exitSpeeds = exitVector.mul(exitSpeed);
jerks = new MoveVector();

done = true;
for (int ax=0;ax<Move.AXES;ax++) {
double jerk = exitSpeeds.getAxis(ax)-entrySpeeds.getAxis(ax);
jerks.setAxis(ax, jerk);
if (Math.abs(jerk) > maxJerks.get(ax)*1.01) {
done = false;

if (Math.signum(exitVector.getAxis(ax)) == Math.signum(entryVector.getAxis(ax))) {
if (Math.abs(entrySpeeds.getAxis(ax)) > Math.abs(exitSpeeds.getAxis(ax))+maxJerks.get(ax)) {
entrySpeed /= Math.abs(entrySpeeds.getAxis(ax)) / (Math.abs(exitSpeeds.getAxis(ax))+maxJerks.get(ax));
} else {
log.info("Fail!"+id);
}
} else {
if (Math.abs(entrySpeeds.getAxis(ax)) > maxJerks.get(ax)/2) {
entrySpeed /= Math.abs(entrySpeeds.getAxis(ax))/(maxJerks.get(ax)/2);
} else {
log.info("Fail!"+id);
}
}
}
}
}

}

public BrokenCornering checkJerks() {
for (int ax=0;ax<Move.AXES;ax++) {
double jerk = jerks.getAxis(ax);

if (Math.abs(jerk) > maxJerks.get(ax)*1.25) {
throw new RuntimeException("Jerk was too large in axis: "+ax+" jerk was "+jerk+" max:"+maxJerks.get(ax)+" for corner id:"+id);
}
}
return this;
}
}
150 changes: 82 additions & 68 deletions host/shiver/src/main/java/dk/osaa/psaw/core/Cornering.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
package dk.osaa.psaw.core;

import dk.osaa.psaw.config.AxisConstraints;
import lombok.Getter;
import lombok.extern.java.Log;
import dk.osaa.psaw.config.PhotonSawMachineConfig;
import dk.osaa.psaw.machine.Move;
import dk.osaa.psaw.machine.MoveVector;

import java.util.ArrayList;
import java.util.List;

/**
* This class wraps up the algorithm needed to change direction without stopping.
*
Expand All @@ -14,6 +18,10 @@
@Log
public class Cornering {

private final List<Double> maxJerks;
private long lineNumber;
@Getter
private final double limitedEntrySpeed;
/**
* The speed along the exit vector after the corner.
*/
Expand All @@ -25,97 +33,103 @@ public class Cornering {

@Getter
MoveVector exitSpeeds;


@Getter
double maxEntrySpeed;

static int id = 0;

private final PhotonSawMachineConfig cfg;



/**
* Calculates the cornering parameters
*
* @param cfg The movement constraints that govern the mechanical system that this drives
* @param cfg The movement constraints that govern the mechanical system that this drives
* @param entryVector The direction of the system before the corner
* @param entrySpeed The speed of the system before the corner
* @param exitVector The direction of the system after the corner
* @param maxExitSpeed The absolute maximum exit speed to target
* @param lineNumber
*/
public Cornering(PhotonSawMachineConfig cfg, MoveVector entryVector, double entrySpeed, MoveVector exitVector, double maxExitSpeed) {
this.cfg = cfg;

public static Cornering corner(PhotonSawMachineConfig cfg, MoveVector entryVector, double entrySpeed, MoveVector exitVector, double maxExitSpeed, long lineNumber) {
List<Double> maxJerks = new ArrayList<>();
for (AxisConstraints ac : cfg.getAxes().getArray()) {
maxJerks.add(ac.getMaxJerk());
}

return new Cornering(maxJerks, entryVector, entrySpeed, exitVector, maxExitSpeed, lineNumber);
}

/**
* Calculates the cornering parameters
* @param maxJerks The max jerk limits for all the axes that govern the mechanical system that this drives
* @param entryVector The direction of the system before the corner
* @param entrySpeed The speed of the system before the corner
* @param exitVector The direction of the system after the corner
* @param maxExitSpeed The absolute maximum exit speed to target
* @param lineNumber
*/
public Cornering(List<Double> maxJerks, MoveVector entryVector, double entrySpeed, MoveVector exitVector, double maxExitSpeed, long lineNumber) {
this.maxJerks = maxJerks;
this.lineNumber = lineNumber;

id++;
if (id == 43) {
log.info("Hit");

//if (lineNumber == 286) {
// log.info("Hit "+id);
//}

// Find the axis that's moving the fastest in the same direction before and after the corner
Integer fixedAxis = null;
double fixedPreservation = 0;
MoveVector preservation = entryVector.mul(exitVector);
for (int ax=0;ax<Move.AXES;ax++) {
double preserved = preservation.getAxis(ax)*entrySpeed;
if (preserved > fixedPreservation) {
fixedPreservation = preserved;
fixedAxis = ax;
}
}

boolean done = false;
while (!done) {
MoveVector entrySpeeds = entryVector.mul(entrySpeed);
double overSpeed = -1;
exitSpeed = maxExitSpeed;
MoveVector maxExitSpeeds = exitVector.mul(maxExitSpeed);

/*
* Find the speed limit for each axis,
* then compare that to the entry speed
* and pick the axis that is going to constrain the corner
*/
for (int ax=0;ax<Move.AXES;ax++) {

double max;
if (Math.signum(exitVector.getAxis(ax)) == Math.signum(entryVector.getAxis(ax))) { // Continuing along in the same direction.
max = cfg.getAxes().getArray()[ax].getMaxJerk() + Math.abs(entrySpeeds.getAxis(ax));

} else { // Direction change or starting from a standstill
max = cfg.getAxes().getArray()[ax].getMaxJerk()/2;
}

// This limits the exit speed under the assumption that entry speed is low enough to be able to corner within the mc.
double os = Math.abs(maxExitSpeeds.getAxis(ax))/max;
if (os > 1 && os > overSpeed) {
overSpeed = os;
}

// Limit the entry speed until all the jerks are under the max jerk limits
while (true) {
exitSpeed = 0;

// An axis was found that moves in the same direction as before, so we'll start out trying to keep that axis moving at exactly the same speed
if (fixedAxis != null) {
exitSpeed = entrySpeed*preservation.getAxis(fixedAxis);
}

if (overSpeed > 1) {
exitSpeed = exitSpeed/overSpeed;

// Limit the exit speed according to the absolute limit passed:
if (exitSpeed > maxExitSpeed) {
exitSpeed = maxExitSpeed;
}

exitSpeeds = exitVector.mul(exitSpeed);

exitSpeeds = exitVector.mul(exitSpeed);
MoveVector entrySpeeds = entryVector.mul(entrySpeed);
jerks = new MoveVector();

done = true;
for (int ax=0;ax<Move.AXES;ax++) {
double jerk = exitSpeeds.getAxis(ax)-entrySpeeds.getAxis(ax);
double biggestOverspeed = 1;
for (int ax = 0; ax < Move.AXES; ax++) {
double jerk = Math.abs(exitSpeeds.getAxis(ax) - entrySpeeds.getAxis(ax));
jerks.setAxis(ax, jerk);
if (Math.abs(jerk) > cfg.getAxes().getArray()[ax].getMaxJerk()*1.01) {
done = false;

if (Math.signum(exitVector.getAxis(ax)) == Math.signum(entryVector.getAxis(ax))) {
if (Math.abs(entrySpeeds.getAxis(ax)) > Math.abs(exitSpeeds.getAxis(ax))+cfg.getAxes().getArray()[ax].getMaxJerk()) {
entrySpeed /= Math.abs(entrySpeeds.getAxis(ax)) / (Math.abs(exitSpeeds.getAxis(ax))+cfg.getAxes().getArray()[ax].getMaxJerk());
} else {
log.info("Fail!"+id);
}
} else {
if (Math.abs(entrySpeeds.getAxis(ax)) > cfg.getAxes().getArray()[ax].getMaxJerk()/2) {
entrySpeed /= Math.abs(entrySpeeds.getAxis(ax))/(cfg.getAxes().getArray()[ax].getMaxJerk()/2);
} else {
log.info("Fail!"+id);
}
}
double overspeed = jerk/maxJerks.get(ax);
if (overspeed > biggestOverspeed) {
biggestOverspeed = overspeed;
}
}

entrySpeed = entrySpeed/biggestOverspeed;
if (biggestOverspeed <= 1) {
break;
}
}


limitedEntrySpeed = entrySpeed;
}

public Cornering checkJerks() {
for (int ax=0;ax<Move.AXES;ax++) {
double jerk = jerks.getAxis(ax);

if (Math.abs(jerk) > cfg.getAxes().getArray()[ax].getMaxJerk()*1.25) {
throw new RuntimeException("Jerk was too large in axis: "+ax+" jerk was "+jerk+" max:"+cfg.getAxes().getArray()[ax].getMaxJerk()+" for corner id:"+id);
if (Math.abs(jerk) > maxJerks.get(ax)*1.25) {
throw new RuntimeException("Jerk was too large in axis: "+ax+" jerk was "+jerk+" max:"+maxJerks.get(ax)+" for corner id:"+id);
}
}
return this;
Expand Down
Loading

0 comments on commit 697d31b

Please sign in to comment.