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