def load_objects(self, file_name): # load an object try: with open (file_name) as json_file: json_data = json.load(json_file) print(json_data) # build message msg = OpalCommand() # add header msg.header = Header() msg.header.stamp = rospy.Time.now() msg.command = OpalCommand.LOAD_OBJECT # add the object properties to the message # (the loaded json data) msg.properties = json.dumps(json_data) # send Opal message to tablet game self.pub.publish(msg) rospy.loginfo(msg) self.r.sleep() except ValueError as e: print('Error! Could not open or parse json config file!' + '\n Did you put only one game object config in' + ' the file?\n Did you use valid json?' + '\nError: %s' % e) except IOError as e: print('Error! Could not open or could not parse json ' +'config file!' + '\n Does the file exist in this directory, or did' + ' you specify the full file path?' + '\n Did you include the file extension, if there is' + ' one?\nError: %s' % e)
def send_opal_command(self, command, properties=None): """ Publish opal command message. Optionally, wait for a response. """ if self._opal_pub is None: self._logger.warning("OpalCommand ROS publisher is none!") return self._logger.info("Sending opal command: " + command) # Build message. msg = OpalCommand() # Add header. msg.header = Header() msg.header.stamp = rospy.Time.now() # We keep a dictionary of the strings used in the script and the actual # OpalCommand constants to use for lookup. If we don't find the command # given to us in our dictionary, we won't send it. We do, however, # print a warning to the user so they can check whether their list of # possible commands to send is up-to-date or whether they spelled # soemthing wrong. try: msg.command = self.OPAL_COMMANDS[command] except KeyError: self._logger.warning("Not sending invalid OpalCommand: ", command) return # Some commands require properties. If the command is one that requires # properties, we shouldn't send the message if we didn't get any # properties. If we got properties but the command doesn't need them, # we won't add them to the message. if ( # Properties: a string with the name of action to do. "SIDEKICK_DO" in command # Properties: a string with the name of audio file to play. or "SIDEKICK_SAY" in command # Properties: JSON defining what object to load. or "LOAD_OBJECT" in command # Properties: JSON defining what object to move where. or "MOVE_OBJECT" in command # Properties: JSON listing names of objects that are correct or # incorrect. or "SET_CORRECT" in command # Properties: a string with name of the object to highlight. or "HIGHLIGHT" in command # Properties: JSON listing scene attributes. or "SETUP_STORY_SCENE" in command # Properties: string name of the story to load next. or "STORY_SELECTION" in command # Properties: int number of the page to go to. or "STORY_GO_TO_PAGE" in command): # Add properties if we got them. We assume any properties # provided are in the correct format for the command. if properties: msg.properties = properties else: self._logger.warning( "Did not get properties for OpalCommand " "{}! Not sending empty command.".format(command)) return # If we have properties for a command that needs them, or no properties # for commands that don't, send the message. self._opal_pub.publish(msg) self._logger.debug(msg)
def send_opal_message(self, command): """ Publish opal command message """ print 'sending opal command: %s' % command msg = OpalCommand() # add header msg.header = Header() msg.header.stamp = rospy.Time.now() msg.command = command self.tablet_pub.publish(msg) rospy.loginfo(msg)
def send_opal_message(self, command): """ Publish opal command message """ if self.tablet_pub is not None: print('sending opal command: %s' % command) msg = OpalCommand() # add header msg.header = Header() msg.header.stamp = rospy.Time.now() msg.command = command self.tablet_pub.publish(msg) rospy.loginfo(msg)
def opal_sender(): # parse python arguments parser = argparse.ArgumentParser( formatter_class=argparse.RawDescriptionHelpFormatter, description='Send a message to a' + ' SAR Opal project tablet. Must have roscore and ' + 'rosbridge_server running for message to be sent.') parser.add_argument('-l', '--load', dest='loadme', action='append', nargs='+', help='load the game object specified in this json config file' + ' on the tablet') parser.add_argument('-t', '--touch', choices=['enable','e','disable','d'], type=str, dest='touch',help='enable/disable touch events on tablet') parser.add_argument('-r', '--reset', action='store_true', help='reload all objects and reset scene on tablet') parser.add_argument('-d', '--sidekick_do', dest='sidekick_do', action='append', nargs='+', type=str, help='tells sidekick to do specified action') parser.add_argument('-s', '--sidekick_say', dest='sidekick_say', action='append', nargs='+', type=str, help='tells sidekick to say specified speech') parser.add_argument('-c', '--clear', dest='clear_me', action='append', nargs='?', type=str, default=None, help='clear objects from tablet screen') parser.add_argument('-m', '--move', dest='moveme', action='append', nargs='+', help='move the game object specified in this json' +' config file to the specified position on the tablet') parser.add_argument('-i', '--highlight', dest='highlight', action='append', nargs='+', type=str, help='highlight ' + 'the specified game object') parser.add_argument('-k', '--keyframe', action='store_true', help='request the state of all objects on the tablet') parser.add_argument('-f', '--fade', choices=['fade','f','unfade','u'], type=str, dest='fade', help='fade/unfade screen on tablet') parser.add_argument('-q', '--quit', action='store_true', help='quit the tablet app') parser.add_argument('-e', '--set_correct', dest='set_correct', action='append', nargs='+', help='tag game objects as correct' + ' or as incorrect') parser.add_argument('-w', '--correct', choices=['show','s','hide','h'], type=str, dest='correct', help='show/hide visual feedback ' + 'for correct/incorrect game objects') parser.add_argument('-u', '--setup_scene', dest='setup_scene', action='append', nargs='+', help='set up initial game scene for' + ' a social stories game') args = parser.parse_args() print(args) # now build a message based on the command: # open ros up here, then run through the below and send all # start ROS node pub = rospy.Publisher('opal_tablet_command', OpalCommand, queue_size=10) rospy.init_node('opal_sender', anonymous=True) r = rospy.Rate(10) # spin at 10 Hz r.sleep() # sleep to wait for subscribers # start building message msg = OpalCommand() # add header msg.header = Header() msg.header.stamp = rospy.Time.now() # fill in command and properties: # load an object if args.loadme: # for each object to load, send a message for obj in args.loadme: # parse config file to get details of object or # background to load try: with open (obj) as json_file: json_data = json.load(json_file) print(json_data) # build message msg.command = OpalCommand.LOAD_OBJECT # add the object properties to the message # (the loaded json data) msg.properties = json.dumps(json_data) except ValueError as e: print('Error! Could not open or parse json config file!' + '\n Did you put only one game object config in' + ' the file?\n Did you use valid json?' + '\nError: %s' % e) except IOError as e: print('Error! Could not open or could not parse json ' +'config file!' + '\n Does the file exist in this directory, or did' + ' you specify the full file path?' + '\n Did you include the file extension, if there is' + ' one?\nError: %s' % e) # sidekick do an action if args.sidekick_do: # build message msg.command = OpalCommand.SIDEKICK_DO msg.properties = args.sidekick_do[0] # sidekick say something if args.sidekick_say: # build message msg.command = OpalCommand.SIDEKICK_SAY msg.properties = args.sidekick_say[0] # send enable or disable touch events command if args.touch: # build message msg.command = OpalCommand.ENABLE_TOUCH if args.touch == 'enabled' \ or args.touch == 'e' else OpalCommand.DISABLE_TOUCH # send reset scene and reload objects command if args.reset: print('reload'); # build message msg.command = OpalCommand.RESET # send clear scene command if args.clear_me: print('clear'); # build message msg.command = OpalCommand.CLEAR if args.clear_me[0]: msg.properties = args.clear_me[0] # send quit command if args.quit: print('quit'); # build message msg.command = OpalCommand.EXIT # send move object command # for each object to move, send a message if args.moveme: for obj in args.moveme: # parse config file to get details of object or # background to load try: with open (obj) as json_file: json_data = json.load(json_file) print(json_data) # build message msg.command = OpalCommand.MOVE_OBJECT # add the object properties to the message # (the loaded json data) msg.properties = json.dumps(json_data) except ValueError as e: print('Error! Could not open or parse json config file!' + '\n Did you put only one game object config in' + ' the file?\n Did you use valid json?' + '\nError: %s' % e) except IOError as e: print('Error! Could not open or could not parse json ' +'config file!' + '\n Does the file exist in this directory, or did' + ' you specify the full file path?' + '\n Did you include the file extension, if there is' + ' one?\nError: %s' % e) # send highlight object command if args.highlight: # build message msg.command = OpalCommand.HIGHLIGHT_OBJECT msg.properties = args.highlight[0] # send request keyframe command if args.keyframe: print('request keyframe'); # build message msg.command = OpalCommand.REQUEST_KEYFRAME # send fade or unfade screen command if args.fade: # build message msg.command = OpalCommand.FADE_SCREEN if args.touch == 'fade' \ or args.touch == 'f' else OpalCommand.UNFADE_SCREEN # send set correct command if args.set_correct: for obj in args.set_correct: # parse config file to get details of object or # background to load try: with open (obj) as json_file: json_data = json.load(json_file) print(json_data) # build message msg.command = OpalCommand.SET_CORRECT # add the object properties to the message # (the loaded json data) msg.properties = json.dumps(json_data) except ValueError as e: print('Error! Could not open or parse json config file!' + '\n Did you use valid json?\nError: %s' % e) except IOError as e: print('Error! Could not open or could not parse json ' +'config file!' + '\n Does the file exist in this directory, or did' + ' you specify the full file path?' + '\n Did you include the file extension, if there is' + ' one?\nError: %s' % e) # send show correct or hide correct command if args.correct: # build message msg.command = OpalCommand.SHOW_CORRECT if args.correct == 'show' \ or args.correct == 's' else OpalCommand.HIDE_CORRECT # send setup social story scene message if args.setup_scene: # for each scene to setup, send a message # it would be weird to do setup more than once, since the scene # clears before setup (so only the last setup would really count) for obj in args.setup_scene: # parse config file to get details of scene try: with open (obj) as json_file: json_data = json.load(json_file) print(json_data) # build message msg.command = OpalCommand.SETUP_STORY_SCENE # add the object properties to the message # (the loaded json data) msg.properties = json.dumps(json_data) except ValueError as e: print('Error! Could not open or parse json config file!' + '\n Did you put only one scene setup config in' + ' the file?\n Did you use valid json?' + '\nError: %s' % e) except IOError as e: print('Error! Could not open or could not parse json ' +'config file!' + '\n Does the file exist in this directory, or did' + ' you specify the full file path?' + '\n Did you include the file extension, if there is' + ' one?\nError: %s' % e) # send Opal message to tablet game pub.publish(msg) rospy.loginfo(msg) r.sleep()
def opal_sender(): # parse python arguments parser = argparse.ArgumentParser( formatter_class=argparse.RawDescriptionHelpFormatter, description='Send a message to a' + ' SAR Opal project tablet. Must have roscore and ' + 'rosbridge_server running for message to be sent.') parser.add_argument('-l', '--load', dest='loadme', action='append', nargs='?', help='load the game object specified in this json config file' + ' on the tablet') parser.add_argument('-t', '--touch', choices=['enable','e','disable','d'], type=str, dest='touch',help='enable/disable touch events on tablet') parser.add_argument('-r', '--reset', action='store_true', help='reload all objects and reset scene on tablet') parser.add_argument('-d', '--sidekick_do', dest='sidekick_do', action='append', nargs='?', type=str, help='tells sidekick to do specified action') parser.add_argument('-s', '--sidekick_say', dest='sidekick_say', action='append', nargs='?', type=str, help='tells sidekick to say specified speech') parser.add_argument('-c', '--clear', action='store_true', help='clear all objects from tablet screen') parser.add_argument('-m', '--move', dest='moveme', action='append', nargs='?', help='move the game object specified in this json' +' config file to the specified position on the tablet') parser.add_argument('-i', '--highlight', dest='highlight', action='append', nargs='?', type=str, help='highlight ' + 'the specified game object') parser.add_argument('-k', '--keyframe', action='store_true', help='request the state of all objects on the tablet') parser.add_argument('-f', '--fade', choices=['fade','f','unfade','u'], type=str, dest='fade', help='fade/unfade screen on tablet') parser.add_argument('-q', '--quit', action='store_true', help='quit the tablet app') parser.add_argument('-e', '--set_correct', dest='set_correct', action='append', nargs='?', help='tag game objects as correct' + ' or as incorrect') parser.add_argument('-w', '--correct', choices=['show','s','hide','h'], type=str, dest='correct', help='show/hide visual feedback ' + 'for correct/incorrect game objects') parser.add_argument('-u', '--setup_scene', dest='setup_scene', action='append', nargs='?', help='set up initial game scene for' + ' a social stories game') args = parser.parse_args() print(args) # now build a message based on the command: # open ros up here, then run through the below and send all # start ROS node pub = rospy.Publisher('opal_tablet_command', OpalCommand, queue_size=10) rospy.init_node('opal_sender', anonymous=True) r = rospy.Rate(10) # spin at 10 Hz r.sleep() # sleep to wait for subscribers # load an object if args.loadme: # for each object to load, send a message for obj in args.loadme: # parse config file to get details of object or # background to load try: with open (obj) as json_file: json_data = json.load(json_file) print(json_data) # build message msg = OpalCommand() # add header msg.header = Header() msg.header.stamp = rospy.Time.now() msg.command = OpalCommand.LOAD_OBJECT # add the object properties to the message # (the loaded json data) msg.properties = json.dumps(json_data) # send Opal message to tablet game pub.publish(msg) rospy.loginfo(msg) r.sleep() except ValueError as e: print('Error! Could not open or parse json config file!' + '\n Did you put only one game object config in' + ' the file?\n Did you use valid json?' + '\nError: %s' % e) except IOError as e: print('Error! Could not open or could not parse json ' +'config file!' + '\n Does the file exist in this directory, or did' + ' you specify the full file path?' + '\n Did you include the file extension, if there is' + ' one?\nError: %s' % e) # sidekick do an action if args.sidekick_do: # build message msg = OpalCommand() # add header msg.header = Header() msg.header.stamp = rospy.Time.now() msg.command = OpalCommand.LOAD_OBJECT msg.command = OpalCommand.SIDEKICK_DO msg.properties = args.sidekick_do[0] # send Opal message to tablet game pub.publish(msg) rospy.loginfo(msg) r.sleep() # sidekick say something if args.sidekick_say: # build message msg = OpalCommand() # add header msg.header = Header() msg.header.stamp = rospy.Time.now() msg.command = OpalCommand.LOAD_OBJECT msg.command = OpalCommand.SIDEKICK_SAY msg.properties = args.sidekick_say[0] # send Opal message to tablet game pub.publish(msg) rospy.loginfo(msg) r.sleep() # send enable or disable touch events command if args.touch: # build message msg = OpalCommand() # add header msg.header = Header() msg.header.stamp = rospy.Time.now() msg.command = OpalCommand.LOAD_OBJECT msg.command = OpalCommand.ENABLE_TOUCH if args.touch == 'enabled' or args.touch == 'e' else OpalCommand.DISABLE_TOUCH # send Opal message to tablet game pub.publish(msg) rospy.loginfo(msg) r.sleep() # send reset scene and reload objects command if args.reset: print('reload'); # build message msg = OpalCommand() # add header msg.header = Header() msg.header.stamp = rospy.Time.now() msg.command = OpalCommand.LOAD_OBJECT msg.command = OpalCommand.RESET # send Opal message to tablet game pub.publish(msg) rospy.loginfo(msg) r.sleep() # send clear scene command if args.clear: print('clear'); # build message msg = OpalCommand() # add header msg.header = Header() msg.header.stamp = rospy.Time.now() msg.command = OpalCommand.LOAD_OBJECT msg.command = OpalCommand.CLEAR # send Opal message to tablet game pub.publish(msg) rospy.loginfo(msg) r.sleep() # send quit command if args.quit: print('quit'); # build message msg = OpalCommand() # add header msg.header = Header() msg.header.stamp = rospy.Time.now() msg.command = OpalCommand.LOAD_OBJECT msg.command = OpalCommand.EXIT # send Opal message to tablet game pub.publish(msg) rospy.loginfo(msg) r.sleep() # send move object command # for each object to move, send a message if args.moveme: for obj in args.moveme: # parse config file to get details of object or # background to load try: with open (obj) as json_file: json_data = json.load(json_file) print(json_data) # build message msg = OpalCommand() # add header msg.header = Header() msg.header.stamp = rospy.Time.now() msg.command = OpalCommand.LOAD_OBJECT msg.command = OpalCommand.MOVE_OBJECT # add the object properties to the message # (the loaded json data) msg.properties = json.dumps(json_data) # send Opal message to tablet game pub.publish(msg) rospy.loginfo(msg) r.sleep() except ValueError as e: print('Error! Could not open or parse json config file!' + '\n Did you put only one game object config in' + ' the file?\n Did you use valid json?' + '\nError: %s' % e) except IOError as e: print('Error! Could not open or could not parse json ' +'config file!' + '\n Does the file exist in this directory, or did' + ' you specify the full file path?' + '\n Did you include the file extension, if there is' + ' one?\nError: %s' % e) # send highlight object command if args.highlight: # build message msg = OpalCommand() # add header msg.header = Header() msg.header.stamp = rospy.Time.now() msg.command = OpalCommand.LOAD_OBJECT msg.command = OpalCommand.HIGHLIGHT_OBJECT msg.properties = args.highlight[0] # send Opal message to tablet game pub.publish(msg) rospy.loginfo(msg) r.sleep() # send request keyframe command if args.keyframe: print('request keyframe'); # build message msg = OpalCommand() # add header msg.header = Header() msg.header.stamp = rospy.Time.now() msg.command = OpalCommand.LOAD_OBJECT msg.command = OpalCommand.REQUEST_KEYFRAME # send Opal message to tablet game pub.publish(msg) rospy.loginfo(msg) r.sleep() # send fade or unfade screen command if args.fade: # build message msg = OpalCommand() # add header msg.header = Header() msg.header.stamp = rospy.Time.now() msg.command = OpalCommand.LOAD_OBJECT msg.command = OpalCommand.FADE_SCREEN if args.touch == 'fade' or args.touch == 'f' else OpalCommand.UNFADE_SCREEN # send Opal message to tablet game pub.publish(msg) rospy.loginfo(msg) r.sleep() # send set correct command if args.set_correct: for obj in args.set_correct: # parse config file to get details of object or # background to load try: with open (obj) as json_file: json_data = json.load(json_file) print(json_data) # build message msg = OpalCommand() # add header msg.header = Header() msg.header.stamp = rospy.Time.now() msg.command = OpalCommand.LOAD_OBJECT msg.command = OpalCommand.SET_CORRECT # add the object properties to the message # (the loaded json data) msg.properties = json.dumps(json_data) # send Opal message to tablet game pub.publish(msg) rospy.loginfo(msg) r.sleep() except ValueError as e: print('Error! Could not open or parse json config file!' + '\n Did you use valid json?\nError: %s' % e) except IOError as e: print('Error! Could not open or could not parse json ' +'config file!' + '\n Does the file exist in this directory, or did' + ' you specify the full file path?' + '\n Did you include the file extension, if there is' + ' one?\nError: %s' % e) # send show correct or hide correct command if args.correct: # build message msg = OpalCommand() # add header msg.header = Header() msg.header.stamp = rospy.Time.now() msg.command = OpalCommand.LOAD_OBJECT msg.command = OpalCommand.SHOW_CORRECT if args.correct == 'show' or args.correct == 's' else OpalCommand.HIDE_CORRECT # send Opal message to tablet game pub.publish(msg) rospy.loginfo(msg) r.sleep() # send setup social story scene message if args.setup_scene: # for each scene to setup, send a message # it would be weird to do setup more than once, since the scene # clears before setup (so only the last setup would really count) for obj in args.setup_scene: # parse config file to get details of scene try: with open (obj) as json_file: json_data = json.load(json_file) print(json_data) # build message msg = OpalCommand() # add header msg.header = Header() msg.header.stamp = rospy.Time.now() msg.command = OpalCommand.LOAD_OBJECT msg.command = OpalCommand.SETUP_STORY_SCENE # add the object properties to the message # (the loaded json data) msg.properties = json.dumps(json_data) # send Opal message to tablet game pub.publish(msg) rospy.loginfo(msg) r.sleep() except ValueError as e: print('Error! Could not open or parse json config file!' + '\n Did you put only one scene setup config in' + ' the file?\n Did you use valid json?' + '\nError: %s' % e) except IOError as e: print('Error! Could not open or could not parse json ' +'config file!' + '\n Does the file exist in this directory, or did' + ' you specify the full file path?' + '\n Did you include the file extension, if there is' + ' one?\nError: %s' % e)
def send_opal_command(self, command, properties=None, response=None, timeout=None): """ Publish opal command message. Optionally, wait for a response. """ self._logger.info("Sending opal command: " + command) # Build message. msg = OpalCommand() # Add header. msg.header = Header() msg.header.stamp = rospy.Time.now() # Add appropriate command and properties if there are any. # We check properties for each command individually, since some # require properties, and if there are none, we shouldn't send # the message. We assume any properties provided are in the # correct format for the command. if "RESET" in command: msg.command = OpalCommand.RESET elif "DISABLE_TOUCH" in command: msg.command = OpalCommand.DISABLE_TOUCH elif "ENABLE_TOUCH" in command: msg.command = OpalCommand.ENABLE_TOUCH elif "SIDEKICK_DO" in command: msg.command = OpalCommand.SIDEKICK_DO # Properties: a string with the name of action to do. elif "SIDEKICK_SAY" in command: msg.command = OpalCommand.SIDEKICK_SAY # Properties: a string with the name of audio file to play. if properties: msg.properties = properties else: self._logger.warning("Did not get properties for a " + "SIDEKICK_SAY command! Not sending empty command.") return elif "LOAD_OBJECT" in command: msg.command = OpalCommand.LOAD_OBJECT # Properties: JSON defining what object to load. if properties: msg.properties = properties else: self._logger.warning("Did not get properties for a " + "LOAD_OBJECT command! Not sending empty command.") return elif "CLEAR" in command: msg.command = OpalCommand.CLEAR # Properties: optionally, string defining what objects to # remove. if properties: msg.properties = properties elif "MOVE_OBJECT" in command: msg.command = OpalCommand.MOVE_OBJECT # Properties: JSON defining what object to move where. if properties: msg.properties = properties else: self._logger.warning("Did not get properties for a " + "MOVE_OBJECT command! Not sending empty command.") return elif "HIGHLIGHT" in command: msg.command = OpalCommand.HIGHLIGHT_OBJECT # Properties: a string with name of the object to highlight. if properties: msg.properties = properties else: self._logger.warning("Did not get properties for a " + "HIGHLIGHT_OBJECT command! Adding null properties.") elif "REQUEST_KEYFRAME" in command: msg.command = OpalCommand.REQUEST_KEYFRAME elif "FADE_SCREEN" in command: msg.command = OpalCommand.FADE_SCREEN elif "UNFADE_SCREEN" in command: msg.command = OpalCommand.UNFADE_SCREEN elif "NEXT_PAGE" in command: msg.command = OpalCommand.NEXT_PAGE elif "PREV_PAGE" in command: msg.command = OpalCommand.PREV_PAGE elif "EXIT" in command: msg.command = OpalCommand.EXIT elif "SET_CORRECT" in command: msg.command = OpalCommand.SET_CORRECT # Properties: JSON listing names of objects that are # correct or incorrect. if properties: msg.properties = properties else: self._logger.warning("Did not get properties for a " + "SET_CORRECT command! Not sending empty command.") return elif "SHOW_CORRECT" in command: msg.command = OpalCommand.SHOW_CORRECT elif "HIDE_CORRECT" in command: msg.command = OpalCommand.HIDE_CORRECT elif "SETUP_STORY_SCENE" in command: msg.command = OpalCommand.SETUP_STORY_SCENE # Properties: JSON listing scene attributes. if properties: msg.properties = properties else: self._logger.warning("Did not get properties for a " + "SETUP_STORY_SCENE command! Not sending empty command.") return else: self._logger.warning("Not sending invalid OpalCommand: ", command) return # Send message. self._game_pub.publish(msg) self._logger.debug(msg) # If we got a response to wait for and a timeout value, wait # for a response. if response and timeout: self.wait_for_response(response, timeout)