class Notifications(object): def __init__(self): self.speaker = speaker.newSpeaker() #interprocess self.DISPATCHER_PORT = 9002 self.dispatcherClient = DispatcherClient(port=self.DISPATCHER_PORT) ## Attach event listeners self.attachEvents(self.speaker) def start(self): self.dispatcherClient.start() def attachEvents(self, mic): ## clear all signals smokesignal.clear() text = "" @smokesignal.on('say') def onSay(args): print "Info from Nav" infoFromNav = eval(args.get('payload')) print infoFromNav infotosay = infoFromNav["text"] print infotosay print "Info from Nav before Mic" mic.say(infotosay)
def __init__(self): ## For interprocess comms self.DISPATCHER_PORT = 9004 self._dispatcherClient = DispatcherClient(port=self.DISPATCHER_PORT) ## Attach event listeners upon instantiation (to prevent duplicates) self.attachEvents() # Latest sonar readings self.sonarLeft = Alert.SONAR_MAX_DISTANCE self.sonarRight = Alert.SONAR_MAX_DISTANCE
def __init__(self): super(Nav, self).__init__() self.runLevel = Nav.RUNLVL_NORMAL ## Sets the run interval, in terms of number of seconds self.RUN_INTERVAL = 2 ########## Private vars ########## self.__model = { 'path': None, 'currLoc': Point.fromParam() } ## For multithreading self._threadListen = None self._active = True ## For interprocess comms self.DISPATCHER_PORT = 9001 self._dispatcherClient = DispatcherClient(port=self.DISPATCHER_PORT) ## Attach event listeners upon instantiation (to prevent duplicates) self.attachEvents() ## For collision detection: lock navigation until ready self.collisionLocked = False self.obstacle = None ## For pausing nav self.toPause = False logging.info('Nav Daemon running.')
def __init__(self): #interprocess self.apple=2 self.endpoint="http://192.249.57.162:1337/" #interprocess self.DISPATCHER_PORT = 9002 self.dispatcherClient = DispatcherClient(port=self.DISPATCHER_PORT)
def test_daemon_can_receive_event_get_new_path(self): """ NOTE: As this test is async, and NoseTest does not support async tests, please check this manually. """ logging.info('') logging.info('---started event test---') ## Setup Nav daemon nav = Nav() nav.start() ## Setup client and send info client = DispatcherClient(port=9002) client.start() client.send(9001, 'newPath', {"from" : "124", "to" : "1210"}) logging.info('Requested for new Path from 9002.') while(True): pass ## Keep daemons alive for 5 seconds. time.sleep(5) client.stop() nav.stop() logging.info('---finished event test---')
def __init__(self): self.speaker = speaker.newSpeaker() #interprocess self.DISPATCHER_PORT = 9002 self.dispatcherClient = DispatcherClient(port=self.DISPATCHER_PORT) ## Attach event listeners self.attachEvents(self.speaker)
def __init__(self): self.speaker = speaker.newSpeaker() #interprocess self.DISPATCHER_PORT = 9002 self.dispatcherClient = DispatcherClient(port=self.DISPATCHER_PORT) self.inputBuffer =[] self.checkNavigation = []
def __init__(self): ## For interprocess comms self.DISPATCHER_PORT = 9004 self._dispatcherClient = DispatcherClient(port=self.DISPATCHER_PORT) ## Attach event listeners upon instantiation (to prevent duplicates) self.attachEvents() self.sendflag=1 self.state=1 #1-proceed #2-stop #3 step right #4 step left self.sendAlertInterval = datetime.datetime(seconds=5) self.triggerAlertime=datetime.datetime(seconds=0)
def __init__(self): """Initializes the daemon. """ self.VOICE_DAEMON_ADDR = 9010 self._active = False self._dispatcherClient = DispatcherClient(port=self.VOICE_DAEMON_ADDR) self._attachHandlers() ## Attach event handlers here ### Start declare variables here ### ### ### ### End declare variables here ### logging.info('Voice Daemon instantiated.')
def test_can_communicate(self): d = VoiceDaemon() d.start() time.sleep(3) # send test stuff sender = DispatcherClient(port=9001) sender.start() ## Dependency injection here sender.send(d.VOICE_DAEMON_ADDR, 'onData', {"count" : "counting numbers"}) logging.info('finished sending.') sender.stop() # stop daemon d.stop()
def __init__(self): self.speaker = speaker.newSpeaker() # #interprocess self.DISPATCHER_PORT = 9002 self.dispatcherClient = DispatcherClient(port=self.DISPATCHER_PORT) ## For collision detection: lock navigation until ready self.collisionLocked = False self.obstacle = None self.OngoingNav = 0 self.cruncherAlert = 0 self.infotosay =None self.cruncherInfotosay="" ## Attach event listeners self.attachEvents(self.speaker)
def test_daemon_update_pos_from_cruncher_event(self): logging.info('') logging.info('---started event test---') ## Setup Nav daemon nav = Nav() nav.start() loc = nav.loc() # get current location as a point x,y,z,angle = loc.getLocTuple() expect(x).to_equal(0) expect(y).to_equal(0) expect(z).to_equal(0) expect(angle).to_equal(0) # Wait for 2 seconds to set-up time.sleep(2) ## Setup mock cruncher client = DispatcherClient(port=9004) client.start() client.send(9001, 'point', { "x": 10, "y": 123, "z": 456, "ang": 1, }) # Wait for 5 seconds to propagate startTime = time.time() while(time.time() - startTime < 5): time.sleep(0.01) loc = nav.loc() # get current location as a point x,y,z,angle = loc.getLocTuple() expect(x).to_equal(10) expect(y).to_equal(123) expect(z).to_equal(456) expect(angle).to_equal(1) client.stop() nav.stop() logging.info('---finished event test---')
def __init__(self): # Set $JASPER_HOME if not os.getenv('VOICE'): os.environ["VOICE"] = os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir)) # # for testing # if len(sys.argv) > 1 and "--local" in sys.argv[1:]: # from client.local_mic import Mic # else: # from client.mic import Mic # Change CWD to $JASPER_HOME/jasper/client client_path = os.path.join(os.getenv("VOICE"), "easyNav-Voice", "client") os.chdir(client_path) # Add $JASPER_HOME/jasper/client to sys.path sys.path.append(client_path) self.speaker = speaker.newSpeaker() #interprocess self.DISPATCHER_PORT = 9002 self.dispatcherClient = DispatcherClient(port=self.DISPATCHER_PORT)
# Send left sonar HTTP request httpClient.post_heartbeat_sonar("left", ns.data['left']) print "Sent sonar to server ", ns.data except: print "Server communications failed." pass # Extract sonar data from generic packet def convertPacketToSonarData(strpkt): sonarData = {strpkt[0]: strpkt[2:5]} return sonarData sprotapi.SPROTInit("/dev/ttyAMA0", baudrate=SERIALMOD_BAUDRATE) dc = DispatcherClient(port=9005) dc.start() PRINT_EVERY_N_ITER = 10 canPrint = False iterationCount = 0 sonar1Data = 0 # Left Sonar sonar2Data = 0 # Right Sonar sonar3Data = 0 # Middle Sonar compassData = 0 footsensData = 0 footsensMutex = threading.Lock() manager = multiprocessing.Manager() ns = manager.Namespace() ns.data = 0
class testNavInstructions(object): def __init__(self): #interprocess self.apple=2 self.endpoint="http://192.249.57.162:1337/" #interprocess self.DISPATCHER_PORT = 9002 self.dispatcherClient = DispatcherClient(port=self.DISPATCHER_PORT) def start(self): self.dispatcherClient.start() self.dispatcherClient.send(9001, "newPath", {"from":1, "to": 6}) #lt15 to P2 # ctr=90 # for c in range(0,17) # ctr-=5 # payload = { "x": 0, "y": 2558, "z": 0, "orientation": (ctr/180.0)*3.142} # r = requests.post(self.endpoint + "heartbeat/location", data=payload) # time.sleep(5) # print payload payload = { "x": 0, "y": 2436, "z": 0, "orientation": (0/180.0)*3.142 } print payload r = requests.post(self.endpoint + "heartbeat/location", data=payload) time.sleep(1) #simulate orientation ctr=0 for c in range(0,2): ctr+=45 if(ctr > 90): payload = { "x": 0, "y": 2436, "z": 0, "orientation": (90/180.0)*3.142} r = requests.post(self.endpoint + "heartbeat/location", data=payload) time.sleep(1) print payload break else: payload = { "x": 0, "y": 2436, "z": 0, "orientation": (ctr/180.0)*3.142 } r = requests.post(self.endpoint + "heartbeat/location", data=payload) time.sleep(1) print payload # payload = { "x": 0, "y": 2558, "z": 0, "orientation": (0/180.0)*3.142 } # r = requests.post(self.endpoint + "heartbeat/location", data=payload) # time.sleep(5) # ctr=0 # print payload # payload = { "x": 50, "y": 2580, "z": 0, "orientation": (0/180.0)*3.142 } # print payload # r = requests.post(self.endpoint + "heartbeat/location", data=payload) # print r.json # time.sleep(5) #simulate movement ctr=0 for c in range(0,29): ctr+=1000 payload = { "x": ctr, "y": 2436, "z": 0, "orientation": (90/180.0)*3.142 } print payload r = requests.post(self.endpoint + "heartbeat/location", data=payload) print r.json time.sleep(1) print payload if ctr == 2000: ctr+=883 payload = { "x": ctr, "y": 2436, "z": 0, "orientation": (90/180.0)*3.142 } print payload r = requests.post(self.endpoint + "heartbeat/location", data=payload) print r.json time.sleep(1) print payload break ctr=90 for c in range(0,2): ctr-=45 if(ctr < 0): payload = {"x": 2883, "y": 2436, "z": 0, "orientation": (0/180.0)*3.142} r = requests.post(self.endpoint + "heartbeat/location", data=payload) time.sleep(1) print payload break else: payload = {"x": 2883, "y": 2436, "z": 0, "orientation": (ctr/180.0)*3.142 } r = requests.post(self.endpoint + "heartbeat/location", data=payload) time.sleep(1) print payload ctr=2436 for c in range(0,9): ctr+=100 payload = {"x": 2883, "y": ctr, "z": 0, "orientation": (0/180.0)*3.142 } r = requests.post(self.endpoint + "heartbeat/location", data=payload) time.sleep(1) print payload if(ctr == 2836): payload = {"x": 2883, "y": 2924, "z": 0, "orientation": (0/180.0)*3.142} r = requests.post(self.endpoint + "heartbeat/location", data=payload) time.sleep(1) print payload break
class VoiceDaemon: """ The Voice Daemon is the voice component for easyNav. Example Code: daemon = VoiceDaemon() daemon.start() # Starts the daemon daemon.stop() # Stops the daemon """ def __init__(self): """Initializes the daemon. """ self.VOICE_DAEMON_ADDR = 9010 self._active = False self._dispatcherClient = DispatcherClient(port=self.VOICE_DAEMON_ADDR) self._attachHandlers() ## Attach event handlers here ### Start declare variables here ### ### ### ### End declare variables here ### logging.info('Voice Daemon instantiated.') def start(self): """Starts the daemon. """ self._active = True ## Run tick thread def runThread(): while(self._active): self._tick() self._threadListen = threading.Thread(target=runThread) self._dispatcherClient.start() # start comms self._threadListen.start() logging.info('Voice Daemon: Thread started.') def stop(self): self._dispatcherClient.stop() # Stop comms self._active = False self._threadListen.join() ### Start De-initialize variables here ### ### ### ### End De-initialize variables here ### logging.info('Serial Daemon: Thread stopped.') def _tick(self): """Tick function run when daemon is active """ ######################################### # <<FILL IN>> # ######################################### pass def _attachHandlers(self): """Attach event handlers here """ ################################################### ####### Define event handlers here ####### ################################################### ######################################### # <<FILL IN>> # ######################################### ### Sample handler @smokesignal.on('onData') def onDataHandler(messageObj): """ Event callback for serial data """ logging.debug('Oh yay! I got triggered!') pass
""" logging.info('Event triggered: Update!') logging.info('JSON output: %s' % args) @smokesignal.on('fun event') def doSomething(args): """This is an event callback. Payload data is passed as args, and is a JSON object """ logging.info('Event triggered: A fun event!') logging.info('JSON output: %s' % args) ## Create two clients. One at 9001, the other 9002 client1 = DispatcherClient(port=9001) client2 = DispatcherClient(port=9002) client1.start() client2.start() client1.send(9002, 'update', {"hello" : "world"}) client1.send(9002, 'update', {"something" : "here"}) client1.send(9002, 'fun event', {"count" : "counting numbers"}) logging.info('finished sending.') ## Keep clients alive for 5 seconds. Note how both are unaffected by block. time.sleep(5)
class Nav(object): """ This is the Nav class, which handles navigation on the Raspberry Pi. It retrieves remote location information and navigates to the point. In addition, this class implements the REST API endpoints from the server. """ HOST_ADDR = "http://*****:*****@smokesignal.on('newPath') def onNewPath(args): logging.debug('Event triggered: Request for new path.') nodeFrom = json.loads(args.get('payload')).get('from') nodeTo = json.loads(args.get('payload')).get('to') if ((nodeTo == None) or (nodeFrom == None)): logging.error('Received no start / end nodes') return # DEPRECATED ------ ## reset current location # self.setPosBySUID(str(nodeFrom)) # /DEPRECATED ------ ## Get new path self.getPathTo(nodeFrom, nodeTo) # @smokesignal.on('obstacle') # def onObstacle(args): # response = int(json.loads(args.get('payload')).get('status')) # if (response == 0): # self.obstacle = None # return # Do not set collision locked # elif (response == 1): # self.obstacle = 'FRONT' # elif (response == 2): # self.obstacle = 'LEFT' # elif (response == 3): # self.obstacle = 'RIGHT' # # If collision, set to true # self.collisionLocked = True @smokesignal.on('point') def onPoint(args): """Update location based on interprocess posting by cruncher """ locInfo = json.loads(args.get('payload')) x = locInfo.get('x') y = locInfo.get('y') z = locInfo.get('z') angle = locInfo.get('ang') self.__model['currLoc'] = Point.fromParam( x=x, y=y, z=z, orientation=angle) # logging.info( # '[ NAV ] Internal pos is currently: (x=%s y=%s z=%s ang=%s)' % # (x,y,z,angle) ) @smokesignal.on('reset') def onReset(args): """If navigation needs to be reset during routing, use this """ self._dispatcherClient.send(9002, 'say', {'text': 'Nav reset.'}) self._resetNavParams() # Reset all navigation params and await new path logging.debug('Nav has been RESET.') @smokesignal.on('pause') def onPause(args): """ Pause navigation. Useful for stairs / etc. """ self.toPause = True self._dispatcherClient.send(9002, 'say', {'text': 'Nav paused.'}) logging.debug('Nav is PAUSED.') @smokesignal.on('unpause') def onPause(args): """ Unpause navigation. Useful for stairs / etc. """ self.toPause = False self._dispatcherClient.send(9002, 'say', {'text': 'Nav resumed.'}) logging.debug('Nav is RESUMED.') @smokesignal.on('checkNavigation') def onPause(args): """ Unpause navigation. Useful for stairs / etc. """ isNavigating = self.isNavigating() self._dispatcherClient.send(9002, 'checkNavigation', {'isNavigating': isNavigating }) logging.debug('Nav state checked.') def setPosByXYZ(self, x=0, y=0, z=0, orientation=0): """ Set position by XYZ """ _x = str(x) _y = str(y) _z = str(z) _orientation = str(orientation) try: r = requests.post(Nav.HOST_ADDR + '/heartbeat/location/?x=' + _x + '&y=' + _y + '&z=' + _z + '&orientation=' + _orientation) except requests.exceptions.RequestException as e: logging.error('Oops! Failed to set position by XYZ. Error: %s' % e) def setPosBySUID(self, suid=0): """Set position on server, by SUID """ ## Get the current old values (orientation workaround) # self.getPos() orientation = 0 # orientation = (self.__model['currLoc'])['orientation'] ### TODO: Fix orientation bug ## Get the SUID coordinates try: r = requests.get(Nav.HOST_ADDR + '/node/?SUID=' + str(suid)) except requests.exceptions.RequestException as e: logging.error('Oops! Failed to set position by SUID. Error: %s' % e) response = json.loads(r.text) ## Invalid point exception if (response == []): logging.error('Oops. No such SUID on server.') return response = response[0] loc = json.loads(response.get('loc')) ## Set coordinates x,y,z = loc.get('x'), loc.get('y'), loc.get('z') self.setPosByXYZ(x,y,z, orientation) def resetMap(self): """Resets the map. """ try: r = requests.delete(Nav.HOST_ADDR + '/map') logging.info('Map deleted.') except requests.exceptions.RequestException as e: logging.error('Oops! Failed to delete map. Is server connected?') def updateMap(self): """Updates the map on server. """ try: r = requests.get(Nav.HOST_ADDR + '/map/update') # self._dispatcherClient.send(9002, 'say', {'text': 'Map updated.'}) logging.info('Map updated.') except requests.exceptions.RequestException as e: logging.error('Oops! Failed to update map. Is server connected?') def updateMapCustom(self, building, floor): """Updates the map on server, with floor and building name. """ try: r = requests.get(Nav.HOST_ADDR + '/map/update?floor=' + floor + '&building=' + building) # self._dispatcherClient.send(9002, 'say', {'text': 'Map updated.'}) logging.info('Map updated with building ' + building + ' at floor ' + floor) except requests.exceptions.RequestException as e: logging.error('Oops! Failed to update map building=%s floor=%s. Is server connected?' % (building, floor)) def getPathTo(self, nodeFrom, nodeTo): """Gets shortest path from point from current location, and updates internal path accordingly. """ try: self._resetNavParams() r = requests.get(Nav.HOST_ADDR + '/map/shortest/' + str(nodeFrom) + '/' + str(nodeTo) ) self.__model['path'] = Path.fromString(r.text) self._dispatcherClient.send(9002, 'say', {'text': 'Retrieved new path.'}) logging.info('Retrieved new path.') except requests.exceptions.RequestException as e: logging.info('Oops! Failed to retrieve shortest path. Is server connected?') def _resetNavParams(self): """Reset nav flags and relevant info. """ self._hasPassedStart = False # Variable to test if start pt has passed self.achievedNode = -1 # Variable to test if previous point was the SAME point!! self.__model['path'] = None # Reset path def path(self): """Returns the current path of nav, as a Path instance. """ return self.__model['path'] def loc(self): """ Returns the current location of user, as a Point instance. """ return self.__model['currLoc'] def isNavigating(self): """ Check for existence of path, and use that to detect isNavigating state """ return not (path == None) def exeLevelNorm(self): """ Called for run level RUNLVL_NORMAL. Do not call externally. """ path = self.path() pt = self.loc() ## Return if no path set! if path == None: logging.debug('No path set.') return logging.debug('Point: %s' % pt) logging.debug('>>>>>> Current target: %s' % path.get()) feedback = path.isOnPath(pt, self.THRESHOLD_DIST, self.THRESHOLD_ANGLE) status = feedback['status'] angleCorrection = int(angles.r2d(float(feedback['angleCorrection']))) ## Collision detection first if (self.collisionLocked): if (self.obstacle == None): # Unlock collisionLocked self._dispatcherClient.send(9002, 'say', {'text': 'Obstacle cleared. Move forward!'}) logging.debug('Obstacle cleared. Move forward!') self.collisionLocked = False time.sleep(5) logging.debug('Time to clear obstacle has passed.') elif (self.obstacle == 'FRONT'): self._dispatcherClient.send(9002, 'say', {'text': 'Obstacle ahead. Turn left or right!'}) logging.debug('Obstacle ahead. Turn left or right!') elif (self.obstacle == 'LEFT'): self._dispatcherClient.send(9002, 'say', {'text': 'Obstacle on the left!'}) logging.debug('Obstacle on the left!') elif (self.obstacle == 'RIGHT'): self._dispatcherClient.send(9002, 'say', {'text': 'Obstacle on the right!'}) logging.debug('Obstacle on the right!') # Do not execute below return if (status is Point.REACHED): ##TODO: Implement print to voice checkpointName = '' ## initialize it first if (path.isAtDest() is False): if ((self._hasPassedStart == False) and (self.__model['path'].ref == 0)): self.__model['path'].next() self._hasPassedStart = True # So this does not trigger again at start self.achievedNode = 0 # elif ( (self.__model['path'].ref != 0) and (self.achievedNode == int(self.__model['path'].ref - 1)) ): else: if (self.achievedNode == (self.__model['path'].ref - 1)): self.achievedNode = self.__model['path'].ref # Update to current node before incrementing ##TODO: Fix this tomorrow try: currNode = self.__model['path'].get() ## Get current node checkpointName = currNode.name() except: logging.error('Oops. Invalid name?') self.__model['path'].next() ## Store the last value, i.e. 'delay' if checkpointName == '': self._dispatcherClient.send(9002, 'say', {'text': 'Checkpoint reached!'}) else: self._dispatcherClient.send(9002, 'say', {'text': 'Checkpoint ' + checkpointName + ' reached!'}) logging.debug('checkpoint reached!') else: self._dispatcherClient.send(9002, 'say', {'text': 'Destination ' + checkpointName + ' reached!'}) self._resetNavParams() # Reset all navigation params and await new path logging.debug('Reached destination, done!') pass elif (status is Point.MOVE_FORWARD): self._dispatcherClient.send(9002, 'say', {'text': 'Move forward!'}) logging.debug('move forward!') pass elif (status is Point.OUT_OF_PATH): self._dispatcherClient.send(9002, 'say', {'text': 'Out of path!'}) logging.debug('Out of path!') ## DEPRECATED -------------------------------- # self.getPathTo( self.path().dest().name() ) ## /DEPRECATED -------------------------------- pass elif (status is Point.ALIGNED): ##TODO: Implement print to voice # self._dispatcherClient.send(9002, 'say', {'text': 'Out of path!'}) logging.debug('Point aligned!') pass elif (status is Point.TURN_LEFT): self._dispatcherClient.send(9002, 'say', {'text': 'Turn left ' + str(angleCorrection) + ' degrees' }) logging.debug('Turn left ' + str(angleCorrection) + ' degrees') pass elif (status is Point.TURN_RIGHT): self._dispatcherClient.send(9002, 'say', {'text': 'Turn right ' + str(angleCorrection) + ' degrees' }) logging.debug('Turn right ' + str(angleCorrection) + ' degrees') pass else: ## Oops uncaught feedback logging.warn('Oops, did we account for all feedback flags?') pass pass # print ('--------------curr node--------', self.__model['path'].ref) # print 'VAL ACHIEVED--------------------', self.achievedNode # print 'VAL TARGETED--------------------', self.__model['path'].ref def exeLevelWarnObstacle(self): """ Called for run level RUNLVL_WARN_OBSTACLE. Do not call externally. """ # TODO: Code warn obstacle stuff self._dispatcherClient.send(9002, 'say', {'text': 'Near obstacle!'}) logging.warn('Near obstacle!!') pass def feedbackCorrection(self): """Feedback correction control, called by Nav daemon automatically. """ if (self.runLevel == Nav.RUNLVL_NORMAL): self.exeLevelNorm() elif (self.runLevel == Nav.RUNLVL_WARNING_OBSTACLE): self.exeLevelWarnObstacle() pass def tick(self, debug=False): """Tick function executed every run cycle, called by #run Param: debug: If False, do not not update position from server Instead do dependency injection manually. """ if (self.toPause == False): self.feedbackCorrection()
""" logging.info('Event triggered: Update!') logging.info('JSON output: %s' % args) @smokesignal.on('fun event') def doSomething(args): """This is an event callback. Payload data is passed as args, and is a JSON object """ logging.info('Event triggered: A fun event!') logging.info('JSON output: %s' % args) ## Create two clients. One at 9001, the other 9002 client1 = DispatcherClient(port=9001) client2 = DispatcherClient(port=9002) client1.start() client2.start() client1.send(9002, 'update', {"hello": "world"}) client1.send(9002, 'update', {"something": "here"}) client1.send(9002, 'fun event', {"count": "counting numbers"}) logging.info('finished sending.') ## Keep clients alive for 5 seconds. Note how both are unaffected by block. time.sleep(5) client.stop()
def test_generic(self): ## Event handler. Note the use of smokesignal label. @smokesignal.on('update') def doSomething(args): """This is an event callback. Payload data is passed as args, and is a JSON object """ logging.info('Event triggered: Update!') logging.info('JSON output: %s' % args) @smokesignal.on('fun event') def doSomething(args): """This is an event callback. Payload data is passed as args, and is a JSON object """ logging.info('Event triggered: A fun event!') logging.info('JSON output: %s' % args) ## Create two clients. One at 9001, the other 9002 client1 = DispatcherClient(port=9001) client2 = DispatcherClient(port=9002) client1.start() client2.start() client1.send(9002, 'update', {"hello": "world"}) client1.send(9002, 'update', {"something": "here"}) client1.send(9002, 'fun event', {"count": "counting numbers"}) logging.info('finished sending.') ## Keep clients alive for 5 seconds. Note how both are unaffected by block. time.sleep(5) client1.stop() client2.stop() logging.info('Ended. Goodbye!') pass
class Nav(object): """ This is the Nav class, which handles navigation on the Raspberry Pi. It retrieves remote location information and navigates to the point. In addition, this class implements the REST API endpoints from the server. """ HOST_ADDR = "http://*****:*****@smokesignal.on('newPath') def onNewPath(args): logging.debug('Event triggered: Request for new path.') nodeTo = args.get('to') if ((nodeTo == None)): logging.error('Received no start / end nodes') return self.getPathTo(nodeTo) @smokesignal.on('obstacle') def onObstacle(args): ##TODO: Implement obstacle detection pass def resetMap(self): """Resets the map. """ r = requests.delete(Nav.HOST_ADDR + '/map') logging.info('Map deleted.') def updateMap(self): """Updates the map on server. """ r = requests.get(Nav.HOST_ADDR + '/map/update') # self._dispatcherClient.send(9002, 'say', {'text': 'Map updated.'}) logging.info('Map updated.') def getPos(self): """Gets the position from server, and updates internal coordinates in Nav module. """ r = requests.get(Nav.HOST_ADDR + '/heartbeat/location') self.__model['currLoc'] = Point.fromJson(r.text) def getPathTo(self, pointId): """Gets shortest path from point from current location, and updates internal path accordingly. """ r = requests.get(Nav.HOST_ADDR + '/map/goto/' + str(pointId)) self.__model['path'] = Path.fromString(r.text) self._dispatcherClient.send(9002, 'say', {'text': 'Retrieved new path.'}) logging.info('Retrieved new path.') def path(self): """Returns the current path of nav, as a Path instance. """ return self.__model['path'] def loc(self): """ Returns the current location of user, as a Point instance. """ return self.__model['currLoc'] def exeLevelNorm(self): """ Called for run level RUNLVL_NORMAL. Do not call externally. """ path = self.path() pt = self.loc() ## Return if no path set! if path == None: return logging.debug('Point: %s' % pt) logging.debug('Current target: %s' % path.get()) feedback = path.isOnPath(pt, self.THRESHOLD_DIST, self.THRESHOLD_ANGLE) status = feedback['status'] if (status is Point.REACHED): ##TODO: Implement print to voice if (path.isAtDest() is False): self.__model['path'].next() self._dispatcherClient.send(9002, 'say', {'text': 'Checkpoint reached!'}) logging.debug('checkpoint reached!') else: self._dispatcherClient.send(9002, 'say', {'text': 'You have reached your destination!'}) logging.debug('Reached destination, done!') pass elif (status is Point.MOVE_FORWARD): self._dispatcherClient.send(9002, 'say', {'text': 'Move forward!'}) logging.debug('move forward!') pass elif (status is Point.OUT_OF_PATH): self._dispatcherClient.send(9002, 'say', {'text': 'Out of path!'}) logging.debug('Out of path!') self.getPathTo( self.path().dest().name() ) pass elif (status is Point.ALIGNED): ##TODO: Implement print to voice # self._dispatcherClient.send(9002, 'say', {'text': 'Out of path!'}) logging.debug('Point aligned!') pass elif (status is Point.TURN_LEFT): self._dispatcherClient.send(9002, 'say', {'text': 'Turn left!'}) logging.debug('Turn left!') pass elif (status is Point.TURN_RIGHT): self._dispatcherClient.send(9002, 'say', {'text': 'Turn right!'}) logging.debug('Turn right!') pass else: ## Oops uncaught feedback logging.warn('Oops, did we account for all feedback flags?') pass pass def exeLevelWarnObstacle(self): """ Called for run level RUNLVL_WARN_OBSTACLE. Do not call externally. """ # TODO: Code warn obstacle stuff self._dispatcherClient.send(9002, 'say', {'text': 'Near obstacle!'}) logging.warn('Near obstacle!!') pass def feedbackCorrection(self): """Feedback correction control, called by Nav daemon automatically. """ if (self.runLevel == Nav.RUNLVL_NORMAL): self.exeLevelNorm() elif (self.runLevel == Nav.RUNLVL_WARNING_OBSTACLE): self.exeLevelWarnObstacle() pass def tick(self, debug=False): """Tick function executed every run cycle, called by #run Param: debug: If False, do not not update position from server Instead do dependency injection manually. """ self.getPos() if (debug is False) else True self.feedbackCorrection() pass
def test_generic(self): ## Event handler. Note the use of smokesignal label. @smokesignal.on('update') def doSomething(args): """This is an event callback. Payload data is passed as args, and is a JSON object """ logging.info('Event triggered: Update!') logging.info('JSON output: %s' % args) @smokesignal.on('fun event') def doSomething(args): """This is an event callback. Payload data is passed as args, and is a JSON object """ logging.info('Event triggered: A fun event!') logging.info('JSON output: %s' % args) ## Create two clients. One at 9001, the other 9002 client1 = DispatcherClient(port=9001) client2 = DispatcherClient(port=9002) client1.start() client2.start() client1.send(9002, 'update', {"hello" : "world"}) client1.send(9002, 'update', {"something" : "here"}) client1.send(9002, 'fun event', {"count" : "counting numbers"}) logging.info('finished sending.') ## Keep clients alive for 5 seconds. Note how both are unaffected by block. time.sleep(5) client1.stop() client2.stop() logging.info('Ended. Goodbye!') pass
httpClient.post_heartbeat_sonar("left", ns.data['left']) print "Sent sonar to server ", ns.data except : print "Server communications failed." pass # Extract sonar data from generic packet def convertPacketToSonarData(strpkt): sonarData = { strpkt[0] : strpkt[2:5] } return sonarData sprotapi.SPROTInit("/dev/ttyAMA0", baudrate=SERIALMOD_BAUDRATE) dc = DispatcherClient(port=9005) dc.start() PRINT_EVERY_N_ITER = 10 canPrint = False iterationCount = 0 sonar1Data = 0 # Left Sonar sonar2Data = 0 # Right Sonar sonar3Data = 0 # Middle Sonar compassData = 0 footsensData = 0 footsensMutex = threading.Lock() manager = multiprocessing.Manager() ns = manager.Namespace() ns.data = 0
class Alert(object): PORT_NAV_MODULE = 9001 # Maximum sonar readings SONAR_MAX_DISTANCE = 700 OBSTACLE_RIGHT = 3 OBSTACLE_LEFT = 2 OBSTACLE_BOTH = 1 OBSTACLE_NONE = 0 # How close an object has to be before it is declared an obstacle (cm) OBSTACLE_DIST_THRESHOLD = 50 def __init__(self): ## For interprocess comms self.DISPATCHER_PORT = 9004 self._dispatcherClient = DispatcherClient(port=self.DISPATCHER_PORT) ## Attach event listeners upon instantiation (to prevent duplicates) self.attachEvents() # Latest sonar readings self.sonarLeft = Alert.SONAR_MAX_DISTANCE self.sonarRight = Alert.SONAR_MAX_DISTANCE def start(self): ## Start inter-process comms self._dispatcherClient.start() def sendAlert(self, alertType): print "Alert : ", alertType self._dispatcherClient.send(Alert.PORT_NAV_MODULE, 'obstacle', {'status': alertType}) # Check for obstacle position and returns OBSTACLE_X, where X is # one of LEFT, RIGHT, BOTH, NONE def checkForObstacle(self): leftObstacle = (self.sonarLeft < Alert.OBSTACLE_DIST_THRESHOLD) rightObstacle = (self.sonarRight < Alert.OBSTACLE_DIST_THRESHOLD) if (leftObstacle and rightObstacle): return Alert.OBSTACLE_BOTH elif (leftObstacle): return Alert.OBSTACLE_LEFT elif (rightObstacle): return Alert.OBSTACLE_RIGHT else: return Alert.OBSTACLE_NONE def convertStr(self, str): maxIndex = 3 for i in range(3): if (str[i].isdigit()): maxIndex = i return str[0:maxIndex + 1] def attachEvents(self): smokesignal.clear() @smokesignal.on('sonarData') def sonardata(args): payload = eval(args.get("payload")) strSonarLeft = self.convertStr(payload['1']) self.sonarLeft = int(strSonarLeft) strSonarRight = self.convertStr(payload['2']) self.sonarRight = int(strSonarRight) self.sendAlert(self.checkForObstacle())
class Notifications(object): def __init__(self): self.speaker = speaker.newSpeaker() # #interprocess self.DISPATCHER_PORT = 9002 self.dispatcherClient = DispatcherClient(port=self.DISPATCHER_PORT) ## For collision detection: lock navigation until ready self.collisionLocked = False self.obstacle = None self.OngoingNav = 0 self.cruncherAlert = 0 self.infotosay =None self.cruncherInfotosay="" ## Attach event listeners self.attachEvents(self.speaker) def attachEvents(self, mic): ## clear all signals smokesignal.clear() text = "" @smokesignal.on('say') def onSay(args): print "Info from Nav" infoFromNav = eval(args.get('payload')) print infoFromNav self.infotosay = infoFromNav["text"] try: if(self.infotosay != None and self.infotosay == 'Retrieved new path.'): self.OngoingNav = 1 #self.speaker.say(self.infotosay) if self.infotosay != None and "Destination" in self.infotosay: self.OngoingNav = 0 self.speaker.say(self.infotosay) # if self.infotosay != None and "reset" in self.infotosay: # self.OngoingNav = 0 # if "paused" in self.infotosay: # self.OngoingNav = 0 # if "resumed" in self.infotosay: # self.OngoingNav=1 if self.infotosay != None and "Checkpoint" in self.infotosay: self.speaker.say(self.infotosay) print self.infotosay except: pass @smokesignal.on('cruncherAlert') def onSay(args): print "Info from Nav" try: if(self.OngoingNav == 1): os.system("sudo pkill -SIGTERM -f \"aplay\" ") infoFromCruncher = eval(args.get('payload')) print infoFromCruncher self.cruncherInfotosay = infoFromCruncher["text"] self.cruncherAlert = 1 print self.cruncherInfotosay except: pass @smokesignal.on('obstacle') def onObstacle(args): try: response = int(json.loads(args.get('payload')).get('status')) if (response == 0): self.obstacle = None return elif (response == 1): self.obstacle = 'FRONT' self.collisionLocked = True elif (response == 2): self.obstacle = 'LEFT' self.collisionLocked = True elif (response == 3): self.obstacle = 'RIGHT' self.collisionLocked = True # If collision, set to true if(self.OngoingNav==1 and not self.collisionLocked): os.system("sudo pkill -SIGTERM -f \"aplay\" ") #self.collisionLocked = True except: pass @smokesignal.on('reset') def onObstacle(args): self.speaker.say("Voice reset") self.OngoingNav = 0 #clear ongoing nav def start(self): self.dispatcherClient.start() #run notifier forever while(1): try: regis = ns.sem ## Collision detection first if (self.collisionLocked and self.OngoingNav == 1 and regis == 0): if (self.obstacle == None): # Unlock collisionLocked self.speaker.say('Obstacle cleared.') self.collisionLocked = False elif (self.obstacle == 'FRONT'): self.speaker.say('Obstacle ahead. Turn 45 degrees left or right!') elif (self.obstacle == 'LEFT'): self.speaker.say('Obstacle on the left!') elif (self.obstacle == 'RIGHT'): self.speaker.say('Obstacle on the right!') elif(self.cruncherAlert == 1 and self.OngoingNav == 1 and regis == 0): self.speaker.say(self.cruncherInfotosay) self.cruncherAlert=0 self.cruncherInfotosay=None else: if(self.infotosay != None and regis == 0): self.speaker.say(self.infotosay) self.infotosay=None except: pass time.sleep(0.1)
class Voice(object): HOST_ADDR = "http://localhost:1337/" def __init__(self): self.speaker = speaker.newSpeaker() #interprocess self.DISPATCHER_PORT = 9002 self.dispatcherClient = DispatcherClient(port=self.DISPATCHER_PORT) self.inputBuffer =[] self.checkNavigation = [] #update locations # self.getLocation = GetLocations.Locations() # self.getLocation.getLoc() def presentMenu(self): self.speaker.say("Key * 1 # to choose map and level and locations") self.speaker.say("Key * 2 # to choose locations") self.speaker.say("Key * 3 # to change destination") self.speaker.say("Key * 4 # to end") def getLocations(self): #get a list of locations filename = "locations.txt" locationFile = open(filename, "r") print "Opened file!!" locations = [] for line in locationFile.readlines(): line = line.replace("\n", "") locations.append(line) print locations return locations def getCoord(self, index): filename = "CoordinateFile.txt" CoordinateFile = open(filename, "r") ctr = 0 startCoord = "" for line in CoordinateFile.readlines(): if ctr == index: line = line.replace("\n", "") startCoord = line ctr+=1 return startCoord def getSUIDIndex(self, SUID): print "in method" filename = "SUIDFile.txt" SUIDFile = open(filename, "r") print "Opened file" index = 0 for line in SUIDFile.readlines(): line = line.replace("\n", "") print line if int(line) == SUID: return index ctr+=1 return -1 def isCancel(self, inputVal): if(inputVal == '999'): self.speaker.say("Cancelling operation") return True return False def start(self): self.dispatcherClient.start() #present menu #self.presentMenu(); #keep listening for keypad activity while(1): try: # self.checkNavigation[0] = ns.OngoingNavigation print self.checkNavigation self.inputBuffer = KeypadLogic.getInput(self.speaker) strInput = ''.join(self.inputBuffer) print strInput if (strInput == '*1'): startBuildingBuf = [] startLevelBuff=[] startNodeBuff=[] endBuildingBuf = [] endLevelBuff=[] endNodeBuff=[] self.speaker.say("Key in start building ID, one for com one, two for com two") startBuildingBuf = KeypadLogic.getInput(self.speaker) strStartBuildingID = ''.join(startBuildingBuf) if(self.isCancel(strStartBuildingID)): continue else: self.speaker.say("you have chosen building " + strStartBuildingID) self.speaker.say("Key in start level ID, zero is basement.") startLevelBuff = KeypadLogic.getInput(self.speaker) strStartLevelID = ''.join(startLevelBuff) if(self.isCancel(strStartLevelID)): continue else: self.speaker.say("you have entered level " + strStartLevelID) self.speaker.say("Key in start node ID") startNodeBuff = KeypadLogic.getInput(self.speaker) strStartNodeID = ''.join(startNodeBuff) if(self.isCancel(strStartNodeID)): continue else: self.speaker.say("you have entered start node " + strStartNodeID) self.speaker.say("Key in destination building ID ") endBuildingBuf = KeypadLogic.getInput(self.speaker) strEndBuildingID = ''.join(endBuildingBuf) if(self.isCancel(strEndBuildingID)): continue else: self.speaker.say("you have entered building " + strEndBuildingID) self.speaker.say("Key in destination level ID") endLevelBuff = KeypadLogic.getInput(self.speaker) strEndLevelID = ''.join(endLevelBuff) if(self.isCancel(strEndLevelID)): continue else: self.speaker.say("you have entered level " + strEndLevelID) self.speaker.say("Key in destination node ID") endNodeBuff = KeypadLogic.getInput(self.speaker) strEndNodeID = ''.join(endNodeBuff) if(self.isCancel(strEndNodeID)): continue else: self.speaker.say("you have entered destination node " + strEndNodeID) #construct start point SUid strStartSUID = strStartBuildingID+strStartLevelID+strStartNodeID #construct dest SUid strEndSUID = strEndBuildingID+strEndLevelID+strEndNodeID try: startSUID = int(strStartSUID) endSUID = int(strEndSUID) print startSUID print endSUID print "not int problem" #get coord r = requests.get(Voice.HOST_ADDR + "node/?SUID=" + strStartSUID) print r for location in r.json(): print location startCoord = location['loc'] print startCoord self.dispatcherClient.send(9003, "starting", eval(startCoord)) self.dispatcherClient.send(9001, "newPath", {"from":startSUID, "to": endSUID}) self.speaker.say("Routing!") except: self.speaker.say("Invalid ID") #find builiding map and get coordinates elif (strInput == '*2'): print "note" startNodeBuff=[] endNodeBuff=[] self.speaker.say("Key in start point ID") startNodeBuff = KeypadLogic.getInput(self.speaker) strStart = ''.join(startNodeBuff) self.speaker.say("you have entered " + strStart) print strStart self.speaker.say("Key in destination ID") endNodeBuff = KeypadLogic.getInput(self.speaker) strEnd = ''.join(endNodeBuff) self.speaker.say("you have entered " + strEnd) try: startSUID = int(strStart) endSUID = int(strEnd) print startSUID print endSUID #get coord r = requests.get(Voice.HOST_ADDR + "node/?SUID=" + strStart) print r for location in r.json(): print location startCoord = location['loc'] print startCoord self.dispatcherClient.send(9003, "starting", eval(startCoord)) self.dispatcherClient.send(9001, "newPath", {"from":startSUID, "to": endSUID}) self.speaker.say("Routing!") except: self.speaker.say("Invalid ID") elif (strInput == '*33'): ns.sem=1 self.speaker.say("Resetting Nav") self.dispatcherClient.send(9001, "reset", {"text": None}) # os.system("sudo pkill -SIGTERM -f \"nav\"") # os.system("sudo pkill -SIGTERM -f \"voice\"") ns.sem=0 elif(strInput == '*55'): ns.sem=1 self.speaker.say("Resuming Nav") self.dispatcherClient.send(9001, "unpause", {"text": None}) ns.sem=0 elif (strInput == '*4'): self.speaker.say("Ending EasyNav, Are you sure?") self.speaker.say("Key in 1 to confirm, 2 to cancel") option = KeypadLogic.getInput(self.speaker) strOption = ''.join(option) try: if(strOption == '1'): self.speaker.say("Hope you had a good journey!") self.speaker.say("Ending all processes, Please wait") time.sleep(1) self.speaker.say("Please remember to switch off the shoe and bag switches...GoodBye") os.system("sudo pkill -SIGTERM -f \"node\" ") time.sleep(1) os.system("sudo sh /home/pi/repos/easyNav-IO/shutdown.sh") else: self.speaker.say("Cancelling") except ValueError: self.speaker.say("Error, key in a proper ID") #troubleshooting commands elif (strInput == "*66"): #lock speech mechanism ns.sem = 1 self.speaker.say("Finding i p") os.system("ifconfig wlan0 | grep inet > myIp.txt") ipFound = False with open("myIp.txt") as IPText: for line in IPText: if "inet" in line: ipFound=True print line lineDic = line.split(" ") for word in lineDic: print word if "addr" in word: print "here" ipAddr = word.replace("addr:", "") self.speaker.say("The I P is " + ipAddr) print word if(not ipFound): self.speaker.say("No i p assigned") #unlock speech mechanism ns.sem = 0 except: pass time.sleep(0.1)
class Alert(object): PORT_NAV_MODULE = 9001 # Maximum sonar readings SONAR_MAX_DISTANCE = 700 OBSTACLE_RIGHT = 3 OBSTACLE_LEFT = 2 OBSTACLE_BOTH = 1 OBSTACLE_NONE = 0 # How close an object has to be before it is declared an obstacle (cm) OBSTACLE_DIST_THRESHOLD = 50 def __init__(self): ## For interprocess comms self.DISPATCHER_PORT = 9004 self._dispatcherClient = DispatcherClient(port=self.DISPATCHER_PORT) ## Attach event listeners upon instantiation (to prevent duplicates) self.attachEvents() # Latest sonar readings self.sonarLeft = Alert.SONAR_MAX_DISTANCE self.sonarRight = Alert.SONAR_MAX_DISTANCE def start(self): ## Start inter-process comms self._dispatcherClient.start() def sendAlert(self, alertType): print "Alert : ", alertType self._dispatcherClient.send(Alert.PORT_NAV_MODULE, 'obstacle', {'status': alertType}) # Check for obstacle position and returns OBSTACLE_X, where X is # one of LEFT, RIGHT, BOTH, NONE def checkForObstacle(self): leftObstacle = (self.sonarLeft < Alert.OBSTACLE_DIST_THRESHOLD) rightObstacle = (self.sonarRight < Alert.OBSTACLE_DIST_THRESHOLD) if (leftObstacle and rightObstacle): return Alert.OBSTACLE_BOTH elif (leftObstacle): return Alert.OBSTACLE_LEFT elif (rightObstacle): return Alert.OBSTACLE_RIGHT else: return Alert.OBSTACLE_NONE def convertStr(self,str): maxIndex = 3 for i in range(3): if(str[i].isdigit()): maxIndex = i return str[0:maxIndex+1] def attachEvents(self): smokesignal.clear() @smokesignal.on('sonarData') def sonardata(args): payload = eval(args.get("payload")) strSonarLeft = self.convertStr(payload['1']) self.sonarLeft = int(strSonarLeft) strSonarRight = self.convertStr(payload['2']) self.sonarRight = int(strSonarRight) self.sendAlert(self.checkForObstacle())
class Voice(object): def __init__(self): # Set $JASPER_HOME if not os.getenv('VOICE'): os.environ["VOICE"] = os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir)) # # for testing # if len(sys.argv) > 1 and "--local" in sys.argv[1:]: # from client.local_mic import Mic # else: # from client.mic import Mic # Change CWD to $JASPER_HOME/jasper/client client_path = os.path.join(os.getenv("VOICE"), "easyNav-Voice", "client") os.chdir(client_path) # Add $JASPER_HOME/jasper/client to sys.path sys.path.append(client_path) self.speaker = speaker.newSpeaker() #interprocess self.DISPATCHER_PORT = 9002 self.dispatcherClient = DispatcherClient(port=self.DISPATCHER_PORT) ## Attach event listeners # self.attachEvents(self.speaker) def start(self): def testConnection(): if Diagnostics.check_network_connection(): print "CONNECTED TO INTERNET" else: print "COULD NOT CONNECT TO NETWORK" self.speaker.say( "Warning: I was unable to connect to a network. Parts of the system may not work correctly, depending on your setup.") def fail(message): traceback.print_exc() self.speaker.say(message) sys.exit(1) def configure(): try: print "COMPILING DICTIONARY FOR MODULES" vocabcompiler.compile( "sentences.txt", "dictionary.dic", "languagemodel.lm") print "COMPILING DICTIONARY OF LOCATIONS OPTIONS" vocabcompiler.compileLocations( "sentences_locations.txt", "dictionary_locations.dic", "languagemodel_locations.lm"); print "STARTING CLIENT PROGRAM" except OSError: print "BOOT FAILURE: OSERROR" fail( "There was a problem starting EasyNav. You may be missing the language model and associated files. Please read the documentation to configure your Raspberry Pi.") except IOError: print "BOOT FAILURE: IOERROR" fail( "There was a problem starting EasyNav. You may have set permissions incorrectly on some part of the filesystem. Please read the documentation to configure your Raspberry Pi.") except: print "BOOT FAILURE" fail( "There was a problem starting EasyNav.") old_client = os.path.abspath(os.path.join(os.pardir, "old_client")) if os.path.exists(old_client): shutil.rmtree(old_client) print "===========================================================" print " JASPER The Talking Computer " print " Copyright 2013 Shubhro Saha & Charlie Marsh " print "===========================================================" self.speaker.say("Hello.... I am EASYNAV... Please wait one moment while I configure.") configure() profile = yaml.safe_load(open("profile.yml", "r")) try: api_key = profile['keys']['GOOGLE_SPEECH'] except KeyError: api_key = None try: stt_engine_type = profile['stt_engine'] except KeyError: print "stt_engine not specified in profile, defaulting to PocketSphinx" stt_engine_type = "sphinx" mic = Mic(self.speaker, stt.PocketSphinxSTT(), stt.newSTTEngine(stt_engine_type, api_key=api_key)) mic.say("Hi...i'm EasyNav.....your friendly navigation assistant....") mic.say("To invoke me, please say my Name......and i will beep....then proceed with your command") mic.say("To find out about commands...please say help......") self.dispatcherClient.start() #GetLocations.getLoc() conversation = Conversation("EASYNAV", mic, profile, self.dispatcherClient) conversation.handleForever()