-
Notifications
You must be signed in to change notification settings - Fork 7
ROS
The Robotic Operating System (ROS) is a management solution for real-time robotic software. ROS provides simple and robust interfaces for communication between software, while allowing for the complete logging of the system. Most popular software packages, such as OpenCV, Mavlink, Python, and MatLab, have a ROS compatible component to allow for easy integration. Additionally, there is a huge amount of user packages available on the community network.
The primary usefulness of ROS is in the libraries available as part of the ROS environment, and how simple they make it to develop modular and interchangeable software. The idea behind developing software in this way is that it allows us to develop both tools that are useful for multiple use cases, as well as tools that are very good at solving a specific problem with as little complexity in the specific node, which aids in development, debugging, and understanding for others. For the most systems, there is no noticeable delay within the system, and if best conventions are followed, a highly dynamic system can be developed without many losses in performance.
The use of different Nodes to handle different problems also allows ease of splitting and integrating intermediate software or data visualizations without any additional programming. It also allows use to collect and analyze data after the experiment and replay the results in "real-time", which allows accurate testing of different methods on real data with no additional effort.
Another major advantage of ROS is that it provides access as a Distributed Network. Each and any node can be ran on different hardware, but will still communicate as if it were all on the same computer, if the network is properly configured. For this reason, a navigation controller and user interface can be ran on a GCS, while the flight control software is ran on-board with the image processing, while the images are post-processed on a second GCS and made available over a web interface. This drastically simplifies the work needed to write interfaces such as sockets and data streams to pass information between the separate systems.
As of the time of writing, it is probably best to use ROS Kinetic (and Ubuntu 16.xx as a result). This is as Kinetic is the current Long Term Release, and should offer the most support for any issues.
For more information, please check: http://wiki.ros.org/
In the installation guide of ROS, it recommends that you install the full desktop stack for the best functionality. It may be more convenient however to install a baseline version, for example if you only need to run ROS on an on-board computer.
For more information on the different meta-packages ROS offers, please check: http://www.ros.org/reps/rep-0142.html#robot-metapackage
As previously described, ROS Nodes are simply individual programs that use ROS to communicate behind the scenes. This section will be a brief overview and breakdown of a basic Node written in both C++ and Python. In the C++ case, there are multiple ways in which this type of node could be constructed, but for the purposes of similarity, we will look at a class-based subscriber/publisher.
For more information on the programming in ROS, and the other sorts of things that are possible, please refer to the ROS Wiki.
The source files for the following examples can be found in the kinetic_sample_packages repository. Before going to check these out, make sure you are familiar with the ROS package structure.
Below, we have the source code for the most basic main of a Node (comments have been removed for brevity). We will also include the class in the same file (where as in the source examples, they are included from a separate class file).
Both examples have been kept as similar as possible, and as such, only the python code will be explained in depth. It assumes that you are familiar with proper python layout.
Python Node
#!/usr/bin/env python
import rospy
if __name__ == '__main__':
rospy.init_node('spinner_py', anonymous=True)
sp = Spinner()
try:
rospy.spin()
except rospy.ROSInterruptException:
sp.shutdown()
C++ Node
#include <ros/ros.h>
int main(int argc, char** argv) {
ros::init(argc, argv, "spinner_cpp");
Spinner sp;
ros::spin();
return 0;
}
Explaination
rospy.init_node('spinner_py', anonymous=True)
This creates initializes the actual ROS node, and allows for communications with the roscore. This should be called before your node attempts to set up any publishers, subscribers (etc.). In C++, you must call this before calling any other ROS interfaces.
sp = Spinner()
This creates an object of the class Spinner (this is discussed below). In a Node of this complexity, this object will run all the functionality of our node.
try:
rospy.spin()
except rospy.ROSInterruptException:
sp.shutdown()
The use of the spin()
function tells the underlying Node to listen for any incoming messages and act on them accordingly. This effectively runs an infinite loop (while(True)
), but allows ROS to handle anything else it needs to do in the background. Without this, the callbacks in the Spinner
class that are triggered when new messages arrive will never be called.
The rospy.spin()
function will lock the thread until something causes the Node to quit. In our case, we wait for the rospy.ROSInterruptException
, which is usually a "CTRL+C" key-press from the user, in which case, we should shutdown the the class, and allow the Node to exit.
In the C++ example, we only need to call ros::spin();
, as the class destructors will handle the shutdown sequence automatically.
Python Spinner Class
C++ Spinner Class
A key idea behind ROS is that it always runs assuming it was on a distributed network. When this is not the case, all information in ROS points towards "localhost". What this means is that when we want to run ROS over a network using multiple systems, all we need to do is change some of these assumptions.
There are 2 main environment variables (ones that you set through the terminal/bash/ssh/etc.) that must be set:
- ROS_MASTER_URI: information on where the ROS master is located, and how it should be contacted.
- ROS_IP: Information on the device that is sending data (and where to connect to for other nodes).
In short, these are the commands needed for each variable. They will need to be set for each and every terminal session that is opened (as the environment is flushed on each new session). For example, the addresses "192.168.1.XXX" and "192.168.1.YYY" refer to the master and slave addresses respectively.
This variable need to be set on the master:
export ROS_IP=192.168.1.XXX
These variables need to be set on the slave:
export ROS_IP=192.168.1.YYY
export ROS_MASTER_URI=http://192.168.1.YYY:11311
To save some time, you could add the following function to the ".bashrc" file. This will allow you to call the command "kinetic" to automatically configure the ROS master, and allow you to call "kinetic 192.168.1.YYY".
kinetic() {
# Setup for distributed ROS
export ROS_IP=$(ip addr | grep 'state UP' -A2 | tail -n1 | awk '{print $2}' | cut -f1 -d'/')
echo "Identifying as: $ROS_IP"
if [ "$#" -eq 1 ]
then
export ROS_MASTER_URI=http://$1:11311
echo "Connecting to: $ROS_MASTER_URI"
fi
}
- Home
- Common Terminology
- UAV Setup Guides (2024)
- UAV Setup Guides (2022)
- UAV Setup Guides (2021)
- UAV Setup Guides (--2020)
- General Computing
- On-Board Computers
- ROS
- Sensors & Estimation
- Flight Controllers & Autopilots
- Control in ROS
- Navigation & Localization
- Communications
- Airframes
- Power Systems
- Propulsion
- Imagery & Cameras
- Image Processing
- Web Interfaces
- Simulation