Robotics StackExchange | Archived questions

Keep velocity in determined value [quadcopter]

I need to test my slow PID controller but my quadcopter is not too stable, so I don't know if it's moving because of my PID or because of it's own movement. I think that the best way to do that is to make steps like this: https://imgur.com/yQAbmUY (I can't paste the picture because I have less than 5 points, sorry)

The output of the controller are the velocities in x, y and z (ux, uy and uz). In the time-lapse of the PID (for example, 0.2 seconds) I want the ux, uy and uz to have a determined value, and then in the time-lapse of the stop I want them to be ux=0.0, uy=0.0 and uz=0.0.

So my code would be something like this:

#!/usr/bin/env python

# a lot of imports

class gonnaGetDown():
    def __init__(self):

        self.velocity_publisher = rospy.Publisher('/cmd_vel', Twist, queue_size=10)
        self.orientation_publisher = rospy.Publisher('/cmd_vel', Twist, queue_size=10)

        print "b"

        global delta_t
        global u_x_k, u_x_k_pre
        global kp_x, ki_x, kd_x
        global Ti_x, Td_x
        global error_x_k, error_x_k_pre, error_x_k_pre_x2
        global setpoint_x
        global u_y_k, u_y_k_pre
        global kp_y, ki_y, kd_y
        global Ti_y, Td_y
        global error_y_k, error_y_k_pre, error_y_k_pre_x2
        global setpoint_y
        global u_z_k, u_z_k_pre
        global kp_z, ki_z, kd_z
        global Ti_z, Td_z
        global error_z_k, error_z_k_pre, error_z_k_pre_x2
        global setpoint_z

        delta_t = 1/3
        setpoint_x = 0
        setpoint_y = 0 
        setpoint_z = 1 

        #x:
        error_x_k, error_x_k_pre, error_x_k_pre_x2 = 0, 0, 0
        u_x_k = 0
        #y:
        error_y_k, error_y_k_pre, error_y_k_pre_x2 = 0, 0, 0
        u_y_k = 0
        #z:
        error_z_k, error_z_k_pre, error_z_k_pre_x2 = 0, 0, 0
        u_z_k = 0

        print "b"

        rospy.Subscriber('/ar_pose_marker', AlvarMarkers, self.detect_marker)

    def detect_marker(self, msg):
        print "c"

        global u_x_k, u_x_k_pre, u_y_k, u_y_k_pre, u_z_k, u_z_k_pre
        global kp_x, ki_x, kd_x, kp_y, ki_y, kd_y, kp_z, ki_z, kd_z
        global delta_t
        global error_x_k, error_x_k_pre, error_x_k_pre_x2, error_y_k, error_y_k_pre, error_y_k_pre_x2, error_z_k, error_z_k_pre, error_z_k_pre_x2
        global contador

        Ti_x, Td_x = kp_x/ki_x, kd_x/kp_x
        Ti_y, Td_y = kp_y/ki_y, kd_y/kp_y
        Ti_z, Td_z = kp_z/ki_z, kd_z/kp_z    

        if not msg.markers:
            print "Tag not found"
            vel_msg = Twist()

            vel_msg.linear.x = 0.0
            vel_msg.linear.y = 0.0
            vel_msg.linear.z = 0.0
            vel_msg.angular.x = 0.0
            vel_msg.angular.y = 0.0
            vel_msg.angular.z = 0.0

            u_x_k = 0.0
            u_y_k = 0.0
            u_z_k = 0.0
            self.velocity_publisher.publish(vel_msg)
            return
        else:
            marker = msg.markers[0]
            print "d"
            #Primero ajusto las posiciones x e y con un PID
            error_x_k_pre_x2 = error_x_k_pre
            error_x_k_pre = error_x_k
            error_x_k = setpoint_x - marker.pose.pose.position.x

            error_y_k_pre_x2 = error_y_k_pre
            error_y_k_pre = error_y_k
            error_y_k = setpoint_y - marker.pose.pose.position.y

            error_z_k_pre_x2 = error_z_k_pre
            error_z_k_pre = error_z_k
            error_z_k = setpoint_z - marker.pose.pose.position.z

            u_x_k = ... # algorithm
            u_y_k = ... # algorithm
            u_z_k = ... # algorithm

            vel_msg = Twist()
            vel_msg.linear.x = u_y_k 
            vel_msg.linear.y = u_x_k 
            vel_msg.linear.z = u_z_k 

            self.velocity_publisher.publish(vel_msg)

            time.sleep(0.2) #0.2 seconds

            vel_msg.linear.x = 0.0
            vel_msg.linear.y = 0.0
            vel_msg.linear.z = 0.0
            self.velocity_publisher.publish(vel_msg)

            time.sleep(0.7) #0.7 seconds


