Example #1
0
    def startWebSocketClient(self):
        self.cannybot = CannybotClient()  #  Connects to the default Cannybot
        self.cannybot.registerReceiveCallback(self.send2scratch)

        # If there's any trouble just exit, the service daemon will restart us
        self.cannybot.registerErrorCallback(self.stop)
        self.cannybot.registerClosedCallback(self.stop)
Example #2
0
 def bleInit(self):
     if sys.platform == 'darwin':
         return
     
     self.ble1 = CannybotClient(botId=0)             
     self.ble2 = CannybotClient(botId=1)             
     self.ble1.registerReceiveCallback(self.bleRacer1ReceviedData)
     self.ble2.registerReceiveCallback(self.bleRacer2ReceviedData)
Example #3
0
    def startWebSocketClient(self):
        self.cannybot = CannybotClient()             #  Connects to the default Cannybot
        self.cannybot.registerReceiveCallback(self.send2scratch)

        # If there's any trouble just exit, the service daemon will restart us
        self.cannybot.registerErrorCallback(self.stop)
        self.cannybot.registerClosedCallback(self.stop)
Example #4
0
import sys
import os
import csv
from time import sleep
from sys import stdin

from cannybots.clients.wsclient import CannybotClient


def dataReceived(message):
    print "Received: " + message


cannybot = CannybotClient()  #  Connects to the first available Cannybot

cannybot.registerReceiveCallback(dataReceived)

sleep(2)  # wait a bit for connection setup

while 1:
    userinput = stdin.readline()
    if len(userinput) > 0:
        cannybot.send(format(ord(userinput[0]), '02X'))
Example #5
0
class ScratchAgent:
    
    def __init__(self):
        log( "Cannybots Scratch Agent starting...")

        self.keepRunning = True
        self.scratchInterface = None
        self.cannybot = None
    
    def startWebSocketClient(self):
        self.cannybot = CannybotClient()             #  Connects to the default Cannybot
        self.cannybot.registerReceiveCallback(self.send2scratch)

        # If there's any trouble just exit, the service daemon will restart us
        self.cannybot.registerErrorCallback(self.stop)
        self.cannybot.registerClosedCallback(self.stop)

    def startScratchClient(self):
        self.scratchInterface = scratch.Scratch()
        self.scratchInterface.connect()


    def  send2scratch(self, msg):
        if self.scratchInterface:
            log("sending to scratch: " + str(msg))
            try:
                self.scratchInterface.broadcast(msg)                
            except scratch.ScratchConnectionError as sce:
                log( "ERROR: (ScratchConnection) " + sce.message)
                self.keepRunning = False
            except Exception as err:
                log( "ERROR: (General, whilst sending to Scatch) " + err.message)
                self.keepRunning = False

            
        else:
            print "WARN: Scratch not yet initialised"


    def send2cannybot(self, message):        
        self.cannybot.send(format(ord(message),'02X'))



    # TODO: make this configurable and general purpose
    def processMessage(self, message):
        commands = { 
            'MoveForward' : self.maze_forward,
            'TurnRight'   : self.maze_right,
            'TurnLeft'    : self.maze_left,
            'Spin'        : self.maze_spin,
            'Stop'        : self.maze_stop
        }
        
        command = message[1]
        #log( "Command: " + command)
        if command in commands:            
            commands[command](message);
        else:
            log( "WARN: Unrecognised message: {}".format(message))
        
        
    # Mazing
    def maze_forward(self, message):
        self.send2cannybot('f')

    def maze_right(self, message):
        self.send2cannybot('r')

    def maze_left(self, message):
        self.send2cannybot('l')

    def maze_spin(self, message):
        self.send2cannybot('p')

    def maze_stop(self, message):
        self.send2cannybot('s')


    #motor commands
    #led and other sensor commands


    def isConnected(self):        
        wsOK = self.cannybot.isConnected()
        scratchOK = self.scratchInterface.connected = True
        
        if (wsOK and scratchOK and self.keepRunning):
            return True
        else:
            if (not scratchOK):
                log( "Not connected to scratch")
            if (not wsOK):
                log( "Not connected to webocket API")
            return False
            
    
    def connect(self):
        self.startScratchClient();
        self.startWebSocketClient();


    def run(self):
        self.workerThread = Thread(target=self._scratch_message_worker)
        self.workerThread.daemon = True
        self.workerThread.name = 'ScratchMsgWorker'
        self.workerThread.start()
        
    def _scratch_message_worker(self):
        try:
            while self.keepRunning:
                for msg in self.listen():
                    if msg[0] == 'broadcast':
                        log( "From scratch (broadcast): " + str(msg))
                        self.processMessage(msg)
                    elif msg[0] == 'sensor-update':
                        log( "From scratch (sensor): " + str(msg))
        except scratch.ScratchError as se:
            log( "ERROR: MsgWorker (Scratch) " + se.message)
        except StopIteration as si:
            log( "ERROR: MsgWorker (MsgProc) " + si.message)
        except Exception as err:
            log( "ERROR: MsgWorker (General) " + err.message)
            
        self.keepRunning = False

          
    def listen(self):
        while True:
            try:
               yield self.scratchInterface.receive()
            except scratch.ScratchError:
               raise StopIteration            

    def start(self):
        try:
            self.connect()
            self.run()
            while True:
                sleep(CONNECTION_CHECK_DELAY)        
                if not self.isConnected():
                    break
        except scratch.ScratchError as se:
            log ("ERROR: Main (Scratch) " + se.message)
        except Exception as err:
            log( "ERROR: Main (General) " + err.message)
        
        

    def stop(self):
        log( "Cannybots Scratch Agent exiting...")
        self.keepRunning=False;
