Posted by
thanhnguyen on
URL: http://official-rtab-map-forum.206.s1.nabble.com/Robot-stuck-in-it-own-footprint-tp3301p3415.html
Hi,
Here is my odometry node, this from the volksbot_odometry. They use "odom_combined" as the parent coordinate frame and "base_footprint" as the child coordinate frame.
#include <geometry_msgs/Twist.h>
#include <nav_msgs/Odometry.h>
#include <tf/transform_broadcaster.h>
#include <tf/transform_listener.h>
#include <sensor_msgs/JointState.h>
#include <ros/ros.h>
#include <ros/console.h>
#include <string>
#include "volksbot.h"
class ROSComm : public Comm
{
public:
ROSComm(
const ros::NodeHandle &n,
double sigma_x,
double sigma_theta,
double cov_x_y,
double cov_x_theta,
double cov_y_theta) :
n_(n),
sigma_x_(sigma_x),
sigma_theta_(sigma_theta),
cov_x_y_(cov_x_y),
cov_x_theta_(cov_x_theta),
cov_y_theta_(cov_y_theta),
publish_tf_(false),
odom_pub_(n_.advertise<nav_msgs::Odometry> ("odom", 10)),
joint_pub_(n_.advertise<sensor_msgs::JointState> ("joint_states", 1)) { }
virtual void send_odometry(double x, double y, double theta, double v_x,
double v_theta, double wheelpos_l, double wheelpos_r);
void setTFPrefix(const std::string &tf_prefix);
private:
void populateCovariance(nav_msgs::Odometry &msg, double v_x, double
v_theta);
ros::NodeHandle n_;
double sigma_x_, sigma_theta_, cov_x_y_, cov_x_theta_, cov_y_theta_;
bool publish_tf_;
std::string tf_prefix_;
tf::TransformBroadcaster odom_broadcaster_;
ros::Publisher odom_pub_;
ros::Publisher joint_pub_;
};
void ROSComm::setTFPrefix(const std::string &tf_prefix)
{
tf_prefix_ = tf_prefix;
}
void ROSComm::populateCovariance(nav_msgs::Odometry &msg, double v_x, double v_theta)
{
double odom_multiplier = 1.0;
if (fabs(v_x) <= 1e-8 && fabs(v_theta) <= 1e-8)
{
//nav_msgs::Odometry has a 6x6 covariance matrix
msg.twist.covariance[0] = 1e-12;
msg.twist.covariance[35] = 1e-12;
msg.twist.covariance[30] = 1e-12;
msg.twist.covariance[5] = 1e-12;
}
else
{
//nav_msgs::Odometry has a 6x6 covariance matrix
msg.twist.covariance[0] = odom_multiplier * pow(sigma_x_, 2);
msg.twist.covariance[35] = odom_multiplier * pow(sigma_theta_, 2);
msg.twist.covariance[30] = odom_multiplier * cov_x_theta_;
msg.twist.covariance[5] = odom_multiplier * cov_x_theta_;
}
msg.twist.covariance[7] = DBL_MAX;
msg.twist.covariance[14] = DBL_MAX;
msg.twist.covariance[21] = DBL_MAX;
msg.twist.covariance[28] = DBL_MAX;
msg.pose.covariance = msg.twist.covariance;
if (fabs(v_x) <= 1e-8 && fabs(v_theta) <= 1e-8)
{
msg.pose.covariance[7] = 1e-12;
msg.pose.covariance[1] = 1e-12;
msg.pose.covariance[6] = 1e-12;
msg.pose.covariance[31] = 1e-12;
msg.pose.covariance[11] = 1e-12;
}
else
{
msg.pose.covariance[7] = odom_multiplier * pow(sigma_x_, 2) * pow(sigma_theta_, 2);
msg.pose.covariance[1] = odom_multiplier * cov_x_y_;
msg.pose.covariance[6] = odom_multiplier * cov_x_y_;
msg.pose.covariance[31] = odom_multiplier * cov_y_theta_;
msg.pose.covariance[11] = odom_multiplier * cov_y_theta_;
}
}
void ROSComm::send_odometry(double x, double y, double theta, double v_x, double v_theta, double wheelpos_l, double wheelpos_r)
{
nav_msgs::Odometry odom;
odom.header.frame_id = tf::resolve(tf_prefix_, "odom_combined");
odom.child_frame_id = tf::resolve(tf_prefix_, "base_footprint");
odom.header.stamp = ros::Time::now();
odom.pose.pose.position.x = x;
odom.pose.pose.position.y = y;
odom.pose.pose.position.z = 0.0;
odom.pose.pose.orientation = tf::createQuaternionMsgFromYaw(theta);
odom.twist.twist.linear.x = v_x;
odom.twist.twist.linear.y = 0.0;
odom.twist.twist.angular.z = v_theta;
populateCovariance(odom, v_x, v_theta);
odom_pub_.publish(odom);
if (publish_tf_)
{
geometry_msgs::TransformStamped odom_trans;
odom_trans.header.frame_id = tf::resolve(tf_prefix_, "odom_combined");
odom_trans.child_frame_id = tf::resolve(tf_prefix_, "base_footprint");
odom_trans.header.stamp = ros::Time::now();
odom_trans.transform.translation.x = x;
odom_trans.transform.translation.y = y;
odom_trans.transform.translation.z = 0.0;
odom_trans.transform.rotation = tf::createQuaternionMsgFromYaw(theta);
odom_broadcaster_.sendTransform(odom_trans);
}
sensor_msgs::JointState joint_state;
joint_state.header.stamp = ros::Time::now();
joint_state.name.resize(6);
joint_state.position.resize(6);
joint_state.name[0] = "left_front_wheel_joint";
joint_state.name[1] = "left_middle_wheel_joint";
joint_state.name[2] = "left_rear_wheel_joint";
joint_state.name[3] = "right_front_wheel_joint";
joint_state.name[4] = "right_middle_wheel_joint";
joint_state.name[5] = "right_rear_wheel_joint";
joint_state.position[0] = joint_state.position[1] = joint_state.position[2] = wheelpos_l;
joint_state.position[3] = joint_state.position[4] = joint_state.position[5] = wheelpos_r;
joint_pub_.publish(joint_state);
}
class ROSCall
{
public:
ROSCall(Volksbot &volksbot, double axis_length) :
volksbot_(volksbot),
axis_length_(axis_length),
last_cmd_vel_time_(0.0) { }
void velCallback(const geometry_msgs::Twist::ConstPtr& msg);
void cmd_velWatchdog(const ros::TimerEvent& event);
private:
Volksbot &volksbot_;
double axis_length_;
ros::Time last_cmd_vel_time_;
};
void ROSCall::velCallback(const geometry_msgs::Twist::ConstPtr& msg)
{
last_cmd_vel_time_ = ros::Time::now();
double max_vel = volksbot_.get_max_vel();
double velocity = msg->linear.x;
velocity = std::min(max_vel, msg->linear.x);
velocity = std::max(-max_vel, msg->linear.x);
volksbot_.set_wheel_speed(velocity - axis_length_ * msg->angular.z * 0.5, velocity + axis_length_ * msg->angular.z * 0.5);
}
void ROSCall::cmd_velWatchdog(const ros::TimerEvent& event)
{
if (ros::Time::now() - last_cmd_vel_time_ > ros::Duration(0.6))
volksbot_.set_wheel_speed(0.0, 0.0);
}
int main(int argc, char** argv)
{
ros::init(argc, argv, "volksbot");
ros::NodeHandle n;
ros::NodeHandle nh_ns("~");
/* This is the wheel Radius for the odometry, accounting for some slip in the movement.
* therefor it's not the same as the one in the volksbot.urdf.xacro */
double wheel_radius;
nh_ns.param("wheel_radius", wheel_radius, 0.0985);
double axis_length;
nh_ns.param("axis_length", axis_length, 0.41);
int gear_ratio;
nh_ns.param("gear_ratio", gear_ratio, 74);
int max_vel_l;
nh_ns.param("max_vel_l", max_vel_l, 8250);
int max_vel_r;
nh_ns.param("max_vel_r", max_vel_r, 8400);
int max_acc_l;
nh_ns.param("max_acc_l", max_acc_l, 10000);
int max_acc_r;
nh_ns.param("max_acc_r", max_acc_r, 10000);
bool drive_backwards;
nh_ns.param("drive_backwards", drive_backwards, false);
double turning_adaptation;
nh_ns.param("turning_adaptation", turning_adaptation, 0.95);
double sigma_x, sigma_theta, cov_x_y, cov_x_theta, cov_y_theta;
nh_ns.param("x_stddev", sigma_x, 0.002);
nh_ns.param("rotation_stddev", sigma_theta, 0.017);
nh_ns.param("cov_xy", cov_x_y, 0.0);
nh_ns.param("cov_xrotation", cov_x_theta, 0.0);
nh_ns.param("cov_yrotation", cov_y_theta, 0.0);
ROSComm roscomm(n, sigma_x, sigma_theta, cov_x_y, cov_x_theta, cov_y_theta);
Volksbot volksbot(roscomm, wheel_radius, axis_length, turning_adaptation, gear_ratio, max_vel_l, max_vel_r, max_acc_l, max_acc_r, drive_backwards);
bool publish_tf;
nh_ns.param("publish_tf", publish_tf, false);
std::string tf_prefix;
tf_prefix = tf::getPrefixParam(nh_ns);
roscomm.setTFPrefix(tf_prefix);
ROSCall roscall(volksbot, axis_length);
ros::Timer timer = n.createTimer(ros::Duration(0.1), &ROSCall::cmd_velWatchdog, &roscall);
ros::Subscriber cmd_vel_sub = n.subscribe("cmd_vel", 10, &ROSCall::velCallback, &roscall);
while (ros::ok())
{
volksbot.odometry();
ros::spinOnce();
}
return 0;
}
I can not find anything wrong here? But in the tf tree if I Remove "odom" publisher. The result would be like that. They are not in the same tree.

2/ Yes you are right, I mount the kinnect camera to volksbot, the laser alredy there before. But I choose the direction same with odometry of the robot, you can see.