Getting started with ROS¶
The Robot Operating System (ROS) is a flexible framework for writing robot software. It is a collection of tools, libraries, and conventions that aim to simplify the task of creating complex and robust robot behavior across a wide variety of robotic platforms.
We have planned this competition around ROS because of its features as well as its widespread use in robotics research and industry.
To get started with ROS (if you are a beginner), we recommend you follow the “Beginner Level” tutorials in the official ROS Tutorials. Ensure you complete at least the following:
ROS OnRamp!¶
Whether you are a beginner or a more advanced ROS developer, we recommend you take some time to review the following ROS tutorials.
- ROS Official Tutorials - Ensure you complete at least chapters 5, 6, and 12.
- ROS Tutorial Youtube Playlist (Strongly recommended for beginners) - Alternatively, we recommend you cover at least parts 1-9. The content is excellent!
Note
Your overall learning experience in this competition is strongly dependent on how much of the fundamental concepts of ROS you can grasp early on. Hence, we strongly recommend that you put in the time to use these resources.
Writing your First ROS Package¶
After you complete the required tutorials listed above, you can start setting up the workspace.
Assuming the workspace at ~/catkin_ws/
as completed from the steps done in setting up your workspace,
This should be your folder structure till now.
~/catkin_ws/
├── build/
│ ├── .
│ └── .
├── devel/
│ ├── .
│ └── .
└── src/
├── CMakeLists.txt
└── parc-engineers-league/
├── parc_robot/
│ ├── .
│ ├── .
│ ├── CMakeLists.txt
│ └── package.xml
├── .
└── .
First step is to create your solution folder in ~/catkin_ws/src/
, we can call it parc_solutions
for example.
And here you can create a new ROS package called test_publisher
(for example) by running the command below,
Moving the Robot Programmatically¶
Setting up your workspace guide has already shown how to control the robot with keyboard using teleoperation
But this guide will help you to move the robot by publishing commands to /cmd_vel
topic programmically using Python, MATLAB and C++. In the competition, you would have to choose one of these languages/platforms to interact with ROS.
To do this, create a file, robot_publisher.py
inside scripts
folder in your ROS package (for example test_publisher
) and make it executable.
MATLAB Note
Ensure you have the MATLAB ROS Toolbox installed and configured. Also, ensure you add test_publisher/scripts/ to the MATLAB path. Instructions for this can be found in the MATLAB documentation.
Python Note
You need to change the permission of the file to executable to be able to run (as done in the last command shown above).
Now open the file and copy and paste the following code inside:
function robot_publisher()
% Script to move Robot
% Initialize ROS node
rosinit('localhost');
% Create a publisher which can "talk" to Robot and tell it to move
pub = rospublisher('/cmd_vel', 'geometry_msgs/Twist');
% Create a Twist message and add linear x and angular z values
move_cmd = rosmessage(pub);
% Set publish rate at 10 Hz
rate = rosrate(10);
%%%%%%%%%% Move Straight %%%%%%%%%%
disp("Moving Straight");
move_cmd.Linear.X = 0.3; % move in X axis at 0.3 m/s
move_cmd.Angular.Z = 0.0;
% For the next 3 seconds publish cmd_vel move commands
now = rostime('now');
while rostime('now') - now < rosduration(3)
send(pub, move_cmd); % publish to Robot
waitfor(rate);
end
%%%%%%%%%% Rotating Counterclockwise %%%%%%%%%%
disp("Rotating");
move_cmd.Linear.X = 0.0;
move_cmd.Angular.Z = 0.2; % rotate at 0.2 rad/sec
% For the next 3 seconds publish cmd_vel move commands
now = rostime('now');
while rostime('now') - now < rosduration(3)
send(pub, move_cmd); % publish to Robot
waitfor(rate);
end
%%%%%%%%%% Stop %%%%%%%%%%
disp("Stopping");
move_cmd.Linear.X = 0.0;
move_cmd.Angular.Z = 0.0; % Giving both zero will stop the robot
% For the next 1 seconds publish cmd_vel move commands
now = rostime('now');
while rostime('now') - now < rosduration(1)
send(pub, move_cmd); % publish to Robot
waitfor(rate);
end
disp("Exit");
% Shutdown ROS node
rosshutdown;
end
#!/usr/bin/env python
"""
Script to move Robot
"""
import rospy
from geometry_msgs.msg import Twist
import time
def move_robot():
rospy.init_node('robot_publisher', anonymous=True)
# Create a publisher which can "talk" to Robot and tell it to move
pub = rospy.Publisher('/cmd_vel', Twist, queue_size=10)
# Set publish rate at 10 Hz
rate = rospy.Rate(10)
# Create a Twist message and add linear x and angular z values
move_cmd = Twist()
######## Move Straight ########
print("Moving Straight")
move_cmd.linear.x = 0.3 # move in X axis at 0.3 m/s
move_cmd.angular.z = 0.0
now = time.time()
# For the next 3 seconds publish cmd_vel move commands
while time.time() - now < 3:
pub.publish(move_cmd) # publish to Robot
rate.sleep()
######## Rotating Counterclockwise ########
print("Rotating")
move_cmd.linear.x = 0.0
move_cmd.angular.z = 0.2 # rotate at 0.2 rad/sec
now = time.time()
# For the next 3 seconds publish cmd_vel move commands
while time.time() - now < 3:
pub.publish(move_cmd) # publish to Robot
rate.sleep()
######## Stop ########
print("Stopping")
move_cmd.linear.x = 0.0
move_cmd.angular.z = 0.0 # Giving both zero will stop the robot
now = time.time()
# For the next 1 seconds publish cmd_vel move commands
while time.time() - now < 1:
pub.publish(move_cmd) # publish to Robot
rate.sleep()
print("Exit")
if __name__ == '__main__':
try:
move_robot()
except rospy.ROSInterruptException:
pass
#include <ros/ros.h>
#include <geometry_msgs/Twist.h>
#include <ctime>
void move_robot()
{
ros::NodeHandle nh;
// Create a publisher which can "talk" to Robot and tell it to move
ros::Publisher pub = nh.advertise<geometry_msgs::Twist>("/cmd_vel", 10);
// Set publish rate at 10 Hz
ros::Rate rate(10);
// Create a Twist message and add linear x and angular z values
geometry_msgs::Twist move_cmd;
//////////// Move Straight ////////////
ROS_INFO("Moving Straight");
move_cmd.linear.x = 0.3; // move in X axis at 0.3 m/s
move_cmd.angular.z = 0.0;
time_t now = time(0);
// For the next 3 seconds publish cmd_vel move commands
while (time(0) - now < 3)
{
pub.publish(move_cmd); // publish to Robot
rate.sleep();
}
//////////// Rotating Counterclockwise ////////////
ROS_INFO("Rotating");
move_cmd.linear.x = 0.0;
move_cmd.angular.z = 0.2; // rotate at 0.2 rad/sec
now = time(0);
// For the next 3 seconds publish cmd_vel move commands
while (time(0) - now < 3)
{
pub.publish(move_cmd); // publish to Robot
rate.sleep();
}
//////////// Stop ////////////
ROS_INFO("Stopping");
move_cmd.linear.x = 0.0;
move_cmd.angular.z = 0.0; // Giving both zero will stop the robot
now = time(0);
// For the next 1 seconds publish cmd_vel move commands
while (time(0) - now < 1)
{
pub.publish(move_cmd); // publish to Robot
rate.sleep();
}
ROS_INFO("Exit");
}
int main(int argc, char **argv)
{
ros::init(argc, argv, "robot_publisher");
try
{
move_robot();
}
catch (ros::Exception &e)
{
ROS_ERROR("Exception encountered: %s", e.what());
return 1;
}
return 0;
}
This code will make the robot move straight for 4 seconds, rotate counterclockwise for 3 seconds and then stop.
Compile and Run¶
Note
For C++, we need to update the CMakeLists.txt
file to include our new program. Add the following line to the CMakeLists.txt
file:
Run the following command to compile the code:
To see it working, first run the robot in simulation by running the following command in one terminal
And run the following command in another terminal to run this new program:
If you have set up everything well, you should see the robot moving in Gazebo as below: