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)
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
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)"]) # scale the input speed to between 0 (stop) and 255 (full speed)
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)
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)"]) # scale the input speed to between 0 (stop) and 255 (full speed) # these values were chosen by hand after inspecting the input data rider1Speed = 255 - (50 + inputDataRider1Speed * 8) rider2Speed = 255 - (50 + inputDataRider2Speed * 8)
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)