Initial version. indigo ROSBook2018final
authorWalter Fetter Lages <w.fetter@ieee.org>
Wed, 14 Mar 2018 15:47:30 +0000 (12:47 -0300)
committerWalter Fetter Lages <w.fetter@ieee.org>
Wed, 14 Mar 2018 15:47:30 +0000 (12:47 -0300)
.gitignore [new file with mode: 0644]
CMakeLists.txt [new file with mode: 0644]
config/odometry_publisher.yaml [new symlink]
config/twil.yaml [new file with mode: 0644]
include/arc_odometry/diff_odometry.h [new file with mode: 0644]
launch/gazebo8.launch [new file with mode: 0644]
package.xml [new file with mode: 0644]
src/diff_odometry.cpp [new file with mode: 0644]
src/odometry_publisher.cpp [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..35d74bb
--- /dev/null
@@ -0,0 +1,51 @@
+devel/
+logs/
+build/
+bin/
+lib/
+msg_gen/
+srv_gen/
+msg/*Action.msg
+msg/*ActionFeedback.msg
+msg/*ActionGoal.msg
+msg/*ActionResult.msg
+msg/*Feedback.msg
+msg/*Goal.msg
+msg/*Result.msg
+msg/_*.py
+build_isolated/
+devel_isolated/
+
+# Generated by dynamic reconfigure
+*.cfgc
+/cfg/cpp/
+/cfg/*.py
+
+# Ignore generated docs
+*.dox
+*.wikidoc
+
+# eclipse stuff
+.project
+.cproject
+
+# qcreator stuff
+CMakeLists.txt.user
+
+srv/_*.py
+*.pcd
+*.pyc
+qtcreator-*
+*.user
+
+/planning/cfg
+/planning/docs
+/planning/src
+
+*~
+
+# Emacs
+.#*
+
+# Catkin custom files
+CATKIN_IGNORE
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644 (file)
index 0000000..816a362
--- /dev/null
@@ -0,0 +1,205 @@
+cmake_minimum_required(VERSION 2.8.3)
+project(arc_odometry)
+
+## Compile as C++11, supported in ROS Kinetic and newer
+# add_compile_options(-std=c++11)
+
+## Find catkin macros and libraries
+## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
+## is used, also find other catkin packages
+find_package(catkin REQUIRED COMPONENTS
+  roscpp
+  nav_msgs
+  sensor_msgs
+  tf
+)
+
+## System dependencies are found with CMake's conventions
+# find_package(Boost REQUIRED COMPONENTS system)
+
+find_package(cmake_modules REQUIRED)
+find_package(Eigen REQUIRED)
+
+
+## Uncomment this if the package has a setup.py. This macro ensures
+## modules and global scripts declared therein get installed
+## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html
+# catkin_python_setup()
+
+################################################
+## Declare ROS messages, services and actions ##
+################################################
+
+## To declare and build messages, services or actions from within this
+## package, follow these steps:
+## * Let MSG_DEP_SET be the set of packages whose message types you use in
+##   your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...).
+## * In the file package.xml:
+##   * add a build_depend tag for "message_generation"
+##   * add a build_depend and a run_depend tag for each package in MSG_DEP_SET
+##   * If MSG_DEP_SET isn't empty the following dependency has been pulled in
+##     but can be declared for certainty nonetheless:
+##     * add a run_depend tag for "message_runtime"
+## * In this file (CMakeLists.txt):
+##   * add "message_generation" and every package in MSG_DEP_SET to
+##     find_package(catkin REQUIRED COMPONENTS ...)
+##   * add "message_runtime" and every package in MSG_DEP_SET to
+##     catkin_package(CATKIN_DEPENDS ...)
+##   * uncomment the add_*_files sections below as needed
+##     and list every .msg/.srv/.action file to be processed
+##   * uncomment the generate_messages entry below
+##   * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...)
+
+## Generate messages in the 'msg' folder
+# add_message_files(
+#   FILES
+#   Message1.msg
+#   Message2.msg
+# )
+
+## Generate services in the 'srv' folder
+# add_service_files(
+#   FILES
+#   Service1.srv
+#   Service2.srv
+# )
+
+## Generate actions in the 'action' folder
+# add_action_files(
+#   FILES
+#   Action1.action
+#   Action2.action
+# )
+
+## Generate added messages and services with any dependencies listed here
+# generate_messages(
+#   DEPENDENCIES
+#   std_msgs  # Or other packages containing msgs
+# )
+
+################################################
+## Declare ROS dynamic reconfigure parameters ##
+################################################
+
+## To declare and build dynamic reconfigure parameters within this
+## package, follow these steps:
+## * In the file package.xml:
+##   * add a build_depend and a run_depend tag for "dynamic_reconfigure"
+## * In this file (CMakeLists.txt):
+##   * add "dynamic_reconfigure" to
+##     find_package(catkin REQUIRED COMPONENTS ...)
+##   * uncomment the "generate_dynamic_reconfigure_options" section below
+##     and list every .cfg file to be processed
+
+## Generate dynamic reconfigure parameters in the 'cfg' folder
+# generate_dynamic_reconfigure_options(
+#   cfg/DynReconf1.cfg
+#   cfg/DynReconf2.cfg
+# )
+
+###################################
+## catkin specific configuration ##
+###################################
+## The catkin_package macro generates cmake config files for your package
+## Declare things to be passed to dependent projects
+## INCLUDE_DIRS: uncomment this if you package contains header files
+## LIBRARIES: libraries you create in this project that dependent projects also need
+## CATKIN_DEPENDS: catkin_packages dependent projects also need
+## DEPENDS: system dependencies of this project that dependent projects also need
+catkin_package(
+  INCLUDE_DIRS include
+  LIBRARIES arc_odometry
+  CATKIN_DEPENDS roscpp nav_msgs sensor_msgs tf
+  DEPENDS Eigen
+)
+
+###########
+## Build ##
+###########
+
+## Specify additional locations of header files
+## Your package locations should be listed before other locations
+include_directories(
+ include
+ ${catkin_INCLUDE_DIRS}
+ ${Eigen_INCLUDE_DIRS}
+)
+
+## Declare a C++ library
+add_library(${PROJECT_NAME}
+   src/diff_odometry.cpp
+)
+
+## Add cmake target dependencies of the library
+## as an example, code may need to be generated before libraries
+## either from message generation or dynamic reconfigure
+# add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
+
+## Declare a C++ executable
+## With catkin_make all packages are built within a single CMake context
+## The recommended prefix ensures that target names across packages don't collide
+add_executable(odometry_publisher src/odometry_publisher.cpp)
+
+## Rename C++ executable without prefix
+## The above recommended prefix causes long target names, the following renames the
+## target back to the shorter version for ease of user use
+## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node"
+# set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "")
+
+## Add cmake target dependencies of the executable
+## same as for the library above
+#add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
+
+## Specify libraries to link a library or executable target against
+target_link_libraries(odometry_publisher ${PROJECT_NAME}
+   ${catkin_LIBRARIES}
+   ${Eigen_LIBRARIES}
+)
+
+#############
+## Install ##
+#############
+
+# all install targets should use catkin DESTINATION variables
+# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html
+
+## Mark executable scripts (Python etc.) for installation
+## in contrast to setup.py, you can choose the destination
+# install(PROGRAMS
+#   scripts/my_python_script
+#   DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
+# )
+
+## Mark executables and/or libraries for installation
+install(TARGETS ${PROJECT_NAME} #${PROJECT_NAME}_node
+   ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
+   LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
+   RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
+)
+
+## Mark cpp header files for installation
+install(DIRECTORY include/${PROJECT_NAME}/
+   DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
+   FILES_MATCHING PATTERN "*.h"
+   PATTERN ".svn" EXCLUDE
+)
+
+## Mark other files for installation (e.g. launch and bag files, etc.)
+# install(FILES
+#   # myfile1
+#   # myfile2
+#   DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}
+# )
+
+#############
+## Testing ##
+#############
+
+## Add gtest based cpp test target and link libraries
+# catkin_add_gtest(${PROJECT_NAME}-test test/test_arc_odometry.cpp)
+# if(TARGET ${PROJECT_NAME}-test)
+#   target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME})
+# endif()
+
+## Add folders to be run by python nosetests
+# catkin_add_nosetests(test)
diff --git a/config/odometry_publisher.yaml b/config/odometry_publisher.yaml
new file mode 120000 (symlink)
index 0000000..2bfa2ed
--- /dev/null
@@ -0,0 +1 @@
+twil.yaml
\ No newline at end of file
diff --git a/config/twil.yaml b/config/twil.yaml
new file mode 100644 (file)
index 0000000..c81d863
--- /dev/null
@@ -0,0 +1,9 @@
+# Watch-out: The indentation here is relevant to the semantic!
+
+odometry_publisher:
+  wheel_separation: 0.322
+  wheel_radius: [0.075, 0.075]
+  odom_frame_id: "odom"
+  base_frame_id: "twil_origin"
+  publish_rate: 100
+  
\ No newline at end of file
diff --git a/include/arc_odometry/diff_odometry.h b/include/arc_odometry/diff_odometry.h
new file mode 100644 (file)
index 0000000..eefa29a
--- /dev/null
@@ -0,0 +1,59 @@
+/******************************************************************************
+                         ROS arc_odometry Package
+                     Differential Drive Odometry Class
+          Copyright (C) 2018 Walter Fetter Lages <w.fetter@ieee.org>
+
+        This program is free software: you can redistribute it and/or modify
+        it under the terms of the GNU General Public License as published by
+        the Free Software Foundation, either version 3 of the License, or
+        (at your option) any later version.
+
+        This program is distributed in the hope that it will be useful, but
+        WITHOUT ANY WARRANTY; without even the implied warranty of
+        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+        General Public License for more details.
+
+        You should have received a copy of the GNU General Public License
+        along with this program.  If not, see
+        <http://www.gnu.org/licenses/>.
+        
+*******************************************************************************/
+
+#ifndef DIFF_ODOMETRY_H
+#define DIFF_ODOMETRY_H
+
+#include <vector>
+
+#include <Eigen/Dense>
+
+#include <ros/time.h>
+
+namespace arc_odometry
+{
+       class DiffOdometry
+       {
+               public:
+               DiffOdometry(double wheelBase,std::vector<double> wheelRadius);
+               ~DiffOdometry(void);
+               
+               void update(double leftDisp,double rightDisp,const ros::Duration &duration);
+               void update(const Eigen::Vector2d &deltaPhi,const ros::Duration &duration);
+               double x(void) const {return x_[0];}
+               double y(void) const {return x_[1];}
+               double heading(void) const {return x_[2];}
+               void getPose(Eigen::Vector3d &x) const {x=x_;}
+               double linear(void) const {return u_[0];}
+               double angular(void) const {return u_[1];}
+               void getVelocity(Eigen::Vector2d &u) const {u=u_;}
+               void setParams(double wheelBase,std::vector<double> wheelRadius);
+               void setPose(const Eigen::Vector3d &x) {x_=x;}
+                               
+               private:
+               std::vector<double>wheelRadius_;
+               double wheelBase_;
+                       
+               Eigen::Vector2d u_;
+               Eigen::Vector3d x_;     
+       };
+}
+#endif
diff --git a/launch/gazebo8.launch b/launch/gazebo8.launch
new file mode 100644 (file)
index 0000000..cb90f30
--- /dev/null
@@ -0,0 +1,30 @@
+<launch>
+       <arg name="paused" default="true"/>
+       <arg name="headless" default="false"/>
+       <arg name="use_sim_time" default="true"/>
+       <arg name="wam" default="false"/>
+
+  <remap from="/command" to="/nonsmooth_backstep_controller/command" />
+
+       <include file="$(find twil_description)/launch/gazebo.launch" >
+               <arg name="paused" value="$(arg paused)"/>
+               <arg name="headless" value="$(arg headless)"/>
+               <arg name="use_sim_time" value="$(arg use_sim_time)"/>
+               <arg name="wam" value="$(arg wam)"/>
+       </include>
+
+  <include file="$(find nonsmooth_backstep_controller)/launch/nonsmooth_backstep.launch" />
+
+  <node name="eight_trajectory" pkg="pose2d_trajectories" type="eight_trajectory" respawn="false" output="screen" args="_x:=0.0 _y:=-0.5  _radius:=1.0 _ang_vel:=0.1"/>
+
+  <node name="pose2d_stamp" pkg="pose2d_trajectories" type="pose2d_stamp" respawn="false" output="screen" args="_frame_id:=map" />
+
+  <node pkg="tf2_ros" type="static_transform_publisher" name="odom_frame_publisher" args="0 0 0 0 0 0 1 map odom" />
+
+  <include file="$(find twil_description)/launch/display.launch" />
+
+  <rosparam file="$(find arc_odometry)/config/odometry_publisher.yaml" command="load"/>
+
+  <node pkg="arc_odometry" type="odometry_publisher" name="odom_publisher" />
+
+</launch>
diff --git a/package.xml b/package.xml
new file mode 100644 (file)
index 0000000..271d74d
--- /dev/null
@@ -0,0 +1,61 @@
+<?xml version="1.0"?>
+<package>
+  <name>arc_odometry</name>
+  <version>0.0.0</version>
+  <description>The arc_odometry package</description>
+
+  <!-- One maintainer tag required, multiple allowed, one person per tag -->
+  <!-- Example:  -->
+  <!-- <maintainer email="jane.doe@example.com">Jane Doe</maintainer> -->
+  <maintainer email="fetter@ece.ufrgs.br">Walter Fetter Lages</maintainer>
+
+
+  <!-- One license tag required, multiple allowed, one license per tag -->
+  <!-- Commonly used license strings: -->
+  <!--   BSD, MIT, Boost Software License, GPLv2, GPLv3, LGPLv2.1, LGPLv3 -->
+  <license>GPLv3</license>
+
+
+  <!-- Url tags are optional, but multiple are allowed, one per tag -->
+  <!-- Optional attribute type can be: website, bugtracker, or repository -->
+  <!-- Example: -->
+  <!-- <url type="website">http://wiki.ros.org/arc_odometry</url> -->
+
+
+  <!-- Author tags are optional, multiple are allowed, one per tag -->
+  <!-- Authors do not have to be maintainers, but could be -->
+  <!-- Example: -->
+  <!-- <author email="jane.doe@example.com">Jane Doe</author> -->
+  <author email="fetter@ece.ufrgs.br">Walter Fetter Lages</author>
+
+
+  <!-- The *_depend tags are used to specify dependencies -->
+  <!-- Dependencies can be catkin packages or system dependencies -->
+  <!-- Examples: -->
+  <!-- Use build_depend for packages you need at compile time: -->
+  <!--   <build_depend>message_generation</build_depend> -->
+  <!-- Use buildtool_depend for build tool packages: -->
+  <!--   <buildtool_depend>catkin</buildtool_depend> -->
+  <!-- Use run_depend for packages you need at runtime: -->
+  <!--   <run_depend>message_runtime</run_depend> -->
+  <!-- Use test_depend for packages you need only for testing: -->
+  <!--   <test_depend>gtest</test_depend> -->
+  <buildtool_depend>catkin</buildtool_depend>
+  <build_depend>roscpp</build_depend>
+  <build_depend>Eigen</build_depend>
+  <build_depend>nav_msgs</build_depend>
+  <build_depend>sensor_msgs</build_depend>
+  <build_depend>tf</build_depend>
+  <run_depend>roscpp</run_depend>
+  <run_depend>Eigen</run_depend>
+  <run_depend>nav_msgs</run_depend>
+  <run_depend>sensor_msgs</run_depend>
+  <run_depend>tf</run_depend>
+
+
+  <!-- The export tag contains other, unspecified, tags -->
+  <export>
+    <!-- Other tools can request additional information be placed here -->
+
+  </export>
+</package>
diff --git a/src/diff_odometry.cpp b/src/diff_odometry.cpp
new file mode 100644 (file)
index 0000000..13b3241
--- /dev/null
@@ -0,0 +1,77 @@
+/******************************************************************************
+                           ROS arc_odometry Package
+                          Differential Odometry Class
+          Copyright (C) 2018 Walter Fetter Lages <w.fetter@ieee.org>
+
+        This program is free software: you can redistribute it and/or modify
+        it under the terms of the GNU General Public License as published by
+        the Free Software Foundation, either version 3 of the License, or
+        (at your option) any later version.
+
+        This program is distributed in the hope that it will be useful, but
+        WITHOUT ANY WARRANTY; without even the implied warranty of
+        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+        General Public License for more details.
+
+        You should have received a copy of the GNU General Public License
+        along with this program.  If not, see
+        <http://www.gnu.org/licenses/>.
+        
+*******************************************************************************/
+
+#include <arc_odometry/diff_odometry.h>
+
+namespace arc_odometry
+{      
+       DiffOdometry::DiffOdometry(double wheelBase,std::vector<double> wheelRadius)
+       {
+               wheelBase_=wheelBase;
+               wheelRadius_=wheelRadius;
+               u_.setZero();
+               x_.setZero();
+       }
+       
+       DiffOdometry::~DiffOdometry(void)
+       {
+
+       }
+               
+       // Incremental encoders sense angular displacement and
+       // not velocity
+       // deltaPhi[0] is the left wheel angular displacement
+       // deltaPhi[1] is the right wheel angular displacement
+       void DiffOdometry::update(const Eigen::Vector2d &deltaPhi,const ros::Duration &duration)
+       {
+               double dt=duration.toSec();
+
+               Eigen::Vector2d deltaU;
+               deltaU << (deltaPhi[0]*wheelRadius_[0]+deltaPhi[1]*wheelRadius_[1])/2.0,
+                       (deltaPhi[1]*wheelRadius_[1]-deltaPhi[0]*wheelRadius_[0])/wheelBase_;
+
+               double deltaS=(fabs(deltaU[1]) > DBL_EPSILON)? 
+                       deltaU[0]*sin(deltaU[1]/2)/(deltaU[1]/2):deltaU[0];
+                     
+               if(dt > DBL_EPSILON) u_ << deltaS/dt , deltaU[1]/dt;
+
+               Eigen::Vector3d deltaX;
+               deltaX << deltaS*cos(x_[2]+deltaU[1]/2.0),
+                       deltaS*sin(x_[2]+deltaU[1]/2.0),
+                       deltaU[1];
+                     
+               x_+=deltaX;
+       }
+       
+       void DiffOdometry::update(double leftDisp,double rightDisp,const ros::Duration &duration)
+       {
+               Eigen::Vector2d deltaPhi;
+               deltaPhi << leftDisp, rightDisp;
+               
+               update(deltaPhi,duration);
+       }
+       
+       void DiffOdometry::setParams(double wheelBase,std::vector<double> wheelRadius)
+       {
+               wheelBase_=wheelBase;
+               wheelRadius_=wheelRadius;
+       }
+}
diff --git a/src/odometry_publisher.cpp b/src/odometry_publisher.cpp
new file mode 100644 (file)
index 0000000..f8cb7a5
--- /dev/null
@@ -0,0 +1,208 @@
+/******************************************************************************
+                         ROS arc_odometry Package
+                          Odometry Publisher Node
+          Copyright (C) 2018 Walter Fetter Lages <w.fetter@ieee.org>
+
+        This program is free software: you can redistribute it and/or modify
+        it under the terms of the GNU General Public License as published by
+        the Free Software Foundation, either version 3 of the License, or
+        (at your option) any later version.
+
+        This program is distributed in the hope that it will be useful, but
+        WITHOUT ANY WARRANTY; without even the implied warranty of
+        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+        General Public License for more details.
+
+        You should have received a copy of the GNU General Public License
+        along with this program.  If not, see
+        <http://www.gnu.org/licenses/>.
+        
+*******************************************************************************/
+
+#include <boost/assign.hpp>
+
+#include <ros/node_handle.h>
+#include <nav_msgs/Odometry.h>
+#include <sensor_msgs/JointState.h>
+#include <tf/tfMessage.h>
+#include <tf/transform_datatypes.h>
+
+#include <arc_odometry/diff_odometry.h>
+
+class OdometryPublisher
+{
+       public:
+               OdometryPublisher(ros::NodeHandle node);
+               ~OdometryPublisher(void);
+               void publish(void) const;
+                       
+       private:
+               ros::NodeHandle node_;
+
+               Eigen::Vector2d phi_;
+
+               ros::Publisher odomPub_;
+               ros::Publisher tfPub_;
+
+               ros::Subscriber jointStateSub_;
+               
+               std::vector<double> wheelRadius_;
+               double wheelBase_;
+
+               arc_odometry::DiffOdometry odom_;
+               
+               std::string odom_frame_id_;
+               std::string base_frame_id_;
+               
+               ros::Time lastSamplingTime_;
+               
+               void jointStateCB(const sensor_msgs::JointState::ConstPtr &jointState);
+};
+
+OdometryPublisher::OdometryPublisher(ros::NodeHandle node):
+       wheelRadius_(2),odom_(wheelBase_,wheelRadius_)
+{
+       node_=node;
+
+       if(!node_.getParam("odometry_publisher/wheel_separation",wheelBase_))
+       {
+               ROS_ERROR("No 'wheel_separation' in node %s.",node_.getNamespace().c_str());
+               return;
+       }
+               
+       if(!node_.getParam("odometry_publisher/wheel_radius",wheelRadius_))
+       {
+               ROS_ERROR("No 'wheel_radius' in node %s.",node_.getNamespace().c_str());
+               return;
+       }
+       
+       odom_.setParams(wheelBase_,wheelRadius_);
+       phi_.setZero();
+       
+       odom_frame_id_="odom";
+       node_.param("odom_frame_id",odom_frame_id_,odom_frame_id_);
+               
+       base_frame_id_="base_link";
+       node_.param("base_frame_id",base_frame_id_,base_frame_id_);
+
+       odomPub_=node_.advertise<nav_msgs::Odometry>("odom",100);
+       
+       tfPub_=node_.advertise<tf::tfMessage>("/tf",100);
+       
+       lastSamplingTime_=ros::Time::now();
+       
+       jointStateSub_=node_.subscribe("joint_states",100,&OdometryPublisher::jointStateCB,this);
+}
+
+OdometryPublisher::~OdometryPublisher(void)
+{
+       tfPub_.shutdown();
+       odomPub_.shutdown();
+       jointStateSub_.shutdown();
+}
+
+void OdometryPublisher::jointStateCB(const sensor_msgs::JointState::ConstPtr &jointState)
+{
+       ros::Time time=jointState->header.stamp;
+       
+       // Incremental encoders sense angular displacement and
+       // not velocity
+       // phi[0] is the left wheel angular displacement
+       // phi[1] is the right wheel angular displacement
+       Eigen::Vector2d deltaPhi=-phi_;
+       for(unsigned int i=0;i < jointState->position.size() && i < phi_.size();i++)
+       {
+               phi_[i]=jointState->position[i];
+       }
+       deltaPhi+=phi_;
+
+       odom_.update(deltaPhi,time-lastSamplingTime_);
+       lastSamplingTime_=time;
+}
+
+void OdometryPublisher::publish(void) const
+{
+       ros::Time time=ros::Time::now();
+       
+       Eigen::Vector3d x;
+       Eigen::Vector2d u;
+       odom_.getPose(x);
+       odom_.getVelocity(u);
+
+       nav_msgs::Odometry odomMsg;
+       odomMsg.header.stamp=time;
+       odomMsg.header.frame_id=odom_frame_id_;
+       odomMsg.child_frame_id=base_frame_id_;
+                                                       
+       odomMsg.pose.pose.position.x=x[0];
+       odomMsg.pose.pose.position.y=x[1];
+       odomMsg.pose.pose.position.z=0;
+
+       odomMsg.pose.pose.orientation=tf::createQuaternionMsgFromYaw(x[2]);
+       
+       // Fake covariance
+       double pose_cov[]={1e-6, 1e-6, 1e-16,1e-16,1e-16,1e-9};
+       odomMsg.pose.covariance=boost::assign::list_of
+               (pose_cov[0]) (0)  (0)  (0)  (0)  (0)
+               (0)  (pose_cov[1]) (0)  (0)  (0)  (0)
+               (0)  (0)  (pose_cov[2]) (0)  (0)  (0)
+               (0)  (0)  (0)  (pose_cov[3]) (0)  (0)
+               (0)  (0)  (0)  (0)  (pose_cov[4]) (0)
+               (0)  (0)  (0)  (0)  (0)  (pose_cov[5]);
+
+
+       odomMsg.twist.twist.linear.x=u[0]*cos(x[2]);
+       odomMsg.twist.twist.linear.y=u[0]*sin(x[2]);
+       odomMsg.twist.twist.linear.z=0;
+       odomMsg.twist.twist.angular.x=0;
+       odomMsg.twist.twist.angular.y=0;
+       odomMsg.twist.twist.angular.z=u[1];
+               
+       //Fake covariance
+       double twist_cov[]={1e-6,1e-6,1e-16,1e-16,1e-16,1e-9};
+       odomMsg.twist.covariance=boost::assign::list_of
+               (twist_cov[0]) (0)  (0)  (0)  (0)  (0)
+               (0)  (twist_cov[1]) (0)  (0)  (0)  (0)
+               (0)  (0)  (twist_cov[2]) (0)  (0)  (0)
+               (0)  (0)  (0)  (twist_cov[3]) (0)  (0)
+               (0)  (0)  (0)  (0)  (twist_cov[4]) (0)
+               (0)  (0)  (0)  (0)  (0)  (twist_cov[5]);
+
+
+       odomPub_.publish(odomMsg);
+
+       tf::tfMessage tfMsg;        
+        tfMsg.transforms.resize(1);
+       tfMsg.transforms[0].transform.translation.z=0.0;
+       tfMsg.transforms[0].child_frame_id=base_frame_id_;
+       tfMsg.transforms[0].header.frame_id=odom_frame_id_;
+        
+       geometry_msgs::TransformStamped &odom_frame=tfMsg.transforms[0];
+       odom_frame.header.stamp=time;
+       odom_frame.transform.translation.x=x[0];
+       odom_frame.transform.translation.y=x[1];
+       odom_frame.transform.rotation=tf::createQuaternionMsgFromYaw(x[2]);
+       
+       tfPub_.publish(tfMsg);
+}
+
+int main(int argc,char* argv[])
+{
+       ros::init(argc,argv,"odometry_publisher");
+       ros::NodeHandle node;
+       
+       OdometryPublisher odomPublisher(node);
+       
+       int rate=100;
+       node.param("publish_rate",rate,rate);
+
+       ros::Rate loop(rate);
+       while(ros::ok())
+       {       
+               odomPublisher.publish();
+               
+               ros::spinOnce();
+               loop.sleep();
+       }
+       return 0;
+}