Example #6
0
class ScratchAgent:
    def __init__(self):
        log("Cannybots Scratch Agent v{} starting...".format(VERSION))

        self.keepRunning = True
        self.scratchInterface = None
        self.cannybot = None

    def startWebSocketClient(self):
        self.cannybot = CannybotClient()  #  Connects to the default Cannybot
        self.cannybot.registerReceiveCallback(self.processCannybotEvent)

        # If there's any trouble just exit, the service daemon will restart us
        self.cannybot.registerErrorCallback(self.stop)
        self.cannybot.registerClosedCallback(self.stop)

        self.joypad = JoypadClient(self.cannybot)

    def startScratchClient(self):
        self.scratchInterface = scratch.Scratch()
        self.scratchInterface.connect()

    def send2scratch(self, msg):
        if self.scratchInterface:
            log("sending to scratch: " + str(msg))
            try:
                self.scratchInterface.broadcast(msg)
            except scratch.ScratchConnectionError as sce:
                log("ERROR: (ScratchConnection) " + sce.message)
                self.keepRunning = False
            except Exception as err:
                log("ERROR: (General, whilst sending to Scatch) " +
                    err.message)
                self.keepRunning = False

        else:
            print "WARN: Scratch not yet initialised"

    def send2cannybot(self, message):
        self.cannybot.send(format(ord(message), '02X'))

    # TODO: make this configurable and general purpose
    def processScratchSensorUpdate(self, message):
        log("processScratchSensorUpdate: {}".format(message))
        for sensor, value in message[1].iteritems():
            log("INFO: processScratchSensorUpdate {} = {}".format(
                sensor, value))
            if sensor == "CannybotSpeed":
                self.joypad.setSpeed(value)

    # TODO: make this configurable and general purpose
    def processScratchBroadcast(self, message):
        commands = {
            'MoveForward': self.maze_forward,
            'TurnRight': self.maze_right,
            'TurnLeft': self.maze_left,
            'Spin': self.maze_spin,
            'Stop': self.maze_stop
        }

        command = message[1]
        #log( "Command: " + command)
        if command in commands:
            commands[command](message)
        else:
            log("WARN: Unrecognised broadcast: {}".format(message))

    # TODO: make this configurable and general purpose
    def processCannybotEvent(self, message):
        log("cannybot event {}".format(message))
        eventTextMappings = {
            'RGB:R': "Red",
            'RGB:G': "Green",
            'RGB:B': "Blue",
            'RGB:Y': "Yellow",
            'LINE:N': "OffTheLine",
            'LINE:Y': "OnTheLine",
        }

        eventText = message
        #log( "Command: " + command)
        if eventText in eventTextMappings:
            eventText = eventTextMappings[eventText]

        self.send2scratch(eventText)

    # Mazing
    def maze_forward(self, message):
        self.send2cannybot('f')

    def maze_right(self, message):
        self.send2cannybot('r')

    def maze_left(self, message):
        self.send2cannybot('l')

    def maze_spin(self, message):
        self.send2cannybot('p')

    def maze_stop(self, message):
        self.send2cannybot('s')

    #motor commands
    #led and other sensor commands

    def isConnected(self):
        wsOK = self.cannybot.isConnected()
        scratchOK = self.scratchInterface.connected = True

        if (wsOK and scratchOK and self.keepRunning):
            return True
        else:
            if (not scratchOK):
                log("Not connected to scratch")
            if (not wsOK):
                log("Not connected to webocket API")
            return False

    def connect(self):
        self.startScratchClient()
        self.startWebSocketClient()

    def run(self):
        self.workerThread = Thread(target=self._scratch_message_worker)
        self.workerThread.daemon = True
        self.workerThread.name = 'ScratchMsgWorker'
        self.workerThread.start()

    def _scratch_message_worker(self):
        try:
            while self.keepRunning:
                for msg in self.listen():
                    if msg[0] == 'broadcast':
                        log("From scratch (broadcast): " + str(msg))
                        self.processScratchBroadcast(msg)
                    elif msg[0] == 'sensor-update':
                        log("From scratch (sensor): " + str(msg))
                        self.processScratchSensorUpdate(msg)
        except scratch.ScratchError as se:
            log("ERROR: MsgWorker (Scratch) " + se.message)
        except StopIteration as si:
            log("ERROR: MsgWorker (MsgProc) " + si.message)
        except Exception as err:
            log("ERROR: MsgWorker (General) " + err.message)

        self.keepRunning = False

    def listen(self):
        while True:
            try:
                yield self.scratchInterface.receive()
            except scratch.ScratchError:
                raise StopIteration

    def start(self):
        try:
            self.connect()
            self.run()
            while True:
                sleep(CONNECTION_CHECK_DELAY)
                if not self.isConnected():
                    break
        except scratch.ScratchError as se:
            log("ERROR: Main (Scratch) " + se.message)
        except Exception as err:
            log("ERROR: Main (General) " + err.message)

    def stop(self):
        log("Cannybots Scratch Agent exiting...")
        self.keepRunning = False
Example #7
0
import csv
from time import sleep

from cannybots.clients.wsclient import CannybotClient
from cannybots.clients.joypad import JoypadClient

SPEED_DURATION = 2  # Number of seconds to hold a speed for

cannybot1 = CannybotClient(
    botId='2'
)  # Connects to the default Cannybot configured in NodeRED (using a local WebSocket API)
cannybot2 = CannybotClient(botId='3')

sleep(2)

rider1 = JoypadClient(
    cannybot1
)  # Creates a Joystick helper that can create and send joystick messages
rider2 = JoypadClient(cannybot2)

# Open a csv files that has rows of Speeds in
# This uses the first row in the CSV for the column names (see the speeds.csv)
input_file = csv.DictReader(
    open("Cycling Data for Cannybots.xlsx - Cyclists.csv"))

for row in input_file:

    # Read the speed from column which has the title of 'Speed' in the current row
    inputDataRider1Speed = float(row["Rider One Speed (km/Hr)"])
    inputDataRider2Speed = float(row["Rider Two Speed (km/Hr)"])
Example #8
0
import sys
import os
import csv
from time import sleep
from sys import stdin


from cannybots.clients.wsclient import CannybotClient


def dataReceived(message):
    print "Received: " + message

cannybot = CannybotClient()             #  Connects to the first available Cannybot

cannybot.registerReceiveCallback(dataReceived)

sleep(2)  # wait a bit for connection setup

while 1:
    userinput = stdin.readline()
    if len(userinput)>0:
        cannybot.send(format(ord(userinput[0]),'02X'))

