Activity: Follow Me

DTC Summer Bootcamp (Day 1)

This is our first activity on the MBot! We will implement a Bang-Bang controller to get the robot to follow the nearest object.


Prerequisites

Grab a robot with a fully charged battery. Before you begin, you will need to have followed these guides on your laptop:


Getting the Code

We will use GitHub Classroom to get the code. Use the link below to accept the assignment.

Once you have accepted the assignment, clone the repository you created on the robot. In a VSCode remote session connected to the robot (tutorial), open a new terminal. Then, type:

git clone <ADDRESS>

Substitute <ADDRESS> with the address for your repo, found on GitHub. You can get the address from your repo page on GitHub:

Open the folder of the repository you just cloned in VSCode by cliking "File" > "Open Folder…" then typing in the name of the repo you cloned:


Code Overview

The code you just cloned has some template files to help you get started. Details on how to compile the code and the code layout are below.

Compiling the Code

We’ll use a tool called CMake to compile the code. CMake finds all the code and external libraries we need and generates instructions to build the executable. To build the code, in a terminal, type:

cd ~/[my-code-dir]/build
cmake ..
make

Remember that the code should be cloned and compiled on the Raspberry Pi. This will fail on your computer! You should replace [my-code-dir] with the name of your Follow Me directoy.

You only need to run cmake .. once. When you start writing code, you can compile it by typing make in the build/ folder. (Calling CMake multiple times won’t hurt, though!)

Running the Code

When you run make successfully, it will generate two executables: follow_1D is the 1D Follow Me code from the file src/follow_1D.cpp, and follow_2D is the 2D Follow Me code from the file src/follow_2D.cpp.

Run them from the command line, in the build/ folder, to test your code for the 1D or 2D follow me:

./follow_1D
./follow_2D

Provided Functions

  • void drive(float vx, float vy, float wz): Send a velocity command to the motors. The velocity command has x and y components in meters per second (vx and vy) and an angular component in radians per second (wz).
    Warning: Once drive is called, the robot will continue to drive at the given speed until you tell it to stop! Use drive(0, 0, 0) to stop the robot.
  • void getLidarScan(std::vector<float>& ranges, std::vector<float>& thetas): Read the most recent Lidar scan and put the resulting ranges in the ranges vector, and angles in the thetas vector.
    Warning: Some rays in the scan never return (for example, if there are no obstacles, or the ray bounces off a material and goes in a different direction). If the ray does not return, its range will be zero. Make sure you check for rays with zero range and ignore them.

Follow Me Activity

We will write code to make the robot follow the nearest object. We will implement a 1D version which follows the object in front of it, and a 2D version that follows the nearest object in any direction.

1D Follow Me

We will write a program to make the robot maintain a fixed distance from the object in front of it. Edit the file src/follow_1D.cpp to implement a Bang-Bang controller.

  • Edit the file src/follow_1D.cpp to implement a Bang-Bang controller. Commit and push your changes to GitHub.
  • Hint: Use the drive(vx, vy, wz) function to move the robot.

2D Follow Me

For this part of the activity, you will be editing src/follow_2D.cpp. First, you will need to write the function findMinDist(). This function should take in a vector of Lidar range values, and return the index of the shortest ray in the scan. Invalid rays will have zero range. You should ignore any zeros when finding the shortest range.

  • Edit the function findMinDist() in the file src/follow_2D.cpp to return the index of the shortest ray.
  • Hint: Remember to ignore rays with zero range when finding the minimum range value. Rays with zero range are invalid. If you forget to check for invalid rays, the minimum range will always be zero.

Next, edit src/follow_2D.cpp to maintain a setpoint distance to the nearest wall in any direction. You will use the function findMinDist() to get the distance and angle to the nearest object. This is done for you in the code:

// Get the distance to the wall.
float min_idx = findMinDist(ranges);
float dist_to_wall = ranges[min_idx];
float angle_to_wall = thetas[min_idx];

The variable dist_to_wall will then contain the distance to the nearest wall, and angle_to_wall will contain the angle to the wall. Your drive commands will now be in the direction of the nearest wall instead of just forward.

  • Edit the main function in file src/follow_2D.cpp to implement a Bang-Bang controller again, but this time maintaining the distance to the nearest wall.