(self, axes: str)
Handle split moves for unsticking axes before home.

        This is particularly ugly bit of code that flips the motor controller
        into relative mode since we don't necessarily know where we are.

        It will induce a movement. It should really only be called before a
        home because it doesn't update the position cache.

        :param axes: A string that is a sequence of plunger axis names.
Handle split moves for unsticking axes before home.
Handle split moves for unsticking axes before home .
async def _do_relative_splits_during_home_for(self, axes: str) -> None:
        """Handle split moves for unsticking axes before home.

        This is particularly ugly bit of code that flips the motor controller
        into relative mode since we don't necessarily know where we are.

        It will induce a movement. It should really only be called before a
        home because it doesn't update the position cache.

        :param axes: A string that is a sequence of plunger axis names.
        """
        assert all(
            ax.lower() in "bc" for ax in axes
        ), "only plunger axes may be unstuck"
        since_moved = self._axes_moved_at.time_since_moved()
        split_currents = _command_builder().add_gcode(gcode=GCODE.SET_CURRENT)
        split_moves = _command_builder().add_gcode(gcode=GCODE.MOVE)
        applicable_speeds: List[float] = []
        log.debug(f"Finding splits for {axes} with since moved {since_moved}")
        to_unstick = [
            ax
            for ax in axes
            if (
                since_moved.get(ax) is None
                or (
                    self._move_split_config.get(ax)
                    and since_moved[ax]  # type: ignore[operator]
                    > self._move_split_config[ax].after_time
                )
            )
        ]
        for axis in axes:
            msc = self._move_split_config.get(axis)
            log.debug(f"axis {axis}: msc {msc}")
            if not msc:
                continue
            if axis in to_unstick:
                log.debug(f"adding unstick for {axis}")
                split_currents.add_float(
                    prefix=axis, value=msc.split_current, precision=None
                )
                split_moves.add_float(
                    prefix=axis, value=-msc.split_distance, precision=None
                )
                applicable_speeds.append(msc.split_speed)
        if not applicable_speeds:
            log.debug("no unstick needed")
            # nothing to do
            return

        fullstep_prefix, fullstep_postfix = self._build_fullstep_configurations(
            "".join(to_unstick)
        )

        command_sequence = [
            fullstep_prefix.add_builder(builder=split_currents)
            .add_gcode(gcode=GCODE.DWELL)
            .add_float(prefix="P", value=CURRENT_CHANGE_DELAY, precision=None)
            .add_builder(builder=self._build_speed_command(min(applicable_speeds)))
            .add_gcode(gcode=GCODE.RELATIVE_COORDS),
            split_moves,
        ]
        try:
            for command_string in command_sequence:
                await self._send_command(
                    command_string,
                    timeout=DEFAULT_EXECUTE_TIMEOUT,
                    suppress_home_after_error=True,
                )
        except SmoothieError:
            pass
        finally:
            await self._send_command(
                _command_builder()
                .add_gcode(gcode=GCODE.ABSOLUTE_COORDS)
                .add_builder(builder=fullstep_postfix)
                .add_builder(builder=self._build_speed_command(self._combined_speed))
            )
async def _do_relative_splits_during_home_for ( self , axes : str ) -> None : assert all ( ax . lower ( ) in "bc" for ax in axes ) , "only plunger axes may be unstuck" since_moved = self . _axes_moved_at . time_since_moved ( ) split_currents = _command_builder ( ) . add_gcode ( gcode = GCODE . SET_CURRENT ) split_moves = _command_builder ( ) . add_gcode ( gcode = GCODE . MOVE ) applicable_speeds : List [ float ] = [ ] log . debug ( f"Finding splits for {axes} with since moved {since_moved}" ) to_unstick = [ ax for ax in axes if ( since_moved . get ( ax ) is None or ( self . _move_split_config . get ( ax ) and since_moved [ ax ] # type: ignore[operator] > self . _move_split_config [ ax ] . after_time ) ) ] for axis in axes : msc = self . _move_split_config . get ( axis ) log . debug ( f"axis {axis}: msc {msc}" ) if not msc : continue if axis in to_unstick : log . debug ( f"adding unstick for {axis}" ) split_currents . add_float ( prefix = axis , value = msc . split_current , precision = None ) split_moves . add_float ( prefix = axis , value = - msc . split_distance , precision = None ) applicable_speeds . append ( msc . split_speed ) if not applicable_speeds : log . debug ( "no unstick needed" ) # nothing to do return fullstep_prefix , fullstep_postfix = self . _build_fullstep_configurations ( "" . join ( to_unstick ) ) command_sequence = [ fullstep_prefix . add_builder ( builder = split_currents ) . add_gcode ( gcode = GCODE . DWELL ) . add_float ( prefix = "P" , value = CURRENT_CHANGE_DELAY , precision = None ) . add_builder ( builder = self . _build_speed_command ( min ( applicable_speeds ) ) ) . add_gcode ( gcode = GCODE . RELATIVE_COORDS ) , split_moves , ] try : for command_string in command_sequence : await self . _send_command ( command_string , timeout = DEFAULT_EXECUTE_TIMEOUT , suppress_home_after_error = True , ) except SmoothieError : pass finally : await self . _send_command ( _command_builder ( ) . add_gcode ( gcode = GCODE . ABSOLUTE_COORDS ) . add_builder ( builder = fullstep_postfix ) . add_builder ( builder = self . _build_speed_command ( self . _combined_speed ) ) )