Example #9
0
import csv
from time import sleep

from cannybots.clients.wsclient import CannybotClient
from cannybots.clients.joypad import JoypadClient

SPEED_DURATION = 2                      # Number of seconds to hold a speed for

cannybot = CannybotClient()             # Connects to the default Cannybot configured in NodeRED (using a local WebSocket API)
joypad   = JoypadClient(cannybot)       # Creates a Joystick helper that can create and send joystick messages


# Open a csv files that has rows of Speeds in
# This uses the first row in the CSV for the column names (see the speeds.csv)
input_file = csv.DictReader(open("speeds.csv"))


for row in input_file:

    # Read the speed from column which has the title of 'Speed' in the current row
    inputDataSpeed = float(row["Speed"])

    # scale the input speed to between 0 (stop) and 255 (full speed)
    # these values were chosen by hand after inspecting the input data
    cannybotSpeed = 50 + inputDataSpeed * 10

    print "Input Data speed: {}  => Cannybot speed: {}".format(inputDataSpeed, cannybotSpeed)

    # send the forward speed
    joypad.update(0, cannybotSpeed, 0, 0)
Example #10
0
class RaceController():
    """ RaceController """

    def __init__(self):
        self.player1Stats = 0
        self.player2Stats = 0
        self.mainScoreBoard = 0

        self.bleInit()
        self.lastUpdateTime = time.time()
        self.running = True
        self.display = Display(windowed=1, windowWidth=1280, windowHeight=800)
        self.screen = self.display.screen
        self.clock = pygame.time.Clock()

        self.appInit()


    def appInit(self):
        self.app = gui.App()
        c = gui.Container(align=0, valign=0)
        self.table = self.setupTable()
        c.add(self.table, 0, 0)
        self.app.init(c)

    def decreasePlayerSpeed(self, player):
        print "decreasePlayerSpeed:%d" % player

    def increasePlayerSpeed(self, player):
        print "increasePlayerSpeed:%d" % player
        if player == 1:
            self.mainScoreBoard.newTime("One", self.player1Stats.currentLapTime, )
        else:
            self.mainScoreBoard.newTime("Two",self.player2Stats.currentLapTime)

    def resetBoard(self, value):
        self.mainScoreBoard.reset()
        self.player1Stats.reset()
        self.player2Stats.reset()


    def createIcon(self, imageFile, text, callback, value):
        e = Obj()
        e.image = pygame.image.load(imageFile)
        e.rect = pygame.Rect(0, 0, e.image.get_width(), e.image.get_height())
        e.align = 0
        btn = gui.Icon(text, style={'font': roboticaSmallFont, 'image': e.image})
        btn.connect(gui.CLICK, callback, value)
        return btn

    def createImage(self, imageFile):
        e = Obj()
        e.image = pygame.image.load(imageFile)
        e.rect = pygame.Rect(0, 0, e.image.get_width(), e.image.get_height())
        e.align = 0
        e.style = {}
        print repr(e.style)
        return e


    def setupTable(self):

        fg = (0, 0, 0)

        self.player1Stats = PlayerTimes(1)
        self.player2Stats = PlayerTimes(2)
        self.mainScoreBoard = LapTimeScoreBoard()

        p1SlowBtn = self.createIcon(basedir+"/images/button.png", "slower", self.decreasePlayerSpeed, 1)
        p1FastBtn = self.createIcon(basedir+"/images/button.png", "faster", self.increasePlayerSpeed, 1)
        p2SlowBtn = self.createIcon(basedir+"/images/button.png", "slower", self.decreasePlayerSpeed, 2)
        p2FastBtn = self.createIcon(basedir+"/images/button.png", "faster", self.increasePlayerSpeed, 2)
        resetBtn = self.createIcon(basedir+"/images/button.png", "reset", self.resetBoard, 1)


        # Create the Table cells

        table = gui.Table(width=self.screen.get_width(), height=self.screen.get_height())

        table.tr()
        table.td(gui.Label(""))
        table.td(gui.Label(""))
        table.td(gui.Image(basedir + "/images/cannybots_logo.png"), colspan=1, rowspan=1, align=0, valign=0)
        table.td(gui.Label(""))
        table.td(gui.Label(""))

        table.tr()
        table.td(gui.Label("Racer One", color=fg, style={'font': roboticaMediumFont}), colspan=2, rowspan=1, align=1,
                 valign=-1)
        table.td(self.mainScoreBoard, colspan=1, rowspan=2)
        table.td(gui.Label("Racer Two", color=fg, style={'font': roboticaMediumFont}), colspan=2, rowspan=1, align=-1,
                 valign=-1)

        table.tr()
        table.td(self.player1Stats, colspan=2, valign=-1)
        table.td(gui.Label(""))
        table.td(self.player2Stats, colspan=2, valign=-1)

        table.tr()
        table.td(p1SlowBtn, rowspan=1, align=-1)
        table.td(p1FastBtn, rowspan=1, align=1)
        table.td(resetBtn)
        table.td(p2SlowBtn, rowspan=1, align=-1)
        table.td(p2FastBtn, rowspan=1, align=1)

        table.tr()

        return table

    def handleEvents(self):
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                self.running = 0
            elif event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
                self.running = False
            else:
                self.app.event(event)


    def draw(self):
        self.screen.fill((255, 255, 255))

        # self.screen.set_clip(self.mainScoreBoard.get_abs_rect())
        # self.screen.set_clip()

        self.app.paint()
        pygame.display.flip()

    def update(self):
        pass
        #if self.player1Stats.timerStarted:
        #    self.player1Stats.setCurrentLapTime(time.time() - self.player1Stats.startTime)
        #if self.player2Stats.timerStarted:
        #    self.player2Stats.setCurrentLapTime(time.time() - self.player2Stats.startTime)

    def run(self):
        while self.running:
            self.handleEvents()
            self.update()
            self.draw()
            self.clock.tick(30)
        pygame.quit()

    def bleRacer1ReceviedData(self, message):
        print "p1: " + str (message)
        if not self.player1Stats:
            return
        if message.startswith("LAP_START"):
            print "Player1 Lap!"
            if self.player1Stats.timerStarted:
                self.player1Stats.setCurrentLapTime(time.time() - self.player1Stats.startTime)
                self.mainScoreBoard.newTime("One", self.player1Stats.currentLapTime)
            self.player1Stats.currentLapTime = 0
            self.player1Stats.timerStarted=True
            self.player1Stats.startTime=time.time()

    def bleRacer2ReceviedData(self, message):
        print "p2: " + str (message)
        if not self.player2Stats:
            return
        if message.startswith("LAP_START"):
            print "Player2 Lap Start!"
            if self.player2Stats.timerStarted:
                self.player2Stats.setCurrentLapTime(time.time() - self.player2Stats.startTime)
                self.mainScoreBoard.newTime("Two", self.player2Stats.currentLapTime)
            self.player2Stats.currentLapTime = 0
            self.player2Stats.timerStarted=True
            self.player2Stats.startTime=time.time()

    def bleInit(self):
        if sys.platform == 'darwin':
            return
        
        self.ble1 = CannybotClient(botId=0)             
        self.ble2 = CannybotClient(botId=1)             
        self.ble1.registerReceiveCallback(self.bleRacer1ReceviedData)
        self.ble2.registerReceiveCallback(self.bleRacer2ReceviedData)
Example #11
0
import sys
import os
import csv
from time import sleep

from cannybots.clients.wsclient import CannybotClient
from cannybots.clients.joypad import JoypadClient


def dataReceived(message):
    print "Received: " + message

cannybot = CannybotClient()             #  Connects to the first available Cannybot
joypad   = JoypadClient(cannybot)
cannybot.registerReceiveCallback(dataReceived)

sleep(2)  # wait a bit for connection setup

joypad.requestStatus()

#for speed in range(-255 , 255):
#    print "Speed: " + str(speed)
#    joypad.update(speed, speed, 0, 0)
#    sleep(0.25)

for speed in range(1,5):
    motorASpeed = speed*50
    motorBSpeed = speed*50
    joypad.update(motorASpeed, motorBSpeed, 0, 0)
    sleep(1)