Z轴可利用代码控制移动

This commit is contained in:
2026-10-10 14:10:59 +08:00
parent b827c5ffee
commit 264275b1e6
9 changed files with 406 additions and 40 deletions
@@ -17,6 +17,7 @@ No test here touches a controller or a DLL.
from __future__ import annotations
import ctypes
import logging
import time
from pathlib import Path
@@ -25,6 +26,7 @@ from orisys_autocal.motion import (
DEFAULT_BAS_TASK,
INIT_OK,
INIT_RUNNING,
BusStatus,
ConnectionSpec,
DemoTransport,
MotionService,
@@ -224,6 +226,44 @@ def test_adopted_program_without_a_known_file_says_so():
assert "文件名" in result.message or "file name" in result.message
def test_connect_reads_axis_4_and_does_not_write_parameters(caplog):
"""Connecting must not replace configuration the vendor software just set."""
transport = DemoTransport()
writes: list[tuple] = []
transport.set_units = lambda axis, value: writes.append(("units", axis, value))
transport.set_speed = lambda axis, value: writes.append(("speed", axis, value))
transport.set_accel = lambda axis, value: writes.append(("accel", axis, value))
transport.bas_download = lambda filename, run_mode=1: writes.append(("bas", filename))
service = MotionService(transport)
with caplog.at_level(logging.INFO):
result = service.connect(ConnectionSpec(mode="demo"))
assert result.ok, result.message
assert writes == []
readback = [record.message for record in caplog.records if record.message.startswith("connect axis 4")]
assert readback, caplog.text
assert "mpos=" in readback[-1]
assert "not written" in caplog.text
def test_axis_4_jog_reuses_the_shared_motion_call_and_logs_position(caplog):
service = MotionService(DemoTransport())
assert service.connect(ConnectionSpec(mode="demo")).ok
service._bus = BusStatus(bus_type="ecat", init_status=INIT_OK, total_axes=4) # noqa: SLF001
with caplog.at_level(logging.INFO):
result = service.jog(4, True)
assert result.ok, result.message
assert result.code == 0
logged = [record.message for record in caplog.records if record.message.startswith("jog axis 4")]
assert logged, caplog.text
assert "ok=True" in logged[-1]
assert "code=0" in logged[-1]
assert "mpos=" in logged[-1]
def test_reinit_needs_the_bus_not_to_be_mid_run():
service = MotionService(DemoTransport())
service.connect(ConnectionSpec(mode="demo"))
+39 -1
View File
@@ -19,7 +19,7 @@ from __future__ import annotations
from orisys_app_shared.i18n import t
from orisys_autocal.motion import BusStatus
from orisys_autocal.motion import AxisState, BusStatus, Snapshot
from orisys_autocal.motion.pose_move import plan_pose_move
@@ -37,6 +37,44 @@ def _connected(make_window, *, confirm: bool = False):
return window
def test_axis_4_controls_stay_available_when_the_bus_count_is_short(make_window):
"""A mapped axis 4 uses the same buttons as axes 0-3.
The bus-count global can still say 4 after the drive is working again.
Type 0 stays disabled, so an axis the controller has not mapped is not
given a button.
"""
window = make_window()
try:
mapped = tuple(AxisState(axis=index, atype=65, read_ok=True) for index in range(5))
window.axis_panel.update_snapshot(
Snapshot(
connected=True,
bus=BusStatus(bus_type="ecat", init_status=1, total_axes=4),
axes=mapped,
)
)
row = window.axis_panel._rows[4] # noqa: SLF001
assert row["enable_button"].isEnabled()
assert row["fwd_button"].isEnabled()
assert row["rev_button"].isEnabled()
assert row["stop_button"].isEnabled()
unmapped = mapped[:-1] + (AxisState(axis=4, atype=0, read_ok=True),)
window.axis_panel.update_snapshot(
Snapshot(
connected=True,
bus=BusStatus(bus_type="ecat", init_status=1, total_axes=4),
axes=unmapped,
)
)
row = window.axis_panel._rows[4] # noqa: SLF001
assert not row["fwd_button"].isEnabled()
assert row["stop_button"].isEnabled() is False
finally:
window.close()
def test_execute_lives_with_the_point_it_executes(make_window):
window = make_window()
try:
+57
View File
@@ -216,6 +216,63 @@ def test_the_guard_names_an_unknown_direction():
# ------------------------------------------------------------------------ mover
def test_an_execute_plan_moves_the_four_axes_together_and_leaves_z():
"""Calibration execute starts yaw, pitch and X/Y in one command. Z stays put."""
service = make_service()
called: list[list[tuple[int, float]]] = []
def record(moves):
called.append(list(moves))
return MotionResult.success()
service.move_abs_many = record # type: ignore[method-assign]
poller = FakePoller(service)
mover = PoseMover(service, poller.submit)
plan = plan_pose_move(
service,
{"x": 2.0, "y": 1.0, "yaw": 10.0, "pitch": -5.0},
hold=("z",),
together=True,
)
assert plan.together
assert [step.role for step in plan.steps] == ["yaw", "pitch", "x", "y"]
assert mover.start(plan).ok
assert len(poller.commands) == 1
poller.commands[0](service)
assert [axis for axis, _value in called[0]] == [3, 2, 0, 1]
mover.on_snapshot(
snapshot_of(service, {0: 1000.0, 1: 0.0, 2: 0.0, 3: 0.0}, idle=False)
)
assert mover.running
assert mover.progress_text().startswith("同时")
assert len(poller.commands) == 1, "a later axis was queued instead of moving with the first"
mover.on_snapshot(
snapshot_of(
service,
{
0: 1000.0,
1: 500.0,
2: -5.0 * 12500.0 / 90.0,
3: 10.0 * 29500.0 / 90.0,
},
)
)
assert mover.state.finished
def test_return_to_zero_stays_one_axis_at_a_time():
service = make_service()
poller = FakePoller(service)
mover = PoseMover(service, poller.submit)
plan = plan_return_to_initial(service)
assert not plan.together
assert mover.start(plan).ok
assert len(poller.commands) == 1
assert mover.state.step.role == "z"
def test_the_mover_commands_one_axis_and_waits_for_it_to_arrive():
service = make_service()
poller = FakePoller(service)