25 imu_received_.store(
true);
26 auto current_time = msg->header.stamp.sec + msg->header.stamp.nanosec / 1e9;
27 double dt = current_time - last_time_;
28 last_time_ = current_time;
35 P_ = F_ * P_ * F_.transpose() + Q_;
37 X_(3) += msg->linear_acceleration.x * dt;
38 X_(4) += msg->linear_acceleration.y * dt;
39 X_(5) += msg->linear_acceleration.z * dt;
41 double euler_angles[3];
43 quaternion_[0] = msg->orientation.x;
44 quaternion_[1] = msg->orientation.y;
45 quaternion_[2] = msg->orientation.z;
46 quaternion_[3] = msg->orientation.w;
49 auto roll = euler_angles[0];
50 auto pitch = euler_angles[1];
51 auto yaw = euler_angles[2];
61 gps_received_.store(
true);
62 constexpr double DEG_TO_RAD_LOCAL = M_PI / 180.0;
65 double lon = msg->longitude;
66 double lat = msg->latitude;
67 double px = lon * DEG_TO_RAD_LOCAL;
68 double py = lat * DEG_TO_RAD_LOCAL;
70 if (utm_target_ == NULL) {
71 std::string proj4_text;
72 int zone =
static_cast<int>(std::ceil((lon + 180.0) / 6.0));
73 proj4_text =
"+proj=utm +zone=" + std::to_string(zone) +
74 " +ellps=WGS84 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs";
75 utm_target_ = pj_init_plus(proj4_text.c_str());
77 pj_transform(wgs84pj_source_, utm_target_, 1, 1, &px, &py, NULL);
79 Z << px, py, msg->altitude, 0, 0, 0, 0, 0, 0;
81 Eigen::MatrixXd y = Z - H_ * X_;
82 Eigen::MatrixXd S = H_ * P_ * H_.transpose() + R_;
83 Eigen::MatrixXd K = P_ * H_.transpose() * S.inverse();
85 P_ = (Eigen::MatrixXd::Identity(9, 9) - K * H_) * P_;
91 if (!gps_received_.load() || !imu_received_.load()) {
95 odom_msg.header.stamp = ros_node_->get_clock()->now();
97 odom_msg.pose.pose.position.x = X_(0);
98 odom_msg.pose.pose.position.y = X_(1);
99 odom_msg.pose.pose.position.z = X_(2);
101 odom_msg.pose.pose.orientation.x = quaternion_[0];
102 odom_msg.pose.pose.orientation.y = quaternion_[1];
103 odom_msg.pose.pose.orientation.z = quaternion_[2];
104 odom_msg.pose.pose.orientation.w = quaternion_[3];
106 odom_msg.twist.twist.linear.x = X_(3);
107 odom_msg.twist.twist.linear.y = X_(4);
108 odom_msg.twist.twist.linear.z = X_(5);
110 for (
int i = 0; i < 6; ++i) {
111 for (
int j = 0; j < 6; ++j) {
112 if (i < 3 && j < 3) {
113 odom_msg.pose.covariance[i * 6 + j] = P_(i, j);
114 }
else if (i >= 3 && j >= 3) {
115 odom_msg.pose.covariance[i * 6 + j] = P_(i + 3, j + 3);
120 for (
int i = 0; i < 3; ++i) {
121 for (
int j = 0; j < 3; ++j) {
122 odom_msg.twist.covariance[i * 6 + j] = P_(i + 3, j + 3);
126 odom_pub_->publish(odom_msg);
127 imu_received_.store(
false);
128 imu_received_.store(
false);