How to get the obstacle information from lidar – English ROS Tutorial

How to get the obstacle information from lidar – English ROS Tutorial

What you are going to learn:

  1. How to get the obstacle information from lidar
  2. Create a package for TurtleBot 3 to stop when an obstacle is detected

Introduction

In this tutorial, we’ll explore how to leverage Lidar data to implement a simple yet effective wall-avoidance mechanism for a robot, specifically the TurtleBot 3. By understanding the ‘ranges’ array from the laser scans, we can program our robot to make informed decisions and navigate around obstacles.

 If you want to learn ROS 2 Python in a practical, hands-on way, check out the course ROS 2 Basics in 5 Days: https://app.theconstruct.ai/courses/132

In this course, you’ll cover the foundational concepts needed to start working with ROS 2, as well as more advanced topics, all while engaging in hands-on practice.

Understanding LiDAR Data:

The Lidar sensor provides an array of values, with the middle values representing distances directly in front of the robot. Visualize the laser’s scope as approximately 180 degrees from right to left. Values at the array’s start and end correspond to side readings (left and right), while those in the middle relate to front readings. This spatial arrangement is crucial for determining the presence of a wall in the robot’s path.

Opening the rosject

In order to follow this tutorial, we need to have ROS 2 installed in our system, and ideally a ros2_ws (ROS2 Workspace). To make your life easier, we have already prepared a rosject for that: https://app.theconstruct.ai/l/639b9a55/

Just by copying the rosject (clicking the link above), you will have a setup already prepared for you.

After the rosject has been successfully copied to your own area, you should see a Run button. Just click that button to launch the rosject.

After pressing the Run button, you should have the rosject loaded. Now, let’s head to the next section to get some real practice.

In order to interact with ROS2, we need a terminal.

Let’s open a terminal by clicking the Open a new terminal button.

Open a new Terminal

If we want to see data being published on /scan topic , we just have to write
rostopic echo /scan

So for our application, we need the value of the array at the middle (index no 360).

Create a package for obstacle avoidance using lidar

Copy the rosject from the link attached at the starting of a tutorial as it already has TurtleBot package in it and write the below commands in web shell
cd simulation_ws/src
catkin_create_pkg lidardata std_msgs rospy cd lidardata
mkdir launch mkdir src
cd launch
touch lidardata.launch cd ..
cd src
touch myscript.py chmod +x myscript.py cd
cd simulation_ws catkin_make

Logic of code

Let’s dive into the logic of our Python code. The goal is simple: if the distance directly in front of the robot is greater than 0.5 meters, it will continue moving forward; otherwise, it stops to avoid a collision.
#! /usr/bin/env python
#Importing all the required Libraries and messages import rospy
from geometry_msgs.msg import Twist
from sensor_msgs.msg import LaserScan
# Create a Twist message to control robot movement
move_robot = Twist()

move_robot.linear.x = 0.5
move_robot.angular.z = 0
#Defining a call back function for the Subcriber. def callback(msg):
#Publish the movement command Pub1.publish(move_robot)
# Check distance directly in front of the robot (at the middle if(msg.ranges[360] > 0.5):
# If the distance is greater than 0.5 meters, move forward move_robot.linear.x = 0.1
move_robot.angular.z = 0.0
elif(msg.ranges[360] < 0.5):
# If the distance is less than 0.5 meters, stop to avoid collis move_robot.linear.x = 0.0
move_robot.angular.z = 0.0
# Initialize the ROS node rospy.init_node('lidar_data_node')
# Set up the robot movement publisher
Pub1 = rospy.Publisher('/cmd_vel',Twist,queue_size = 1)
# Set up the Lidar data subscriber
Sub1 = rospy.Subscriber('/scan',LaserScan,callback)
# Keep the node running and processing Lidar data rospy.spin()

Now we have created a node named ‘lidar_data_node’ which subscribes to topic ‘/scan’ and publishes velocity data to ‘/cmd_vel’.

graph TD
lidar_data_node --> /cmd_vel
/scan --> lidar_data_node

To launch this node let’s create a launch file.
<launch>
<!-- My Package launch file -->
<node pkg="lidardata" type="my_script.py" name="lidar_data_
</node>
</launch>

Test the package

  1. To spawn turtle bot at origin in gazabo
    roslaunch realrobotlab main.launch

2. To launch lidar data.launch

roslaunch lidardata lidardata.launch

You can now see that TurtleBot moves from its origin in a straight line up until the distance in front of it is less than 0.5 m.

Congratulations. You now have a basic understanding of parameters and are familiar with creating and using services.

