joy.py
Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 
00003 import math
00004 import numpy
00005 
00006 import rospy
00007 import os
00008 import sys
00009 
00010 import imp
00011 try:
00012   imp.find_module("sensor_msgs")
00013 except:
00014   import roslib; roslib.load_manifest('jsk_teleop_joy')
00015 
00016 
00017 from sensor_msgs.msg import Joy
00018 from diagnostic_msgs.msg import DiagnosticStatus, DiagnosticArray
00019 import tf.transformations
00020 from joy_status import XBoxStatus, PS3Status, PS3WiredStatus
00021 from jsk_rviz_plugins.msg import OverlayMenu
00022 from plugin_manager import PluginManager
00023 from status_history import StatusHistory
00024 from diagnostic_updater import Updater as DiagnosticUpdater
00025 
00026 AUTO_DETECTED_CLASS = None
00027 
00028 def autoJoyDetect(msg):
00029   global AUTO_DETECTED_CLASS
00030   if AUTO_DETECTED_CLASS:
00031     return
00032   if len(msg.axes) == 27 and len(msg.buttons) == 19:
00033     rospy.loginfo("auto detected as ps3wired")
00034     AUTO_DETECTED_CLASS = PS3WiredStatus
00035   elif len(msg.axes) == 8 and len(msg.buttons) == 11:
00036     rospy.loginfo("auto detected as xbox")
00037     AUTO_DETECTED_CLASS = XBoxStatus
00038   elif len(msg.axes) == 20 and len(msg.buttons) == 17:
00039     rospy.loginfo("auto detected as ps3")
00040     AUTO_DETECTED_CLASS = PS3Status
00041   else:
00042     AUTO_DETECTED_CLASS = "UNKNOWN"
00043     
00044 class JoyManager():
00045   STATE_INITIALIZATION = 1
00046   STATE_RUNNING = 2
00047   STATE_WAIT_FOR_JOY = 3
00048 
00049   MODE_PLUGIN = 0
00050   MODE_MENU = 1
00051   mode = 0
00052   
00053   plugin_instances = []
00054   def stateDiagnostic(self, stat):
00055     if self.state == self.STATE_INITIALIZATION:
00056       stat.summary(DiagnosticStatus.WARN,
00057                    "initializing JoyManager")
00058     elif self.state == self.STATE_RUNNING:
00059       stat.summary(DiagnosticStatus.OK,
00060                    "running")
00061       stat.add("Joy stick type", str(self.JoyStatus))
00062     elif self.state == self.STATE_WAIT_FOR_JOY:
00063       stat.summary(DiagnosticStatus.WARN,
00064                    "waiting for joy message to detect joy stick type")
00065     return stat
00066   def pluginStatusDiagnostic(self, stat):
00067     if len(self.plugin_instances) == 0:
00068         stat.summary(DiagnosticStatus.ERROR, "no plugin is loaded")
00069     else:
00070         stat.summary(DiagnosticStatus.OK, 
00071                      "%d plugins are loaded" % (len(self.plugin_instances)))
00072         stat.add("instances", ", ".join([p.name for p in self.plugin_instances]))
00073     return stat
00074   def __init__(self):
00075     self.state = self.STATE_INITIALIZATION
00076     self.pre_status = None
00077     self.history = StatusHistory(max_length=10)
00078     self.menu_pub = rospy.Publisher("/overlay_menu", OverlayMenu)
00079     self.controller_type = rospy.get_param('~controller_type', 'auto')
00080     self.plugins = rospy.get_param('~plugins', {})
00081     self.current_plugin_index = 0
00082     self.selecting_plugin_index = 0
00083     #you can specify the limit of the rate via ~diagnostic_period
00084     self.diagnostic_updater = DiagnosticUpdater()
00085     self.diagnostic_updater.setHardwareID("teleop_manager")
00086     self.diagnostic_updater.add("State", self.stateDiagnostic)
00087     self.diagnostic_updater.add("Plugin Status", self.pluginStatusDiagnostic)
00088     #self.diagnostic_updater.add("Joy Input", self.joyInputDiagnostic)
00089     self.diagnostic_updater.update()
00090     if self.controller_type == 'xbox':
00091       self.JoyStatus = XBoxStatus
00092     elif self.controller_type == 'ps3':
00093       self.JoyStatus = PS3Status
00094     elif self.controller_type == 'ps3wired':
00095       self.JoyStatus = PS3WiredStatus
00096     elif self.controller_type == 'auto':
00097       s = rospy.Subscriber('/joy', Joy, autoJoyDetect)
00098       self.state = self.STATE_WAIT_FOR_JOY
00099       error_message_published = False
00100       r = rospy.Rate(1)
00101       while not rospy.is_shutdown():
00102         self.diagnostic_updater.update()
00103         if AUTO_DETECTED_CLASS == "UNKNOWN":
00104           if not error_message_published:
00105             rospy.logfatal("unknown joy type")
00106             error_message_published = True
00107           r.sleep()
00108         elif AUTO_DETECTED_CLASS:
00109           self.JoyStatus = AUTO_DETECTED_CLASS
00110           s.unregister()
00111           break
00112         else:
00113           r.sleep()
00114     self.diagnostic_updater.update()
00115     self.plugin_manager = PluginManager('jsk_teleop_joy')
00116     self.loadPlugins()
00117   def loadPlugins(self):
00118     self.plugin_manager.loadPlugins()
00119     self.plugin_instances = self.plugin_manager.loadPluginInstances(self.plugins, self)
00120   def switchPlugin(self, index):
00121     self.current_plugin_index = index
00122     if len(self.plugin_instances) <= self.current_plugin_index:
00123       self.current_plugin_index = 0
00124     elif self.current_plugin_index < 0:
00125       self.current_plugin_index = len(self.plugin_instances)
00126     self.current_plugin.disable()
00127     self.current_plugin = self.plugin_instances[self.current_plugin_index]
00128     self.current_plugin.enable()
00129   def nextPlugin(self):
00130     rospy.loginfo('switching to next plugin')
00131     self.switchPlugin(self, self.current_plugin_index + 1)
00132   def start(self):
00133     self.publishMenu(0, close=True) # close menu anyway
00134     self.diagnostic_updater.force_update()
00135     if len(self.plugin_instances) == 0:
00136       rospy.logfatal('no valid plugins are loaded')
00137       return False
00138     self.current_plugin = self.plugin_instances[0]
00139     self.current_plugin.enable()
00140     self.joy_subscriber = rospy.Subscriber('/joy', Joy, self.joyCB)
00141     self.state = self.STATE_RUNNING
00142     return True
00143   def publishMenu(self, index, close=False):
00144     menu = OverlayMenu()
00145     menu.menus = [p.name for p in self.plugin_instances]
00146     menu.current_index = index
00147     menu.title = "Joystick"
00148     if close:
00149       menu.action = OverlayMenu.ACTION_CLOSE
00150     self.menu_pub.publish(menu)
00151   def forceToPluginMenu(self, publish_menu=False):
00152     self.selecting_plugin_index = self.current_plugin_index
00153     if publish_menu:
00154       self.publishMenu(self.current_plugin_index)
00155     self.mode = self.MODE_MENU
00156   def processMenuMode(self, status, history):
00157     if history.new(status, "down") or history.new(status, "left_analog_down"):
00158       self.selecting_plugin_index = self.selecting_plugin_index + 1
00159       if self.selecting_plugin_index >= len(self.plugin_instances):
00160         self.selecting_plugin_index = 0
00161       self.publishMenu(self.selecting_plugin_index)
00162     elif history.new(status, "up") or history.new(status, "left_analog_up"):
00163       self.selecting_plugin_index = self.selecting_plugin_index - 1
00164       if self.selecting_plugin_index < 0:
00165         self.selecting_plugin_index = len(self.plugin_instances) - 1
00166       self.publishMenu(self.selecting_plugin_index)
00167     elif history.new(status, "cross") or history.new(status, "center"):
00168       self.publishMenu(self.selecting_plugin_index, close=True)
00169       self.mode = self.MODE_PLUGIN
00170     elif history.new(status, "circle"):
00171       self.publishMenu(self.selecting_plugin_index, close=True)
00172       self.mode = self.MODE_PLUGIN
00173       self.switchPlugin(self.selecting_plugin_index)
00174     else:
00175       self.publishMenu(self.selecting_plugin_index)
00176   def joyCB(self, msg):
00177     status = self.JoyStatus(msg)
00178     if self.mode == self.MODE_MENU:
00179       self.processMenuMode(status, self.history)
00180     else:
00181       if self.history.new(status, "center"):
00182         self.forceToPluginMenu()
00183       else:
00184         self.current_plugin.joyCB(status, self.history)
00185     self.pre_status = status
00186     self.history.add(status)
00187     self.diagnostic_updater.update()
00188     
00189 def main():
00190   global g_manager
00191   rospy.sleep(1)
00192   rospy.init_node('jsk_teleop_joy')
00193   g_manager = JoyManager()
00194   result = g_manager.start()
00195   if not result:
00196     rospy.logfatal("Fatal Error")
00197     return False
00198   else:
00199     rospy.spin()
00200   
00201 if __name__ == '__main__':
00202   main()
00203   


jsk_teleop_joy
Author(s): Ryohei Ueda
autogenerated on Wed Sep 16 2015 04:37:30