Skip to content

Commit e0e8710

Browse files
rtuck99jacob720
andauthored
Mx bluesky 1492 reset robot error for sample position not ready (#1972)
* Fix sample position not ready retry * Rewrite to cater for prg and controller errors separately * Apply suggestions from code review --------- Co-authored-by: Jacob Williamson <jacobwilliamson11@yahoo.co.uk>
1 parent 7aebba2 commit e0e8710

2 files changed

Lines changed: 245 additions & 46 deletions

File tree

src/dodal/devices/robot.py

Lines changed: 68 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,32 @@ async def raise_if_error(self, raise_from: Exception):
7070
raise RobotLoadError(int(error_code), error_string) from raise_from
7171

7272

73+
# Error codes that we do special things on
74+
class ProgErrorCode(IntEnum):
75+
NO_ERROR = 0
76+
SAMPLE_POSITION_NOT_READY = 9
77+
NO_PIN_ERROR_CODE = 25
78+
79+
@classmethod
80+
def is_retryable(cls, error_code: int) -> bool:
81+
return error_code in {
82+
ProgErrorCode.NO_ERROR,
83+
ProgErrorCode.SAMPLE_POSITION_NOT_READY,
84+
}
85+
86+
87+
class ControllerErrorCode(IntEnum):
88+
NO_ERROR = 0
89+
LIGHT_CURTAIN_TRIPPED = 40
90+
91+
@classmethod
92+
def is_retryable(cls, error_code: int) -> bool:
93+
return error_code in {
94+
ControllerErrorCode.NO_ERROR,
95+
ControllerErrorCode.LIGHT_CURTAIN_TRIPPED,
96+
}
97+
98+
7399
class BartRobot(StandardReadable, Movable[SampleLocation]):
74100
"""The sample changing robot."""
75101

@@ -79,11 +105,6 @@ class BartRobot(StandardReadable, Movable[SampleLocation]):
79105
# How long to wait for the actual load to happen
80106
LOAD_TIMEOUT = 60
81107

82-
# Error codes that we do special things on
83-
NO_ERROR = 0
84-
NO_PIN_ERROR_CODE = 25
85-
LIGHT_CURTAIN_TRIPPED = 40
86-
87108
# How far the gonio position can be out before loading will fail
88109
LOAD_TOLERANCE_MM = 0.02
89110

@@ -138,19 +159,32 @@ async def beamline_status_or_error(self, expected_state: BeamlineStatus):
138159
there is an error a RobotLoadError error is raised.
139160
"""
140161

141-
async def raise_if_error():
162+
async def raise_if_prog_error():
142163
await wait_for_value(
143-
self.prog_error.code, lambda value: value != self.NO_ERROR, None
164+
self.prog_error.code,
165+
lambda value: value != ProgErrorCode.NO_ERROR,
166+
None,
144167
)
145168
error_code = await self.prog_error.code.get_value()
146169
error_msg = await self.prog_error.str.get_value()
147170
raise RobotLoadError(error_code, error_msg)
148171

172+
async def raise_if_ctl_error():
173+
await wait_for_value(
174+
self.controller_error.code,
175+
lambda value: value != ControllerErrorCode.NO_ERROR,
176+
None,
177+
)
178+
error_code = await self.controller_error.code.get_value()
179+
error_msg = await self.controller_error.str.get_value()
180+
raise RobotLoadError(error_code, error_msg)
181+
149182
async def wait_for_expected_state():
150183
await wait_for_value(self.beamline_disabled, expected_state.value, None)
151184

152185
tasks = [
153-
(Task(raise_if_error())),
186+
(Task(raise_if_prog_error())),
187+
(Task(raise_if_ctl_error())),
154188
(Task(wait_for_expected_state())),
155189
]
156190
try:
@@ -170,10 +204,32 @@ async def wait_for_expected_state():
170204

171205
raise
172206

173-
async def _load_pin_and_puck(self, sample_location: SampleLocation):
174-
if await self.controller_error.code.get_value() == self.LIGHT_CURTAIN_TRIPPED:
175-
LOGGER.info("Light curtain tripped, trying again")
207+
async def _check_errors_and_clear_if_retryable(self):
208+
ctl_err_code = await self.controller_error.code.get_value()
209+
prog_err_code = await self.prog_error.code.get_value()
210+
if (
211+
ctl_err_code != ControllerErrorCode.NO_ERROR
212+
or prog_err_code != ProgErrorCode.NO_ERROR
213+
):
214+
ctl_err_msg = await self.controller_error.str.get_value()
215+
prog_err_msg = await self.prog_error.str.get_value()
216+
if ctl_err_code != ControllerErrorCode.NO_ERROR:
217+
LOGGER.info(
218+
f"Detected error from previous load/unload attempt controller_error {ctl_err_code}:{ctl_err_msg}"
219+
)
220+
if prog_err_code != ProgErrorCode.NO_ERROR:
221+
LOGGER.info(
222+
f"Detected error from previous load/unload attempt prog_error {prog_err_code}:{prog_err_msg}"
223+
)
224+
if not ProgErrorCode.is_retryable(prog_err_code):
225+
raise RobotLoadError(prog_err_code, prog_err_msg)
226+
if not ControllerErrorCode.is_retryable(ctl_err_code):
227+
raise RobotLoadError(ctl_err_code, ctl_err_msg)
228+
229+
LOGGER.info("Errors are retryable, resetting errors and trying again")
176230
await self.reset.trigger()
231+
232+
async def _load_pin_and_puck(self, sample_location: SampleLocation):
177233
LOGGER.info(f"Loading pin {sample_location}")
178234
if await self.program_running.get_value():
179235
LOGGER.info(
@@ -210,6 +266,7 @@ async def set(self, value: SampleLocation):
210266
sample.
211267
"""
212268
try:
269+
await self._check_errors_and_clear_if_retryable()
213270
if value != SAMPLE_LOCATION_EMPTY:
214271
await wait_for(
215272
self._load_pin_and_puck(value),

0 commit comments

Comments
 (0)