Posted by
Drane on
URL: http://official-rtab-map-forum.206.s1.nabble.com/Autonomous-Navigation-using-RTAB-Map-s-RGBD-Odometry-tp6223.html
Hi Mr Mathieu,
Is it possible to do autonomous navigation using RTAB-Map's RGBD Odometry as the only odometry source?
I've tried to do this using the following commands:
Mapping
roscore
rosrun serial serial
rosrun rosserial_python serial_node.py /dev/ttyUSB0 _baud:=230400
roslaunch kinect2_bridge kinect2_bridge.launch publish_tf:=true
roslaunch rtabmap_ros rgbd_mapping_kinect2.launch resolution:=qhd rtabmap_args:="--delete_db_on_start" rviz:=true rtabmapviz:=false
rosrun teleop_twist_keyboard teleop_twist_keyboard.py
Navigation
rosrun depthimage_to_laserscan depthimage_to_laserscan image:=/kinect2/qhd/image_depth_rect camera_info:=/camera/camera_info
My robot doesn't have nav_msgs/Odometry and tf, then I'm trying to use the /rtabmap/odom topic:
publish_odom.cpp
#include <ros/ros.h>
#include <tf/transform_broadcaster.h>
#include <nav_msgs/Odometry.h>
#include "geometry_msgs/Pose2D.h"
#include "geometry_msgs/Twist.h"
#include "std_msgs/Char.h"
#include "std_msgs/UInt16.h"
#include "angles/angles.h"
#include "iostream"
ros::Publisher pub_velocity;
ros::Timer tim_50hz;
//odometry & gyro
double pos_x,pos_y;
double theta;
double buffer_pos_x, buffer_pos_y, buffer_theta;
double offset_pos_x = 0, offset_pos_y = 0, offset_theta = 0;
double linearposx = 0, linearposy = 0, quatx = 0, quaty = 0, quatz = 0, quatw = 0, vex = 0, vey = 0, vez = 0;
//velocity
double vx = 0,vy = 0,vw = 0;
double buffer_vx = 0, buffer_vy = 0, buffer_vw = 0;
double buffer_vx_new = 0, buffer_vy_new = 0, buffer_vw_new = 0;
void manual_move(int _vx, int _vy, int _vw)
{
geometry_msgs::Twist msg_velocity;
msg_velocity.linear.x = vx = _vx;
msg_velocity.linear.y = vy = _vy;
msg_velocity.angular.z = vw = _vw;
pub_velocity.publish(msg_velocity);
}
void callback_velocity (const geometry_msgs::TwistPtr &msg)
{
buffer_vx_new = msg->linear.x;
buffer_vx = buffer_vx_new *40;
buffer_vy_new = msg->linear.y;
buffer_vy = buffer_vy_new *40;
buffer_vw_new = msg->angular.z;
buffer_vw = buffer_vw_new *40;
}
void callback_odometry (const nav_msgs::Odometry::ConstPtr &msg)
{
linearposx=msg->pose.pose.position.x;
linearposy=msg->pose.pose.position.y;
quatx=msg->pose.pose.orientation.x;
quaty=msg->pose.pose.orientation.y;
quatz=msg->pose.pose.orientation.z;
quatw=msg->pose.pose.orientation.w;
vex=msg->twist.twist.linear.x;
vey=msg->twist.twist.linear.y;
vez=msg->twist.twist.angular.z;
}
void callback_50hz(const ros::TimerEvent &time)
{
manual_move(buffer_vx,buffer_vy,buffer_vw);
ROS_INFO("%f", theta);
}
int main(int argc, char** argv){
ros::init(argc, argv, "odometry_publisher");
ros::NodeHandle n;
ros::Publisher odom_pub = n.advertise<nav_msgs::Odometry>("odom", 50);
pub_velocity = n.advertise<geometry_msgs::Twist>("pc2stm_velocity",8);
tf::TransformBroadcaster odom_broadcaster;
ros::Subscriber sub_odometry = n.subscribe("/rtabmap/odom", 50,callback_odometry);
ros::Subscriber sub_velocity = n.subscribe("cmd_vel", 8, callback_velocity);
tim_50hz = n.createTimer(ros::Duration(0.02), callback_50hz);
ros::Time current_time, last_time;
current_time = ros::Time::now();
last_time = ros::Time::now();
ros::Rate r(50);
while(n.ok()){
ros::spinOnce(); // check for incoming messages
current_time = ros::Time::now();
//first, we'll publish the transform over tf
geometry_msgs::TransformStamped odom_trans;
odom_trans.header.stamp = current_time;
odom_trans.header.frame_id = "odom";
odom_trans.child_frame_id = "base_link";
odom_trans.transform.translation.x = linearposx;
odom_trans.transform.translation.y = linearposy;
odom_trans.transform.translation.z = 0.0;
odom_trans.transform.rotation.x = quatx;
odom_trans.transform.rotation.y = quaty;
odom_trans.transform.rotation.z = quatz;
odom_trans.transform.rotation.w = quatw;
//send the transform
odom_broadcaster.sendTransform(odom_trans);
//next, we'll publish the odometry message over ROS
nav_msgs::Odometry odom;
odom.header.stamp = current_time;
odom.header.frame_id = "odom";
//set the position
odom.pose.pose.position.x = linearposx;
odom.pose.pose.position.y = linearposy;
odom.pose.pose.position.z = 0.0;
odom.pose.pose.orientation.x = quatx;
odom.pose.pose.orientation.y = quaty;
odom.pose.pose.orientation.z = quatz;
odom.pose.pose.orientation.w = quatw;
//set the velocity
odom.child_frame_id = "base_link";
odom.twist.twist.linear.x = vex;
odom.twist.twist.linear.y = vey;
odom.twist.twist.angular.z = vez;
//publish the message
odom_pub.publish(odom);
last_time = current_time;
r.sleep();
}
}
tf_broadcaster.cpp
#include <ros/ros.h>
#include <tf/transform_broadcaster.h>
int main(int argc, char** argv){
ros::init(argc, argv, "mobile_robot_tf_publisher");
ros::NodeHandle nh;
ros::Rate r(100);
tf::TransformBroadcaster base_to_laser_broadcaster;
while(nh.ok()){
/*base_to_laser_broadcaster.sendTransform(
tf::StampedTransform(
tf::Transform(tf::Quaternion(0, 0, 0, 1), tf::Vector3(0, 0, 0)),
ros::Time::now(),"map", "odom"));*/
base_to_laser_broadcaster.sendTransform(
tf::StampedTransform(
tf::Transform(tf::Quaternion(0, 0, 0, 1), tf::Vector3(0, 0, 0)),
ros::Time::now(),"odom", "base_link"));
base_to_laser_broadcaster.sendTransform(
tf::StampedTransform(
tf::Transform(tf::Quaternion(0, 0, 0, 1), tf::Vector3(0.07, 0.0, 0.64)),
ros::Time::now(),"base_link", "base_laser"));
base_to_laser_broadcaster.sendTransform(
tf::StampedTransform(
tf::Transform(tf::Quaternion(0, 0, 0, 1), tf::Vector3(0, 0, 0)),
ros::Time::now(),"base_laser", "camera_link"));
base_to_laser_broadcaster.sendTransform(
tf::StampedTransform(
tf::Transform(tf::Quaternion(0, 0, 0, 1), tf::Vector3(0, 0, 0)),
ros::Time::now(),"camera_link", "kinect2_base_link"));
r.sleep();
}
}
move_base.launch (using default parameters in http://wiki.ros.org/navigation/Tutorials/RobotSetup except robot_footprint)
<?xml version="1.0"?>
<launch>
<master auto="start"/>
<arg name="map_topic" default="/rtabmap/grid_map"/>
<remap from="map" to="$(arg map_topic)"/>
<!-- Run the map server
<node name="map_server" pkg="map_server" type="map_server" args="$(find mobile_robot_2dnav)/maps/map.yaml"/> -->
<node pkg="move_base" type="move_base" respawn="false" name="move_base" output="screen">
<rosparam file="$(find mobile_robot_2dnav)/param/costmap_common_params.yaml" command="load" ns="global_costmap" />
<rosparam file="$(find mobile_robot_2dnav)/param/costmap_common_params.yaml" command="load" ns="local_costmap" />
<rosparam file="$(find mobile_robot_2dnav)/param/local_costmap_params.yaml" command="load" />
<rosparam file="$(find mobile_robot_2dnav)/param/global_costmap_params.yaml" command="load" />
<rosparam file="$(find mobile_robot_2dnav)/param/base_local_planner_params.yaml" command="load" />
</node>
</launch>
When I do the mapping process the robot's tf moved according to the robot, but when I run the publish_odom.cpp the robot's tf is not moving correctly, and there are errors relating to the odom's quaternion. I can't set the 2D Pose Estimate in rviz too and when I send the 2D Nav Goal the robot will travel some distance and then keep rotating in place.
So I think the odom is not published correctly or the subscribed topic is wrong? How can I publish RTAB-Map's RGBD Odometry correctly?
Thank You