Section 2 ROS Basics 5 days Python

Hello everyone.

I am having a hard time on the Section 2 of Course Project of ROS Basics (Python).

I wanted to run my python script before creating a service server launch file. I always used rosrun package_name python_script_name to make it work.

But I seem to be missing something for this Section 2 because it doesn’t work.

Here is how my IDE looks like (no launch files because I am just at the begining and already in difficulty) :

image

A list of a few things that I did to make run correctly :

  • catkin_make and source devel/setup.bash once I edited my CMakeList.txt and package.xml
  • checked the rossrv list
    image
  • delete build and devel from the catkin_ws repertory and rm -rf build/ devel/ then catkin_make and source devel/setup.bash again

find_wall_service_server.py

#! /usr/bin/env python

import rospy
from geometry_msgs.msg import Twist
from sensor_msgs.msg import LaserScan
from wall_follow.srv import FindWall, FindWallResponse

def get_min_value(ranges):
    ranges
    min_val = ranges[0]
    min_val_idx = 0
    for i in range(len(ranges)):
        if ranges[i] < min_val:
            min_val = ranges[i]
            min_val_idx = i
    
    return min_val, min_val_idx
    
def subscriber_callback(msg):
    global readings 
    readings = msg

def service_callback(request):
    global readings
    rospy.loginfo('The service move_nearest_wall has been called')
    
    min_val, min_val_idx = get_min_value(readings.ranges)

    front_value = round(readings.ranges[360], 3)
    right_value = round(readings.ranges[270], 3)
    print(min_val, min_val_idx, front_value, right_value)
    
    rospy.loginfo('Looking for the closest wall...')

    while not (min_val_idx <= 362 and min_val_idx >= 358):
        # print("Rotating to face the wall")
        move2wall.linear.x = 0.0
        move2wall.angular.z = 0.1
        _, min_val_idx = get_min_value(readings.ranges)
        # print("updated", min_val_idx)
        my_pub.publish(move2wall)
        rate.sleep()
    
    rospy.loginfo('Approaching to the closest wall...')

    while (front_value > 0.25):
        # print("Approaching the wall", front_value)
        move2wall.linear.x = 0.05
        move2wall.angular.z = 0.0
        front_value = round(readings.ranges[360], 3)
        my_pub.publish(move2wall)
        rate.sleep()

    rospy.loginfo('Turning to follow the wall...')

    while not (min_val_idx <= 181 and min_val_idx >= 179):
        # print("Turning to follow the wall")
        move2wall.linear.x = 0.0
        move2wall.angular.z = 0.1
        _, min_val_idx = get_min_value(readings.ranges)
        # print("updated right_value", min_val_idx)
        my_pub.publish(move2wall)
        rate.sleep()

    rospy.loginfo('Ready to follow the wall')
    move2wall.linear.x = 0.0
    move2wall.angular.z = 0.0
    my_pub.publish(move2wall)
    rate.sleep()

    result = FindWallResponse()
    result.wallfound = True
    return result

rospy.init_node('service_find_wall')
my_sub = rospy.Subscriber('/scan', LaserScan, subscriber_callback)
nearest_wall_service = rospy.Service('/find_wall', FindWall, service_callback)
my_pub = rospy.Publisher('/cmd_vel', Twist, queue_size=1)
rate = rospy.Rate(10)

move2wall = Twist()
readings = LaserScan()

rospy.spin()

CMakeLists.txt

cmake_minimum_required(VERSION 3.0.2)

project(wall_follow)

## Compile as C++11, supported in ROS Kinetic and newer

# add_compile_options(-std=c++11)

## Find catkin macros and libraries

## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)

## is used, also find other catkin packages

find_package(catkin REQUIRED COMPONENTS

rospy

)

## System dependencies are found with CMake's conventions

# find_package(Boost REQUIRED COMPONENTS system)

## Uncomment this if the package has a setup.py. This macro ensures

## modules and global scripts declared therein get installed

## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html

# catkin_python_setup()

################################################

## Declare ROS messages, services and actions ##

################################################

## To declare and build messages, services or actions from within this

## package, follow these steps:

