Module micromelon.motors

Collection of functions to control the movement of the robot

Expand source code
"""
Collection of functions to control the movement of the robot
"""
from ._motors import *

__all__ = [
    "write",
    "moveDistance",
    "turn",
    "turnDegrees",
    "setDegreesOffset",
]

Functions

def moveDistance(lDist, lSpeed=15, rDist=None, rSpeed=None, syncStop=False)

Drives each side of the robot by the distances and speeds specified.
If only lDist is specified then both motors will drive that distance at 15cm/s
If lDist and lSpeed are specified then both motors will drive that distance at that speed
If syncStop is True then both motors will stop when one completes its operation

Note that this is a blocking call and won't return until the operation has completed
Note that operations that will take longer than 2 minutes will time out

Args

lDist : float
distance in cm for left motor
lSpeed : float
speed in cm/s for left motor (must be between -30 and 30)
rDist : float
distance in cm for right motor
lSpeed : float
speed in cm/s for left motor (must be between -30 and 30)
syncStop : boolean
whether or not to stop both motors as soon as one completes

Raises

Exception on invalid arguments

Returns

None

Expand source code
def moveDistance(lDist, lSpeed=15, rDist=None, rSpeed=None, syncStop=False):
    """
    Drives each side of the robot by the distances and speeds specified.
    If only lDist is specified then both motors will drive that distance at 15cm/s
    If lDist and lSpeed are specified then both motors will drive that distance at that speed
    If syncStop is True then both motors will stop when one completes its operation

    Note that this is a blocking call and won't return until the operation has completed
    Note that operations that will take longer than 2 minutes will time out

    Args:
      lDist (float): distance in cm for left motor
      lSpeed (float): speed in cm/s for left motor (must be between -30 and 30)
      rDist (float): distance in cm for right motor
      lSpeed (float): speed in cm/s for left motor (must be between -30 and 30)
      syncStop (boolean): whether or not to stop both motors as soon as one completes

    Raises:
      Exception on invalid arguments

    Returns:
      None
    """
    motorValues = _buildMotorValuesArray(lDist, lSpeed, rDist, rSpeed, syncStop)
    # Give it two minutes max to complete the operation
    _rc.doMotorOperation(
        OPTYPE.MOTOR_SET, _buildMotorPacketData(motorValues), timeout=120
    )
def setDegreesOffset(offset)

Applies offset as a difference to all degrees arguments in the Motor control functions.
If it is big enough to change the sign of degrees it will not be applied.

Args

offset : float
Number of degrees offset to apply to all motor functions that take degrees
as an argument

Raises

Exception if offset is not a number

Returns

None

Expand source code
def setDegreesOffset(offset):
    """
    Applies offset as a difference to all degrees arguments in the Motor control functions.
    If it is big enough to change the sign of degrees it will not be applied.

    Args:
      offset (float): Number of degrees offset to apply to all motor functions that take degrees
                      as an argument

    Raises:
      Exception if offset is not a number

    Returns:
      None
    """
    if not isNumber(offset):
        raise Exception("Degrees offset must be a number")
    global _degreesCalibrationOffset
    _degreesCalibrationOffset = offset
def turn(speed, secs=None, radius=0, reverse=False)

Makes the robot turn at the specified speed for the specified number of seconds.
If seconds is a number > 0 the function will block (wait) until that time has elapsed and stop the motors
If seconds is None then the speeds will be set and the function will return
Negative speed is a left turn. Speeds are cm/s must be between -30 and 30.
By default it turns on the spot, but a radius in cm can be specified.

Args

speed : float
Motor speed to base the turn off. If turning on the spot this will be actual speed.
Will be scaled if radius > 0. Must be between -30 and 30 (cm/s)
secs : float
Optional number of seconds to leave the motors running at the desired speed before stopping
radius : float
Optional radius (in cm) to make the turn in
reverse : boolean
If True then the turn will be done in reverse

Raises

Exception on invalid arguments

Returns

None

Expand source code
def turn(speed, secs=None, radius=0, reverse=False):
    """
    Makes the robot turn at the specified speed for the specified number of seconds.
    If seconds is a number > 0 the function will block (wait) until that time has elapsed and stop the motors
    If seconds is None then the speeds will be set and the function will return
    Negative speed is a left turn. Speeds are cm/s must be between -30 and 30.
    By default it turns on the spot, but a radius in cm can be specified.

    Args:
      speed (float): Motor speed to base the turn off.  If turning on the spot this will be actual speed.
                    Will be scaled if radius > 0. Must be between -30 and 30 (cm/s)
      secs (float): Optional number of seconds to leave the motors running at the desired speed before stopping
      radius (float): Optional radius (in cm) to make the turn in
      reverse (boolean): If True then the turn will be done in reverse

    Raises:
      Exception on invalid arguments

    Returns:
      None
    """
    speed = restrictSpeed(speed)
    radius = restrictRadius(radius)

    params = _calcMotorSpeedsAndTime(speed, radius, None, reverse)
    speeds = params["speeds"]

    if secs != None:
        secs = restrictTime(secs)
    else:
        secs = 0
    write(speeds[0], speeds[1], secs)
