Professional Documents
Culture Documents
Unti 5
Unti 5
• Technical requirements
• Fabrication of robot chassis and building complete structure
• Integrating various sensor modules and hardware setup
• Launchpad receive and send all sensor data values and control to PC
• Launchpad through serial port read and send sensor values
• Embedded C code, ROS python node, topics and subscriber
• SLAM and AMCL runs on PC to navigate robot
Building Chefbot hardware structure
• Configuration, setup, integrating all sensor modules
• Base plate, middle plate and upper plate setup and wheel
configuration
Fully assembled robot body
ChefBot PCB prototype
Fully assembled robot body
Configuring ChefBot PC and setting ChefBot
ROS packages
• NUC PC handles sensor data and processes it.
• Install Ubuntu 16.04 LTS, ROS,ROS packages
• Install ChefBOT packages on PC
• Clone ChefBot's software packages from GitHub using the following
command:
• $ git clone
https://github.com/qboticslabs/learning_robotics_2nd_ed
Contd..
• Clone this code in PC and copy the ChefBot folder to Intel's NUC PC.
• The ChefBot folder consists of the ROS packages of the ChefBot
hardware.
• In the NUC PC, create a ROS catkin workspace, copy the ChefBot
folder, and move it inside the src directory of the catkin workspace.
• Build and install the source code of ChefBot by simply using the
following command.
• This should be executed inside the catkin workspace we created:
• $ catkin_make
• If all dependencies are properly installed in the NUC, the ChefBot
packages will be build and installed
• Tiva-C Launchpad loaded with embedded C code
Interfacing ChefBot sensors to the Tiva-C
LaunchPad (sensor interconnection with Launchpad)
Embedded code for ChefBot
The following are the header files used in the code:
//Library to communicate with I2C devices
#include "Wire.h"
//I2C communication library for MPU6050
#include "I2Cdev.h"
//MPU6050 interfacing library
#include "MPU6050_6Axis_MotionApps20.h"
//Processing incoming serial data
#include <Messenger.h>
//Contain definition of maximum limits of various data type
#include <limits.h>
Contd..
we need to create an object to handle MPU6050 and process the
incoming serial data using the Messenger class:
• //Creating MPU6050 Object
• MPU6050 accelgyro(0x68);
• //Messenger object
• Messenger Messenger_Handler = Messenger();
Setup functions
• The main section deals with assigning pins for
the //Setup Ultrasonic
• motor driver, encoder, ultrasonic sensor, MPU SetupUltrasonic();
6050, reset, and battery pins. //Setup MPU 6050
• The definition of the setup() function is given in Setup_MPU6050();
the following code:
//Setup serial, encoders, ultrasonic, MPU6050 //Setup Reset pins
and Reset functions SetupReset();
Void setup() //Set up Messenger object handler
{ Messenger_Handler.attach(OnMssageCompleted);
//Init Serial port with 115200 baud rate }
Serial.begin(115200);
//Setup Encoders
SetupEncoders(); function contains a custom routine to configure and allocate pins for all
//Setup Motors of the sensors. This function will initialize serial communication with a
115,200 baud rate and set pins for the encoder, motor driver, ultrasonic
SetupMotors(); sensors, and MPU6050. The SetupReset() function will assign a pin to
reset the device,
The following is the main loop() function of the code. The main
purpose of this function is to read and process serial data, as well
as send available sensor values:
void loop() //Update motor speed values with
{ corresponding speed received from PC and
send speed values through serial port
//Read from Serial port
Read_From_Serial(); Update_Motors();
//Send time information through serial //Send MPU 6050 values through serial
port port
Update_Time(); Update_MPU6050();
//Send encoders values through serial //Send battery values through serial port
port
Update_Encoders(); Update_Battery();
//Send ultrasonic values through serial }
port //We can compile the code in Energia's IDE
Update_Ultra_Sonic(); and burn the code in LaunchPad.
Inertial navigation (IMU) –converts IMU
values to odometry data
IMU with Inertial Navigation system
MPU-6000/MPU-6050 - InvenSense
• The MPU-6000/MPU-6050 family of parts is the world's first and only
six-axis motion tracking devices designed for the low power, low cost,
and high-performance requirements of smartphones, tablets,
wearable sensors, and robotics.
• The MPU-6000/6050 devices combine a three-axis gyroscope and
three-axis accelerometer
• On the silicon die together with an onboard digital motion processor
capable of processing complex nine-axis motion fusion algorithms.
Interfacing code of Energia
#include "Wire.h" void Setup_MPU6050()
#include "I2Cdev.h" {
#include "MPU6050.h" Wire.begin();
MPU6050 accelgyro; // initialize device
void setup() Serial.println("Initializing I2C devices...");
{ accelgyro.initialize();
//Init Serial port with 115200 buad // verify connection
rate
Serial.begin(115200); Serial.println("Testing device connections...");
Setup_MPU6050(); Serial.println(accelgyro.testConnection() ?
"MPU6050 connection
} successful" : "MPU6050 connection failed");
}
void loop() • Output from MPU 6050 in the
{ Linux Terminal using Python
script
//Update MPU 6050
Update_MPU6050();
}
• The Update_MPU6050() custom
function is responsible for
printing the updated value from
MPU 6050
The definition of Update_MPU6050()
void Update_MPU6050() Serial.print(ay); Serial.print("t");
{ Serial.print(az); Serial.print("t");
int16_t ax, ay, az; Serial.print(gx); Serial.print("t");
int16_t gx, gy, gz; Serial.print(gy); Serial.print("t");
// read raw accel/gyro measurements Serial.println(gz);
from device Serial.print("n");
accelgyro.getMotion6(&ax, &ay, &az, }
&gx, &gy, &gz);
// display tab-separated accel/gyro x/y/z Output from serial Moitor
values
Serial.print("i");Serial.print("t");
Serial.print(ax); Serial.print("t");
Writing a ROS Python driver for ChefBot
• The serial data from LaunchPad #This python module helps to receive
is taken and convert it to ROS values from serial port which execute in
topics for further processing. a thread
• The launchpad_node.py ROS from SerialDataGateway import
Python driver node interfaces SerialDataGateway
Tiva-C LaunchPad with ROS. #Importing required ROS data types for
#ROS Python client the code
import rospy from std_msgs.msg import Int16,Int32,
Int64, Float32, String, Header, UInt64
import sys
#Importing ROS data type for IMU
import time
from sensor_msgs.msg import Imu
import math
custom module written to receive serial data from the LaunchPad
board in a thread. Also need some data types of ROS to handle the
sensor data.
if __name__ =='__main__': launchpad.Reset_Launchpad()
rospy.init_node('launchpad_ros',anony launchpad.Stop()
mous=True)
launchpad = Launchpad_Class()
try:
launchpad.Start()
rospy.spin()
except rospy.ROSInterruptException:
rospy.logwarn("Error in main function")
Retrieve the port and baud rate of the LaunchPad board from the ROS
parameters and initialize the SerialDataGateway object using these
parameters.
• #Get serial port and baud rate of Tiva C • #Initializing SerialDataGateway
Launchpad • object with serial port, baud
• port = rospy.get_param("~port", • rate and callback function to handle
"/dev/ttyACM0") incoming serial
• baudRate = • dataself._SerialDataGateway =
int(rospy.get_param("~baudRate", SerialDataGateway(port,
115200))
• baudRate, self._HandleReceivedLine)
• rospy.loginfo("Starting with serial port:
• rospy.loginfo("Started serial
• " + port + ", baud rate: " + communication")
str(baudRate))
Publisher ROS nodes
#Publisher for left and right wheel #Publisher for Battery level(for
encoder values upgrade purpose)
self._Left_Encoder = self._Battery_Level =
rospy.Publisher('lwheel',Int64,queue_si rospy.Publisher('battery_level',Flo
ze = 10) at32,queue_size = 10)
self._Right_Encoder = #Publisher for Ultrasonic distance
rospy.Publisher('rwheel',Int64,queue_s sensor
ize= 10) self._Ultrasonic_Value =
rospy.Publisher('ultrasonic_distan
ce',Float32,queue_size = 10)
Publisher ROS nodes contd..
• #Publisher for IMU rotation values #Publisher for entire serial data
• self._qx_ = self._SerialPublisher=rospy.Publisher('serial
rospy.Publisher('qx',Float32,queue_size ', String,queue_size=10)
= 10)
• self._qy_ =
rospy.Publisher('qy',Float32,queue_size
= 10)
• self._qz_ =
rospy.Publisher('qz',Float32,queue_size
= 10)
• self._qw_ =
rospy.Publisher('qw',Float32,queue_size
= 10)
Contd..
• Create the ROS publisher object for sensors such as the encoder, IMU, and
ultrasonic sensor, as well as for the entirety of the serial data for
debugging purposes
• Subscribe speed command for left and right wheel of the robot
• When a speed command arrives on the topic, it calls the respective
callbacks to send speed commands to the robot's LaunchPad:
self._left_motor_speed =
rospy.Subscriber('left_wheel_speed',Float32,self._Update_Left_Speed)
self._right_motor_speed =
rospy.Subscriber('right_wheel_speed',Float32,self._Update_Right_Speed)
Block diagram Robot ROS nodes
differential_drive package to be used
The purpose of each node in the ChefBot_bringup
package is as follows
• twist_to_motors.py:
• This node will convert a ROS Twist command or linear and
• angular velocity to an individual motor velocity target.
• The target velocities are published at a rate of the ~rate (measured in
Hertz) and the publish timeout_ticks time's velocity after the Twist
message stops.
• The following are the topics and parameters that will be published
and subscribed to by this node:
Publishing and subscribing Topics
• Publishing topics:
• lwheel_vtarget(std_msgs/Float32): This is the target velocity of the
left wheel (measured in m/s).
• rwheel_vtarget (std_msgs/Float32): This is the target velocity of the
right wheel (measured in m/s).
• Subscribing topics:
• Twist (geometry_msgs/Twist): This is the target Twist command for
the robot.
• The linear velocity in the x-direction and the angular velocity theta of
the Twist messages are used in this robot
ROS parameters
• Important ROS parameters:
• ~base_width (float, default: 0.1): This is the distance between the
robot's two wheels in meters.
• ~rate (int, default: 50): This is the rate at which the velocity target is
published (Hertz).
• ~timeout_ticks (int, default:2): This is the number of the velocity
target message published after stopping the Twist messages.
pid_velocity.py: ROS node
• This is a simple PID controller to control the speed of each motor by
taking feedback from the wheel encoders.
• In a differential drive system, we need one PID controller for each
wheel. It will read the encoder data from each wheel and control the
speed of each wheel.
• Publishing topics:
• motor_cmd (Float32): This is the final output of the PID controller
that goes to the motor.
• We can change the range of the PID output using the out_min and
out_max ROS parameter.
• wheel_vel (Float32): This is the current velocity of the robot wheel in
m/s.
Contd..
• Subscribing topics:
• wheel (Int16): This topic is the output of a rotary encoder. There are
individual topics for each encoder of the robot.
• wheel_vtarget (Float32): This is the target velocity in m/s.
• Important parameters:
• ~Kp (float, default: 10): This parameter is the proportional gain of the PID
controller.
• ~Ki (float, default: 10): This parameter is the integral gain of the PID
controller.
• ~Kd (float, default: 0.001): This parameter is the derivative gain of the PID
• controller.
• ~out_min (float, default: 255): This is the minimum limit of the velocity
value to the motor. This parameter limits the velocity's value to the motor
called the wheel_vel topic.
Contd..
• ~out_max (float, default: 255): This is the maximum limit of the
wheel_vel topic (measured in Hertz).
• ~rate (float, default: 20): This is the rate of publishing the wheel_vel
topic.
• ticks_meter (float, default: 20): This is the number of wheel encoder
ticks per meter. This is a global parameter because it's used in other
nodes too.
• vel_threshold (float, default: 0.001): If the robot velocity drops below
this parameter, we consider the wheel as stationary. If the velocity of
the wheel is less than vel_threshold, we consider it as zero.
• encoder_min (int, default: 32768): This is the minimum value of
encoder reading.
• encoder_max (int, default: 32768): This is the maximum value of
encoder reading.
Contd..