Arquivos
falkor_ardrone/nodes/ardrone_follow.py
T

262 linhas
8.2 KiB
Python
Arquivo Executável

#!/usr/bin/env python
import roslib
roslib.load_manifest('falkor_ardrone')
import sys
import rospy
import math
import pid
import cv2
import numpy as np
from cv_bridge import CvBridge, CvBridgeError
from geometry_msgs.msg import Point
from geometry_msgs.msg import Twist
from std_msgs.msg import Empty
from sensor_msgs.msg import Joy, Image
from ardrone_autonomy.msg import Navdata
from ardrone_autonomy.srv import LedAnim
class ArdroneFollow:
def __init__( self ):
self.led_service = rospy.ServiceProxy( "ardrone/setledanimation", LedAnim )
# print "waiting for driver to startup"
# rospy.wait_for_service( self.led_service )
self.tracker_sub = rospy.Subscriber( "ardrone_tracker/found_point",
Point, self.found_point_cb )
self.goal_vel_pub = rospy.Publisher( "goal_vel", Twist )
self.found_time = None
self.tracker_img_sub = rospy.Subscriber( "ardrone_tracker/image",
Image, self.image_cb )
self.tracker_image = None
self.timer = rospy.Timer( rospy.Duration( 0.10 ), self.timer_cb, False )
self.land_pub = rospy.Publisher( "ardrone/land", Empty )
self.takeoff_pub = rospy.Publisher( "ardrone/takeoff", Empty )
self.reset_pub = rospy.Publisher( "ardrone/reset", Empty )
self.angularZlimit = 3.141592 / 2
self.linearXlimit = 1.0
self.linearZlimit = 2.0
self.xPid = pid.Pid( 0.020, 0.0, 0.0, self.angularZlimit )
self.yPid = pid.Pid( 0.020, 0.0, 0.0, self.linearZlimit )
self.zPid = pid.Pid( 0.070, 0.0, 0.0, self.linearXlimit )
self.xPid.setPointMin = 40
self.xPid.setPointMax = 60
self.yPid.setPointMin = 40
self.yPid.setPointMax = 60
self.zPid.setPointMin = 17
self.zPid.setPointMax = 23
self.lastAnim = -1
self.found_point = Point( 0, 0, -1 )
self.old_cmd = self.current_cmd = Twist()
self.joy_sub = rospy.Subscriber( "joy", Joy, self.callback_joy )
self.manual_cmd = False
self.auto_cmd = False
self.bridge = CvBridge()
cv2.namedWindow( 'AR.Drone Follow', cv2.cv.CV_WINDOW_NORMAL )
def image_cb( self, data ):
try:
cv_image = self.bridge.imgmsg_to_cv( data, "passthrough" )
except CvBridgeError, e:
print e
self.tracker_image = np.asarray( cv_image )
def increase_z_setpt( self ):
self.zPid.setPointMin *= 1.01
self.zPid.setPointMax *= 1.01
def decrease_z_setpt( self ):
self.zPid.setPointMin /= 1.01
self.zPid.setPointMax /= 1.01
def callback_joy( self, data ):
empty_msg = Empty()
if data.buttons[12] == 1 and self.last_buttons[12] == 0:
self.takeoff()
if data.buttons[14] == 1 and self.last_buttons[14] == 0:
self.land()
if data.buttons[13] == 1 and self.last_buttons[13] == 0:
self.reset()
if data.buttons[15] == 1 and self.last_buttons[15] == 0:
self.auto_cmd = not self.auto_cmd
self.hover()
if data.buttons[4] == 1:
self.increase_z_setpt()
if data.buttons[6] == 1:
self.decrease_z_setpt()
self.last_buttons = data.buttons
# Do cmd_vel
self.current_cmd = Twist()
self.current_cmd.angular.x = self.current_cmd.angular.y = 0
self.current_cmd.angular.z = data.axes[2] * self.angularZlimit
self.current_cmd.linear.z = data.axes[3] * self.linearZlimit
self.current_cmd.linear.x = data.axes[1] * self.linearXlimit
self.current_cmd.linear.y = data.axes[0] * self.linearXlimit
if ( self.current_cmd.linear.x == 0 and
self.current_cmd.linear.y == 0 and
self.current_cmd.linear.z == 0 and
self.current_cmd.angular.z == 0 ):
self.manual_cmd = False
else:
self.setLedAnim( 9 )
self.manual_cmd = True
self.goal_vel_pub.publish( self.current_cmd )
def setLedAnim( self, animType, freq = 10 ):
if self.lastAnim == type:
return
msg = LedAnim();
msg.type = animType;
msg.freq = freq;
msg.duration = 3600;
self.led_service( type = animType, freq = freq, duration = 255 )
self.lastAnim = type
def takeoff( self ):
self.takeoff_pub.publish( Empty() )
self.setLedAnim( 9 )
def land( self ):
self.land_pub.publish( Empty() )
def reset( self ):
self.reset_pub.publish( Empty() )
def navdata_cb( self, data ):
self.vx = data.vx/1e3
self.vy = data.vy/1e3
self.vz = data.vz/1e3
self.ax = (data.ax*9.82)
self.ay = (data.ay*9.82)
self.az = (data.az - 1)*9.82
def found_point_cb( self, data ):
self.found_point = data
self.found_time = rospy.Time.now()
def hover( self ):
hoverCmd = Twist()
self.goal_vel_pub.publish( hoverCmd )
def hover_cmd_cb( self, data ):
self.hover()
def draw_picture( self ):
if self.tracker_image == None:
return
vis = self.tracker_image.copy()
(ySize, xSize, depth) = vis.shape
cx_min = int(self.xPid.setPointMin * xSize / 100)
cx_max = int(self.xPid.setPointMax * xSize / 100)
cx = int( ( cx_min + cx_max ) / 2 )
cy_min = int(self.yPid.setPointMin * ySize / 100)
cy_max = int(self.yPid.setPointMax * ySize / 100)
cy = int( ( cy_min + cy_max ) / 2 )
cv2.rectangle( vis, ( cx_min, cy_min ), ( cx_max, cy_max ),
( 0, 255, 255 ) )
areasqrt = np.sqrt( 640 * 480 )
side_min_half = int( self.zPid.setPointMin * areasqrt / 100 / 2 )
side_max_half = int( self.zPid.setPointMax * areasqrt / 100 / 2 )
cv2.rectangle( vis, ( cx - side_min_half, cy - side_min_half ),
( cx + side_min_half, cy + side_min_half ),
( 255, 255, 0 ) )
cv2.rectangle( vis, ( cx - side_max_half, cy - side_max_half ),
( cx + side_max_half, cy + side_max_half ),
( 255, 255, 0 ) )
if self.current_cmd.linear.x > 0:
line_color = ( 0, 255, 0 )
else:
line_color = ( 0, 0, 255 )
cv2.line( vis, ( 320, 180 ), ( int( xSize/2 - self.current_cmd.angular.z * 320 ),
int( ySize/2 - self.current_cmd.linear.z * 180 ) ),
line_color,
min( max( int( abs( self.current_cmd.linear.x ) * 255 ), 0 ), 255 ) )
cv2.imshow( 'AR.Drone Follow', vis )
cv2.waitKey( 1 )
def timer_cb( self, event ):
self.draw_picture()
# If we haven't received a found point in a second, let found_point be
# (0,0,-1)
if ( self.found_time == None or
( rospy.Time.now() - self.found_time ).to_sec() > 1 ):
self.found_point = Point( 0, 0, -1.0 )
self.found_time = rospy.Time.now()
if event.last_real == None:
dt = 0
else:
dt = ( event.current_real - event.last_real ).to_sec()
if self.found_point.z == -1.0:
self.current_cmd = Twist()
self.setLedAnim( 0, 2 )
else:
self.current_cmd.angular.z = self.xPid.get_output( self.found_point.x,
dt )
self.current_cmd.linear.z = self.yPid.get_output( self.found_point.y,
dt )
self.current_cmd.linear.x = self.zPid.get_output( self.found_point.z,
dt )
self.setLedAnim( 8, 2 )
if self.auto_cmd == False or self.manual_cmd == True:
self.setLedAnim( 9 )
return
self.goal_vel_pub.publish( self.current_cmd )
def main():
rospy.init_node( 'ardrone_follow' )
af = ArdroneFollow()
try:
rospy.spin()
except KeyboardInterrupt:
print "Keyboard interrupted"
if __name__ == '__main__':
main()