def turnDegrees(degrees, speed=15, radius=0, reverse=False)

Makes the robot turn at the specified number of degrees.
Function will block (wait) until the operation has completed
Negative speed is a left turn. Speeds are cm/s must be between -30 and 30.
By default it turns on the spot, but a radius in cm can be specified.

Note that operations that will take longer than 2 minutes will time out

Args

degrees : float
Number of degrees to turn. Negative degrees is a left turn
speed : float
Motor speed to base the turn off. If turning on the spot this will be actual speed.
Will be scaled if radius > 0. Must be between -30 and 30 (cm/s)
radius : float
Optional radius (in cm) to make the turn in
reverse : boolean
If True then the turn will be done in reverse

Raises

Exception on invalid arguments

Returns

None

Expand source code
def turnDegrees(degrees, speed=15, radius=0, reverse=False):
    """
    Makes the robot turn at the specified number of degrees.
    Function will block (wait) until the operation has completed
    Negative speed is a left turn. Speeds are cm/s must be between -30 and 30.
    By default it turns on the spot, but a radius in cm can be specified.

    Note that operations that will take longer than 2 minutes will time out

    Args:
      degrees (float): Number of degrees to turn.  Negative degrees is a left turn
      speed (float): Motor speed to base the turn off.  If turning on the spot this will be actual speed.
                    Will be scaled if radius > 0. Must be between -30 and 30 (cm/s)
      radius (float): Optional radius (in cm) to make the turn in
      reverse (boolean): If True then the turn will be done in reverse

    Raises:
      Exception on invalid arguments

    Returns:
      None
    """
    speed = restrictSpeed(speed)
    radius = restrictRadius(radius)
    if not isNumber(degrees):
        raise Exception("Degrees must be a number")

    if degrees == 0:
        return True

    params = _calcMotorSpeedsAndTime(speed, radius, degrees, reverse)

    motorValues = _buildMotorValuesArray(
        params["distances"][0],
        params["speeds"][0],
        params["distances"][1],
        params["speeds"][1],
        True,
    )

    if _rc.connectedRobotIsSimulated():
        motorValues.append(abs(degrees))
        # Give it two minutes max to complete the operation
        _rc.doMotorOperation(
            OPTYPE.TURN_DEGREES, _buildMotorPacketData(motorValues), timeout=120
        )
        return

    # Fall back to move distance for non-simulated robots
    return moveDistance(
        params["distances"][0],
        params["speeds"][0],
        params["distances"][1],
        params["speeds"][1],
        True,
    )

    # Both the below approaches should work:
    #   Time control prevents error accumulation in the encoders but relies on good latency
    # return moveDistance(params['distances'][0], params['speeds'][0],
    #     params['distances'][1], params['speeds'][1], True)
    # return write(params['speeds'][0], params['speeds'][1], params['seconds'])
def write(left, right=None, secs=0)

Set the speed of the robot motors in cm/s
If only one argument is given then both motors will be set to the same speed
If secs is given then the set the motor speeds and block (wait) for that many seconds
and then stop the motors

Args

left, right (float): motor speeds must be between -30 and 30 (cm/s)
secs : float
Optional number of seconds to wait for after setting the speeds then stop

Raises

Exception on invalid arguments

Returns

None

Expand source code
def write(left, right=None, secs=0):
    """
    Set the speed of the robot motors in cm/s
    If only one argument is given then both motors will be set to the same speed
    If secs is given then the set the motor speeds and block (wait) for that many seconds
    and then stop the motors

    Args:
      left, right (float): motor speeds must be between -30 and 30 (cm/s)
      secs (float): Optional number of seconds to wait for after setting the speeds then stop

    Raises:
      Exception on invalid arguments

    Returns:
      None
    """
    if right == None:
        right = left
    left = restrictSpeed(left)
    right = restrictSpeed(right)
    secs = restrictTime(secs)

    _rc.writeAttribute(OPTYPE.MOTOR_SET, _buildMotorPacketData([left, right]))
    if secs != 0:
        time.sleep(secs)
        _rc.writeAttribute(OPTYPE.MOTOR_SET, _buildMotorPacketData([0, 0]))