-
Notifications
You must be signed in to change notification settings - Fork 39
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
microcontroller: remove is_simulated at Microcontroller level, and in…
…stead implement simulated firmware at Serial level (#33) We added back in an is_simulated flag in the Microcontroller implementation. This isn't ideal because it meant we had to go and put `if self.is_simulated:` in all the `Microcontroller` methods and take custom action in simulation mode. This meant that none of our regular path code was tested when running in simulation, and that the `Microcontroller` code had a lot of noise in it to handle the simulation case. This moves the simulation handling down to the Serial / simulated firmware level by handling and responding to `CMD_SET` commands (like our firmware does) in our simulated serial device. Tested by: Unit tests
- Loading branch information
Showing
3 changed files
with
198 additions
and
55 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
import pytest | ||
import control._def | ||
import control.microcontroller | ||
|
||
def assert_pos_almost_equal(expected, actual): | ||
assert len(actual) == len(expected) | ||
for (e, a) in zip(expected, actual): | ||
assert a == pytest.approx(e) | ||
|
||
def test_create_simulated_microcontroller(): | ||
micro = control.microcontroller.Microcontroller(existing_serial=control.microcontroller.SimSerial()) | ||
|
||
def test_microcontroller_simulated_positions(): | ||
micro = control.microcontroller.Microcontroller(existing_serial=control.microcontroller.SimSerial()) | ||
|
||
micro.move_x_to_usteps(1000) | ||
micro.wait_till_operation_is_completed() | ||
micro.move_y_to_usteps(2000) | ||
micro.wait_till_operation_is_completed() | ||
micro.move_z_to_usteps(3000) | ||
micro.wait_till_operation_is_completed() | ||
micro.move_theta_usteps(4000) | ||
micro.wait_till_operation_is_completed() | ||
|
||
assert_pos_almost_equal((1000, 2000, 3000, 4000), micro.get_pos()) | ||
|
||
micro.home_x() | ||
micro.wait_till_operation_is_completed() | ||
assert_pos_almost_equal((0, 2000, 3000, 4000), micro.get_pos()) | ||
|
||
micro.home_y() | ||
micro.wait_till_operation_is_completed() | ||
assert_pos_almost_equal((0, 0, 3000, 4000), micro.get_pos()) | ||
|
||
micro.home_z() | ||
micro.wait_till_operation_is_completed() | ||
assert_pos_almost_equal((0, 0, 0, 4000), micro.get_pos()) | ||
|
||
micro.home_theta() | ||
micro.wait_till_operation_is_completed() | ||
assert_pos_almost_equal((0, 0, 0, 0), micro.get_pos()) | ||
|
||
micro.move_x_to_usteps(1000) | ||
micro.wait_till_operation_is_completed() | ||
micro.move_y_to_usteps(2000) | ||
micro.wait_till_operation_is_completed() | ||
micro.move_z_to_usteps(3000) | ||
micro.wait_till_operation_is_completed() | ||
micro.move_theta_usteps(4000) | ||
micro.wait_till_operation_is_completed() | ||
assert_pos_almost_equal((1000, 2000, 3000, 4000), micro.get_pos()) | ||
|
||
# Multiply by the sign so we get a positive move. The way these relative move helpers work right now | ||
# is that they multiply by the sign, but the read back is not multiplied by the sign. So if | ||
# the movement sign is -1, doing a relative move of 100 will result in the get_pos() value being -100. | ||
# | ||
# NOTE(imo): This seems probably not right, so this might get fixed and this comment might be out of date. | ||
micro.move_x_usteps(control._def.STAGE_MOVEMENT_SIGN_X * 1) | ||
micro.wait_till_operation_is_completed() | ||
micro.move_y_usteps(control._def.STAGE_MOVEMENT_SIGN_Y * 2) | ||
micro.wait_till_operation_is_completed() | ||
micro.move_z_usteps(control._def.STAGE_MOVEMENT_SIGN_Z * 3) | ||
micro.wait_till_operation_is_completed() | ||
micro.move_theta_usteps(control._def.STAGE_MOVEMENT_SIGN_THETA * 4) | ||
micro.wait_till_operation_is_completed() | ||
assert_pos_almost_equal((1001, 2002, 3003, 4004), micro.get_pos()) | ||
|
||
micro.zero_x() | ||
micro.wait_till_operation_is_completed() | ||
assert_pos_almost_equal((0, 2002, 3003, 4004), micro.get_pos()) | ||
|
||
micro.zero_y() | ||
micro.wait_till_operation_is_completed() | ||
assert_pos_almost_equal((0, 0, 3003, 4004), micro.get_pos()) | ||
|
||
micro.zero_z() | ||
micro.wait_till_operation_is_completed() | ||
assert_pos_almost_equal((0, 0, 0, 4004), micro.get_pos()) | ||
|
||
micro.zero_theta() | ||
micro.wait_till_operation_is_completed() | ||
assert_pos_almost_equal((0, 0, 0, 0), micro.get_pos()) | ||
|
||
micro.move_x_to_usteps(1000) | ||
micro.wait_till_operation_is_completed() | ||
micro.move_y_to_usteps(2000) | ||
micro.wait_till_operation_is_completed() | ||
micro.move_z_to_usteps(3000) | ||
micro.wait_till_operation_is_completed() | ||
# There's no move_theta_to_usteps. | ||
assert_pos_almost_equal((1000, 2000, 3000, 0), micro.get_pos()) | ||
|
||
micro.home_xy() | ||
micro.wait_till_operation_is_completed() | ||
assert_pos_almost_equal((0, 0, 3000, 0), micro.get_pos()) | ||
|
||
@pytest.mark.skip(reason="This is likely a bug, but I'm not sure yet. Tracking in https://linear.app/cephla/issue/S-115/microcontroller-relative-and-absolute-position-sign-mismatch") | ||
def test_microcontroller_absolute_and_relative_match(): | ||
micro = control.microcontroller.Microcontroller(existing_serial=control.microcontroller.SimSerial()) | ||
|
||
def wait(): | ||
micro.wait_till_operation_is_completed() | ||
|
||
micro.home_x() | ||
wait() | ||
|
||
micro.home_y() | ||
wait() | ||
|
||
micro.home_z() | ||
wait() | ||
|
||
micro.home_theta() | ||
wait() | ||
|
||
# For all our axes, we'd expect that moving to an absolute position from zero brings us to that position. | ||
# Then doing a relative move of the negative of the absolute position should bring us back to zero. | ||
abs_position = 1234 | ||
|
||
# X | ||
micro.move_x_to_usteps(abs_position) | ||
wait() | ||
assert_pos_almost_equal((abs_position, 0, 0, 0), micro.get_pos()) | ||
|
||
micro.move_x_usteps(-abs_position) | ||
wait() | ||
assert_pos_almost_equal((0, 0, 0, 0), micro.get_pos()) | ||
|
||
# Y | ||
micro.move_y_to_usteps(abs_position) | ||
wait() | ||
assert_pos_almost_equal((0, abs_position, 0, 0), micro.get_pos()) | ||
|
||
micro.move_y_usteps(-abs_position) | ||
wait() | ||
assert_pos_almost_equal((0, 0, 0, 0), micro.get_pos()) | ||
|
||
# Z | ||
micro.move_z_to_usteps(abs_position) | ||
wait() | ||
assert_pos_almost_equal((0, 0, abs_position, 0), micro.get_pos()) | ||
|
||
micro.move_z_usteps(-abs_position) | ||
wait() | ||
assert_pos_almost_equal((0, 0, 0, 0), micro.get_pos()) |