36 #include <Eigen/Geometry> 40 #include <geometry_msgs/Twist.h> 41 #include <nav_msgs/Odometry.h> 42 #include <sensor_msgs/Imu.h> 43 #include <std_msgs/Float32.h> 57 Eigen::Vector3d
toEigen(
const geometry_msgs::Vector3& a)
59 return Eigen::Vector3d(a.x, a.y, a.z);
61 Eigen::Vector3d
toEigen(
const geometry_msgs::Point& a)
63 return Eigen::Vector3d(a.x, a.y, a.z);
65 Eigen::Quaterniond
toEigen(
const geometry_msgs::Quaternion& a)
67 return Eigen::Quaterniond(a.w, a.x, a.y, a.z);
69 geometry_msgs::Point
toPoint(
const Eigen::Vector3d& a)
71 geometry_msgs::Point b;
77 geometry_msgs::Vector3
toVector3(
const Eigen::Vector3d& a)
79 geometry_msgs::Vector3 b;
96 std::shared_ptr<message_filters::Subscriber<nav_msgs::Odometry>>
sub_odom_;
97 std::shared_ptr<message_filters::Subscriber<sensor_msgs::Imu>>
sub_imu_;
98 std::shared_ptr<message_filters::Synchronizer<SyncPolicy>>
sync_;
134 odom_prev_.pose.pose.position.z = msg->data;
136 void cbOdomImu(
const nav_msgs::Odometry::ConstPtr& odom_msg,
const sensor_msgs::Imu::ConstPtr& imu_msg)
139 "Synchronized timestamp: odom %0.3f, imu %0.3f",
140 odom_msg->header.stamp.toSec(),
141 imu_msg->header.stamp.toSec());
145 void cbImu(
const sensor_msgs::Imu::ConstPtr& msg)
147 if (base_link_id_.size() == 0)
149 ROS_ERROR(
"base_link id is not specified.");
153 imu_.header = msg->header;
159 geometry_msgs::Vector3Stamped vin, vout;
160 vin.header = imu_.header;
162 vin.vector = msg->linear_acceleration;
164 imu_.linear_acceleration = vout.vector;
166 vin.header = imu_.header;
168 vin.vector = msg->angular_velocity;
170 imu_.angular_velocity = vout.vector;
173 geometry_msgs::QuaternionStamped qmin, qmout;
174 qmin.header = imu_.header;
175 qmin.quaternion = msg->orientation;
178 auto axis = qin.getAxis();
179 auto angle = qin.getAngle();
180 geometry_msgs::Vector3Stamped axis2;
181 geometry_msgs::Vector3Stamped axis1;
193 imu_.orientation = qmout.quaternion;
207 void cbOdom(
const nav_msgs::Odometry::ConstPtr& msg)
209 nav_msgs::Odometry odom = *msg;
212 const double dt = (odom.header.stamp - odomraw_prev_.header.stamp).toSec();
213 if (base_link_id_overwrite_.size() == 0)
215 base_link_id_ = odom.child_frame_id;
224 double slip_ratio = 1.0;
226 odom.twist.twist.angular = imu_.angular_velocity;
227 odom.pose.pose.orientation = imu_.orientation;
229 double w_imu = imu_.angular_velocity.z;
230 const double w_odom = msg->twist.twist.angular.z;
232 if (w_imu * w_odom < 0 && !negative_slip_)
235 slip_.
predict(-slip_.
x_ * dt * predict_filter_tc_, dt * sigma_predict_);
236 if (std::abs(w_odom) > sigma_odom_ * 3)
239 slip_ratio = w_imu / w_odom;
242 const double slip_ratio_per_angvel =
243 (w_odom - w_imu) / (w_odom * std::abs(w_odom));
244 double slip_ratio_per_angvel_sigma =
245 sigma_odom_ * std::abs(2.0 * w_odom * sigma_odom_ / std::pow(w_odom * w_odom - sigma_odom_ * sigma_odom_, 2));
246 if (std::abs(w_odom) < sigma_odom_)
247 slip_ratio_per_angvel_sigma = std::numeric_limits<double>::infinity();
249 slip_.
measure(slip_ratio_per_angvel, slip_ratio_per_angvel_sigma);
256 printf(
"%0.3f %0.3f %0.3f %0.3f %0.3f %0.3f %0.3f\n",
257 imu_.angular_velocity.z,
258 msg->twist.twist.angular.z,
261 odom.twist.twist.linear.x, dist_);
263 dist_ += odom.twist.twist.linear.x * dt;
265 const Eigen::Vector3d
diff =
toEigen(msg->pose.pose.position) -
toEigen(odomraw_prev_.pose.pose.position);
267 toEigen(odom.pose.pose.orientation) *
toEigen(msg->pose.pose.orientation).inverse() * diff;
273 odom.pose.pose.position =
toPoint(
toEigen(odom_prev_.pose.pose.position) + v);
274 if (z_filter_timeconst_ > 0)
280 geometry_msgs::TransformStamped odom_trans;
282 odom_trans.header = odom.header;
284 odom_trans.transform.translation =
toVector3(
toEigen(odom.pose.pose.position));
285 odom_trans.transform.rotation = odom.pose.pose.orientation;
289 odomraw_prev_ = *msg;
298 , tf_listener_(tf_buffer_)
302 bool enable_tcp_no_delay;
303 pnh_.
param(
"enable_tcp_no_delay", enable_tcp_no_delay,
true);
307 pnh_.
param(
"without_odom", without_odom_,
false);
313 pnh_.
param(
"base_link_id", base_link_id_, std::string(
"base_link"));
314 pnh_.
param(
"odom_id", odom_id_, std::string(
"odom"));
332 pnh_.
param(
"sync_window", sync_window, 50);
335 SyncPolicy(sync_window), *sub_odom_, *sub_imu_));
338 pnh_.
param(
"base_link_id", base_link_id_overwrite_, std::string(
""));
342 nh_,
"reset_odometry_z",
344 pub_odom_ = nh_.
advertise<nav_msgs::Odometry>(
"odom", 8);
348 z_filter_timeconst_ = -1.0;
350 if (pnh_.
getParam(
"z_filter", z_filter))
352 const double odom_freq = 100.0;
353 if (0.0 < z_filter && z_filter < 1.0)
354 z_filter_timeconst_ = (1.0 / odom_freq) / (1.0 - z_filter);
357 "track_odometry: ~z_filter parameter (exponential filter (1 - alpha) value) is deprecated. " 358 "Use ~z_filter_timeconst (in seconds) instead. " 359 "Treated as z_filter_timeconst=%0.6f. (negative value means disabled)",
360 z_filter_timeconst_);
364 pnh_.
param(
"z_filter_timeconst", z_filter_timeconst_, -1.0);
366 pnh_.
param(
"tf_tolerance", tf_tolerance_, 0.01);
367 pnh_.
param(
"use_kf", use_kf_,
true);
368 pnh_.
param(
"enable_negative_slip", negative_slip_,
false);
369 pnh_.
param(
"debug", debug_,
false);
370 pnh_.
param(
"publish_tf", publish_tf_,
true);
372 if (base_link_id_overwrite_.size() > 0)
378 pnh_.
param(
"sigma_odom", sigma_odom_, 0.005);
380 pnh_.
param(
"sigma_predict", sigma_predict_, 0.5);
382 pnh_.
param(
"predict_filter_tc", predict_filter_tc_, 1.0);
392 nav_msgs::Odometry::Ptr odom(
new nav_msgs::Odometry);
396 odom->pose.pose.orientation.w = 1.0;
414 int main(
int argc,
char* argv[])
void cbOdom(const nav_msgs::Odometry::ConstPtr &msg)
std::string base_link_id_
TransportHints & reliable()
void publish(const boost::shared_ptr< M > &message) const
TF2SIMD_FORCE_INLINE tf2Scalar angle(const Quaternion &q1, const Quaternion &q2)
void measure(const double x_in, const double sigma_in)
virtual geometry_msgs::TransformStamped lookupTransform(const std::string &target_frame, const std::string &source_frame, const ros::Time &time, const ros::Duration timeout) const
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
IMETHOD Vector diff(const Vector &p_w_a, const Vector &p_w_b, double dt=1)
void set(const double x0=0.0, const double sigma0=std::numeric_limits< double >::infinity())
tf2_ros::Buffer tf_buffer_
ros::Subscriber subscribe(ros::NodeHandle &nh_new, const std::string &topic_new, ros::NodeHandle &nh_old, const std::string &topic_old, uint32_t queue_size, void(*fp)(M), const ros::TransportHints &transport_hints=ros::TransportHints())
tf2_ros::TransformListener tf_listener_
void doTransform(const T &data_in, T &data_out, const geometry_msgs::TransformStamped &transform)
message_filters::sync_policies::ApproximateTime< nav_msgs::Odometry, sensor_msgs::Imu > SyncPolicy
ros::Subscriber sub_reset_z_
ROSCPP_DECL void spin(Spinner &spinner)
geometry_msgs::Vector3 toVector3(const Eigen::Vector3d &a)
tf2_ros::TransformBroadcaster tf_broadcaster_
ros::Subscriber sub_imu_raw_
TransportHints & tcpNoDelay(bool nodelay=true)
#define ROS_ERROR_THROTTLE(rate,...)
geometry_msgs::Point toPoint(const Eigen::Vector3d &a)
double z_filter_timeconst_
std::shared_ptr< message_filters::Subscriber< sensor_msgs::Imu > > sub_imu_
bool param(const std::string ¶m_name, T ¶m_val, const T &default_val) const
std::shared_ptr< message_filters::Synchronizer< SyncPolicy > > sync_
void fromMsg(const A &, B &b)
Timer createTimer(Rate r, Handler h, Obj o, bool oneshot=false, bool autostart=true) const
void cbImu(const sensor_msgs::Imu::ConstPtr &msg)
int main(int argc, char *argv[])
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
void cbOdomImu(const nav_msgs::Odometry::ConstPtr &odom_msg, const sensor_msgs::Imu::ConstPtr &imu_msg)
double predict_filter_tc_
void cbResetZ(const std_msgs::Float32::Ptr &msg)
nav_msgs::Odometry odomraw_prev_
nav_msgs::Odometry odom_prev_
track_odometry::KalmanFilter1 slip_
bool getParam(const std::string &key, std::string &s) const
void predict(const double x_plus, const double sigma_plus)
std::shared_ptr< message_filters::Subscriber< nav_msgs::Odometry > > sub_odom_
Eigen::Vector3d toEigen(const geometry_msgs::Vector3 &a)
bool hasParam(const std::string &key) const
void setData(const T &input)
std::string base_link_id_overwrite_
void cbTimer(const ros::TimerEvent &event)