Action quiz catkin_make error


Hello everyone, when I followed the course instruction step by step, I didn’t get the expected result.

The actions_quiz pkg is not found and I didn’t get the Action message as well.

Here is the config I set.

The way I used to complie the pkg is :

Any help will be appreciated

One more error…

@xj2106

Please don’t create packages by copying/modifying existing ones. Create everything afresh and prevent this kind of trouble. You should have run:

cd ~/catkin_ws/src/
catkin_create_pkg topics_quiz

and then create and change the files required as show in the examples.

@bayodesegun
I created a new packages using
cd ~/catkin_ws/src/
catkin_create_pkg topics_quiz

But the issue is still there

This is my pkg link. Would you mind taking a look at it?

I’m sorry I may not be able to look at it anytime soon.

But now I see that I wrote topics_quiz instead of actions_quiz. You should use the latter, since we are talking about Actions Quiz here. And when you do, please carefully go through all the steps given to create the custom message and the Python script. Then compile and source the workspace on every shell where you want to run the program.

Hello @bayodesegun I made a stupid mistake that I named the .py file the same name as launch file.
Now the messages are shown properly
image

However, When I publish the TAKEOFF or LAND command to the action server. One error message came out:

This is the code, do you know what my problem is?

#! /usr/bin/python

import rospy
import actionlib
from std_msgs.msg import Empty
from actions_quiz.msg import *

def publish_once(pub, msg):
    r = rospy.Rate(1)
    while True:
        connections = pub.get_num_connections()
        if connections > 0:
            pub.publish(msg)
            rospy.loginfo("Publishing msg")
            break
        else:
            r.sleep()

class CustomActionServer:

    def __init__(self):
        rospy.init_node('action_custom_msg_as', log_level=rospy.DEBUG)
        self.action_server = actionlib.SimpleActionServer('action_custom_msg_as', CustomActionMsgAction, self.callback, auto_start=False)
        self.rate = rospy.Rate(10)
    
    def takeoff(self):
        rospy.loginfo("Taking off...")
        self.pub_takeoff = rospy.Publisher('/drone/takeoff', Empty, queue_size=1)
        msg = Empty()
        publish_once(self.pub_takeoff, msg)
    
    def land(self):
        rospy.loginfo("Landing...")
        self.pub_land = rospy.Publisher('drone/land', Empty, queue_size=1)
        msg = Empty()
        publish_once(self.pub_land, msg)

    def callback(self, goal):
        if goal=='TAKEOFF':
            self.takeoff()
            feedback = 'Taking off...'
        elif goal=='LAND':
            self.land()
            feedback = 'Taking off...'
        
        for i in range(5):
            self.action_server.publish_feedback(feedback)
            rospy.sleep(1)

    def start(self):
        self.action_server.start()
        rospy.spin()

if __name__=='__main__':
    custom_action_server = CustomActionServer()
    custom_action_server.start() 

Thank you in advance

1 Like

@bayodesegun @roalgoal @albertoezquerro Hello teachers. My Gradebot got stuck in the last part. Even after the drone was landed, it is still checking the LAND call works…
After 2 hours it is still there.

It stuck here

After I resubmitted it without changing anything, an error appears:

I am sure that I :“1.I terminated all the programs in your Web Shells. 2.the drone is landed (not flying).”

Here is the demo gif:
demo

Here is my updated code:

#! /usr/bin/python

import rospy
import time
import actionlib
from std_msgs.msg import Empty
from actions_quiz.msg import *


def publish_once(pub, msg):
    r = rospy.Rate(1)
    while True:
        connections = pub.get_num_connections()
        if connections > 0:
            pub.publish(msg)
            rospy.loginfo("Publishing msg")
            break
        else:
            r.sleep()

class CustomActionServer:
    _feedback = CustomActionMsgFeedback()

    def __init__(self):
        rospy.init_node('action_custom_msg_as', log_level=rospy.DEBUG)
        self.action_server = actionlib.SimpleActionServer('action_custom_msg_as', CustomActionMsgAction, self.callback, auto_start=False)
        self.rate = rospy.Rate(10)
    
    def takeoff(self):
        rospy.loginfo("Taking off...")
        self.pub_takeoff = rospy.Publisher('/drone/takeoff', Empty, queue_size=1)
        self._takeoff_msg = Empty()
        i=0
        while not i == 3:
            self.pub_takeoff.publish(self._takeoff_msg)
            rospy.loginfo('Taking off...')
            time.sleep(1)
            i += 1
    
    def land(self):
        rospy.loginfo("Landing...")
        self.pub_land = rospy.Publisher('drone/land', Empty, queue_size=1)
        self._land_msg = Empty()

        i=0
        while not i == 3:
            self.pub_land.publish(self._land_msg)
            rospy.loginfo('Landing...')
            time.sleep(1)
            i += 1

    def callback(self, goal):
        if goal.goal=='TAKEOFF':
            self.takeoff()
            self._feedback.feedback = 'Taking off...'
        elif goal.goal=='LAND':
            self.land()
            self._feedback.feedback = 'landing off...'
        
        for i in range(5):
            self.action_server.publish_feedback(self._feedback)
            rospy.sleep(1)

    def start(self):
        self.action_server.start()
        rospy.spin()

if __name__=='__main__':
    custom_action_server = CustomActionServer()
    custom_action_server.start() 

For publishing to the drone, try using the publish_once method, instead of the loop. That should be something like:

def takeoff(self):
  # ...
  publish_once(self.pub_takeoff, self._takeoff_msg)

def land(self):
  #...
  publish_once(self.pub_land, self._land_msg)

Why is this necessary? Every time you takeoff or land, you are creating the publisher afresh so it might not be ready by the time you are publishing in the loop, even if you are “sleeping” in the loop.

To make your code better:

  • Define the takeoff and land publisher in __init__.
  • Define the empty message also in __init__, and use it for both takeoff and land.
  • You can also bring your publish_once method into the class. It could be something like
def publish_once(self, pub):
 # ...
 pub.publish(self.empty_msg)
 #...

Thank you so so much. Thank you for you patience.
I got 10 now. You made me a better person, and I love ROS even more now!

1 Like

This topic was automatically closed after 31 hours. New replies are no longer allowed.