Getting Started with C++ for Robotics Projects

Let’s learn how to compile and run C++ code.

Prerequisites

ROS 2 C++ Style Guide

Before we get started, it is important to note that we will be following the ROS 2 C++ Style Guide throughout this tutorial and future tutorials where we use C++. This guide is based on the Google C++ Style Guide:

  • 2 spaces for indents
  • 100 characters max per line
  • Header files should use the .hpp extension
  • Implementation files should use the .cpp extension
  • snake_case for variable names
  • Function naming can use either CamelCase or snake_case
  • CamelCase for class names

Adhering to these guidelines will help make sure your code is consistent with ROS 2 projects in the community that use C++.

Create a Folder to Store Your C++ Code

Let’s start by creating a folder to store our C++ code. Open a terminal window, and type:

mkdir -p ~/Documents/cpp_tutorial
cd ~/Documents/cpp_tutorial

Open and Configure Visual Studio Code (Recommended)

For those of you who will be using Visual Studio Code for your C++ development, type this:

code .

To compile and run C++ code in Visual Studio Code, we need to check if we have a C++ compiler installed. A compiler translates your code into a format that can be run on your computer.

Search for “C++” and install the “C/C++” package by Microsoft.

1-cpp-extension

Go to Terminal -> New Terminal, and write this command:

gcc -v
2-gcc-terminal

We can see that we have the GNU Compiler Collection already installed.

If GCC is not installed, type these commands to install it:

sudo apt-get update
sudo apt-get install build-essential gdb

To clear the terminal, type:

clear

Creating Your First C++ Program

Create a new file by clicking on File > New File in the menu. You can also go to the File Explorer pane on the left and click the new file icon.

3-new-file-button

Save the file with a meaningful name and the “.cpp” extension, for example, “hello_world.cpp“.

Let’s write a basic C++ program that prints a message related to robotics.

Type the following code into the editor:

#include <iostream>

int main() {
    std::cout << "Hello, Automatic Addison!" << std::endl;
    return 0;
}

Press CTRL + S to save the file, or go to File -> Save. 

This code includes the iostream library, which allows us to use std::cout for printing to the console. The main() function is the entry point of the program, and it prints the message “Hello, Automatic Addison!” followed by a new line (std::endl).

You can now run your C++ code directly from the editor. 

Press the play button at the top-right corner of the editor.

4-press-play

Choose g++ build and debug active file from the list of detected compilers on your system.

5-gpp-build-debug

This is the first and only time you will be asked to select a compiler for your C++ code. This compiler will be set as the default compiler in the tasks.json file.

When you run the code, you will see this output on the Terminal tab.

6-output

The long string with “/usr/bin/gdb” is debugging-related output that you can ignore – it’s just VS Code’s debugger working in the background.

Now click on the file explorer on the left and open the tasks.json file. When you press the play button, it will read from tasks.json to determine how to build and run your C++ program.

Here is what your tasks.json file should look like:

{
  "tasks": [
    {
      "type": "cppbuild",
      "label": "C/C++: g++ build active file",
      "command": "/usr/bin/g++",
      "args": [
        "-fdiagnostics-color=always",
        "-g",
        "${file}",
        "-o",
        "${fileDirname}/${fileBasenameNoExtension}"
      ],
      "options": {
        "cwd": "${fileDirname}"
      },
      "problemMatcher": [
        "$gcc"
      ],
      "group": {
        "kind": "build",
        "isDefault": true
      },
      "detail": "Task generated by Debugger."
    }
  ],
  "version": "2.0.0"
}

To make life easier for us for all the code we will run, let’s install Code Runner. It has some settings that let you quickly run C++ code.

First go to Extensions.

Click the Extensions icon in the left sidebar (looks like 4 squares).

Type “Code Runner” in the search box.

Look for “Code Runner” by Jun Han (it should be the first result).

Click “Install”

After installation, we need to set it up.

Click “File” in the top menu

Click “Preferences”

Click “Settings”

Type “settings” in the settings search box.

Click “Edit settings.json” to open the settings.json file.

7-settings-json

Add these settings at the bottom just above the closing curly bracket:

8-just-above-curly-bracket

Go back to your hello_world.cpp file.

Right-click anywhere in your code.

Select Run Code from the menu.

9-run-code

Code Runner will automatically compile and run your code.

Click the OUTPUT tab, and you should see this:

Alternatively, you can run the code manually by typing this into the terminal.

./hello_world
11-run-manually

We could have also compiled and ran the code manually:

cd ~/Documents/cpp_tutorial
g++ hello_world.cpp -o hello_world 
./hello_world 

Demonstrating Commenting Techniques