To learn more about ROS 2, have a look at the course below:

We hope this tutorial was really helpful to you.

This tutorial is created by Robotics Ambassador Raunak.

Rosbotics Ambassador Program https://www.theconstruct.ai/rosbotics-ambassador/)

 

Video Tutorial

How to dynamically spawn objects in Gazebo Simulation using Python – English ROS Tutorial

How to dynamically spawn objects in Gazebo Simulation using Python – English ROS Tutorial

What are we going to Learn?

  1. How to create ROS2 Package
  2. How to compile ROS2 workspace
  3. How to create node in Python to spawn new object in Gazebo Simulation


Overview:

ROS (Robot Operating System) is a de facto standard for Robotics. In order to program Robots, simulation of Real world systems is very important to test and debug the systems. For simulations of Robotics systems, Gazebo is used commonly in ROS. In this post we will learn how to add new objects in simulation scene without terminating the simulation entirely.

In general, if we want to add new object in simulation scene, we have to terminate all running nodes in simulation, edit the World file (description file for simulation in Gazebo). In order to add new objects, without terminating nodes, we can use Gazebo API in Python to spawn new objects in simulation dynamically.

If you want to learn ROS 2 Python in a practical, hands-on way, check out the course ROS 2 Basics in 5 Days: https://app.theconstruct.ai/courses/132

In this course, you’ll cover the foundational concepts needed to start working with ROS 2, as well as more advanced topics, all while engaging in hands-on practice.

 

Opening the ROSJect:

To follow along the post, we need to have ROS2 installed in our system. To make things easier, we have created ROSJect to follow along: https://app.theconstructsim.com/rosjects/741580

Just open the ROSJect in your browser

Click on “FORK”

Next, Click on “RUN”

Open the new Web Shell

 

Go to the ROS2 Workspace

cd ros2_ws

Then, source the workspace

source install/setup.bash

In one web shell, run Gazebo

gazebo –verbose -s libgazebo_ros_factory.so

In another web shell, run the ROS2 Node

ros2 run robot_spawner_pkg spawn_turtlebot the_robot_name robot_namespace 0.0 0.0 0.1

Congratulations. You have now learned how to spawn objects in Gazebo Simulation using Python.

To learn more about ROS 2, have a look at the course below:

We hope this tutorial was really helpful to you.

This tutorial is created by Robotics Ambassador Muhammad.

Video Tutorial

How to use C++ and Python in the same ROS 2 package –  English ROS 2 Tutorial

How to use C++ and Python in the same ROS 2 package – English ROS 2 Tutorial

What we are going to learn:

  1. How to set up the package architecture to accommodate C++ and Python in the same package
  2. How to configure this package (by modifying package.xml and CMakeLists.txt)
  3. How to compile and run Python and C++ nodes from this package

If you want to learn ROS 2 Python in a practical, hands-on way, check out the course
ROS 2 Basics in 5 Days: https://app.theconstruct.ai/courses/132

In this course, you’ll cover the foundational concepts needed to start working with ROS 2, as well as more advanced topics, all while engaging in hands-on practice.

Opening the rosject

In order to follow this tutorial, we need to have ROS2 installed in our system, and ideally a ros2_ws (ROS2 Workspace). To make your life easier, we have already prepared a rosject for that: https://app.theconstructsim.com/l/5e01d324/

Just by copying the rosject (clicking the link above), you will have a setup already prepared for you.

After the rosject has been successfully copied to your own area, you should see a Run button. Just click that button to launch the rosject ( see this example).

After pressing the Run button, you should have the rosject loaded. Now, let’s head to the next section to get some real practice.

In order to interact with ROS2, we need a terminal.

Let’s open a terminal by clicking the Open a new terminal button.

Open a new Terminal

 

Setup the package architecture

Create a standard C++ package


With dependencies on rclpy and rclcpp:

With dependencies on rclpy:

cd ~/ros2_ws/src/
ros2 pkg create cpp_py_pkg –build-type ament_cmake –dependencies rclpy rclcpp

Run the “tree . command to see the folder structure. If you don’t have the command installed, you can install it using:

sudo apt-get update
sudo apt-get install -y tree

You should be able to see this structure which you are already familiar with:

cpp_py_pkg/
├── CMakeLists.txt
├── include
│ └── cpp_py_pkg
├── package.xml
└── src

Add a C++ node and header

cd cpp_py_pkg/
touch src/cpp_node.cpp
touch include/cpp_py_pkg/cpp_header.hpp

