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()];
|
block_t *block = &block_buffer[block_index.back()];
|
||||||
|
|
||||||
// Bail if this is a zero-length block
|
// 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) {
|
if (block->steps <= config::dropSegments) {
|
||||||
// behave as-if the block has been scheduled
|
// behave as-if the block has been scheduled
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Direction and speed for this block
|
// Direction and speed for this block
|
||||||
block->direction = (target >= position);
|
block->direction = steps >= 0;
|
||||||
block->nominal_rate = feed_rate;
|
block->nominal_rate = feed_rate;
|
||||||
|
|
||||||
// Acceleration of the segment, in steps/sec^2
|
// Acceleration of the segment, in steps/sec^2
|
||||||
|
|
|
||||||
|
|
@ -195,16 +195,19 @@ private:
|
||||||
/// Calculate the trapezoid parameters for the block
|
/// Calculate the trapezoid parameters for the block
|
||||||
void CalculateTrapezoid(block_t *block, steps_t entry_speed, steps_t exit_speed);
|
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
|
/// Return the axis shift introduced by the current (live) block
|
||||||
inline pos_t CurBlockShift() const {
|
inline pos_t CurBlockShift() const {
|
||||||
steps_t steps_missing = (current_block->steps - steps_completed);
|
steps_t steps_missing = (current_block->steps - steps_completed);
|
||||||
return current_block->direction ? steps_missing : -steps_missing;
|
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
|
} // namespace pulse_gen
|
||||||
|
|
|
||||||
|
|
@ -278,3 +278,27 @@ TEST_CASE("motion::long_pulley_move", "[motion]") {
|
||||||
motion.PlanMoveTo<Pulley>(mm400, 1._mm_s);
|
motion.PlanMoveTo<Pulley>(mm400, 1._mm_s);
|
||||||
REQUIRE(stepUntilDone() == p);
|
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