naoqi_node.py
Go to the documentation of this file.
00001 # Copyright 2009-2011 Armin Hornung, University of Freiburg
00002 # http://www.ros.org/wiki/nao
00003 #
00004 # Redistribution and use in source and binary forms, with or without
00005 # modification, are permitted provided that the following conditions are met:
00006 #
00007 #    # Redistributions of source code must retain the above copyright
00008 #       notice, this list of conditions and the following disclaimer.
00009 #    # Redistributions in binary form must reproduce the above copyright
00010 #       notice, this list of conditions and the following disclaimer in the
00011 #       documentation and/or other materials provided with the distribution.
00012 #    # Neither the name of the University of Freiburg nor the names of its
00013 #       contributors may be used to endorse or promote products derived from
00014 #       this software without specific prior written permission.
00015 #
00016 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00017 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00018 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00019 # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00020 # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00021 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00022 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00023 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00024 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00025 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00026 # POSSIBILITY OF SUCH DAMAGE.
00027 #
00028 
00029 from threading import Thread
00030 
00031 import rospy
00032 
00033 # import Aldebaran API (must be in PYTHONPATH):
00034 try:
00035     from naoqi import ALProxy
00036 except ImportError:
00037     raise RuntimeError("Error importing NaoQI. Please make sure that Aldebaran's NaoQI API is in your PYTHONPATH.")
00038 
00039 class NaoqiNode(Thread):
00040     """
00041     A ROS Node wrapper that can help you connect to NAOqi and deal with ROS shutdown
00042     To start your node, just call:
00043     my_node = MyNode('my_node')
00044     my_node.start() # that will spawn your node in a thread (and run whatever is in the run() function
00045     rospy.spin()
00046     # when killing ROS, the node will automatically stop its main loop, exit, and then unsubscribe from ALMemory events
00047     # and call whatever you have in unsubscribe()
00048     Then, if your node needs to process data, you just needs to have a run function:
00049 
00050     def run(Self):
00051         #do some initialization
00052         while self.is_looping():
00053             # do something
00054         # do some post processing
00055     """
00056     def __init__(self, name):
00057         """
00058         :param name: the name of the ROS node
00059         """
00060         super(NaoqiNode, self).__init__()
00061 
00062         # A distutils.version.LooseVersion that contains the current verssion of NAOqi we're connected to
00063         self.__naoqi_version = None
00064         self.__name = name
00065 
00066         ## NAOqi stuff
00067         # dict from a modulename to a proxy
00068         self.__proxies = {}
00069 
00070         # Initialize ros, before getting parameters.
00071         rospy.init_node(self.__name)
00072 
00073         # If user has set parameters for ip and port use them as default
00074         default_ip = rospy.get_param("~pip", "127.0.0.1")
00075         default_port = rospy.get_param("~pport", 9559)
00076 
00077         # get connection from command line:
00078         from argparse import ArgumentParser
00079         parser = ArgumentParser()
00080         parser.add_argument("--pip", dest="pip", default=default_ip,
00081                           help="IP/hostname of parent broker. Default is 127.0.0.1.", metavar="IP")
00082         parser.add_argument("--pport", dest="pport", default=default_port, type=int,
00083                           help="port of parent broker. Default is 9559.", metavar="PORT")
00084 
00085         import sys
00086         args = parser.parse_args(args=rospy.myargv(argv=sys.argv)[1:])
00087         self.pip = args.pip
00088         self.pport = args.pport
00089 
00090         ## ROS stuff
00091         self.__stop_thread = False
00092         # make sure that we unregister from everything when the module dies
00093         rospy.on_shutdown(self.__on_ros_shutdown)
00094 
00095     def __on_ros_shutdown(self):
00096         """
00097         Callback function called whenever rospy.spin() stops
00098         """
00099         rospy.loginfo('Stopping ' + self.__name)
00100 
00101         self.__stop_thread = True
00102         # wait for the thread to be done
00103         if self.is_alive():
00104             self.join()
00105 
00106         rospy.loginfo(self.__name + ' stopped')
00107 
00108     def run(self):
00109         """
00110         This is a virtual method that corresponds to the code of the Node that runs continuously
00111         It should have a while loop calling the self.is_looping() function
00112         """
00113         """
00114         # code example
00115         #do some initialization
00116         while self.is_looping():
00117             # do something
00118         # do some post processing
00119         """
00120         raise NotImplementedError('Implement the run function of your NaoNode !')
00121 
00122     def is_looping(self):
00123         """
00124         :return: whether the thread is supposed to be running
00125         """
00126         return not self.__stop_thread
00127 
00128     def get_proxy(self, name, warn=True):
00129         """
00130         Returns a proxy to a specific module. If it has not been created yet, it is created
00131         :param name: the name of the module to create a proxy for
00132         :return: a proxy to the corresponding module
00133         """
00134         if name in self.__proxies and self.__proxies[name] is not None:
00135             return self.__proxies[name]
00136 
00137         proxy = None
00138         try:
00139             proxy = ALProxy(name,self.pip,self.pport)
00140         except RuntimeError,e:
00141             if warn:
00142                 rospy.logerr("Could not create Proxy to \"%s\". \nException message:\n%s",name, e)
00143 
00144         self.__proxies[name] = proxy
00145         return proxy
00146 
00147     def get_version(self):
00148         """
00149         Returns the NAOqi version.
00150         A proxy for ALMemory is automatically created if needed as self.memProxy.
00151         You can then simply have code that runs or not depending on the NAOqi version.
00152         E.g. if distutils.version.LooseVersion('1.6') < get_version()    ....
00153         :return: a distutils.version.LooseVersion object with the NAOqi version
00154         """
00155         if self.__naoqi_version is None:
00156             proxy = self.get_proxy('ALMemory')
00157             if proxy is None:
00158                 # exiting is bad but it should not happen
00159                 # except maybe with NAOqi versions < 1.6 or future ones
00160                 # in which case we will adapt that code to call the proper
00161                 # version function
00162                 exit(1)
00163 
00164             from distutils.version import LooseVersion
00165             self.__naoqi_version = LooseVersion(proxy.version())
00166 
00167         return self.__naoqi_version


naoqi_driver
Author(s): Armin Hornung, Armin Hornung, Stefan Osswald, Daniel Maier, Miguel Sarabia, Severin Lemaignan
autogenerated on Fri Jul 3 2015 12:51:45