Ex 8.6 Action_server

I don’t get any error in this script but the it not working the drone is not taking off, its not even moving . I cross checked my code with solution and its almost similar But I don’t know why my code is not working. Can anyone help me with this ??

task_8.6.py

#! /usr/bin/env python

import rospy
import time
import actionlib

from std_msgs.msg import Empty
from geometry_msgs.msg import Twist
from ardrone_as.msg import ArdroneAction, ArdroneGoal, ArdroneResult, ArdroneFeedback


# PADWE
PENDING = 0
ACTIVE = 1
DONE = 2
WARN = 3
ERROR = 4

nImage = 1
# defing the feedback for action server


def feedback_callback(feedback):

    global nImage
    print('[Feeback] image is n.%d' % nImage)
    nImage += 1


rospy.init_node('ardrone_circle_move')

# declaring Action_server
action_server_name = '/ardone_action_server'
client = actionlib.SimpleActionClient(action_server_name, ArdroneAction)
# Declaring Velocity publisher
pub = rospy.Publisher('/cmd_vel', Twist, queue_size=1)
cmde = Twist()
# Declaring takeoff
takeoff = rospy.Publisher('/drone/takeoff', Empty, queue_size=1)
takeoff_msg = Empty()
# Declaring Landing
land = rospy.Publisher('/drone/land', Empty, queue_size=1)
land_msg = Empty()

# Waiting for action_server to start
rospy.loginfo("Waiting the Action_server " +action_server_name)
client.wait_for_server()
rospy.loginfo("Action_server_found.... " +action_server_name)

# sending Goal
# goal = ArdroneGoal()
# goal.nseconds = 10

goal = ArdroneGoal()
goal.nseconds = 10 # indicates, take pictures along 10 seconds
client.send_goal(goal, feedback_cb=feedback_callback)


state_result = client.get_state()

rate = rospy.Rate(1)

rospy.loginfo('state_result: ' + str(state_result))

for i in range(3):
    takeoff.publish(takeoff_msg)
    rospy.loginfo('Pavan Taking off Captain')
    rate.sleep()

while state_result < DONE:
    cmde.linear.x = 1
    cmde.angular.z = 1
    pub.publish(cmde)
    rate.sleep()
    state_result = client.get_state()
    rospy.loginfo('state_result: ' + str(state_result))

rospy.loginfo("[Result] State: "+str(state_result))
if state_result == WARN:
    rospy.logwarn("Warning state result is " + str(state_result))
if state_result == ERROR:
    rospy.logerr('Error state result' + str(state_result))


for i in range(3):
    rospy.loginfo('landing the robot')
    cmde.linear.x = 0.3
    cmde.angular.z = 0.3
    pub.publish(cmde)
    land.publish(land_msg)
    rospy.loginfo('Task Completed Drone Landed')
    rate.sleep()

my launch file : action_service_circle.launch

<launch>

<node
    pkg = "my_action_client_eg_pkg"
    type = "task_8.6.py"
    name = "ardrone_circle_move"
    output = "screen" >
</node>
</launch>

@girishkumar.kannan

Hi @balajigunasekeran22 ,

I think you have not understood the “actions” concept well.

Why have you programmed robot controls in action client program?

You must do all the robot control programming in the action server program. Action client just sends the goal call to the action server. The action server controls the robot.

Currently, your action client program has takeoff, movement and landing control - naturally, your action client will not work!

Please read the action topic again to get a better understanding of the concept.

Regards,
Girish

Hello @girishkumar.kannan ,

Yes you are correct movement control should be declared in Server and Client only send the goal to server. But excersie 8.6 has the following tasks

  • Create a package that contains and launches the action client from Exercise {8.4a}: ardrone_action_client.py, from a launch file.
  • Add some code that makes the quadcopter move around while the action server has been called (in order to take pictures while the robot is moving).
  • Stop the movement of the quadcopter when the last picture has been taken (action server has finished).

So my understanding is The exercise instructions only ask you to create a package that contains and launches the action client from Exercise 8.4a (ardrone_action_client.py) using a launch file.

However, the exercise also asks you to add some code to make the quadcopter move around while the action server has been called (in order to take pictures while the robot is moving) and to stop the movement of the quadcopter when the last picture has been taken (action server has finished). So, you will need to modify the existing ardrone_action_client.py file to include this movement t.

Am I wrong in my interpretation ???

And this is the solution given by construct

#! /usr/bin/env python

import rospy
import time
import actionlib
from ardrone_as.msg import ArdroneAction, ArdroneGoal, ArdroneResult, ArdroneFeedback
from geometry_msgs.msg import Twist
from std_msgs.msg import Empty

# We create some constants with the corresponing vaules from the SimpleGoalState class
PENDING = 0
ACTIVE = 1
DONE = 2
WARN = 3
ERROR = 4

nImage = 1

# definition of the feedback callback. This will be called when feedback
# is received from the action server
# it just prints a message indicating a new message has been received
def feedback_callback(feedback):

    global nImage
    print('[Feedback] image n.%d received'%nImage)
    nImage += 1

# initializes the action client node
rospy.init_node('drone_action_client')