Let’s explore the importance of commenting in C++ programming, especially in the context of robotics. Commenting is an important practice that enhances code readability, maintainability, and collaboration.  Comments help other developers, including your future self, understand your code’s purpose, functionality, and any important considerations.

Create a new file and save it with a meaningful name, such as robot_commenting.cpp.

Let’s consider a simple example that calculates the distance traveled by a robot.

Type the following code into the editor:

#include <iostream>

int main() {
    // Declare and initialize variables
    double speed = 0.5;    // Speed of the robot in meters per second
    double time = 10.0;    // Time traveled in seconds
    
    /* Calculate the distance traveled
       distance = speed * time
    */
    double distance = speed * time;
    
    // Print the result
    std::cout << "The robot traveled " << distance << " meters." << std::endl;
    
    return 0;
}

In this code, we’ve used two types of comments:

  1. Single-line comments: These start with // and extend until the end of the line. They’re used for brief explanations or notes, such as describing variables or providing short insights.
  2. Multi-line comments: These start with /* and end with */. They can span multiple lines and are useful for more detailed explanations or temporarily disabling code blocks. Here, we’ve used a multi-line comment to explain the distance calculation formula.

Now, let’s run this code and see the output. 

12-robot-traveled-5-meters

You should see the message “The robot traveled 5 meters.” printed in the terminal.

That’s it for getting started with C++. Stay tuned for more C++ tutorials.

Keep building!

How to Work with Python Databases & Other Advanced Features

In this tutorial, we are going to learn how to use Python databases and other advanced features.

Prerequisites

Connecting to a Database

Managing database connections is important for logging sensor data, storing robot configurations, or even tracking operational data in real-time robotics applications.

Create a new file called database_connection.py inside the following folder: ~/Documents/python_tutorial.

We’ll use sqlite3, which is a built-in Python library that allows you to interact with SQLite databases. This makes it a good choice for demonstration purposes and smaller projects.

import sqlite3

def create_connection(db_file):
    """ Create a database connection to the SQLite database specified by db_file """
    conn = None
    try:
        conn = sqlite3.connect(db_file)
        print("SQLite database version:", sqlite3.sqlite_version)
    except sqlite3.Error as e:
        print(e)
    finally:
        if conn:
            conn.close()

if __name__ == "__main__":
    create_connection("example.db")

This script attempts to connect to an SQLite database specified by the filename. If example.db doesn’t exist, SQLite will create it automatically when we try to connect. The connection is closed immediately after being opened to ensure there are no loose ends.

Let’s run this script to test our database connection.

1-database-connections

You should see the SQLite database version printed, indicating that the connection was successfully established. If there’s an error, it will be printed instead.

Working with Recursive Functions

Let’s dive into recursive functions—a technique that can help you solve problems that involve nested structures or repetitive tasks.

We’ll demonstrate recursion with a robotics-related example: navigating a robot hierarchy. 

Let’s say we have a robot structure where each robot can have multiple sub-robots. Our task is to calculate the total number of all robots and sub-robots within this hierarchy.
Create a file named recursive_robotics.py inside the following folder: ~/Documents/python_tutorial.

class Robot:
    def __init__(self, name):
        self.name = name
        self.sub_robots = []

    def add_sub_robot(self, sub_robot):
        self.sub_robots.append(sub_robot)

def count_robots(robot):
    """ Return the total count of robots in the hierarchy using recursion """
    total = 1  # Start with the current robot
    for sub_robot in robot.sub_robots:
        total += count_robots(sub_robot)  # Recursive call for each sub-robot
    return total

Here, we define a Robot class with a method to add sub-robots. The count_robots function starts counting with the current robot, then recursively counts each sub-robot in the sub_robots list.

Let’s create a robot hierarchy to test our recursive function:

root_robot = Robot("Root")
child_robot1 = Robot("Child1")
child_robot2 = Robot("Child2")
sub_child_robot1 = Robot("SubChild1")

root_robot.add_sub_robot(child_robot1)
root_robot.add_sub_robot(child_robot2)
child_robot1.add_sub_robot(sub_child_robot1)

print("Total number of robots:", count_robots(root_robot))

Run the script.

2-recursive-robotics

You will see the total count of robots in the hierarchy, which includes the root robot, its children, and sub-children.

Working with Modules

Let’s explore how to work with modules in Python—a fundamental concept that allows you to organize your code better, making it more readable, maintainable, and reusable. For robotics engineers, using modules can help structure control systems, sensor integration, and interaction logic into separate components.

Create a new file called robot_modules.py inside the following folder: ~/Documents/python_tutorial.

Save it.

Now let’s create a module that we’ll use as a utility for our robotic operations. This module will include functions to calculate the area of different shapes which could, for example, be useful in path planning or space management in robotics applications.

Create another file in the same directory named geometry.py and type in the following code:

def rectangle_area(length, width):
    return length * width

def circle_area(radius):
    from math import pi
    return pi * radius ** 2

Now, in your robot_modules.py file, let’s write this code:

import geometry

def main():
    rect_area = geometry.rectangle_area(5, 3)
    circ_area = geometry.circle_area(7)
    print(f"Area of the rectangle: {rect_area}")
    print(f"Area of the circle: {circ_area}")

if __name__ == "__main__":
    main()

Here, we have imported the geometry module, which contains our area calculation functions. We can now use these functions in our main program to calculate the area of a rectangle and a circle.

Let’s run our script to see modules in action. 

3-robot-modules

You will see the areas of the rectangle and circle printed out, showcasing how our main program can use functions defined in another module.

Creating a GUI

Let’s learn how to create a graphical user interface, or GUI, using Python. This skill is helpful when you need to create an interface for interacting with robots, such as controlling movements or monitoring sensor data.

Create a new file called robot_gui.py inside the following folder: ~/Documents/python_tutorial.

We’ll use tkinter, the standard GUI library for Python, to create a basic interface. It’s included with Python, so you don’t need to install anything extra.

import tkinter as tk
from tkinter import simpledialog

def main():
    root = tk.Tk()
    root.title("Robot Control Panel")

    def handle_command():
        response = simpledialog.askstring("Input", "Enter a command for the robot:")
        print(f"Command received: {response}")

    command_button = tk.Button(root, text="Send Command", command=handle_command)
    command_button.pack(pady=20)

    exit_button = tk.Button(root, text="Exit", command=root.destroy)
    exit_button.pack(pady=20)

    root.mainloop()

if __name__ == "__main__":
    main()

In this script, we create a basic window with a button. When clicked, this button prompts the user to enter a command, which could hypothetically be sent to a robot. The mainloop() method keeps the window open and waits for user interaction.

Now, run the script.

4-tkinter-gui
5-enter-a-command

A window titled “Robot Control Panel” should appear with a button labeled “Send Command”. Clicking the button will open a dialog box asking for a command input.

Click Exit when you are finished.

And there you have it—a basic GUI for controlling a robot using Python and tkinter.

This concludes the Python for Robotics course. Thank you for following along.

Keep building!

How to Use Python Multithreading and Regular Expressions

In this tutorial, we are going to learn how to use threads in Python  to perform multiple tasks simultaneously.

Prerequisites

Understanding Threads

Create a file called threading_example.py inside the following folder: ~/Documents/python_tutorial.

Now write the following code:

import threading
import time

def robot_task(name, duration):
    print(f"{name} starting task.")
    time.sleep(duration)
    print(f"{name} has completed its task.")

# Creating threads
thread1 = threading.Thread(target=robot_task, args=("Robot 1", 2))
thread2 = threading.Thread(target=robot_task, args=("Robot 2", 3))

Here, we define a simple function robot_task that simulates a task by sleeping for a specified duration. Then, we create two threads, each assigned to execute this function.

Let’s complete the threading example by starting the threads and waiting for them to finish:

thread1.start()
thread2.start()

# Wait for both threads to complete
thread1.join()
thread2.join()

print("Both robots have completed their tasks.")

Now, run the script.

1-threading-example

You should see output indicating that both robots are starting and completing their tasks, potentially overlapping in time, showing how threads allow simultaneous task execution.

Working with Regular Expressions

Let’s check out an indispensable tool for processing text data effectively—regular expressions, often abbreviated as regex.

Understanding how to use regular expressions will help you handle complex string manipulation tasks, which can be particularly useful in robotics for parsing logs, sensor data, or commands.

Create a new file named regex_examples.py inside the following folder: ~/Documents/python_tutorial.

First, we need to import the re module, which is Python’s library for handling regular expressions:

import re

Let’s define a function to demonstrate a basic regex operation—finding dates within a string. Imagine we’re processing a log file and we want to extract date entries formatted as dd-mm-yyyy.

def find_dates(text):
    pattern = r'\b\d{2}-\d{2}-\d{4}\b'
    dates = re.findall(pattern, text)
    return dates

This function uses the re.findall() method, which searches through the text and returns all non-overlapping matches of the pattern described. Here, our pattern \b\d{2}-\d{2}-\d{4}\b looks for sequences that match the date format.

Let’s add a test case to use our function:

log_entry = "Error reported on 23-10-2023 at node 3. Previous error was on 01-10-2023."
found_dates = find_dates(log_entry)
print("Dates found:", found_dates)

Now, run the script.

2-regex-examples

You should see the output displaying the dates extracted from the string. This illustrates how regular expressions can simplify the task of searching and extracting data from text.

And that’s it for regular expressions. 

Thanks, and I’ll see you in the next tutorial.

Keep building!