ROS navigation stack drives the robot by publishing velocity commands to /cmd_vel topic using geometry/Twist messages. The base controller on the Teensy board receives the twist messages through rosserial_python and translates the velocites to motor commands. A PID controller maintains the robot’s speed by calculating how much PWM signal must be generated to spin each motor based from the total error over time. Errors are derived by comparing the actual motor’s speed to the desired speed sent by navigation stack.
This section will show you how to tune the PID controller with lino_pid, wire up the components, and upload the base controller’s code on the Teensy board.
2.1 Building the hardware
Before wiring up the components, build a base made up of wood plank, acrylic sheet or any material that you can mount the electronics, motors and wheels. Some ideas for your robot base:
Storage box from Ikea. (Photo by Ikea)
Plastic enclosure box. You can easily find this on hardwares.
Tin storage box. (More metallic look)
Once you have a base, wire up the components as shown below (2.1.2).
2.1.1 Parts List
1 x XV-11 Lidar with Controller or any supported 2D lidar.
1 x Ubuntu Installed laptop/desktop (Development Computer)
1 x Radxa Rock Pro (Robot’s computer) or any supported dev boards
1 x Teensy 3.1 Board or latest.
1 x GY-85 IMU
2 x L298 Beakout Board or any motor driver that has PWM (EN) and input pins (IN1 and IN2)
1 x Breadboard or Prototyping Board
1 x 12V Battery (Preferably 3S Li-Po Battery)
1 x Caster Wheels (only for 2WD)
2 x Robot Wheels (only for 2WD)
4 x Robot Wheels (only for 4wD)
4 x Mecanum Wheels (only for Mecanum Drive)
1 x Servo (only for Ackermann Steering)
1 x Robot Chassis
2.1.2 Wire up
The hardware is designed to be modular and scalable in the future. All the platforms are built using a L298N motor driver (2 Amperes) and motors with built-in encoders. If your robot requires a much higher motor rating or higher encoder resolution, you can opt for components with better specification and use the same pin assignments as below without rewriting the firmware.
Not all motors have built-in encoders especially high torque motors. Shall you need to use an external encoder, you can use a bi-shaft motor to leave the spare shaft for the encoder or use a pulley to drive both the wheels and the encoder.
A photo of a bi-shaft motor connected on a wheel (left side) and a wheel encoder (right side).
Motor with built-in encoder
If you’re replacing the motor driver with a higher specification, make sure the motor’s power draw is less than the motor driver’s power rating. You can use the same firmware and follow the same pin assignments below as long as your new motor driver has PWM, IN1, and IN2 pins. Below is an example how to choose an alternative for your motor driver. The photo on the right (VNH5019 driver) has a continuous current rating of 12A and the same pinout as L298N breakout board.
4WD and Mecanum Drive Hardware
Ackermann Steering Hardware
2.2 Uploading the Arduino codes
2.2.1 Define robot’s specifications
Before uploading the codes, identify and define your robot’s specification on the config file.
On your robot’s computer, open and edit the config.h:
and change the values of the variables accordingly (*You don’t need to define k_p, k_i, and k_i for now).
Make sure to define variable DEBUG as 1 for debugging later.
The firmware is configured to work on L298 motor driver. Uncomment BTS7960_DRIVER and comment out L298_DRIVER if you are using a BTS7960 motor driver.
If you are unsure what is the encoder’s PPR (COUNTS_PER_REV) – you can check the encoder’s total count from bringup.launch’s terminal (see 2.3.1). Get the recent count and rotate the wheel 360 degrees:
PPR = abs(RECENT_COUNT – INITIAL_COUNT)
If you have the encoder and motor’s specification:
PPR = MOTOR_GEAR_RATIO * ENCODER_RES
2.2.2 Upload the codes
The first time you upload your codes using platformio, it will prompt if you want to install the framework (ie. ‘teensy’) you are using. Press ‘y’ to proceed with the installation. Once the framework is installed, plug in the Teensy board to the robot’s computer and upload the codes:
2.3 Running the robot
2.3.1 Drive the robot
Now check if the wheels’ direction is correct. Lift the robot off the ground so the wheels can move freely.
If you’re building a mecanum drive robot take note of the roller’s orientation below:
On your robot’s computer, run the launch file to start ROS and rosserial_python:
On your development computer, run teleop_twist_keyboard:
Follow the instructions on the terminal to move the robot.
For the Ackermann steering robot, the angular velocity is translated to steering angle since it can’t rotate in-place. Check if the front wheels steer left and right when you press ‘j’ and ‘l’ respectively.
2.3.2 Check the encoder readings
Next, check if the encoder readings are correct from the terminal where you ran bringup.launch. All encoder readings must increase as you drive forward, and decrease as you drive in reverse.
If the wheel’s direction is wrong as you drive forward or reverse, swap the pin assignments for MOTOR*_IN_A and MOTOR_IN_B in the config file found in section 2.1.1.
If the encoder returns opposite results, swap the pin assignments for MOTOR*_ENCODER_A and MOTOR_ENCODER_B in the config file found in section 2.1.1
If the front wheels on the Ackermann robot are steering in the opposite direction, swap the operators in steer() function’s “if” conditions.
2.4 Calibrating PID
In order to maintain the speed sent by navigation stack, your PID controller has to be tuned properly. You can use lino_pid to tune your PID constants.
On your robot’s computer, open 2 new terminal windows:
On your development computer, open 2 new terminal windows:
Once the dashboard is open, import the .perspective file by clicking Perspective > Import and choose lino_pid.perspective from lino_pid package: ~/catkin_ws/src/lino_pid/lino_pid.perspective
Click pid_configure under Dynamic Reconfigure window and slide the parameters at the bottom right window to tune your PID constants. Drive the robot and see the results from the graph.
Here are some tips how to configure your PID constants(Page 13).
Once your PID constants are tuned, record the values and edit the config file:
and change the values of K_P, K_I, K_D to the PID values you have recorded.
Upload the updated PID constants to the Teensy board:
cd ~/catkin_ws/src/linorobot/arduino/firmware platformio run --target upload
Great! The robot base is done and ready for dead reckoning. Please proceed to odometry page.