In order to compile the package later, we need at least a main function in the C++ node. For this tutorial for simplicity, we can just add this minimal code to the cpp_node.cpp file:

#include “rclcpp/rclcpp.hpp”
// Include your header file to use it
#include “cpp_py_pkg/cpp_header.hpp”
int main(int argc, char **argv)
{
// Initiate ROS communications
    rclcpp::init(argc, argv);
// Instantiate the node
    auto node = std::make_shared<rclcpp::Node>(“my_node_name”);
// Make the node spin
    rclcpp::spin(node);
// Shutdown ROS communications
    rclcpp::shutdown();
    return 0;
}


Add a Python node and module to import

For Python, we need to create additional folders first:

mkdir cpp_py_pkg
touch cpp_py_pkg/__init__.py
mkdir scripts

Then we can add the files:

touch cpp_py_pkg/module_to_import.py
touch scripts/py_node.py


You have to add a shebang line first thing in the py_node.py file otherwise you will get an error when trying to run the node:

#!/usr/bin/env python3
import rclpy
from rclpy.node import Node
# Import a specific function/class from your module
# from cpp_py_pkg.module_to_import import …
def main(args=None):
# Initiate ROS communications
    rclpy.init(args=args)
# Instantiate the node
    node = Node(‘my_node_name’)
# Make the node spin
    rclpy.spin(node)
# Shutdown ROS communications
    rclpy.shutdown()
if __name__ == ‘__main__’:
    main()

 

Final package architecture

Run the “tree . command to see the folder structure. I have added additional comments and files to make it clearer:

cpp_py_pkg/
# –> package info, configuration, and compilation
├── CMakeLists.txt
├── package.xml
# Python stuff
# –> empty init file & any python library or module files we want to import
├── cpp_py_pkg
│ ├── __init__.py
│ └── module_to_import.py
│ └── another_module_to_import.py
# –> python executables/nodes
├── scripts
│ └── py_node.py
# Cpp stuff
# –> cpp header files
├── include
│ └── cpp_py_pkg
│ └── cpp_header.hpp
│ └── another_cpp_header.hpp
# –> cpp executables/nodes
└── src
└── cpp_node.cpp

The CMakeLists.txt and package.xml will be shared by Python and C++, which is what we will edit in the next section to configure the package for both Python and C++.

Configure the package

package.xml


Add a buildtool_depend tag for ament_cmake_python:

<buildtool_depend>ament_cmake_python</buildtool_depend>

So your package.xml should look like this:

<?xml version=”1.0″?>
<?xml-model href=”http://download.ros.org/schema/package_format3.xsd” schematypens=”http://www.w3.org/2001/XMLSchema”?>
<package format=”3″>
<name>cpp_py_pkg</name>
<version>0.0.0</version>
<description>TODO: Package description</description>
<maintainer email=”user@todo.todo”>user</maintainer>
<license>TODO: License declaration</license>

<buildtool_depend>ament_cmake</buildtool_depend>
<buildtool_depend>ament_cmake_python</buildtool_depend>

<depend>rclpy</depend>
<depend>rclcpp</depend>

<test_depend>ament_lint_auto</test_depend>
<test_depend>ament_lint_common</test_depend>

<export>
<build_type>ament_cmake</build_type>
</export>
</package>

cd ~/ros2_ws/
colcon build –packages-select py_pkg

 

CMakeLists.txt

Add this external dependency:

find_package(ament_cmake_python REQUIRED)

Add this for C++:

# Include Cpp “include” directory
include_directories(include)

# Create Cpp executable and link with dependencies
add_executable(cpp_executable src/cpp_node.cpp)
ament_target_dependencies(cpp_executable rclcpp)

# Install Cpp executables in the ros2_ws/install/cpp_py_pkg/lib/cpp_py_pkg/ folder
install(TARGETS
cpp_executable
DESTINATION lib/${PROJECT_NAME}
)

Add this for Python:

# Install Python modules
ament_python_install_package(${PROJECT_NAME})

# Install Python executables in the ros2_ws/install/cpp_py_pkg/lib/cpp_py_pkg/ folder
install(PROGRAMS
scripts/py_node.py
DESTINATION lib/${PROJECT_NAME}
)

So your CMakeLists.txt should look like this:

source ~/.bashrc # . ~/.bashrc

So your CMakeLists.txt should look like this:

cmake_minimum_required(VERSION 3.8)
project(cpp_py_pkg)

if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES “Clang”)
add_compile_options(-Wall -Wextra -Wpedantic)
endif()