if __name__ == '__main__':

    rospy.init_node('go_down', anonymous=True)

    try:
        rate = rospy.Rate(0.1) 
        gonna_get_down = gonnaGetDown()
        while not rospy.is_shutdown():

            print "a"

            rate.sleep()
    except rospy.ROSInterruptException:
        rospy.loginfo("Node terminated.")

It enters to the function detect_marker each 1/3 second.

I want the code to maintain the velocity in a determined value. For example, when it's value must be 0.0, I want to be 0.0 in all the 0.7 time-lapse (i.e, if there's wind that moves the drone, I want the drone to try to keep in the same position without moving).

How can I make that happen? Thanks (if you think that there's a better way to do this, please tell me)

Asked by Dylan on 2019-01-24 15:36:51 UTC

Comments

Are you asking how to write a PID controller?

Asked by jayess on 2019-01-24 15:44:04 UTC

No. I'm asking how to keep the velocity (vel_msg.linear.x, for example) in a determined value for a period of time. For example, I want to keep the vel_msg.linear.x=0.0 for 0.7 seconds. How can I do that? I imagine that a for loop can do that but the computational cost would be high

Asked by Dylan on 2019-01-24 15:52:28 UTC

I mean, I want to update vel_msg.linear.x multiple times for a period of time, so if there's an external disturbance or something, it keeps the same value (if I put vel_msg.linear.x=0.0 and I hit the quadcopter, the vel_msg.linear.x would be different than 0.0 and wouldn't return to 0.0)

Asked by Dylan on 2019-01-24 15:54:29 UTC

So, you're only talking about publishing messages for certain periods and not maintaining your quadcopter at a certain velocity then?

Asked by jayess on 2019-01-24 16:17:39 UTC

No. I want to maintain the velocity of the quadcopter at a determined value for a period of time. For example, if I want the velocity is 0.2, then I want the velocity to be 0.2 in all that time-lapse. If I hit the quadcopter from behind at make it higher, then it slows down, and viceversa

Asked by Dylan on 2019-01-24 16:20:23 UTC

You want to write some kind of controller then

Asked by jayess on 2019-01-24 16:22:08 UTC

No. For example, a for loop that lasts 1 second would be a solution, because it would post the same velocity for 1 second. But how many iterations do I have to do in 1 second? And it would be really expensive computationally, I suppose

Asked by Dylan on 2019-01-24 16:26:06 UTC

If you're wanting to maintain a certain velocity, then you want a controller. Simply publishing a message telling your quadcopter to go a certain velocity won't cut it (unless you happen to be very lucky and it just happens to work out).

Asked by jayess on 2019-01-24 16:28:42 UTC

Loops don't have to be computationally expensive. That's what sleep is for (the ROS version, not the Python version, which you're using and shouldn't be).

Asked by jayess on 2019-01-24 16:30:23 UTC

The question is where do the vel_msg messages go? The will go to another node which has a controller which will be adjusting the rotor speeds of the drone to try and match the desired velocity. Sending more identical messages on the topic will have no effect, because the set point will stay the same

Asked by PeteBlackerThe3rd on 2019-01-25 06:28:13 UTC

Answers