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 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)
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'))
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;
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
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)"])
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'))
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)
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)
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)