# ROS (Robot Operating System)
## Cheat Sheet
http://github.com/ros/cheatsheet/releases/download/0.0.1/ROScheatsheet_catkin.pdf
## ROS Workspace Environment
### Overview
Defines context for the current workspace
### Load default workspace
```
source /opt/ros/indigo/setup.bash
```
### Overlay your *catkin* workspace
```
cd ~/catkin_ws
source devel/setup.bash
```
### Check workspace
```
echo $ROS_PACKAGE_PATH
```
## ROS Master
### Overview
* Manages the communication between nodes
* Every node registers at startup with the master
### Start Master
```
roscore
```
## ROS Nodes
### Overview
* Single purpose, executable program
* Individually compiled, executed and managed
* Organized in packages
### Run a node
```
rosrun package_name node_name
```
### See active nodes
```
rosnode list
```
### Retrieve information about a node
```
rosnode info node_name
```
## ROS Topics
### Overview
* Nodes communicate over topics
* Nodes can publish or subscribe to a topic
* Topic is a name for a stream of messages
### List active topics
```
rostopic list
```
### Subscribe and print contents of a topic
```
rostopic echo /topic
```
### Show information about a topic
```
rostopic info /topic
```
### Analayze the frequency
```
rostopic hz /topic
```
## ROS Messages
### Overview
* Data structure defining the *type* of a topic
* Compromised of a nested structure of integers, floats, booleans, strings etc. and arrays of objects
* Defined in *.msg files
### See type of a topic
```
rostopic type /topic
```
### Publish a message to a topic
```
rostopic pub /topic type args
```
## catkin Build System
```
catkin_make
```
### Navigate to catkin workspace
```
cd ~/catkin_ws
```
### Build package
```
catkin build package_name
```
### !! If you build a new package -> update your environment !!
```
source devel/setup.bash
```
### Clean entire build and devel space
```
catkin clean
```
### Check catkin workspace setup
```
catkin config
```
## ROS Launch
### Overview
* *launch* is a tool for launching multiple nodes
* are written in SML as *.launch files
* launch starts automatically a roscore, if it is not running yet
### Start a launch file
```
roslaunch file_name.launch
```
### Start launch file from a package
```
roslaunch package_name file_name.launch
```
### See content of the launch file
```
rosed file_name.launch
```
### File Structur
Example
```
<launch>
<node name="node_name" pkg="package_name" type="listener/talker" output="screen"/>
<node name="node_name" pkg="package_name" type="listener/talker" output="screen"/>
</launch>
```
Explanation
* launch
root element of the launch file
* node
each < node > tag specifies a node to be launched
* name
name of the node
* pkg
package containing the node
* type
type of the node, there must be a corresponding executable with the same name
* output
specifies where to output log messages(screen: console, log: log file)
### Arguments
```
<arg name="arg_name" default="default_value"/>
```
Example
```
<arg name="use_sim_time" default="true"/>
```
#### Use arguments in launch a file
```
$(arg arg_name)
```
Example
```
if="$(arg use_sim_time)"
```
#### Launching arguments can be set with
```
roslaunch launch_file.launch arg_name:=value
```
### Including Other Launch Files
#### Include other launch files
```
<include file="package_name"/>
```
#### Find the system path to other packages
```
$(find package_name)
```
#### Pass arguments to the included file
```
<arg name="arg_name" value="value"/>
```
## ROS Packages
* ROS software is organized into packages, which can contain source code, launch files, configuartion files, message definitions, data and documentation
* A packge that builds up on/requires other packages, declares these as dependencies
```
catkin_create_pkg package_name {dependencies}
```
### CMakeLists.xml
```
cmake_minimum_required(VERSION 2.8.3)
project(ros_package_template)
## Use C++11
add_definitions(--std=c++11)
## Find catkin macros and libraries
find_package(catkin REQUIRED
COMPONENTS
roscpp
sensor_msgs
)
catkin_package(
INCLUDE_DIRS include
#LIBRARIES
CATKIN_DEPENDS roscpp sensor_msgs
#DEPENDS
)
include_directories(include ${catkin_INCLUDE_DIRS})
add_executable(${PROJECT_NAME} src/${PROJECT_NAME}_node.cpp
src/name.cpp)
target_link_libraries(${PROJECT_NAME} ${catkin_LIBRARIES})
```
* ```project(ros_package_template)```
Use the same name as in the package.xml
* ```add_definitions(--std=c ++ 11)```
use C ++ 11 by default
* ```find_package(catkin REQUIRED COMPONENTS roscpp sensor_msgs)```
List the packages that your package requires to build (have to be listed in package.xml)
* ```catkin_package( INCLUDE_DIRS include CATKIN_DEPENDS roscpp sensor_msgs)```
Specify build export information
INCLUDE_DIRS -> Directories with header files
LIBRARIES -> Libraries created in this project
CATKIN_DEPENDS -> Packages depent projects alsoneed
DEPENDS -> System dependencies dependent projects also need (have to be listed in package.xml)
* ```include_directories(include ${catkin_INCLUDE_DIRS})```
Specify locations of header files
* ```add_executable(${PROJECT_NAME} src/${PROJECT_NAME}_node.cpp src/name.cpp)```
Declare a C++ executable
* ```target_link_libraries(${PROJECT_NAME} ${catkin_LIBRARIES})```
Specify libraries to link the execuble against
## Easy ROS C++ Example (Hello World)
```
#include <ros/ros.h>
```
ROS main header file include
```
int main(int argc, char** argv)
{
ros::init(argc, argv, "hello_world");
```
ros::init(...) hasto be calle before calling other ROS functions
```
ros::NodeHandle nodeHandle;
```
The node handle is the access point for communications with the ROS system(topics services parameters)
```
ros::Rate loopRate(10);
```
ros::Rate is a helper class to run loops at a desired frequency
```
unsigned int count = 0;
while(ros::ok()){
```
ros::ok() check if a node should continue running
*Returns false if SIGINT is received(Ctrl + C) or ros::shutdown() has been called*
```
ROS_INFO_STREAM("Hello World" << count);
```
ROS_INFO() logs messages to the filesystem
```
ros::spinOnce();
```
ros::spinOnce() processes incoming messages via callbacks
```
loopRate.sleep();
count++;
}
return 0;
}
```
## Node Handles (Recoommended)
* Default (public) node handle:
nh_ = ros::NodeHandle();
/namespace/topic
* Private node handle:
nh_private_ = ros::NodeHandle("~");
/namespace/node/topic
* Namespaced node hanle:
nh_eth_ = ros::NodeHandle("eth");
/namespace/eth/topic
## Logging
```
/rosout topic
```
In the program:
```
ROS_INFO("Result: %d", result);
ROS_INFO_STREAM("Result: "<< result);
```
To see it in the console, set the output configuration to *screen* in the launch file
```
<launch>
<node name="node_name" output="screen"/>
</launch>
```
## Subscriber
```
#include "ros/ros.h"
#include "std_msgs/String.h"
void chatterCallback(const std_msgs::Sring::ConstPtr& msg)
{
ROS_INFO("message: [%s]", msg->data.c_str());
}
int main(int argc, char **argv)
{
ros::init(argc, argv, "listener");
ros::NodeHandle node;
ros::Subscriber subscriber = node.subscribe("chatter",10, chatterCallback);
ros::spin();
return 0;
}
```
* ```ros::Subscriber subscriber = node.subscribe("chatter",10, chatterCallback);```
Start listeninig to a topic by calling the method subscribe() of the node handle
ros:: Subscriber subscriber = nodeHandle.subscribe(topic, queue_size, callback_function);
* ```void chatterCallback(const std_msgs::Sring::ConstPtr& msg){ROS_INFO("message: [%s]", msg->data.c_str()); }```
When a message is received -> callback function is called with the contents of the message as argument
* ```ros::spin();```
ros::spin() processes callbacks and will not return until the node has been shutdown
## Publisher
```
#include <ros/ros.h>
#include <std_msgs/String.h>
int main(int argc, char **argv){
ros::init(argc, argv, "name");
ros::NodeHandle nh;
ros::Publisher chatterPublisher = nh.advertise<std_msgs::String>("chatter",1);
ros::Rate loopRate(10);
unsigned int count = 0;
while(ros::ok()){
std_msgs::String message;
message.data = "hello world" + std::to_string(count);
ROS_INFO_STREAM(message.data);
chatterPublisher.publish(message);
ros::spinOnce();
loopRate.sleep();
count++;
}
return 0;
}
```
* Create a publisher with help of the node handle
```
ros::Publisher publisher = nh.advertise<message_type>(topic, queue_size);
```
* ``` message.data = "hello world" + std::to_string(count);```
Create the message contents
## ROS Parameter Service
### Overview
* Nodes use the *parameter server* to store and retrieve parameters at runtime
* Best used for static data such as configuration parameters
* Parameters can be defined in launch files or separate YAML files
* Parameters can be defined in lauch files or separate YAML files
```
<launch>
<node name="name" pkg="package" type="node_type">
<rosparam command="load" file="$(find package)/config/config.yaml"/>
</node>
</launch>
```
### List all parameters
```
rosparam list
```
### Get value of a parameter
```
rosparam get parameter_name
```
### Set value of a parameter
```
rosparam set parameter_name value
```
## C++ API
* Get a parameter in C++
```
nodeHandle.getParam(parameter_name, variable)
```
This method returns *true* if parameter was found, *false* otherwise
* Global and relative parameter access
* Global parameter name with preceding /
```
nodeHandle.getParam("/package/camera/left/exposure", variable)
```
* Relative parameter name (relative to the node handle)
```
nodeHandle.getParam("camera/left/exposure", variable)
```
* For parameters, typically use the private node handle
```
ros::NodeHandle("~")
```
```
ros::NodeHandle nodeHandle("~");
std::string topic;
if(!nodeHandle.getParam("topic_name", topic0)){
ROS_ERROR("Could not find topic parameter!")
}
```
## ERRORS
* ### RLException: [file_name.launch] is neither a launch file in package [package_name] nor is [package_name] a launch file name
The traceback for the exception was written to the log file
**Solution:**
source ~/.bashrc
* ###[gazebo-2] process has died [pid < pidnr >, exit code 255, cmd /opt/ros/melodic/lib/gazebo_ros/gzserver -e ode /home/name/mybot_ws/src/mybot_gazebo/worlds/mybot.world __name:=gazebo __log:=/home/name/.ros/log/3aa819c6-a2f5-11e9-a3ef-080027af97c9/gazebo-2.log].
log file: /home/name/.ros/log/3aa819c6-a2f5-11e9-a3ef-080027af97c9/gazebo-2*.log
**Solution**
killall gzserver
kilall gzclient
(and with ctrl+C in the terminal)
* ### Add the installation prefix of "tf2_sensor_msgs" to CMAKE_PREFIX_PATH or
set "tf2_sensor_msgs_DIR" to a directory containing one of the above files.
**Solution**
sudo apt-get install ros-melodic-tf2-sensor-msgs
* ### RLException: roscore cannot run as another roscore/master is already running.
Please kill other roscore/master processes before relaunching.
The ROS_MASTER_URI is http://miriam-HP-ProBook-470-G4:11311/
The traceback for the exception was written to the log file
**Solution**
killall -9 roscore
killall -9 rosmaster
* ### Could not find a package configuration file provided by "joy" with any of
the following names:
joyConfig.cmake
joy-config.cmake
**Solution**
$ sudo apt-get install ros-melodic-joy*