Go to the documentation of this file.00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 PKG_NAME = 'art_teleop'
00011 
00012 
00013 import sys
00014 import math
00015 
00016 import pilot_cmd                
00017 import nav_estop                
00018 
00019 
00020 import roslib;
00021 roslib.load_manifest(PKG_NAME)
00022 import rospy
00023 
00024 
00025 from art_msgs.msg import ArtVehicle
00026 from art_msgs.msg import Gear
00027 from joy.msg import Joy
00028 
00029 
00030 from driver_base.msg import SensorLevels
00031 from dynamic_reconfigure.server import Server as ReconfigureServer
00032 import art_teleop.cfg.JoyConfig as JoyConfig
00033 
00034 def clamp(minimum, value, maximum):
00035     "constrain value to the range [minimum .. maximum]"
00036     return max(minimum, min(value, maximum))
00037 
00038 class JoyNode():
00039     "Vehicle joystick tele-operation node."
00040 
00041     def __init__(self):
00042         "JoyNode constructor"
00043 
00044         
00045         self.run = 3                    
00046         self.suspend = 12               
00047         self.estop = 13                 
00048 
00049         
00050         self.steer = 0                  
00051         self.drive = 4                  
00052         self.reverse = 6                
00053         self.park = 7                   
00054         self.throttle = 18              
00055         self.throttle_start = True
00056         self.brake = 19                 
00057         self.brake_start = True
00058         self.lowincrease_max = 11       
00059         self.highincrease_max = 9       
00060         self.lowdecrease_max = 10       
00061         self.highdecrease_max = 8       
00062         
00063 
00064         
00065         rospy.init_node('josh_teleop')
00066         self.pilot = pilot_cmd.PilotCommand()
00067         self.reconf_server = ReconfigureServer(JoyConfig, self.reconfigure)
00068         self.joy = rospy.Subscriber('joy', Joy, self.joyCallback)
00069 
00070 
00071     def joyCallback(self, joy):
00072         "invoked every time a joystick message arrives"
00073         rospy.logdebug('joystick input:\n' + str(joy))
00074 
00075         
00076         if joy.buttons[self.estop]:
00077             rospy.logwarn('emergency stop')
00078             if self.use_navigator:
00079                 self.nav.pause()        
00080             else:
00081                 self.pilot.halt()       
00082         elif joy.buttons[self.suspend] and self.use_navigator:
00083             rospy.logwarn('suspend autonomous operation')
00084             self.nav.suspend()
00085         elif joy.buttons[self.run] and self.use_navigator:
00086             rospy.logwarn('start autonomous operation')
00087             self.nav.run()
00088 
00089         
00090         if joy.buttons[self.drive]:
00091             self.pilot.shift(Gear.Drive)
00092             rospy.loginfo('shifting to drive')
00093         elif joy.buttons[self.reverse]:
00094             self.pilot.shift(Gear.Reverse)
00095             rospy.loginfo('shifting to reverse')
00096         elif joy.buttons[self.park]:
00097             self.pilot.shift(Gear.Park)
00098             rospy.loginfo('shifting to park')
00099 
00100         
00101         if joy.buttons[self.lowincrease_max]:
00102                 self.config['limit_forward'] += .5
00103         if joy.buttons[self.highincrease_max]:
00104                 self.config['limit_forward'] += 2
00105         if joy.buttons[self.lowdecrease_max]:
00106                 self.config['limit_forward'] -= .5
00107         if joy.buttons[self.highdecrease_max]:
00108                 self.config['limit_forward'] -= 2
00109 
00110         
00111         self.setAngle(joy.axes[self.steer])
00112 
00113         
00114         
00115         
00116         br = (-joy.axes[self.brake] + 1) / 2
00117         th = (-joy.axes[self.throttle] + 1) / 2
00118         rospy.logdebug('joystick brake, throttle: '
00119                        + str(br) + ', ' + str(th))
00120 
00121         
00122         
00123         dv = 0
00124         if self.brake_start:
00125             if br == 0.5:
00126                 br = 0
00127             else:
00128                 self.brake_start = False
00129 
00130         if self.throttle_start:
00131             if th == 0.5:
00132                 th = 0
00133             else:
00134                 self.throttle_start = False
00135 
00136         if br > 0:
00137                 dv = -br * 3
00138 
00139         elif th == 0 and self.pilot.pstate.current.speed > 0:
00140                 dv = -.1
00141                 
00142                 
00143 
00144         elif th > 0:
00145                 if self.pilot.pstate.current.speed < self.config['limit_forward']*th:
00146                         dv = self.config['limit_forward']*th - self.pilot.pstate.current.speed
00147                         if dv > 1:
00148                                 dv = 1 + math.pow(dv/self.config['limit_forward'], 2) 
00149                         else:
00150                                 dv = math.pow(dv, 2) 
00151                 elif self.pilot.pstate.current.speed > self.config['limit_forward']*th:
00152                         dv = -.1
00153                 else:
00154                     dv = 0
00155         else:
00156                 dv = 0
00157 
00158         
00159         self.pilot.car_ctl.acceleration = dv * 10
00160         if self.pilot.car_ctl.gear.value == Gear.Drive:
00161                 self.pilot.car_ctl.speed = self.config['limit_forward']*th
00162         elif self.pilot.car_ctl.gear.value == Gear.Reverse:
00163                 self.pilot.car_ctl.speed = -self.config['limit_reverse']*th
00164         else:                   
00165                 self.pilot.car_ctl.speed = 0.0
00166                 self.pilot.car_ctl.acceleration = 0.0
00167 
00168 
00169         if self.nav.is_suspended(): 
00170             self.pilot.publish()
00171         else:
00172             rospy.logdebug('car running autonomously (command ignored)')
00173 
00174     def reconfigure(self, config, level):
00175         "Dynamic reconfigure server callback."
00176         rospy.loginfo('Reconfigure callback, level ' + str(level))
00177         rospy.loginfo('New config ' + str(config))
00178 
00179         if level & SensorLevels.RECONFIGURE_CLOSE:
00180             
00181             self.use_navigator = config['use_navigator']
00182             rospy.loginfo('use navigator = ' + str(self.use_navigator))
00183 
00184             self.nav = nav_estop.EstopNavigator(self.use_navigator)
00185 
00186         self.pilot.reconfigure(config['limit_forward'],
00187                                config['limit_reverse'])
00188 
00189         self.config = config
00190         return config
00191 
00192     def setAngle(self, turn):
00193         "set wheel angle"
00194 
00195         
00196         
00197         
00198         
00199         
00200         
00201 
00202         
00203         if self.pilot.pstate.current.speed == 0:
00204                 percentage = 1
00205         else:
00206                 percentage = -0.2738*(math.log(math.fabs(self.pilot.pstate.current.speed))) + 0.6937
00207         turn = turn * percentage * ArtVehicle.max_steer_radians
00208 
00209         
00210         self.pilot.steer(turn)
00211 
00212         def maxFinder(self):
00213                 if self.pilot.pstate.current.speed > self.config['limit_forward']:
00214                         return self.pilot.state.current
00215                 return self.config['limit_forward']
00216 
00217 joynode = None
00218 
00219 
00220 def main():
00221     global joynode
00222     joynode = JoyNode()
00223     rospy.loginfo('joystick vehicle controller starting')
00224     try:
00225         rospy.spin()
00226     except rospy.ROSInterruptException: pass
00227     rospy.loginfo('joystick vehicle controller finished')
00228 
00229 if __name__ == '__main__':
00230     
00231     sys.exit(main())