action_server_name = '/ardrone_action_server'
client = actionlib.SimpleActionClient(action_server_name, ArdroneAction)
move = rospy.Publisher('/cmd_vel', Twist, queue_size=1) #Create a Publisher to move the drone
move_msg = Twist() #Create the message to move the drone
takeoff = rospy.Publisher('/drone/takeoff', Empty, queue_size=1) #Create a Publisher to takeoff the drone
takeoff_msg = Empty() #Create the message to takeoff the drone
land = rospy.Publisher('/drone/land', Empty, queue_size=1) #Create a Publisher to land the drone
land_msg = Empty() #Create the message to land the drone

# waits until the action server is up and running
rospy.loginfo('Waiting for action Server '+action_server_name)
client.wait_for_server()
rospy.loginfo('Action Server Found...'+action_server_name)

# creates a goal to send to the action server
goal = ArdroneGoal()
goal.nseconds = 10 # indicates, take pictures along 10 seconds

client.send_goal(goal, feedback_cb=feedback_callback)


# You can access the SimpleAction Variable "simple_state", that will be 1 if active, and 2 when finished.
#Its a variable, better use a function like get_state.
#state = client.simple_state
# state_result will give the FINAL STATE. Will be 1 when Active, and 2 if NO ERROR, 3 If Any Warning, and 3 if ERROR
state_result = client.get_state()

rate = rospy.Rate(1)

rospy.loginfo("state_result: "+str(state_result))

#We takeoff the drone during the first 3 seconds
i=0
while not i == 3:
    takeoff.publish(takeoff_msg)
    rospy.loginfo('Taking off...')
    time.sleep(1)
    i += 1

#We move the drone in a circle wile the state of the Action is not DONE yet
while state_result < DONE:
    move_msg.linear.x = 1
    move_msg.angular.z = 1
    move.publish(move_msg)
    rate.sleep()
    state_result = client.get_state()
    rospy.loginfo('Moving around...')
    rospy.loginfo("state_result: "+str(state_result))
    
rospy.loginfo("[Result] State: "+str(state_result))
if state_result == ERROR:
    rospy.logerr("Something went wrong in the Server Side")
if state_result == WARN:
    rospy.logwarn("There is a warning in the Server Side")

# We land the drone when the action is finished
i=0
while not i == 3:
    move_msg.linear.x = 0
    move_msg.angular.z = 0
    move.publish(move_msg)
    land.publish(land_msg)
    rospy.loginfo('Landing...')
    time.sleep(1)
    i += 1

As you said and also from my understanding movement publisher in client will not make the robot move as it only sends goal to server. But If I run this solution program in my file the drone moves. I am lost Like where exactly is my mistake. @girishkumar.kannan Could you please point my mistakes so that I can work on this topic again for better understanding.

Hi @balajigunasekeran22 ,

Ok, I was wrong when I said the action client does not have robot control code.
I did not remember this exercise well since I did this long back.

Anyways, I looked back into this and get to know how this exercise works.

I just compared your solution with the course solution and my solution - they seem to be similar.

I guess you might have had some connectivity issues.
Try resetting your webshells.
Before starting the action client, make sure the action server is running.

Otherwise, I do not see any problems.

Regards,
Girish

Hi @girishkumar.kannan ,

I Tired Resetting the webshells and started action_server 1st as you said and then the action_client but still the same issue.

Hi @balajigunasekeran22 ,

Your program literally says “Waiting for Action Server /ardrone_action_server”!
That means the action server was never started!

You NEED TO HAVE the action server running for the action client to work.
It is better to start the action server before the action client starts.
You can start the action server after action client IF AND ONLY IF action client does not have a timeout for waiting on action server.

Start your action server in another terminal, your program should work fine!

Regards,
Girish

Hi @girishkumar.kannan ,

I started my action_server first and then my action_client this is what I don’t understand in my code. Its waiting for action_server even when the action_server is running.
Below is the image of my webshell for your reference.

Terminal 1 : Action_server

Terminal 2 : Action_client

Hi @balajigunasekeran22 ,

I think there is a naming-mismatch with the action server.
Check the name of action server and verify if the action server that you are connecting to with your action client is connecting to the proper action server.

I think your action server name is /ardrone_as but you are connecting to /ardrone_action_server. Re-check this and that should fix your problem.

Let me know if you still have issues.

Regards,
Girish

Hi @girishkumar.kannan ,

Still facing the same issue. Actually /ardrone_action_server is the one we previously used in excerise 8.4 and all. I even tired /ardone_as but still facing the same issue.

Thank you,

Regards,
BG

Hi @girishkumar.kannan ,

I figured it out. The program work for me. I have made a simple spelling mistake in calling the service_name instead of ‘/ardrone_action_server’ I did ‘/ardone_action_server’ missed out 'r '. Sorry I did’nt notice it.

Thank you for helping me out,

Regards,
BG

Hi @balajigunasekeran22 ,

Glad to know that you fixed your problem yourself.

This kind of issue is what I call as silly / stupid mistake. The only way to find these mistakes is to check line-by-line for mistakes.

Well, in your case the action server was never found to be running… so the the error has to be in that line where you have defined the action server name.

Anyways, glad you found the error.

Regards,
Girish

1 Like