def run_for_time(self, msec, speed, stop=MotorStop.BRAKE, block=True, **kwargs): """ Run the motor at ``speed`` for ``msec`` Args: msec (int): the number of milliseconds to run the motor speed (MotorSpeed): the speed of the motor stop (MotorStop): how to stop the motors, defaults to :class:`MotorStop.BRAKE` block (bool): if True this function will not return until the motors have finished moving **kwargs: optional kwargs that will pass all the way down to the LEGO ``hub.port.X.motor`` API call """ if msec < 0: raise ValueError("msec was {}, must be >= 0".format(msec)) elif msec == 0: return raw_speed = self._speed_percentage(speed) log_msg( "{}: run_for_time {}ms at speed {}, raw_speed {}, stop {}, block {}" .format(self, msec, speed, raw_speed, stop, block)) self.rxed_callback = False self.port_motor.run_for_time(msec, raw_speed, stop=stop, **kwargs) if block: self._wait()
def run_for_distance(self, distance, speed, stop=MotorStop.BRAKE, block=True, **kwargs): """ Drive in a straight line for ``distance`` Args: distance (DistanceValue): how far the midpoint between the wheels should travel speed (MotorSpeed): how fast the midpoint between the wheels should travel stop (MotorStop): how to stop the motors, defaults to :class:`MotorStop.BRAKE` block (bool): if True this function will not return until the motors have finished moving **kwargs: optional kwargs that will pass all the way down to the LEGO ``hub.port.X.motor`` API call """ distance_mm = distance_in_mm(distance) rotations = distance_mm / self.wheel.circumference_mm degrees = int(rotations * 360) log_msg("{}: run_for_distance distance_mm {}, rotations {}, speed {}". format(self, distance_mm, rotations, speed)) MoveTank.run_for_degrees(self, degrees, speed, speed, stop=stop, block=block, **kwargs)
def run_to_position(self, left_position, right_position, speed, stop=MotorStop.BRAKE, block=True, **kwargs): """ Run both motors at ``speed`` to the desired positions Args: left_position (int): the target position for the left motor right_position (int): the target position for the right motor speed (MotorSpeed): the speed of both motors stop (MotorStop): how to stop the motors, defaults to :class:`MotorStop.BRAKE` block (bool): if True this function will not return until the motors have finished moving **kwargs: optional kwargs that will pass all the way down to the LEGO ``hub.port.X.motor`` API call """ log_msg( "{}: run_to_position left_position {}, right_position {}, at speed {}" .format(self, left_position, right_position, speed)) speed = self._speed_percentage(speed) self.rxed_callback = False self.pair.run_to_position(left_position, right_position, speed, stop=stop, **kwargs) if block: self._wait()
def run_for_degrees(self, degrees, left_speed, right_speed, stop=MotorStop.BRAKE, block=True, **kwargs): """ Run the motors at the specified speeds, the two motors combined will move an average of ``degrees`` Args: degrees (int): the average number of degrees for the two motors to move left_speed (MotorSpeed): the speed of the left motor right_speed (MotorSpeed): the speed of the right motor stop (MotorStop): how to stop the motors, defaults to :class:`MotorStop.BRAKE` block (bool): if True this function will not return until the motors have finished moving **kwargs: optional kwargs that will pass all the way down to the LEGO ``hub.port.X.motor`` API call """ log_msg( "{}: run_for_degrees {} at left_speed {}, right_speed {}".format( self, degrees, left_speed, right_speed)) left_speed = self._speed_percentage(left_speed) right_speed = self._speed_percentage(right_speed) self.rxed_callback = False (left_speed, right_speed) = self._speed_with_polarity(left_speed, right_speed) self.pair.run_for_degrees(degrees, left_speed, right_speed, stop=stop, **kwargs) if block: self._wait()
def _run_arc(self, radius_mm, distance_mm, speed, stop, block, arc_right, **kwargs): """ Drive in a circle with ``radius`` for ``distance`` """ if radius_mm < self.min_circle_radius_mm: raise ValueError( "{}: radius_mm {} is less than min_circle_radius_mm {}".format( self, radius_mm, self.min_circle_radius_mm)) speed = self._speed_percentage(speed) # The circle formed at the halfway point between the two wheels is the # circle that must have a radius of radius_mm circle_outer_mm = 2 * math.pi * (radius_mm + (self.wheel_distance_mm / 2)) # circle_middle_mm = 2 * math.pi * radius_mm circle_inner_mm = 2 * math.pi * (radius_mm - (self.wheel_distance_mm / 2)) if arc_right: # The left wheel is making the larger circle and will move at 'speed' # The right wheel is making a smaller circle so its speed will be a fraction of the left motor's speed left_speed = speed right_speed = float(circle_inner_mm / circle_outer_mm) * left_speed else: # The right wheel is making the larger circle and will move at 'speed' # The left wheel is making a smaller circle so its speed will be a fraction of the right motor's speed right_speed = speed left_speed = float(circle_inner_mm / circle_outer_mm) * right_speed avg_wheel_rotations = float(distance_mm / self.wheel.circumference_mm) avg_wheel_degrees = int(avg_wheel_rotations * 360) log_msg( "{}: arc {}, radius {}, distance {}, left-speed {}, right-speed {}, " .format(self, "right" if arc_right else "left", radius_mm, distance_mm, left_speed, right_speed) + "wheel circumference_mm {}, avg_wheel_rotations {}, avg_wheel_degrees {}" .format(self.wheel.circumference_mm, avg_wheel_rotations, avg_wheel_degrees)) MoveTank.run_for_degrees(self, avg_wheel_degrees, left_speed, right_speed, stop=stop, block=block, **kwargs)
def run_for_time(self, msec, left_speed, right_speed, stop=MotorStop.BRAKE, block=True, **kwargs): """ Run the motors at the specified speeds for ``msec`` Args: msec (int): the number of milliseconds to run the motors left_speed (MotorSpeed): the speed of the left motor right_speed (MotorSpeed): the speed of the right motor stop (MotorStop): how to stop the motors, defaults to :class:`MotorStop.BRAKE` block (bool): if True this function will not return until the motors have finished moving **kwargs: optional kwargs that will pass all the way down to the LEGO ``hub.port.X.motor`` API call """ """ rxed_callback = False def local_callback(reason): rxed_callback = True log_msg("rxed callback with reason {}".format(reason)) if block: self.pair.callback(local_callback) else: self.pair.callback(None) """ log_msg( "{}: run_for_time {}ms at left_speed {}, right_speed {}".format( self, msec, left_speed, right_speed)) left_speed = self._speed_percentage(left_speed) right_speed = self._speed_percentage(right_speed) (left_speed, right_speed) = self._speed_with_polarity(left_speed, right_speed) self.rxed_callback = False self.pair.run_for_time(msec, left_speed, right_speed, stop=stop, **kwargs) if block: self._wait()
def _callback(mtr, reason): if reason == MotorCallbackEvent.COMPLETED: mtr.interrupted = False mtr.stalled = False # log_msg("{}: _callback COMPLETED".format(mtr)) elif reason == MotorCallbackEvent.INTERRUPTED: mtr.interrupted = True mtr.stalled = False log_msg("{}: _callback INTERRUPTED".format(mtr)) elif reason == MotorCallbackEvent.STALL: mtr.interrupted = False mtr.stalled = True log_msg("{}: _callback STALL".format(mtr)) else: raise ValueError("invalid callback reason {}".format(reason)) mtr.rxed_callback = True
def wait_for_bump(self, timeout_ms=None): """ Wait ``timeout_ms`` for the ``TouchSensor`` to be bumped. Return ``True`` if the button was bumped within ``timeout_ms``, else return ``False``. If ``timeout_ms`` is ``None`` this will wait for forever. """ if self.is_pressed(): if self.wait_for_released(timeout_ms): log_msg("{} bumped".format(self)) return True else: log_msg("{} was not bumped within {}ms".format( self, timeout_ms)) return False else: if self.wait_for_pressed(timeout_ms) and self.wait_for_released( timeout_ms): log_msg("{} bumped".format(self)) return True else: log_msg("{} was not bumped within {}ms".format( self, timeout_ms)) return False
def wait_for_pressed(self, timeout_ms=None): """ Wait ``timeout_ms`` for the button to be pressed. Return ``True`` if the button was pressed within ``timeout_ms``, else return ``False``. If ``timeout_ms`` is ``None`` this will wait for forever. """ if self.is_pressed(): log_msg("{} already pressed".format(self)) return True self._rxed_callback = False if self._wait(timeout_ms): log_msg("{} pressed".format(self)) return True else: log_msg("{} was not pressed within {}ms".format(self, timeout_ms)) return False
def wait_for_released(self, timeout_ms=None): """ Wait ``timeout_ms`` for the ``TouchSensor`` to be released. Return ``True`` if the button was released within ``timeout_ms``, else return ``False``. If ``timeout_ms`` is ``None`` this will wait for forever. """ if self.is_released(): log_msg("{} already released".format(self)) return True stopwatch = StopWatch() stopwatch.start() while not self.is_released(): if timeout_ms is not None and stopwatch.value_ms >= timeout_ms: log_msg("{} was not released within {}ms".format( self, timeout_ms)) return False utime.sleep(0.01) log_msg("{} released".format(self)) return True
# standard libraries import utime # third party libraries import hub # spikedev libraries from spikedev.logging import log_msg from spikedev.sensor import DistanceSensor, DistanceSensorMode log_msg("start") ds = DistanceSensor(hub.port.A, mode=DistanceSensorMode.DISTL) for x in range(10): log_msg(ds.value()) utime.sleep(0.1) log_msg("finish")
# third party libraries import hub # spikedev libraries from spikedev.logging import log_msg from spikedev.sensor import TouchSensor, TouchSensorMode log_msg("start") ts = TouchSensor(hub.port.B, mode=TouchSensorMode.TOUCH) ts.wait_for_bump(5000) log_msg("finish")