## * Let MSG_DEP_SET be the set of packages whose message types you use in

## your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...).

## * In the file package.xml:

## * add a build_depend tag for "message_generation"

## * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET

## * If MSG_DEP_SET isn't empty the following dependency has been pulled in

## but can be declared for certainty nonetheless:

## * add a exec_depend tag for "message_runtime"

## * In this file (CMakeLists.txt):

## * add "message_generation" and every package in MSG_DEP_SET to

## find_package(catkin REQUIRED COMPONENTS ...)

## * add "message_runtime" and every package in MSG_DEP_SET to

## catkin_package(CATKIN_DEPENDS ...)

## * uncomment the add_*_files sections below as needed

## and list every .msg/.srv/.action file to be processed

## * uncomment the generate_messages entry below

## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...)

## Generate messages in the 'msg' folder

# add_message_files(

# FILES

# Message1.msg

# Message2.msg

# )

## Generate services in the 'srv' folder

# add_service_files(

# FILES

# Service1.srv

# Service2.srv

# )

## Generate actions in the 'action' folder

# add_action_files(

# FILES

# Action1.action

# Action2.action

# )

## Generate added messages and services with any dependencies listed here

# generate_messages(

# DEPENDENCIES

# std_msgs # Or other packages containing msgs

# )

################################################

## Declare ROS dynamic reconfigure parameters ##

################################################

## To declare and build dynamic reconfigure parameters within this

## package, follow these steps:

## * In the file package.xml:

## * add a build_depend and a exec_depend tag for "dynamic_reconfigure"

## * In this file (CMakeLists.txt):

## * add "dynamic_reconfigure" to

## find_package(catkin REQUIRED COMPONENTS ...)

## * uncomment the "generate_dynamic_reconfigure_options" section below

## and list every .cfg file to be processed

## Generate dynamic reconfigure parameters in the 'cfg' folder

# generate_dynamic_reconfigure_options(

# cfg/DynReconf1.cfg

# cfg/DynReconf2.cfg

# )

###################################

## catkin specific configuration ##

###################################

## The catkin_package macro generates cmake config files for your package

## Declare things to be passed to dependent projects

## INCLUDE_DIRS: uncomment this if your package contains header files

## LIBRARIES: libraries you create in this project that dependent projects also need

## CATKIN_DEPENDS: catkin_packages dependent projects also need

## DEPENDS: system dependencies of this project that dependent projects also need

catkin_package(

# INCLUDE_DIRS include

# LIBRARIES services_quiz

# CATKIN_DEPENDS rospy

# DEPENDS system_lib

)

###########

## Build ##

###########

## Specify additional locations of header files

## Your package locations should be listed before other locations

include_directories(

# include

${catkin_INCLUDE_DIRS}

)

## Declare a C++ library

# add_library(${PROJECT_NAME}

# src/${PROJECT_NAME}/services_quiz.cpp

# )

## Add cmake target dependencies of the library

## as an example, code may need to be generated before libraries

## either from message generation or dynamic reconfigure

# add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})

## Declare a C++ executable

## With catkin_make all packages are built within a single CMake context

## The recommended prefix ensures that target names across packages don't collide

# add_executable(${PROJECT_NAME}_node src/services_quiz_node.cpp)

## Rename C++ executable without prefix

## The above recommended prefix causes long target names, the following renames the

## target back to the shorter version for ease of user use

## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node"

# set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "")

## Add cmake target dependencies of the executable

## same as for the library above

# add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})

## Specify libraries to link a library or executable target against

# target_link_libraries(${PROJECT_NAME}_node

# ${catkin_LIBRARIES}

# )

#############

## Install ##

#############

# all install targets should use catkin DESTINATION variables

# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html

## Mark executable scripts (Python etc.) for installation

## in contrast to setup.py, you can choose the destination

# catkin_install_python(PROGRAMS

# scripts/my_python_script

# DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}

# )

## Mark executables for installation

## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_executables.html

# install(TARGETS ${PROJECT_NAME}_node

# RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}

# )

## Mark libraries for installation

## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_libraries.html

# install(TARGETS ${PROJECT_NAME}

# ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}

# LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}

# RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION}

