I'm currently attempting the Topics quiz. I'm so close but I'm stuck!

I’ve reached a point at which the robot can both move and tell me how far away the wall is from it, but I think I’ve done it in a way such that I cannot alter the movement of the robot in response to its distance from the wall.

I’m not sure whether the publisher and the subscriber should be in the same program: I could only get one to work at a time at a time when they were in the same script (whichever appeared first).

I got around this by creating separate scripts for each. This solved my original problem, but created two more problems:

  1. I cannot work out how to communicate the laser readings from one script to the other (which is frustrating because isn’t that the whole point of topics?!)

  2. In the launch file, I had to create a separate launch tag for the second script, which required a new node to be created: this is against the rules of the quiz, which suggested that only one node should be created/referenced.

Here is my code: (Package name: Topics_quiz)

#LAUNCH FILE

<!-- My Package launch file -->

<node pkg="topics_quiz" type="my_script_2.py" name="topics_quiz_node_2"  output="screen">

</node>

<node pkg="topics_quiz" type="my_script.py" name="topics_quiz_node"  output="screen">

</node>

#MY_SCRIPT.PY

#! /usr/bin/env python

import rospy
from sensor_msgs.msg import LaserScan
from geometry_msgs.msg import Twist

rospy.init_node(“topics_quiz_node”)

def callback(msg):
global Distance
Distance=float(msg.ranges[360])
print(Distance)

sub = rospy.Subscriber(’/kobuki/laser/scan’, LaserScan, callback)
rospy.spin()

#MY_SCRIPT_2.PY

#! /usr/bin/env python

import rospy
from sensor_msgs.msg import LaserScan
from geometry_msgs.msg import Twist

rospy.init_node(“topics_quiz_node”)

pub = rospy.Publisher(’/cmd_vel’, Twist, queue_size=1)
rate = rospy.Rate(2)
var = Twist()
var.linear.x=(0.5)
var.angular.z=(0)

while not rospy.is_shutdown():
pub.publish(var)
rate.sleep()

Thank you for your help!

Hello @benradick,

After looking at both your script, I could see that the script2 where you are publishing the velocity has no connection with the distance left from the wall (as you haven’t subscribed to the laser topic in the particular script.)

I would suggest you to include the subscriber and the publisher in one script(will make life much easier ,lol). Subscriber to robot’s Laser in front, left end and right end as the ranges[360] will only help the robot to read the distance in front but when the robot turns, either of it’s end would be closer to wall, ranges[0] or ranges[720]. Read the distance information from here too and change the angular.z (turning the robot left or right) accordingly. I am sure, you will be able to solve it.

1 Like

Thanks for your response! When I put the publisher and the subscriber in the same script, I cannot get both to work at the same time. e.g.

#! /usr/bin/env python

import rospy
from sensor_msgs.msg import LaserScan
from geometry_msgs.msg import Twist

rospy.init_node(“topics_quiz_node”)

def callback(msg):
global Distance
Distance=float(msg.ranges[360])
print(Distance)

sub = rospy.Subscriber(’/kobuki/laser/scan’, LaserScan, callback)
rospy.spin()

pub = rospy.Publisher(’/cmd_vel’, Twist, queue_size=1)
rate = rospy.Rate(2)
var = Twist()
var.linear.x=(0.5)
var.angular.z=(0)

while not rospy.is_shutdown():
pub.publish(var)
rate.sleep()

When I run this code, the script returns the laser readings, but the robot does not move forward. Similarly, if the subscriber is placed first, the robot moves forwards but does not return laser readings. How can I get both to happen simultaneously?

Put your logic and publishing into the callback. Something like so:

#! /usr/bin/env python

import rospy
from sensor_msgs.msg import LaserScan
from geometry_msgs.msg import Twist

rospy.init_node(“topics_quiz_node”)
var = Twist()
pub = rospy.Publisher(’/cmd_vel’, Twist, queue_size=1)

def callback(msg):
    Distance=float(msg.ranges[360])
    print(Distance)
   #add some logic based on distance here
    var.linear.x=(0.5)
    var.angular.z=(0)
    pub.publish(var)

sub = rospy.Subscriber(’/kobuki/laser/scan’, LaserScan, callback)
rospy.spin()
1 Like

Ahhhhhhhhhhhhhhhhhhhhhhh.
I think I get it.

Does the rospy.spin() at the end repeat the whole code starting from the rospy.init_node line?

No, read about rospy.spin() here: