Hi,
I’m working on the topics quiz and when submitting the quiz, Gradebot says that I’m not subscribed to /odom. My code runs fine when I run it locally (not through gradebot). I’ve checked the basics as to why that could be, but haven’t found the reason as to what it is. (I also did check the discussion with someone saying the same thing, but my node name is topics_quiz_node unlike theirs). Here is my code for my main file, launch file, setup file and picture workspace tree: (Note: The warning is from unused objects pitch and roll)
import rclpy
# import the ROS2 python libraries
from rclpy.node import Node
# import the Twist module from geometry_msgs interface
from geometry_msgs.msg import Twist
# import the Odometry module from nav_msgs interface
from nav_msgs.msg import Odometry
import numpy as np
from rclpy.qos import ReliabilityPolicy, QoSProfile
class TopicsQuiz(Node):
def __init__(self):
# Here you have the class constructor
# call the class constructor
super().__init__('topics_quiz_node')
# create the publisher object
self.publisher_ = self.create_publisher(Twist, 'cmd_vel', 10)
# create the subscriber object
self.subscriber = self.create_subscription(
Odometry, '/odom', self.odom_callback, QoSProfile(depth=10, reliability=ReliabilityPolicy.RELIABLE))
# define the timer period for 0.5 seconds
self.timer_period = 0.5
# define the variable to save the received info
self.odom_msg = 0
# create a Twist message
self.cmd = Twist()
self.timer = self.create_timer(self.timer_period, self.motion)
def euler_from_quaternion(self, quaternion):
"""
Converts quaternion (w in last place) to euler roll, pitch, yaw
quaternion = [x, y, z, w]
Below should be replaced when porting for ROS2 Python tf_conversions is done.
"""
x = quaternion.x
y = quaternion.y
z = quaternion.z
w = quaternion.w
sinr_cosp = 2 * (w * x + y * z)
cosr_cosp = 1 - 2 * (x * x + y * y)
roll = np.arctan2(sinr_cosp, cosr_cosp)
sinp = 2 * (w * y - z * x)
pitch = np.arcsin(sinp)
siny_cosp = 2 * (w * z + x * y)
cosy_cosp = 1 - 2 * (y * y + z * z)
yaw = np.arctan2(siny_cosp, cosy_cosp)
return roll, pitch, yaw
def odom_callback(self, msg):
# print the log info in the terminal
# self.get_logger().info('I receive odom: "%s"' % str(msg))
# Save the odom msg
self.odom_msg = msg
def motion(self):
# print the data
# self.get_logger().info('I receive motion: "%s"' % str(self.odom_msg))
# Logic of move
postion_x = self.odom_msg.pose.pose.position.x
postion_y = self.odom_msg.pose.pose.position.y
orientation = self.odom_msg.pose.pose.orientation
roll, pitch, yaw = self.euler_from_quaternion(orientation)
self.get_logger().info('position X: "%s"' % str(postion_x))
self.get_logger().info('position Z: "%s"' % str(postion_y))
self.get_logger().info('yaw: "%s"' % str(yaw))
if postion_x < 0.8:
self.cmd.linear.x = 0.2
self.cmd.angular.z = 0.0
elif postion_x > 0.75 and yaw < 1.40:
self.cmd.linear.x = 0.0
self.cmd.angular.z = 0.25
elif postion_y < 0.75:
self.cmd.linear.x = 0.2
self.cmd.angular.z = 0.0
else:
self.cmd.linear.x = 0.0
self.cmd.angular.z = 0.0
# Publishing the cmd_vel values to a Topic
self.publisher_.publish(self.cmd)
def main(args=None):
# initialize the ROS communication
rclpy.init(args=args)
# declare the node constructor
topics_quiz_node = TopicsQuiz()
# pause the program execution, waits for a request to kill the node (ctrl+c)
rclpy.spin(topics_quiz_node)
# Explicity destroy the node
topics_quiz_node.destroy_node()
# shutdown the ROS communication
rclpy.shutdown()
if __name__ == '__main__':
main()
Launch file:
from launch import LaunchDescription
from launch_ros.actions import Node
def generate_launch_description():
return LaunchDescription([
Node(
package='topics_quiz',
executable='topics_quiz_node',
output='screen'),
])
setup.py:
from setuptools import setup
import os
from glob import glob
package_name = 'topics_quiz'
setup(
name=package_name,
version='0.0.0',
packages=[package_name],
data_files=[
('share/ament_index/resource_index/packages',
['resource/' + package_name]),
('share/' + package_name, ['package.xml']),
(os.path.join('share', package_name), glob('launch/*.launch.py'))
],
install_requires=['setuptools'],
zip_safe=True,
maintainer='somebody very awesome',
maintainer_email='user@user.com',
description='TODO: Package description',
license='TODO: License declaration',
tests_require=['pytest'],
entry_points={
'console_scripts': [
'topics_quiz_node = topics_quiz.topics_quiz_node:main'
],
},
)
Workspace Pic:
And this is when the program is run: