motion: PlanMove() correctly also when overflowing Position()
Correctly compute both the number of steps and direction when under/overflowing the current position by performing a relative move. This makes a repeated PlanMove() _always_ perform the move correcly, even when the upper-level code might require to handle the overflow itself for measurement. Add tests for this condition by exposing the internal CurBlockShift() to the motion unit tests.pull/161/head
parent
1a2034f545
commit
3fbdf8bb2b
|
|
@ -96,14 +96,15 @@ bool PulseGen::PlanMoveTo(pos_t target, steps_t feed_rate, steps_t end_rate) {
|
|||
block_t *block = &block_buffer[block_index.back()];
|
||||
|
||||
// Bail if this is a zero-length block
|
||||
block->steps = abs(target - position);
|
||||
pos_t steps = target - position;
|
||||
block->steps = abs(steps);
|
||||
if (block->steps <= config::dropSegments) {
|
||||
// behave as-if the block has been scheduled
|
||||
return true;
|
||||
}
|
||||
|
||||
// Direction and speed for this block
|
||||
block->direction = (target >= position);
|
||||
block->direction = steps >= 0;
|
||||
block->nominal_rate = feed_rate;
|
||||
|
||||
// Acceleration of the segment, in steps/sec^2
|
||||
|
|
|
|||
|
|
@ -195,16 +195,19 @@ private:
|
|||
/// Calculate the trapezoid parameters for the block
|
||||
void CalculateTrapezoid(block_t *block, steps_t entry_speed, steps_t exit_speed);
|
||||
|
||||
/// Return the axis shift introduced by the specified full block
|
||||
static inline pos_t BlockShift(const block_t *block) {
|
||||
return block->direction ? block->steps : -block->steps;
|
||||
}
|
||||
|
||||
#ifdef UNITTEST_MOTION
|
||||
public:
|
||||
#endif
|
||||
/// Return the axis shift introduced by the current (live) block
|
||||
inline pos_t CurBlockShift() const {
|
||||
steps_t steps_missing = (current_block->steps - steps_completed);
|
||||
return current_block->direction ? steps_missing : -steps_missing;
|
||||
}
|
||||
|
||||
/// Return the axis shift introduced by the specified full block
|
||||
static inline pos_t BlockShift(const block_t *block) {
|
||||
return block->direction ? block->steps : -block->steps;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace pulse_gen
|
||||
|
|
|
|||
|
|
@ -278,3 +278,27 @@ TEST_CASE("motion::long_pulley_move", "[motion]") {
|
|||
motion.PlanMoveTo<Pulley>(mm400, 1._mm_s);
|
||||
REQUIRE(stepUntilDone() == p);
|
||||
}
|
||||
|
||||
TEST_CASE("motion::pos_overflow", "[motion]") {
|
||||
ResetMotionSim();
|
||||
|
||||
// set a position _at_ the overflow limit
|
||||
mm::pos_t pos_max = std::numeric_limits<mm::pos_t>::max();
|
||||
mm::motion.SetPosition(mm::Pulley, pos_max);
|
||||
REQUIRE(mm::motion.Position(mm::Pulley) == pos_max);
|
||||
|
||||
// plan a move which will overflow
|
||||
mm::pos_t steps = 10;
|
||||
mm::motion.PlanMove(mm::Pulley, steps, 1);
|
||||
|
||||
// ensure we did overflow
|
||||
REQUIRE(mm::motion.Position(mm::Pulley) < pos_max);
|
||||
|
||||
// step once to setup current_block
|
||||
mm::motion.Step();
|
||||
|
||||
// ensure the move direction and step count is correct despite the overflow
|
||||
// abuse CurBlockShift to get both, accounting for the useless single step
|
||||
// we performed just above.
|
||||
REQUIRE(mm::motion.CtrlForAxis(mm::Pulley).CurBlockShift() == steps - 1);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue