Exemplo n.º 1
0
class Roomba(object):
    def __init__(self, comPort, baudrate):
        self.API = RoombaAPI(comPort, baudrate)
#        print "Connecting"
#        self.API.connect()
        self.API.full()
        self.ECS = ECSRoomba(comPort)
        self.ECS.Control() # Set rto control mode
        self.ECS.sci.full() # Set to full mode
        self.sensors = Sensors(self, 10)

################################### DRIVING ###################################
#==============================================================================
    def drive(self, velocity, radius):  
    # UNDER CONSTRUCTION     
        
        velocity *= 1000 # m/s to mm/s
        radius *= 1000 # m/s to mm/s
        self.API.drive(int(velocity), int(radius))

            
#==============================================================================
    def driveStraight(self, velocity, distance, overrideSafe = False):
        """
        Function that makes the Roomba drive in a straight line, at a specified
        speed for a specified distance.
        
        INPUTS:
            velocity = velocity in m/s at which the Roomba will drive
            distance = distance in m which the Roomba will drive, negative 
                       distance means the roomba will drive backwards.
            overrideSafe = bool that says wether Roomba should stop when bumped
                           or when picked up (True), or whether it should stop
                           driving (False).
        OUTPUTS:
            None
        """
        s = 0 #distance driven
        th = 0 #angle turned
        velocity = abs(velocity*1000) #mm/s to m/s
        
        if self.sensors.checkSafe()  or overrideSafe:
            self.API.speed = int(velocity)
            
            if distance <= 0:
                self.API.backward()
                direction = 'BWD'
                # Call getodometry once without assigning output because 
                # when quickly changing directions tics count in opposite 
                # direction on first call.
                self.sensors.getOdometry(direction)
            else:
                self.API.forward()
                direction = 'FWD'
                # Call getodometry once without assigning output because 
                # when quickly changing directions tics count in opposite 
                # direction on first call.
                self.sensors.getOdometry(direction)
    
            while abs(s) < abs(distance) and (self.sensors.checkSafe() or overrideSafe):   
                     
                ds, dth = self.sensors.getOdometry(direction)
                
                s += ds
                th += dth
            
            self.stop()
        
        else:
            self.stop()
#==============================================================================
    def turnAngle(self, velocity, angle, overrideSafe = False):
        """
        Function that lets the Roomba turn a specified angle around it axis.
        
        INPUTS:
            velocity = the velocity in m/s at which the wheels will turn.
            angle = the angle in radians that the Roomba will turn, a positive
                    angle means that the Roomba will turn CCW, a negative angle
                    means that the Roomba will turn CW.
            overrideSafe = bool that says wether Roomba should stop when bumped
               or when picked up (True), or whether it should stop
               driving (False).
        
        OUTPUTS:
            None
        
        """
        s = 0 #distance driven
        th = 0 #angle turned
        dth = 0
        ds  = 0
        velocity = abs(velocity*1000) #mm/s to m/s
        
        if self.sensors.checkSafe() or overrideSafe:
            self.API.speed = int(velocity)
            
            if angle <= 0:
                self.API.spin_right()
                direction = 'CW'
                # Call getodometry once without assigning output because 
                # when quickly changing directions tics count in opposite 
                # direction on first call.
                self.sensors.getOdometry(direction)
            else:
                self.API.spin_left()
                direction = 'CCW'
                # Call getodometry once without assigning output because 
                # when quickly changing directions tics count in opposite 
                # direction on first call.
                self.sensors.getOdometry(direction)
    
            while abs(th) < abs(angle) and (self.sensors.checkSafe() or overrideSafe):                        
                ds, dth = self.sensors.getOdometry(direction)  
                # Handle unexpected odometry errors
                if abs(dth) >= 100: 
                    dth = 0
                s += ds
                th += dth
            
            self.stop()
        
        else:
            self.stop()  
#==============================================================================
    def driveArc(self, velocity, radius, angle, wallFollower = False):
        """
        Function that lets Roomba drive an arc segment, specified by a radius 
        and an angle, at a certain velocity.
        
        INPUTS:
            velocity = speed at which roomba will drive in m/s, positive 
                       speed makes Roomba drive forward, negative speed makes
                       roomba drive backwards.
            radius  = radius of the arc segment in m. Negative radius makes 
                      radius makes Roomba turn CW, positive radius makes Roomba
                      turn CCW.
            angle  = angle of the arc segment in radians
            
        OUTPUTS:
            None
        """
        s = 0
        th = 0
        dth = 0
        ds  = 0
        # Conversion from m to mm
        velocity *= 1000
        radius *= 1000
        safe = self.sensors.checkSafe()
        
        if safe:
            
            self.API.drive(int(velocity), int(radius))

            if velocity < 0:
                direction = 'BWD'
                # Call getodometry once without assigning output because 
                # when quickly changing directions tics count in opposite 
                # direction on first call.
                self.sensors.getOdometry(direction)
            else:
                direction = 'FWD'
                # Call getodometry once without assigning output because 
                # when quickly changing directions tics count in opposite 
                # direction on first call.
                self.sensors.getOdometry(direction)
            
            while abs(th) < abs(angle) and safe:
                ds, dth = self.sensors.getOdometry(direction)
                
                # Handle unexpected odometry errors
                if abs(dth) >= 100: 
                    dth = 0
                safe = self.sensors.checkSafe()
                wall = self.sensors.getWallSensor()
                if wallFollower:
                    if wall:
                        safe = False
                s += ds
                th += dth
                
            self.stop()
        else:
            self.stop()
        
#==============================================================================
    def stop(self):
        """
        Function to stop Roomba from driving
        
        INPUTS:
            None
        
        OUTPUTS:
            None
        """
        try:
            self.API.stop()
        except:
            self.ECS.Stop()     
            
################################### BUTTONS ###################################
    def getClean(self):
        """
        Function that returns the current status of the clean button. 
        
        INPUTS:
            None
        
        OUTPUTS:
            clean = status of clean button. False if button is not pressed, 
                    True if buttton is pressed.
        
        """
        clean = self.API.sensors.buttons.clean
        return clean
#==============================================================================
    def getDock(self):
        """
        Function that returns the current status of the dock button. 
        
        INPUTS:
            None
        
        OUTPUTS:
            dock = status of dock button. False if button is not pressed, 
                    True if buttton is pressed.
        
        """
        dock = self.API.sensors.buttons.dock
        return dock
#==============================================================================
    def getSpot(self):
        """
        Function that returns the current status of the spot button. 
        
        INPUTS:
            None
        
        OUTPUTS:
            spot = status of dock button. False if button is not pressed, 
                    True if buttton is pressed.
        
        """
        spot = self.API.sensors.buttons.spot
        return spot
            
##################################### LED #####################################      
    def turnOnLED(self, color, intensity):
        """
        Function to turn on 'clean' LED in the middle of the roomba.
        
        INPUTS:
            
            color = string that selects the color that the LED will have, allowed 
                    inputs are:
                    
                        'g'  = green
                        'y' = yellow
                        'o' = orange
                        'r' = red 
            
            intensity = number from 0-100 that represents the intensity, 0 means 
                        LED is off, 100 is maximum intensity.
                        
        OUTPUTS:
           none
        """
        
        if color == 'g':
            colorNum = 0
        elif color == 'y':
            colorNum = 8
        elif color == 'o':
            colorNum = 128
        elif color == 'r':
            colorNum = 255
        else:
            print "Invalid input for color, setting color to red."
            colorNum = 255
            
        intensityNum = int(255*intensity)/100 #Converting intensity to int bewteen 0 and 255
            
        self.API.led(0, colorNum, intensityNum)
#==============================================================================
    def flashLED(self, color, numOfFlashes, flashTime):
        """
            Function to flash 'clean' LED in the middle of the roomba.
            
            INPUTS:
                
                color = single character that selects the color that the LED will
                        have, allowed inputs are:
                        
                            'g'  = green
                            'y' = yellow
                            'o' = orange
                            'r' = red 
               numOfFlashes = number of times the LED will flash.
               
               flashTime = time in seconds between flashes
               
            OUTPUTS:
               None
        """
    
    
        
        for i in range(numOfFlashes):
            self.turnOnLED(color, 100)
            time.sleep(flashTime)
            self.turnOnLED(color, 0)
            time.sleep(flashTime)

##################################### SOUND ###################################
#==============================================================================
    def loadSong(self, songNum, song = 'BEEP'):
        """
        Function that loads a song onto the Roomba at a specified songNum.
        This song can later be played by using the function 'play'.
        
        INPUTS:
            songNum: Number (0-4) that specifies where the song will be saved
                     This is the number that later has to be used when calling play().
            song: predefined song that can be loaded, possible songs are:
                  BEEP: plays a sound simular to the charging sound.
                  TFC: plays the first 4 notes of the final countdown.
                  
        OUTPUTS:
            None
        """
        self.API.song(songNum, song)
#==============================================================================
    def play(self, songNum):
        """
        Function plays a preloaded song.
        
        INPUTS:
            songNum: location of the song, as specified in song()
        
        OUTPUTS:
            None
        """
        self.API.play(songNum)       
Exemplo n.º 2
0
class Roomba(object):
    def __init__(self, comPort, baudrate):
        self.API = RoombaAPI(comPort, baudrate)
        #        print "Connecting"
        #        self.API.connect()
        self.API.full()
        self.ECS = ECSRoomba(comPort)
        self.ECS.Control()  # Set rto control mode
        self.ECS.sci.full()  # Set to full mode
        self.sensors = Sensors(self, 10)

################################### DRIVING ###################################
#==============================================================================

    def drive(self, velocity, radius):
        # UNDER CONSTRUCTION

        velocity *= 1000  # m/s to mm/s
        radius *= 1000  # m/s to mm/s
        self.API.drive(int(velocity), int(radius))

#==============================================================================

    def driveStraight(self, velocity, distance, overrideSafe=False):
        """
        Function that makes the Roomba drive in a straight line, at a specified
        speed for a specified distance.
        
        INPUTS:
            velocity = velocity in m/s at which the Roomba will drive
            distance = distance in m which the Roomba will drive, negative 
                       distance means the roomba will drive backwards.
            overrideSafe = bool that says wether Roomba should stop when bumped
                           or when picked up (True), or whether it should stop
                           driving (False).
        OUTPUTS:
            None
        """
        s = 0  #distance driven
        th = 0  #angle turned
        velocity = abs(velocity * 1000)  #mm/s to m/s

        if self.sensors.checkSafe() or overrideSafe:
            self.API.speed = int(velocity)

            if distance <= 0:
                self.API.backward()
                direction = 'BWD'
                # Call getodometry once without assigning output because
                # when quickly changing directions tics count in opposite
                # direction on first call.
                self.sensors.getOdometry(direction)
            else:
                self.API.forward()
                direction = 'FWD'
                # Call getodometry once without assigning output because
                # when quickly changing directions tics count in opposite
                # direction on first call.
                self.sensors.getOdometry(direction)

            while abs(s) < abs(distance) and (self.sensors.checkSafe()
                                              or overrideSafe):

                ds, dth = self.sensors.getOdometry(direction)

                s += ds
                th += dth

            self.stop()

        else:
            self.stop()
#==============================================================================

    def turnAngle(self, velocity, angle, overrideSafe=False):
        """
        Function that lets the Roomba turn a specified angle around it axis.
        
        INPUTS:
            velocity = the velocity in m/s at which the wheels will turn.
            angle = the angle in radians that the Roomba will turn, a positive
                    angle means that the Roomba will turn CCW, a negative angle
                    means that the Roomba will turn CW.
            overrideSafe = bool that says wether Roomba should stop when bumped
               or when picked up (True), or whether it should stop
               driving (False).
        
        OUTPUTS:
            None
        
        """
        s = 0  #distance driven
        th = 0  #angle turned
        dth = 0
        ds = 0
        velocity = abs(velocity * 1000)  #mm/s to m/s

        if self.sensors.checkSafe() or overrideSafe:
            self.API.speed = int(velocity)

            if angle <= 0:
                self.API.spin_right()
                direction = 'CW'
                # Call getodometry once without assigning output because
                # when quickly changing directions tics count in opposite
                # direction on first call.
                self.sensors.getOdometry(direction)
            else:
                self.API.spin_left()
                direction = 'CCW'
                # Call getodometry once without assigning output because
                # when quickly changing directions tics count in opposite
                # direction on first call.
                self.sensors.getOdometry(direction)

            while abs(th) < abs(angle) and (self.sensors.checkSafe()
                                            or overrideSafe):
                ds, dth = self.sensors.getOdometry(direction)
                # Handle unexpected odometry errors
                if abs(dth) >= 100:
                    dth = 0
                s += ds
                th += dth

            self.stop()

        else:
            self.stop()
#==============================================================================

    def driveArc(self, velocity, radius, angle, wallFollower=False):
        """
        Function that lets Roomba drive an arc segment, specified by a radius 
        and an angle, at a certain velocity.
        
        INPUTS:
            velocity = speed at which roomba will drive in m/s, positive 
                       speed makes Roomba drive forward, negative speed makes
                       roomba drive backwards.
            radius  = radius of the arc segment in m. Negative radius makes 
                      radius makes Roomba turn CW, positive radius makes Roomba
                      turn CCW.
            angle  = angle of the arc segment in radians
            
        OUTPUTS:
            None
        """
        s = 0
        th = 0
        dth = 0
        ds = 0
        # Conversion from m to mm
        velocity *= 1000
        radius *= 1000
        safe = self.sensors.checkSafe()

        if safe:

            self.API.drive(int(velocity), int(radius))

            if velocity < 0:
                direction = 'BWD'
                # Call getodometry once without assigning output because
                # when quickly changing directions tics count in opposite
                # direction on first call.
                self.sensors.getOdometry(direction)
            else:
                direction = 'FWD'
                # Call getodometry once without assigning output because
                # when quickly changing directions tics count in opposite
                # direction on first call.
                self.sensors.getOdometry(direction)

            while abs(th) < abs(angle) and safe:
                ds, dth = self.sensors.getOdometry(direction)

                # Handle unexpected odometry errors
                if abs(dth) >= 100:
                    dth = 0
                safe = self.sensors.checkSafe()
                wall = self.sensors.getWallSensor()
                if wallFollower:
                    if wall:
                        safe = False
                s += ds
                th += dth

            self.stop()
        else:
            self.stop()

#==============================================================================

    def stop(self):
        """
        Function to stop Roomba from driving
        
        INPUTS:
            None
        
        OUTPUTS:
            None
        """
        try:
            self.API.stop()
        except:
            self.ECS.Stop()

################################### BUTTONS ###################################

    def getClean(self):
        """
        Function that returns the current status of the clean button. 
        
        INPUTS:
            None
        
        OUTPUTS:
            clean = status of clean button. False if button is not pressed, 
                    True if buttton is pressed.
        
        """
        clean = self.API.sensors.buttons.clean
        return clean
#==============================================================================

    def getDock(self):
        """
        Function that returns the current status of the dock button. 
        
        INPUTS:
            None
        
        OUTPUTS:
            dock = status of dock button. False if button is not pressed, 
                    True if buttton is pressed.
        
        """
        dock = self.API.sensors.buttons.dock
        return dock
#==============================================================================

    def getSpot(self):
        """
        Function that returns the current status of the spot button. 
        
        INPUTS:
            None
        
        OUTPUTS:
            spot = status of dock button. False if button is not pressed, 
                    True if buttton is pressed.
        
        """
        spot = self.API.sensors.buttons.spot
        return spot

##################################### LED #####################################

    def turnOnLED(self, color, intensity):
        """
        Function to turn on 'clean' LED in the middle of the roomba.
        
        INPUTS:
            
            color = string that selects the color that the LED will have, allowed 
                    inputs are:
                    
                        'g'  = green
                        'y' = yellow
                        'o' = orange
                        'r' = red 
            
            intensity = number from 0-100 that represents the intensity, 0 means 
                        LED is off, 100 is maximum intensity.
                        
        OUTPUTS:
           none
        """

        if color == 'g':
            colorNum = 0
        elif color == 'y':
            colorNum = 8
        elif color == 'o':
            colorNum = 128
        elif color == 'r':
            colorNum = 255
        else:
            print "Invalid input for color, setting color to red."
            colorNum = 255

        intensityNum = int(
            255 *
            intensity) / 100  #Converting intensity to int bewteen 0 and 255

        self.API.led(0, colorNum, intensityNum)
#==============================================================================

    def flashLED(self, color, numOfFlashes, flashTime):
        """
            Function to flash 'clean' LED in the middle of the roomba.
            
            INPUTS:
                
                color = single character that selects the color that the LED will
                        have, allowed inputs are:
                        
                            'g'  = green
                            'y' = yellow
                            'o' = orange
                            'r' = red 
               numOfFlashes = number of times the LED will flash.
               
               flashTime = time in seconds between flashes
               
            OUTPUTS:
               None
        """

        for i in range(numOfFlashes):
            self.turnOnLED(color, 100)
            time.sleep(flashTime)
            self.turnOnLED(color, 0)
            time.sleep(flashTime)

##################################### SOUND ###################################
#==============================================================================

    def loadSong(self, songNum, song='BEEP'):
        """
        Function that loads a song onto the Roomba at a specified songNum.
        This song can later be played by using the function 'play'.
        
        INPUTS:
            songNum: Number (0-4) that specifies where the song will be saved
                     This is the number that later has to be used when calling play().
            song: predefined song that can be loaded, possible songs are:
                  BEEP: plays a sound simular to the charging sound.
                  TFC: plays the first 4 notes of the final countdown.
                  
        OUTPUTS:
            None
        """
        self.API.song(songNum, song)
#==============================================================================

    def play(self, songNum):
        """
        Function plays a preloaded song.
        
        INPUTS:
            songNum: location of the song, as specified in song()
        
        OUTPUTS:
            None
        """
        self.API.play(songNum)