0
$\begingroup$

Rosanswers logo

I have successfully sourced and compiled so I can fly my bebop drone using the teleop_twist_keyboard python script.

However I am currently having to run a separate terminal to make the bebop land and take off. Can someone help with how to edit the python script so I can assign the keys 1 ans 2 to mean take off and land respectively.

I have tried various combinations none with any luck (in addition to the original teleop twist keyboard script)

def takeoff():
   pub = rospy.Publisher("bebop/takeoff", Empty, queue_size=10 )
   rospy.init_node('takeoff', anonymous=True)
   rate = rospy.Rate(10) # 10hz
   while not rospy.is_shutdown():
       pub.publish(Empty())
       rate.sleep()

if __name__ == '__main__':
   try:
       takeoff()
   except rospy.ROSInterruptException:
       pass

def land():
   pub = rospy.Publisher("ardrone/land", Empty, queue_size=10 )
   rospy.init_node('land', anonymous=True)
   rate = rospy.Rate(10) # 10hz
   while not rospy.is_shutdown():
       pub.publish(Empty())
       rate.sleep()

if __name__ == '__main__':
   try:
       land()
   except rospy.ROSInterruptException:
       pass
1= takeoff()
2= land()

(didnt expect this one to work )Also tried:

moveBindings = {
        'i':(1,0,0,0),
        'o':(1,0,0,-1),
        'j':(0,0,0,1),
        'l':(0,0,0,-1),
        'u':(1,0,0,1),
        ',':(-1,0,0,0),
        '.':(-1,0,0,1),
        'm':(-1,0,0,-1),
        'O':(1,-1,0,0),
        'I':(1,0,0,0),
        'J':(0,1,0,0),
        'L':(0,-1,0,0),
        'U':(1,1,0,0),
        '<':(-1,0,0,0),
        '>':(-1,-1,0,0),
        'M':(-1,1,0,0),
        't':(0,0,1,0),
        'b':(0,0,-1,0),
        '1'= rostopic pub --once [namespace]/takeoff std_msgs/Empty,
        '2'= rostopic pub --once [namespace]/land std_msgs/Empty  }`enter code here`

Originally posted by jfursdon on ROS Answers with karma: 3 on 2017-10-24

Post score: 0


Original comments

Comment by jayess on 2017-10-24:
This repo isn't exactly what you're looking for (it's for the AR.Drone 2.0), but it may be helpful. Also, checkout Mike Hamer's tutorial for the 2.0 as well.

Comment by jayess on 2017-10-24:
Also, you said

I have tried various combinations

what are these exactly? Can you update your question with your attempts?

Comment by jfursdon on 2017-10-24:
Thanks for the link but these do not explain how to change a python script. They are relating to configuring a joystick which I am not using. Thanks though.

Comment by jayess on 2017-10-24:
There is a keyboard teleop node too. And as I asked earlier, can you please update your question with what you've tried.

Comment by jayess on 2017-10-26:
Thanks for the update, but in order to make the question readable please use the Preformatted Text (1010101) button to properly format your code.

$\endgroup$

2 Answers 2

0
$\begingroup$

Rosanswers logo

Hello,

I have made a couple of very simple modifications to the original script in order to achieve that. What I've done is the following. First, import the Empty message:

import roslib; roslib.load_manifest('teleop_twist_keyboard')
import rospy

from geometry_msgs.msg import Twist
from std_msgs.msg import Empty

Then, create 2 new Publishers, one for landing and the other one for taking off. And create an instance of the Empty message:

if __name__=="__main__":
        settings = termios.tcgetattr(sys.stdin)
    
    pub = rospy.Publisher('cmd_vel', Twist, queue_size = 1)
    rospy.init_node('teleop_twist_keyboard')
    pub2 = rospy.Publisher('drone/takeoff', Empty, queue_size = 1)
    pub3 = rospy.Publisher('drone/land', Empty, queue_size = 1)
    empty_msg = Empty()

Finally, just add 2 conditions for the new keys:

while(1):
    key = getKey()
    if key in moveBindings.keys():
        x = moveBindings[key][0]    
        y = moveBindings[key][1]    
        z = moveBindings[key][2]    
        th = moveBindings[key][3]
    elif key in speedBindings.keys():   
        speed = speed * speedBindings[key][0]   
        turn = turn * speedBindings[key][1]

        print vels(speed,turn)  
        if (status == 14):
            print msg   
        status = (status + 1) % 15

    elif key == '1':
        pub2.publish(empty_msg)
    elif key == '2':
        pub3.publish(empty_msg)

    else:
        x = 0   
        y = 0   
        z = 0   
        th = 0  
        if (key == '\x03'):
            break

    twist = Twist()
twist.linear.x = x*speed; twist.linear.y = y*speed; twist.linear.z = z*speed;
twist.angular.x = 0; twist.angular.y = 0; twist.angular.z = th*turn
pub.publish(twist)

I have also created a video showing how to do it and testing the script. Hope it helps!


Originally posted by Alberto E. with karma: 356 on 2017-10-30

This answer was ACCEPTED on the original site

Post score: 1


Original comments

Comment by jfursdon on 2017-10-30:
Thank you very much, it worked a treat. The video really helped allow me to understand what was being done and why.

$\endgroup$
0
$\begingroup$

Rosanswers logo

Edit: I think the suggestion by @jayess is actually a very good one: the repository he links you to contains a good example of a proper keyboard teleop / controller node that you could very likely use with your specific drone as well. See mikehamer/ardrone_tutorials/src/keyboard_controller.py.


I believe your issue is that you're creating Publisher inside the callback function that handles your keypress. That is not going to work: setting up Publishers and getting Subscribers to notice them and subscribe to them is going to take some time.

You'll want to treat Publishers and Subscribers as persistent objects, that you create once, somewhere in the initialisation phase of your program, and then use inside your callback.

Second: never include any sort of blocking while inside a callback: callbacks like this are supposed to quickly process an event and then return. Including a loop of any kind will make that impossible, and may even block your entire program. With Python this is sometimes hard to detect / notice, as it may spawn N threads to process these things. In your case, that may lead to N instances of Publisher, all publishing Empty msgs at 10 Hz to the bebop/takeoff, even after you've let go of the key.

My advise would be to structure your code similar to how teleop_twist_key.py is setup already, but making sure that the Empty msg gets published by your Publisher when the key you'd like to use is pressed. You'll have to make sure that the code doesn't get to this section if your keys are pressed, because otherwise it will also publish a Twist msg, which is probably not what you want (or it could be, if you'd like to exploit the "publish all-zeros Twist if I haven't pressed any key" behaviour).


Originally posted by gvdhoorn with karma: 86574 on 2017-10-29

This answer was NOT ACCEPTED on the original site

Post score: 1


Original comments

Comment by jfursdon on 2017-10-30:
Thanks very much for the explanation. Helped a lot

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.