# find dependencies
find_package(ament_cmake REQUIRED)
find_package(rclpy REQUIRED)
find_package(rclcpp REQUIRED)
find_package(ament_cmake_python REQUIRED)

# Include Cpp “include” directory
include_directories(include)

# Create Cpp executable and link with dependencies
add_executable(cpp_executable src/cpp_node.cpp)
ament_target_dependencies(cpp_executable rclcpp)

# Install Cpp executables in the ros2_ws/install/cpp_py_pkg/lib/cpp_py_pkg/ folder
install(TARGETS
cpp_executable
DESTINATION lib/${PROJECT_NAME}
)

# Install Python modules
ament_python_install_package(${PROJECT_NAME})

# Install Python executables in the ros2_ws/install/cpp_py_pkg/lib/cpp_py_pkg/ folder
install(PROGRAMS
scripts/py_node.py
DESTINATION lib/${PROJECT_NAME}
)

if(BUILD_TESTING)
find_package(ament_lint_auto REQUIRED)
# the following line skips the linter which checks for copyrights
# comment the line when a copyright and license is added to all source files
set(ament_cmake_copyright_FOUND TRUE)
# the following line skips cpplint (only works in a git repo)
# comment the line when this package is in a git repo and when
# a copyright and license is added to all source files
set(ament_cmake_cpplint_FOUND TRUE)
ament_lint_auto_find_test_dependencies()
endif()

ament_package()

Compile package, then run C++ node and Python node

cd ~/ros2_ws/
colcon build –packages-select cpp_py_pkg

Source ROS2 environment and start C++ node in one terminal:

source ~/ros2_ws/install/setup.bash
ros2 run cpp_py_pkg cpp_executable

Source ROS2 environment and start Python node in another terminal:

source ~/ros2_ws/install/setup.bash
ros2 run cpp_py_pkg py_node.py

That’s it! If there are no errors when you run the nodes then it means that it was successful (remember that our nodes do not do anything except spin).

Congratulations. You now know how to use C++ and Python in the same ROS 2 package.

To learn more about ROS 2, have a look at the course below:

We hope this post was really helpful to you.

This tutorial is created by Robotics Ambassador Ernest.

Video Tutorial

How to import custom Python3 modules in a ROS 2 package

How to import custom Python3 modules in a ROS 2 package

What we are going to learn:

  1. How to set up the package architecture to have custom Python modules inside the ROS2 package
  2. How to configure setup.py so that the modules can be imported
  3. How to import modules and use them in a Python node script

 

If you want to learn ROS 2 Python in a practical, hands-on way, check out the course ROS 2 Basics in 5 Days: https://app.theconstruct.ai/courses/132

In this course, you’ll cover the foundational concepts needed to start working with ROS 2, as well as more advanced topics, all while engaging in hands-on practice.

Opening the rosject

In order to follow this tutorial, we need to have ROS2 installed in our system, and ideally a ros2_ws (ROS2 Workspace). To make your life easier, we have already prepared a rosject for that: https://app.theconstructsim.com/l/5e6f9418/

Just by copying the rosject (clicking the link above), you will have a setup already prepared for you.

After the rosject has been successfully copied to your own area, you should see a Run button. Just click that button to launch the rosject ( see this example).

After pressing the Run button, you should have the rosject loaded. Now, let’s head to the next section to get some real practice.

In order to interact with ROS2, we need a terminal.

Let’s open a terminal by clicking the Open a new terminal button.

Open a new Terminal

 

Setup the package architecture

Create a standard ROS2 package using ament_python

With dependencies on rclpy:

cd ~/ros2_ws/src/
ros2 pkg create py_pkg –build-type ament_python –dependencies rclpy

Run the “tree . command to see the folder structure. If you don’t have the command installed, you can install it using:

sudo apt-get update
sudo apt-get install -y tree

You should be able to see this structure which you are already familiar with:

`– py_pkg
|– package.xml
|– py_pkg
| `– __init__.py
|– resource
| `– py_pkg
|– setup.cfg
|– setup.py
`– test
|– test_copyright.py
|– test_flake8.py
`– test_pep257.py

Add custom Python module(s) that you want to import

You will need to add module files under the directory with the same name as the package (in this case py_pkg):

cd py_pkg/py_pkg
touch module_to_import.py

For this tutorial for simplicity, we can just add this minimal function to the module_to_import.py file that just prints hello world:

def function_to_import():
print(“hello world”)


Create a scripts directory for your Python node(s)

Specify the directory as a Python package by creating an empty__init__.pyfile (essential for the folder to be recognized by Python as a package), then add a Python node:

cd ..
mkdir scripts
touch scripts/__init__.py
touch scripts/py_node.py
Here is a simple node implementation (to paste in py_node.py) that imports and uses the function from the module we just created:
import rclpy
from rclpy.node import Node
# Import a specific function/class from your module
from py_pkg.module_to_import import function_to_import
class MyPythonNode(Node):
    def __init__(self):
        super().__init__(“my_node_name”)
# Run the imported function
        function_to_import()
def main(args=None):
    # Initiate ROS communications
    rclpy.init(args=args)
    # Instantiate the node
    node = MyPythonNode()
    # Make the node spin
    rclpy.spin(node)
    # Destroy the node object
    node.destroy_node()
    # Shutdown ROS communications
    rclpy.shutdown()
if __name__ == ‘__main__’:
    main()

Final package architecture

Run the “tree. command to see the folder structure inside py_pkg:

|– package.xml
|– py_pkg
| |– __init__.py
| `– module_to_import.py
|– resource
| `– py_pkg
|– scripts
| |– __init__.py
| `– py_node.py
|– setup.cfg
|– setup.py
`– test
|– test_copyright.py
|– test_flake8.py
`– test_pep257.py

Configure the package and test

Modify setup.py

  1. Add scripts to the list of Python packages:

packages=[package_name, ‘scripts’],

This is so that later when you build with colcon, ROS2 knows to put the Python packages here ~/<workspace_name>/install/<package_name>/lib/<python_version>/site-packages/<package_name> (in our case <workspace_name> is ros2_ws, <python_version> ispython3.10, and <package_name> is py_pkg).

2. State the entry point:

entry_points={
‘console_scripts’: [
‘py_node_executable = scripts.py_node:main’
],

So your setup.py should look like this:

from setuptools import setup

package_name = ‘py_pkg’

setup(
name=package_name,
version=’0.0.0′,
packages=[package_name, ‘scripts’],
data_files=[
(‘share/ament_index/resource_index/packages’,
[‘resource/’ + package_name]),
(‘share/’ + package_name, [‘package.xml’]),
],
install_requires=[‘setuptools’],
zip_safe=True,
maintainer=’user’,
maintainer_email=’user@todo.todo’,
description=’TODO: Package description’,
license=’TODO: License declaration’,
tests_require=[‘pytest’],
entry_points={
‘console_scripts’: [
‘py_node_executable = scripts.py_node:main’
],
},
)

Compile the Package

cd ~/ros2_ws/
colcon build –packages-select py_pkg

There is a good chance that you will get a SetuptoolsDeprecationWarning:

Starting >>> py_pkg
— stderr: py_pkg
/usr/lib/python3/dist-packages/setuptools/command/install.py:34: SetuptoolsDeprecationWarning: setup.py install is deprecated. Use build and pip and other standards-based tools.
warnings.warn(

Finished <<< py_pkg [1.88s]

Summary: 1 package finished [2.21s]
1 package had stderr output: py_pkg

If there is no warning then that’s great, but don’t worry if you get it as it is just a warning (not an error) and you will still be able to build successfully.

As of the time of writing this tutorial, the developers hope to have it fixed for Jazzy in May 2024, but for now, there are workarounds to remove the warning. The original workaround was to downgrade the version of setuptools that is currently installed by doing pip install setuptools==58.2.0 in the terminal. However, that is not recommended. Instead you should use the PYTHONWARNINGS environment variable to suppress that particular warning by adding this to the ~/.bashrc file:

PYTHONWARNINGS=”ignore:setup.py install is deprecated::setuptools.command.install”; export PYTHONWARNINGS

You could do this by entering this into the terminal:

echo “PYTHONWARNINGS=\”ignore:setup.py install is deprecated::setuptools.command.install\”; export PYTHONWARNINGS” >> ~/.bashrc

Don’t forget to source the .bashrc in the terminal before compiling the package to register the changes:

source ~/.bashrc # . ~/.bashrc

You should now be able to compile the package without the warning.

cd ~/ros2_ws/
colcon build –packages-select py_pkg

Run the node

In the terminal, source the ROS2 environment and start the Python node:

source ~/ros2_ws/install/setup.bash
ros2 run py_pkg py_node_executable

If you get the following output, that means it was successful!

hello world

Congratulations. You now know how to import custom Python3 modules in a ROS 2 package.

To learn more about ROS 2, have a look at the course below:

We hope this post was really helpful to you.

This tutorial is created by Robotics Ambassador Ernest.

Video Tutorial

Pin It on Pinterest