Tips and tricks for Robot Operating System. A few code snippets/functions that come in handy when developing with ROS.
Receive only one message on topic (usefull for configuraitons):
ros::NodeHandle nh;
sensor_msgs::CameraInfoConstPtr msg = ros::topic::waitForMessage<sensor_msgs::CameraInfo>("/camera_info", nh, 10.0);
Function that looks up the TF transform between parent and child frame and handles errors
bool getTransform(const std::string &refFrame, const std::string &childFrame, tf::StampedTransform &transform) {
std::string errMsg;
tf::TransformListener tf_listener;
if (!tf_listener.waitForTransform(refFrame, childFrame, ros::Time(0), ros::Duration(0.6), ros::Duration(0.1), &errMsg)) {
ROS_ERROR_STREAM("!!! transform | Unable to get pose from TF: " << errMsg);
return false;
} else {
try {
tf_listener.lookupTransform(refFrame, childFrame, ros::Time(0), transform);
}
catch (const tf::TransformException &e) {
ROS_ERROR_STREAM("!!! | Error in lookupTransform of " << childFrame << " in " << refFrame);
return false;
}
}
return true;
}
How to get yaw from quaternion
double q0 = msg->pose.orientation.w;
double q1 = msg->pose.orientation.x;
double q2 = msg->pose.orientation.y;
double q3 = msg->pose.orientation.z;
double yaw = atan2(2 * (q0 * q3 + q1 * q2),1 - 2 * (q2 * q2 + q3 * q3)) + 3.14159;
Publish single marker sphere/arrow to topic
ros::Publisher pub_marker = nh.advertise<visualization_msgs::Marker>("/markers", 10);
void publishMarker(double x, double y, int id, double color){
visualization_msgs::Marker marker;
marker.header.frame_id = "laser";
marker.header.stamp = ros::Time::now();
marker.id = id;
marker.type = visualization_msgs::Marker::SPHERE;
marker.action = visualization_msgs::Marker::ADD;
marker.pose.position.x = x;
marker.pose.position.y = y;
marker.pose.position.z = 0.1;
marker.pose.orientation.x = 0.0;
marker.pose.orientation.y = 0.0;
marker.pose.orientation.z = 0.0;
marker.pose.orientation.w = 1.0;
marker.scale.x = 0.1;
marker.scale.y = 0.1;
marker.scale.z = 0.1;
marker.color.a = 0.8;
marker.color.r = 1.0;
marker.color.g = 1.0;
marker.color.b = color;
marker.lifetime = ros::Duration(0.5);
pub_marker.publish(marker);
}
void publishMarkerArrow(double x, double y, double roll,double pitch, double yaw, int id){
visualization_msgs::Marker marker;
marker.header.frame_id = "laser";
marker.header.stamp = ros::Time::now();
marker.id = id;
marker.type = visualization_msgs::Marker::ARROW;
marker.action = visualization_msgs::Marker::ADD;
marker.pose.position.x = x;
marker.pose.position.y = y;
marker.pose.position.z = 0.1;
geometry_msgs::Quaternion q_msg = tf::createQuaternionMsgFromRollPitchYaw(roll,pitch,yaw);
marker.pose.orientation = q_msg;
marker.scale.x = 1;
marker.scale.y = 0.02;
marker.scale.z = 0.02;
marker.color.a = 0.8;
marker.color.r = 0.0;
marker.color.g = 0.9;
marker.color.b = 0.9;
marker.lifetime = ros::Duration(0.5);
pub_marker.publish(marker);
}
Function that reads a message of type sensor_msgs::CameraInfo and saves camera matrix and distortion to matrices as are required by OpenCV functions.
cv::Mat cameraMatrix;
cv::Mat distortionCoeffs;
void camInfoCallback(const sensor_msgs::CameraInfoConstPtr &msg){
std::vector<double> dist = msg->D;
cv::Mat distortionCoeffs_l = cv::Mat(1, msg->D.size(), cv::CV_64FC1, &dist[0]);
double cam_array[9];
std::copy(msg->K.begin(),msg->K.end(), std::begin(cam_array));
cv::Mat cameraMatrix_l = cv::Mat(3,3, CV_64FC1, &cam_array);
distCoeffs_l.copyTo(distCoeffs); //TODO: without that additional copy they become strange when function gets out of scope
cameraMatrix_l.copyTo(cameraMatrix);
ROS_INFO("Got calibration parameters");
ROS_INFO_STREAM("Distortion coefs:" <<distortionCoeffs);
ROS_INFO_STREAM("Camera matrix:"<<cameraMatrix);
}
If you want to disable compression and theora set following parameters:
<rosparam param="/camera_topic/image_raw/disable_pub_plugins">
- 'image_transport/compressedDepth'
- 'image_transport/theora'
- 'image_transport/compressed'
</rosparam>
How to list all plugins for costmap/move_base/nodelets
rospack plugins --attrib=plugin costmap_2d
rospack plugins --attrib=plugin nav_core
rospack plugins --attrib=plugin nodelet
Simple service definitions link
Synchronize multiple topics to one callback funciton link
Script that lets you easily set up one master over multiple PCs. click this link
subst_value=true
Allows use of substitution args in the YAML text when loaded with `<rosparam command="load" .../>
add to package.xml
<exec_depend>gazebo_ros</exec_depend>
<export>
<gazebo_ros gazebo_media_path="${prefix}"/>
</export>
In urdf model add
<gazebo reference="marker_link">
<material>Marker46Material</material>
</gazebo>
In package add
-media/materials/scripts/example.materials
-media/materials/textures/marker.png
Where example.materials
is
material Marker46Material{
technique
{
pass
{
texture_unit
{
texture marker.png
}
}
}
}