# )

## Mark cpp header files for installation

# install(DIRECTORY include/${PROJECT_NAME}/

# DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}

# FILES_MATCHING PATTERN "*.h"

# PATTERN ".svn" EXCLUDE

# )

## Mark other files for installation (e.g. launch and bag files, etc.)

# install(FILES

# # myfile1

# # myfile2

# DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}

# )

#############

## Testing ##

#############

## Add gtest based cpp test target and link libraries

# catkin_add_gtest(${PROJECT_NAME}-test test/test_services_quiz.cpp)

# if(TARGET ${PROJECT_NAME}-test)

# target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME})

# endif()

## Add folders to be run by python nosetests

# catkin_add_nosetests(test)

package.xml

<?xml version="1.0"?>
<package format="2">
  <name>wall_follow</name>
  <version>0.0.0</version>
  <description>The wall_follow package</description>

  <!-- One maintainer tag required, multiple allowed, one person per tag -->
  <!-- Example:  -->
  <!-- <maintainer email="jane.doe@example.com">Jane Doe</maintainer> -->
  <maintainer email="user@todo.todo">user</maintainer>


  <!-- One license tag required, multiple allowed, one license per tag -->
  <!-- Commonly used license strings: -->
  <!--   BSD, MIT, Boost Software License, GPLv2, GPLv3, LGPLv2.1, LGPLv3 -->
  <license>TODO</license>


  <!-- Url tags are optional, but multiple are allowed, one per tag -->
  <!-- Optional attribute type can be: website, bugtracker, or repository -->
  <!-- Example: -->
  <!-- <url type="website">http://wiki.ros.org/services_quiz</url> -->


  <!-- Author tags are optional, multiple are allowed, one per tag -->
  <!-- Authors do not have to be maintainers, but could be -->
  <!-- Example: -->
  <!-- <author email="jane.doe@example.com">Jane Doe</author> -->


  <!-- The *depend tags are used to specify dependencies -->
  <!-- Dependencies can be catkin packages or system dependencies -->
  <!-- Examples: -->
  <!-- Use depend as a shortcut for packages that are both build and exec dependencies -->
  <!--   <depend>roscpp</depend> -->
  <!--   Note that this is equivalent to the following: -->
  <!--   <build_depend>roscpp</build_depend> -->
  <!--   <exec_depend>roscpp</exec_depend> -->
  <!-- Use build_depend for packages you need at compile time: -->
  <!--   <build_depend>message_generation</build_depend> -->
  <!-- Use build_export_depend for packages you need in order to build against this package: -->
  <!--   <build_export_depend>message_generation</build_export_depend> -->
  <!-- Use buildtool_depend for build tool packages: -->
  <!--   <buildtool_depend>catkin</buildtool_depend> -->
  <!-- Use exec_depend for packages you need at runtime: -->
  <!--   <exec_depend>message_runtime</exec_depend> -->
  <!-- Use test_depend for packages you need only for testing: -->
  <!--   <test_depend>gtest</test_depend> -->
  <!-- Use doc_depend for packages you need only for building documentation: -->
  <!--   <doc_depend>doxygen</doc_depend> -->
  <buildtool_depend>catkin</buildtool_depend>
  <build_depend>rospy</build_depend>
  <build_export_depend>rospy</build_export_depend>
  <exec_depend>rospy</exec_depend>


  <!-- The export tag contains other, unspecified, tags -->
  <export>
    <!-- Other tools can request additional information be placed here -->

  </export>
</package>

I repeated what I did for the services_quiz of the Unit 6, so I don’t quite really understand why I have this error message !

Big thanks for anyone who is willing to help !

Hi @valerietran1,

could it be that you compiled using catkin build instead of catkin_make?

If that is the case, I would recommend you remove the devel and build folders and compile again using catkin_make.

Example:

cd ~/catkin_ws

rm -rf devel build 

catkin_make 

source devel/setup.bash

rosrun wall_follow find_wall_service_server.py

Hello @ralves,

That is not the case, I did compile using catkin_make.
But I still tried it again, it is not working as it should be.

Thanks for the response.

This is truly weird. As far as I can see, you have done everything required, but the error indicates that it could not find the package!

You can try something else to make the system detect your package. In a new web shell, try:

cd ~/catkin_ws
source devel/setup.bash

# see if your package is detected and listed
rospack profile 

# try rosrun again
rosrun...

Hello @bayodesegun,

Indeed, I don’t see my package in

rospack profile

It has never happened to me before !

I see.

It would help if you went over the package creation steps and carefully recreated the package.

I would also recommend removing the build/ and devel/` folder as recommended by @ralves, before compiling again.

Yes I tried again, and the error is still here.
I went back and copy/paste my python script from the section 1, and it worked : the scripts ran.
But when I went back to the python script for the section 2, error.
And I tested multiples scripts.

I guess I won’t to the Course Project, its not a big deal, I’m just disappointed !

Wait…

I’m confused about something. By “course project”, do you mean the Real Robot Project (the rosject you copied after the topics quiz)?

If you are interested in getting a certificate for the course, you need to complete the project. Besides, it’s a good way to try out the knowledge gained in the course.

Some more hints:

  • copy/paste can result in subtle errors like these. When dealing with problematic cases, it’s better to create the package from scratch and modify every file by hand to be sure.
  • Again, are section 1 and section 2 sharing the same catkin_ws workspace? Are they in the rosject or the course?

If you are talking about a unit of the course, it’s good to have too, but not as important as the Real Robot Project.

Hello,

I am talking about the ROS Basics in 5 Days Real Robot Project, it’s what you call 'the Real Robot Project".

Reminder : My problem was this error message, I am actually at the section 2 :

So it tells me that the module “wall_follow” is not recognized.

I know that it should not be the case, so I tested the command with an another python script to see the result :

rosrun find_wall find_wall_service_server.py

I used the wall following python script asked for the section 1 :

#! /usr/bin/env python

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

regions = {
‘right’: 0,
‘front’: 0,
‘left’: 0
}

def callback(msg):

#Regions

regions = {
    'right': msg.ranges[179],
    'front': msg.ranges[360],
    'left': msg.ranges[539]
}

print(regions)


if regions['front'] < 0.5:
    print("Turn fast to left")
    move.linear.x = 0.05
    move.angular.z = 0.5
    ray_angle = msg.angle_min + (regions['front'] * msg.angle_max)

elif regions['right'] > 0.3:
    print("Find the wall")
    move.linear.x = 0.1
    move.angular.z = -0.1
    ray_angle = msg.angle_min + (regions['right'] * msg.angle_max)

elif regions['right'] < 0.2:
    print("Move away from the wall")
    move.linear.x = 0.05
    move.angular.z = 0.05
    ray_angle = msg.angle_min + (regions['right'] * msg.angle_max)

elif regions['right'] > 0.2 and regions['right'] < 0.3:
    print("Follow the wall")
    move.linear.x = 0.1
    move.angular.z = 0
    move_angle = msg.angle_min + (regions['right'] * msg.angle_max)

elif regions['left'] < 0.3:
    print("Move away from obstacle")
    move.linear.x = 0.0
    move.angular.z = -0.1
    move_angle = msg.angle_min + (regions['left'] * msg.angle_max)

else:
    print("Stop")
    move.linear.x = 0
    move.angular.z = 0

rospy.init_node(‘scan_values’)
sub = rospy.Subscriber(‘/scan’, LaserScan, callback)
pub = rospy.Publisher(‘/cmd_vel’, Twist, queue_size=1)
rate = rospy.Rate(2)

move = Twist()

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

Result :

So this command works and the python script is executable :

rosrun find_wall find_wall_service_server.py

Now that I know this, I went back to the python script for the section 2, I need to create a service server that will make the robot to the nearest wall.
I replace in the script my new script :

#! /usr/bin/env python

import rospy
from geometry_msgs.msg import Twist
from sensor_msgs.msg import LaserScan
from wall_follow.srv import FindWall, FindWallResponse

def get_min_value(ranges):
ranges
min_val = ranges[0]
min_val_idx = 0
for i in range(len(ranges)):
if ranges[i] < min_val:
min_val = ranges[i]
min_val_idx = i

return min_val, min_val_idx

def subscriber_callback(msg):
global readings
readings = msg

def service_callback(request):
global readings
rospy.loginfo(‘The service move_nearest_wall has been called’)

min_val, min_val_idx = get_min_value(readings.ranges)

front_value = round(readings.ranges[360], 3)
right_value = round(readings.ranges[270], 3)
print(min_val, min_val_idx, front_value, right_value)

rospy.loginfo('Looking for the closest wall...')

while not (min_val_idx <= 362 and min_val_idx >= 358):
    # print("Rotating to face the wall")
    move2wall.linear.x = 0.0
    move2wall.angular.z = 0.1
    _, min_val_idx = get_min_value(readings.ranges)
    # print("updated", min_val_idx)
    my_pub.publish(move2wall)
    rate.sleep()

rospy.loginfo('Approaching to the closest wall...')

while (front_value > 0.25):
    # print("Approaching the wall", front_value)
    move2wall.linear.x = 0.05
    move2wall.angular.z = 0.0
    front_value = round(readings.ranges[360], 3)
    my_pub.publish(move2wall)
    rate.sleep()

rospy.loginfo('Turning to follow the wall...')

while not (min_val_idx <= 181 and min_val_idx >= 179):
    # print("Turning to follow the wall")
    move2wall.linear.x = 0.0
    move2wall.angular.z = 0.1
    _, min_val_idx = get_min_value(readings.ranges)
    # print("updated right_value", min_val_idx)
    my_pub.publish(move2wall)
    rate.sleep()

rospy.loginfo('Ready to follow the wall')
move2wall.linear.x = 0.0
move2wall.angular.z = 0.0
my_pub.publish(move2wall)
rate.sleep()

result = FindWallResponse()
result.wallfound = True
return result

rospy.init_node(‘service_find_wall’)
my_sub = rospy.Subscriber(‘/scan’, LaserScan, subscriber_callback)
nearest_wall_service = rospy.Service(‘/find_wall’, FindWall, service_callback)
my_pub = rospy.Publisher(‘/cmd_vel’, Twist, queue_size=1)
rate = rospy.Rate(10)

move2wall = Twist()
readings = LaserScan()

rospy.spin()

And obviously with the srv repertory etc etc…
Tried to make the command run again :

Error !
As I said before, I already recompiled, did catkin_make multiples time, delete the build and devel…
I created the package from scratch at least 20 times, modify by hand.
And yes as you can see they are sharing the same catkin_ws. I am not skilled enough to use 2 differents catkin_ws

.

I’m not interested in certification, I just want to finish the project. But honestly I tried everything I could so I don’t see what I can do more.

From this image, I get the impression that you have the packages wall_follow and find_wall inside two different src folders inside catkin_ws.

This might be the catch here because the system recognized one, and could not find the other.

Please ensure all your packages are created inside one catkin_ws/src, preferably the src folder whose package is already recognized.


Other things:

  • Are wall_follow and find_wall supposed to be different packages in the project, or are you just mixing the names?
    • If they are supposed to be different packages, I expect to see them both in your directory structure:
      • catkin_ws/src/wall_follow
      • catkin_ws/src/find_wall

OK, I think I understand what you mean !
I indeed created two different packages, if I remember well, the first one was wall_follow and the second one was my second attempt with find_wall.
Now I deleted everything I could to start from scratch by hand, this time with my only package find_wall, so now I should not mix the names again.

Test first the first script :

It works.

Test with the second script :

Error, even though I used the same command… the only thing that changed is the code

Thanks for the detailed explanation; things are getting clearer now.

Same package, different scripts. The bit that’s causing the error in this case is your import:

from find_wall.srv import FindWall, FindWallResponse

The error is a Python module error, and does not mean the package does not exist.

My diagnosis here is that the FindWall custom service message has not been properly set up and built. If you run source ~/catkin_ws/devel/setup.bash on the same shell, run the same script again and it fails, this diagnosis is confirmed.

When the custom message is properly built, it would create a Python module that would support that import. Please review the steps for creating that custom message and try again.

This topic was automatically closed 5 days after the last reply. New replies are no longer allowed.