diff --git a/README.md b/README.md
index 852cccd4..49c19371 100755
--- a/README.md
+++ b/README.md
@@ -171,7 +171,8 @@ To visualize the eagleye output location /eagleye/fix, for example, use the foll
To convert from eagleye/fix to eagleye/pose, use the following command 
- ros2 launch eagleye_fix2pose fix2pose.xml
+ ros2 launch eagleye_geo_pose_fusion geo_pose_fusion.launch.xml
+ ros2 launch eagleye_geo_pose_converter geo_pose_converter.launch.xml
## Sample data
### ROSBAG(ROS1)
diff --git a/eagleye_core/navigation/src/position.cpp b/eagleye_core/navigation/src/position.cpp
index 7eaf78ca..9e672719 100755
--- a/eagleye_core/navigation/src/position.cpp
+++ b/eagleye_core/navigation/src/position.cpp
@@ -60,42 +60,7 @@ void position_estimate_(geometry_msgs::msg::TwistStamped velocity,eagleye_msgs::
enu_pos[1] = position_status->enu_pos[1];
enu_pos[2] = position_status->enu_pos[2];
- if(!position_status->gnss_update_failure)
- {
- gnss_status = true;
-
- geometry_msgs::msg::PoseStamped pose;
-
- pose.pose.position.x = enu_pos[0];
- pose.pose.position.y = enu_pos[1];
- pose.pose.position.z = enu_pos[2];
-
- heading_interpolate_3rd.heading_angle = fmod(heading_interpolate_3rd.heading_angle,2*M_PI);
- tf2::Transform transform;
- tf2::Quaternion q;
- transform.setOrigin(tf2::Vector3(pose.pose.position.x, pose.pose.position.y, pose.pose.position.z));
- q.setRPY(0, 0, (90* M_PI / 180)-heading_interpolate_3rd.heading_angle);
- transform.setRotation(q);
-
- tf2::Transform transform2, transform3;
- tf2::Quaternion q2(position_parameter.tf_gnss_rotation_x,position_parameter.tf_gnss_rotation_y,
- position_parameter.tf_gnss_rotation_z,position_parameter.tf_gnss_rotation_w);
- transform2.setOrigin(tf2::Vector3(position_parameter.tf_gnss_translation_x, position_parameter.tf_gnss_translation_y,
- position_parameter.tf_gnss_translation_z));
- transform2.setRotation(q2);
- transform3 = transform * transform2.inverse();
-
- tf2::Vector3 tmp_pos;
- tmp_pos = transform3.getOrigin();
-
- enu_pos[0] = tmp_pos.getX();
- enu_pos[1] = tmp_pos.getY();
- enu_pos[2] = tmp_pos.getZ();
- }
- else
- {
- gnss_status = false;
- }
+ gnss_status = !position_status->gnss_update_failure;
if (heading_interpolate_3rd.status.estimate_status == true && velocity_status.status.enabled_status == true)
{
diff --git a/eagleye_core/navigation/src/rtk_dead_reckoning.cpp b/eagleye_core/navigation/src/rtk_dead_reckoning.cpp
index 05cf1bf9..649d2206 100755
--- a/eagleye_core/navigation/src/rtk_dead_reckoning.cpp
+++ b/eagleye_core/navigation/src/rtk_dead_reckoning.cpp
@@ -64,31 +64,6 @@ void rtk_dead_reckoning_estimate_(geometry_msgs::msg::Vector3Stamped enu_vel, nm
llh2xyz(llh_rtk,ecef_rtk);
xyz2enu(ecef_rtk,ecef_base_pos,enu_rtk);
- geometry_msgs::msg::PoseStamped pose;
-
- pose.pose.position.x = enu_rtk[0];
- pose.pose.position.y = enu_rtk[1];
- pose.pose.position.z = enu_rtk[2];
-
- heading.heading_angle = fmod(heading.heading_angle,2*M_PI);
- tf2::Transform transform;
- tf2::Quaternion q;
- transform.setOrigin(tf2::Vector3(pose.pose.position.x, pose.pose.position.y, pose.pose.position.z));
- q.setRPY(0, 0, (90* M_PI / 180)-heading.heading_angle);
- transform.setRotation(q);
-
- tf2::Transform transform2;
- tf2::Quaternion q2(rtk_dead_reckoning_parameter.tf_gnss_rotation_x,rtk_dead_reckoning_parameter.tf_gnss_rotation_y,rtk_dead_reckoning_parameter.tf_gnss_rotation_z,rtk_dead_reckoning_parameter.tf_gnss_rotation_w);
- transform2.setOrigin(transform*tf2::Vector3(-rtk_dead_reckoning_parameter.tf_gnss_translation_x, -rtk_dead_reckoning_parameter.tf_gnss_translation_y,-rtk_dead_reckoning_parameter.tf_gnss_translation_z));
- transform2.setRotation(transform*q2);
-
- tf2::Vector3 tmp_pos;
- tmp_pos = transform2.getOrigin();
-
- enu_rtk[0] = tmp_pos.getX();
- enu_rtk[1] = tmp_pos.getY();
- enu_rtk[2] = tmp_pos.getZ();
-
if (rtk_dead_reckoning_status->position_stamp_last != gga_time && gga.gps_qual == 4)
{
rtk_dead_reckoning_status->provisional_enu_pos_x = enu_rtk[0];
diff --git a/eagleye_rt/launch/eagleye_rt.launch.xml b/eagleye_rt/launch/eagleye_rt.launch.xml
index 8408db42..ec9d50d8 100644
--- a/eagleye_rt/launch/eagleye_rt.launch.xml
+++ b/eagleye_rt/launch/eagleye_rt.launch.xml
@@ -145,7 +145,9 @@
-
+
+
+
diff --git a/eagleye_util/fix2pose/src/fix2pose.cpp b/eagleye_util/fix2pose/src/fix2pose.cpp
deleted file mode 100644
index 8ed4fe7f..00000000
--- a/eagleye_util/fix2pose/src/fix2pose.cpp
+++ /dev/null
@@ -1,348 +0,0 @@
-// Copyright (c) 2019, Map IV, Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-// * Redistributions of source code must retain the above copyright notice,
-// this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-// * Neither the name of the Map IV, Inc. nor the names of its contributors
-// may be used to endorse or promote products derived from this software
-// without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER BE LIABLE FOR ANY
-// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-/*
- * fix2pose.cpp
- * Author MapIV Sekino
- */
-
-#include "rclcpp/rclcpp.hpp"
-#include "geometry_msgs/msg/point_stamped.hpp"
-#include "geometry_msgs/msg/pose_stamped.hpp"
-#include "geometry_msgs/msg/pose_with_covariance_stamped.hpp"
-#include "sensor_msgs/msg/nav_sat_fix.hpp"
-#include "eagleye_msgs/msg/rolling.hpp"
-#include "eagleye_msgs/msg/pitching.hpp"
-#include "eagleye_msgs/msg/heading.hpp"
-#include "eagleye_msgs/msg/position.hpp"
-#include "tf2_ros/transform_broadcaster.h"
-#include
-#include
-#ifdef ROS_DISTRO_GALACTIC
-#include
-#else
-#include
-#endif
-#include "eagleye_coordinate/eagleye_coordinate.hpp"
-#include
-#include
-
-#include
-#include
-
-rclcpp::Clock _ros_clock(RCL_ROS_TIME);
-
-static eagleye_msgs::msg::Rolling _eagleye_rolling;
-static eagleye_msgs::msg::Pitching _eagleye_pitching;
-static eagleye_msgs::msg::Heading _eagleye_heading;
-static geometry_msgs::msg::Quaternion _quat;
-
-rclcpp::Publisher::SharedPtr _pub;
-rclcpp::Publisher::SharedPtr _pub2;
-rclcpp::Publisher::SharedPtr _pub3;
-std::shared_ptr _br;
-std::shared_ptr _br2;
-static geometry_msgs::msg::PoseStamped _pose;
-static geometry_msgs::msg::PoseWithCovarianceStamped _pose_with_covariance;
-
-static std::string _parent_frame_id, _child_frame_id;
-static std::string _base_link_frame_id, _gnss_frame_id;
-
-std::string geoid_file_path = ament_index_cpp::get_package_share_directory("llh_converter") + "/data/gsigeo2011_ver2_1.asc";
-llh_converter::LLHConverter _lc(geoid_file_path);
-llh_converter::LLHParam _llh_param;
-
-bool _fix_only_publish = false;
-int _fix_judgement_type = 0;
-int _fix_gnss_status = 0;
-double _fix_std_pos_thres = 0.1; // [m]
-
-std::string _node_name = "eagleye_fix2pose";
-
-tf2_ros::Buffer _tf_buffer(std::make_shared(_ros_clock));
-
-void heading_callback(const eagleye_msgs::msg::Heading::ConstSharedPtr msg)
-{
- _eagleye_heading = *msg;
-}
-
-void rolling_callback(const eagleye_msgs::msg::Rolling::ConstSharedPtr msg)
-{
- _eagleye_rolling = *msg;
-}
-
-void pitching_callback(const eagleye_msgs::msg::Pitching::ConstSharedPtr msg)
-{
- _eagleye_pitching = *msg;
-}
-
-void fix_callback(const sensor_msgs::msg::NavSatFix::ConstSharedPtr msg)
-{
- if(!_eagleye_heading.status.enabled_status)
- {
- RCLCPP_WARN(rclcpp::get_logger(_node_name), "heading is not enabled to publish pose");
- return;
- }
-
- if(_fix_only_publish)
- {
- if(_fix_judgement_type == 0)
- {
- if(!msg->status.status == 0)
- {
- RCLCPP_WARN(rclcpp::get_logger(_node_name), "status.status is not 0");
- return;
- }
- }
- else if(_fix_judgement_type == 1)
- {
- if(msg->position_covariance[0] > _fix_std_pos_thres * _fix_std_pos_thres)
- {
- RCLCPP_WARN(rclcpp::get_logger(_node_name), "position_covariance[0] is over %f", _fix_std_pos_thres * _fix_std_pos_thres);
- return;
- }
- }
- else
- {
- RCLCPP_ERROR(rclcpp::get_logger(_node_name), "fix_judgement_type is not valid");
- rclcpp::shutdown();
- }
- }
-
- double llh[3] = {0};
- double xyz[3] = {0};
-
- llh[0] = msg->latitude * M_PI / 180;
- llh[1] = msg->longitude* M_PI / 180;
- llh[2] = msg->altitude;
-
- _lc.convertRad2XYZ(llh[0], llh[1], llh[2], xyz[0], xyz[1], xyz[2], _llh_param);
-
- double eagleye_heading = 0;
- tf2::Quaternion localization_quat;
- eagleye_heading = fmod((90* M_PI / 180)-_eagleye_heading.heading_angle,2*M_PI);
- llh_converter::LLA lla_struct;
- llh_converter::XYZ xyz_struct;
- lla_struct.latitude = msg->latitude;
- lla_struct.longitude = msg->longitude;
- lla_struct.altitude = msg->altitude;
- xyz_struct.x = xyz[0];
- xyz_struct.y = xyz[1];
- xyz_struct.z = xyz[2];
- double mca = llh_converter::getMeridianConvergence(lla_struct, xyz_struct, _lc, _llh_param); // meridian convergence angle
- eagleye_heading += mca;
-
- localization_quat.setRPY(0, 0, eagleye_heading);
- _quat = tf2::toMsg(localization_quat);
-
-
- _pose.header = msg->header;
- _pose.header.frame_id = "map";
- _pose.pose.position.x = xyz[0];
- _pose.pose.position.y = xyz[1];
- _pose.pose.position.z = xyz[2];
- _pose.pose.orientation = _quat;
-
- geometry_msgs::msg::PoseStamped::Ptr transformed_pose_msg_ptr(
- new geometry_msgs::msg::PoseStamped);
-
- if(_fix_only_publish)
- {
- geometry_msgs::msg::TransformStamped::Ptr TF_sensor_to_base_ptr(new geometry_msgs::msg::TransformStamped);
- try
- {
- *TF_sensor_to_base_ptr = _tf_buffer.lookupTransform(_gnss_frame_id, _base_link_frame_id, tf2::TimePointZero);
-
- tf2::Transform transform, transform2, transfrom3;
- transform.setOrigin(tf2::Vector3(_pose.pose.position.x, _pose.pose.position.y,
- _pose.pose.position.z));
- transform.setRotation(localization_quat);
- tf2::Quaternion q2(TF_sensor_to_base_ptr->transform.rotation.x, TF_sensor_to_base_ptr->transform.rotation.y,
- TF_sensor_to_base_ptr->transform.rotation.z, TF_sensor_to_base_ptr->transform.rotation.w);
- transform2.setOrigin(tf2::Vector3(TF_sensor_to_base_ptr->transform.translation.x,
- TF_sensor_to_base_ptr->transform.translation.y, TF_sensor_to_base_ptr->transform.translation.z));
- transform2.setRotation(q2);
- transfrom3 = transform * transform2;
-
- _pose.header.frame_id = _parent_frame_id;
- _pose.pose.position.x = transfrom3.getOrigin().getX();
- _pose.pose.position.y = transfrom3.getOrigin().getY();
- _pose.pose.position.z = transfrom3.getOrigin().getZ();
- _pose.pose.orientation.x = transfrom3.getRotation().getX();
- _pose.pose.orientation.y = transfrom3.getRotation().getY();
- _pose.pose.orientation.z = transfrom3.getRotation().getZ();
- _pose.pose.orientation.w = transfrom3.getRotation().getW();
-
- }
- catch (tf2::TransformException& ex)
- {
- RCLCPP_WARN(rclcpp::get_logger(_node_name), "%s", ex.what());
- return;
- }
- }
-
- _pub->publish(_pose);
-
- _pose_with_covariance.header = _pose.header;
- _pose_with_covariance.pose.pose = _pose.pose;
- // TODO(Map IV): temporary value
- double std_dev_roll = 100; // [rad]
- double std_dev_pitch = 100; // [rad]
- double std_dev_yaw = 100; // [rad]
- if(_eagleye_rolling.status.enabled_status) std_dev_roll = 0.5 / 180 * M_PI;
- if(_eagleye_pitching.status.enabled_status) std_dev_pitch = 0.5 / 180 * M_PI;
- if(_eagleye_heading.status.enabled_status) std_dev_yaw = std::sqrt(_eagleye_heading.variance);
- _pose_with_covariance.pose.covariance[0] = msg->position_covariance[0];
- _pose_with_covariance.pose.covariance[7] = msg->position_covariance[4];
- _pose_with_covariance.pose.covariance[14] = msg->position_covariance[8];
- _pose_with_covariance.pose.covariance[21] = std_dev_roll * std_dev_roll;
- _pose_with_covariance.pose.covariance[28] = std_dev_pitch * std_dev_pitch;
- _pose_with_covariance.pose.covariance[35] = std_dev_yaw * std_dev_yaw;
- _pub2->publish(_pose_with_covariance);
-
- tf2::Transform transform;
- tf2::Quaternion q;
- transform.setOrigin(tf2::Vector3(_pose.pose.position.x, _pose.pose.position.y, _pose.pose.position.z));
- q.setRPY(0, 0, (90* M_PI / 180)- _eagleye_heading.heading_angle);
- transform.setRotation(q);
-
- geometry_msgs::msg::TransformStamped trans_msg;
- trans_msg.header.stamp = msg->header.stamp;
- trans_msg.header.frame_id = _parent_frame_id;
- trans_msg.child_frame_id = _child_frame_id;
- trans_msg.transform = tf2::toMsg(transform);
- _br->sendTransform(trans_msg);
-}
-
-int main(int argc, char** argv)
-{
- int plane = 7;
- int tf_num = 7;
- int convert_height_num = 7;
- int geoid_type = 0;
-
- rclcpp::init(argc, argv);
- auto node = rclcpp::Node::make_shared(_node_name);
-
- node->declare_parameter("plane", plane);
- node->declare_parameter("tf_num", tf_num);
- node->declare_parameter("convert_height_num", convert_height_num);
- node->declare_parameter("geoid_type", geoid_type);
- node->declare_parameter("parent_frame_id", _parent_frame_id);
- node->declare_parameter("child_frame_id", _child_frame_id);
- node->declare_parameter("fix_only_publish", _fix_only_publish);
- node->declare_parameter("fix_judgement_type", _fix_judgement_type);
- node->declare_parameter("fix_gnss_status", _fix_gnss_status);
- node->declare_parameter("fix_std_pos_thres", _fix_std_pos_thres);
- node->declare_parameter("base_link_frame_id", _base_link_frame_id);
- node->declare_parameter("gnss_frame_id", _gnss_frame_id);
-
- node->get_parameter("plane", plane);
- node->get_parameter("tf_num", tf_num);
- node->get_parameter("convert_height_num", convert_height_num);
- node->get_parameter("geoid_type", geoid_type);
- node->get_parameter("parent_frame_id", _parent_frame_id);
- node->get_parameter("child_frame_id", _child_frame_id);
- node->get_parameter("fix_only_publish", _fix_only_publish);
- node->get_parameter("fix_judgement_type", _fix_judgement_type);
- node->get_parameter("fix_gnss_status", _fix_gnss_status);
- node->get_parameter("fix_std_pos_thres", _fix_std_pos_thres);
- node->get_parameter("base_link_frame_id", _base_link_frame_id);
- node->get_parameter("gnss_frame_id", _gnss_frame_id);
-
- std::cout<< "plane "<< plane<create_subscription("heading_interpolate_3rd", 1000, heading_callback);
- auto sub3 = node->create_subscription("fix", 1000, fix_callback);
- auto sub4 = node->create_subscription("rolling", 1000, rolling_callback);
- auto sub5 = node->create_subscription("pitching", 1000, pitching_callback);
- _pub = node->create_publisher("pose", 1000);
- _pub2 = node->create_publisher("pose_with_covariance", 1000);
- _br = std::make_shared(node, 100);
- _br2 = std::make_shared(node, 100);
- rclcpp::spin(node);
-
- return 0;
-}
diff --git a/eagleye_util/fix2pose/CMakeLists.txt b/eagleye_util/geo_pose_converter/CMakeLists.txt
similarity index 80%
rename from eagleye_util/fix2pose/CMakeLists.txt
rename to eagleye_util/geo_pose_converter/CMakeLists.txt
index 24c2ef71..c7346092 100644
--- a/eagleye_util/fix2pose/CMakeLists.txt
+++ b/eagleye_util/geo_pose_converter/CMakeLists.txt
@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.5)
-project(eagleye_fix2pose)
+project(eagleye_geo_pose_converter)
# Default to C99
if(NOT CMAKE_C_STANDARD)
@@ -15,17 +15,13 @@ if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
add_compile_options(-Wall -Wextra -Wpedantic)
endif()
-if($ENV{ROS_DISTRO} STREQUAL "galactic")
- add_definitions(-DROS_DISTRO_GALACTIC)
-endif()
-
find_package(ament_cmake_auto REQUIRED)
ament_auto_find_build_dependencies()
include_directories(include)
-ament_auto_add_executable(fix2pose
- src/fix2pose.cpp
+ament_auto_add_executable(geo_pose_converter
+ src/geo_pose_converter.cpp
)
install(TARGETS
diff --git a/eagleye_util/fix2pose/launch/fix2pose.launch.xml b/eagleye_util/geo_pose_converter/launch/geo_pose_converter.launch.xml
similarity index 50%
rename from eagleye_util/fix2pose/launch/fix2pose.launch.xml
rename to eagleye_util/geo_pose_converter/launch/geo_pose_converter.launch.xml
index 9f130a90..b79016f9 100644
--- a/eagleye_util/fix2pose/launch/fix2pose.launch.xml
+++ b/eagleye_util/geo_pose_converter/launch/geo_pose_converter.launch.xml
@@ -1,10 +1,10 @@
+
-
-
-
+
+
@@ -12,23 +12,13 @@
-
+
-
-
-
-
-
-
-
-
-
-
diff --git a/eagleye_util/fix2pose/package.xml b/eagleye_util/geo_pose_converter/package.xml
similarity index 77%
rename from eagleye_util/fix2pose/package.xml
rename to eagleye_util/geo_pose_converter/package.xml
index 5f022163..b3169206 100644
--- a/eagleye_util/fix2pose/package.xml
+++ b/eagleye_util/geo_pose_converter/package.xml
@@ -1,35 +1,36 @@
- eagleye_fix2pose
+ eagleye_geo_pose_converter
1.0.0
- fix2pose package
+ geo_pose_converter package
OsamuSekino
+ Koji Minoda
BSD3
- ament_cmake
+ ament_cmake_auto
rclcpp
- rclpy
std_msgs
eagleye_msgs
eagleye_navigation
tf2_ros
eagleye_coordinate
+ geographic_msgs
rclcpp
- rclpy
std_msgs
eagleye_msgs
eagleye_navigation
tf2_ros
eagleye_coordinate
+ geographic_msgs
rclcpp
- rclpy
std_msgs
eagleye_msgs
eagleye_navigation
tf2_ros
eagleye_coordinate
+ geographic_msgs
llh_converter
std_srvs
diff --git a/eagleye_util/geo_pose_converter/src/geo_pose_converter.cpp b/eagleye_util/geo_pose_converter/src/geo_pose_converter.cpp
new file mode 100644
index 00000000..59746d03
--- /dev/null
+++ b/eagleye_util/geo_pose_converter/src/geo_pose_converter.cpp
@@ -0,0 +1,245 @@
+// Copyright (c) 2019, Map IV, Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of the Map IV, Inc. nor the names of its contributors
+// may be used to endorse or promote products derived from this software
+// without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+/*
+ * geo_pose_converter.cpp
+ * Author MapIV Sekino
+ */
+
+#include "rclcpp/rclcpp.hpp"
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#ifdef ROS_DISTRO_GALACTIC
+#include
+#else
+#include
+#endif
+#include
+#include
+
+#include
+
+rclcpp::Clock _ros_clock(RCL_ROS_TIME);
+
+rclcpp::Publisher::SharedPtr _pub;
+rclcpp::Publisher::SharedPtr _pub2;
+std::shared_ptr _br;
+
+static std::string _parent_frame_id, _child_frame_id;
+static std::string _base_link_frame_id, _gnss_frame_id;
+
+std::string geoid_file_path = ament_index_cpp::get_package_share_directory("llh_converter") + "/data/gsigeo2011_ver2_1.asc";
+llh_converter::LLHConverter _lc(geoid_file_path);
+llh_converter::LLHParam _llh_param;
+
+std::string _node_name = "eagleye_geo_pose_converter";
+
+tf2_ros::Buffer _tf_buffer(std::make_shared(_ros_clock));
+
+void geo_pose_callback(const geographic_msgs::msg::GeoPoseWithCovarianceStamped::ConstSharedPtr msg)
+{
+ double llh[3] = {0};
+ double xyz[3] = {0};
+
+ llh[0] = msg->pose.pose.position.latitude * M_PI / 180;
+ llh[1] = msg->pose.pose.position.longitude* M_PI / 180;
+ llh[2] = msg->pose.pose.position.altitude;
+
+ _lc.convertRad2XYZ(llh[0], llh[1], llh[2], xyz[0], xyz[1], xyz[2], _llh_param);
+
+ geometry_msgs::msg::PoseStamped pose;
+ pose.header = msg->header;
+ pose.header.frame_id = "map";
+ pose.pose.position.x = xyz[0];
+ pose.pose.position.y = xyz[1];
+ pose.pose.position.z = xyz[2];
+ pose.pose.orientation = msg->pose.pose.orientation;
+
+ const auto localization_quat = tf2::Quaternion(pose.pose.orientation.x, pose.pose.orientation.y,
+ pose.pose.orientation.z, pose.pose.orientation.w);
+
+ geometry_msgs::msg::PoseStamped::SharedPtr transformed_pose_msg_ptr(
+ new geometry_msgs::msg::PoseStamped);
+
+ geometry_msgs::msg::TransformStamped::SharedPtr TF_sensor_to_base_ptr(new geometry_msgs::msg::TransformStamped);
+ try
+ {
+ *TF_sensor_to_base_ptr = _tf_buffer.lookupTransform(_gnss_frame_id, _base_link_frame_id, tf2::TimePointZero);
+
+ tf2::Transform transform, transform2, transfrom3;
+ transform.setOrigin(tf2::Vector3(pose.pose.position.x, pose.pose.position.y,
+ pose.pose.position.z));
+ transform.setRotation(localization_quat);
+ tf2::Quaternion q2(TF_sensor_to_base_ptr->transform.rotation.x, TF_sensor_to_base_ptr->transform.rotation.y,
+ TF_sensor_to_base_ptr->transform.rotation.z, TF_sensor_to_base_ptr->transform.rotation.w);
+ transform2.setOrigin(tf2::Vector3(TF_sensor_to_base_ptr->transform.translation.x,
+ TF_sensor_to_base_ptr->transform.translation.y, TF_sensor_to_base_ptr->transform.translation.z));
+ transform2.setRotation(q2);
+ transfrom3 = transform * transform2;
+
+ pose.header.frame_id = _parent_frame_id;
+ pose.pose.position.x = transfrom3.getOrigin().getX();
+ pose.pose.position.y = transfrom3.getOrigin().getY();
+ pose.pose.position.z = transfrom3.getOrigin().getZ();
+ pose.pose.orientation.x = transfrom3.getRotation().getX();
+ pose.pose.orientation.y = transfrom3.getRotation().getY();
+ pose.pose.orientation.z = transfrom3.getRotation().getZ();
+ pose.pose.orientation.w = transfrom3.getRotation().getW();
+
+ }
+ catch (tf2::TransformException& ex)
+ {
+ RCLCPP_WARN(rclcpp::get_logger(_node_name), "%s", ex.what());
+ return;
+ }
+
+ _pub->publish(pose);
+
+ geometry_msgs::msg::PoseWithCovarianceStamped pose_with_covariance;
+ pose_with_covariance.header = pose.header;
+ pose_with_covariance.pose.pose = pose.pose;
+
+ // Covariance in NavSatFix is in ENU coordinate while the one in GeoPoseWithCovariance is in Lat/Lon/Alt coordinate.
+ // In order to be consistent with the msg definition, we need to swap the covariance of x and y.
+ pose_with_covariance.pose.covariance[0] = msg->pose.covariance[7];
+ pose_with_covariance.pose.covariance[7] = msg->pose.covariance[0];
+ pose_with_covariance.pose.covariance[14] = msg->pose.covariance[14];
+ pose_with_covariance.pose.covariance[21] = msg->pose.covariance[21];
+ pose_with_covariance.pose.covariance[28] = msg->pose.covariance[28];
+ pose_with_covariance.pose.covariance[35] = msg->pose.covariance[35];
+ _pub2->publish(pose_with_covariance);
+
+ tf2::Transform transform;
+ transform.setOrigin(tf2::Vector3(pose.pose.position.x, pose.pose.position.y, pose.pose.position.z));
+ // NOTE: currently geo_pose_fuser, the node before this node, ignores roll and pitch for robust estimation results.
+ transform.setRotation(localization_quat);
+
+ geometry_msgs::msg::TransformStamped trans_msg;
+ trans_msg.header.stamp = msg->header.stamp;
+ trans_msg.header.frame_id = _parent_frame_id;
+ trans_msg.child_frame_id = _child_frame_id;
+ trans_msg.transform = tf2::toMsg(transform);
+ _br->sendTransform(trans_msg);
+}
+
+int main(int argc, char** argv)
+{
+ int plane = 7;
+ int tf_num = 7;
+ int convert_height_num = 7;
+ int geoid_type = 0;
+
+ rclcpp::init(argc, argv);
+ auto node = rclcpp::Node::make_shared(_node_name);
+
+ node->declare_parameter("plane", plane);
+ node->declare_parameter("tf_num", tf_num);
+ node->declare_parameter("convert_height_num", convert_height_num);
+ node->declare_parameter("geoid_type", geoid_type);
+ node->declare_parameter("parent_frame_id", _parent_frame_id);
+ node->declare_parameter("child_frame_id", _child_frame_id);
+ node->declare_parameter("base_link_frame_id", _base_link_frame_id);
+ node->declare_parameter("gnss_frame_id", _gnss_frame_id);
+
+ node->get_parameter("plane", plane);
+ node->get_parameter("tf_num", tf_num);
+ node->get_parameter("convert_height_num", convert_height_num);
+ node->get_parameter("geoid_type", geoid_type);
+ node->get_parameter("parent_frame_id", _parent_frame_id);
+ node->get_parameter("child_frame_id", _child_frame_id);
+ node->get_parameter("base_link_frame_id", _base_link_frame_id);
+ node->get_parameter("gnss_frame_id", _gnss_frame_id);
+
+ std::cout<< "plane "<< plane<create_subscription("eagleye/geo_pose_with_covariance", 1000, geo_pose_callback);
+ _pub = node->create_publisher("eagleye/pose", 1000);
+ _pub2 = node->create_publisher("eagleye/pose_with_covariance", 1000);
+ _br = std::make_shared(node, 100);
+ rclcpp::spin(node);
+
+ return 0;
+}
diff --git a/eagleye_util/geo_pose_fusion/CMakeLists.txt b/eagleye_util/geo_pose_fusion/CMakeLists.txt
new file mode 100644
index 00000000..7780d41a
--- /dev/null
+++ b/eagleye_util/geo_pose_fusion/CMakeLists.txt
@@ -0,0 +1,40 @@
+cmake_minimum_required(VERSION 3.5)
+project(eagleye_geo_pose_fusion)
+
+# Default to C99
+if(NOT CMAKE_C_STANDARD)
+ set(CMAKE_C_STANDARD 99)
+endif()
+
+# Default to C++14
+if(NOT CMAKE_CXX_STANDARD)
+ set(CMAKE_CXX_STANDARD 14)
+endif()
+
+if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
+ add_compile_options(-Wall -Wextra -Wpedantic)
+endif()
+
+find_package(ament_cmake_auto REQUIRED)
+ament_auto_find_build_dependencies()
+
+include_directories(include)
+
+ament_auto_add_executable(geo_pose_fusion
+ src/geo_pose_fusion.cpp
+)
+
+install(TARGETS
+ DESTINATION lib/$(PROJECT_NAME)
+)
+
+install(DIRECTORY launch
+ DESTINATION share/${PROJECT_NAME}
+)
+
+if(BUILD_TESTING)
+ find_package(ament_lint_auto REQUIRED)
+ ament_lint_auto_find_test_dependencies()
+endif()
+
+ament_auto_package()
diff --git a/eagleye_util/geo_pose_fusion/launch/geo_pose_fusion.launch.xml b/eagleye_util/geo_pose_fusion/launch/geo_pose_fusion.launch.xml
new file mode 100644
index 00000000..2224bf18
--- /dev/null
+++ b/eagleye_util/geo_pose_fusion/launch/geo_pose_fusion.launch.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/eagleye_util/geo_pose_fusion/package.xml b/eagleye_util/geo_pose_fusion/package.xml
new file mode 100644
index 00000000..66c0170b
--- /dev/null
+++ b/eagleye_util/geo_pose_fusion/package.xml
@@ -0,0 +1,31 @@
+
+
+ eagleye_geo_pose_fusion
+ 1.0.0
+ geo_pose_fusion package
+
+ Ryohei Sasaki
+ Koji Minoda
+
+ BSD3
+
+ ament_cmake_auto
+ rclcpp
+ eagleye_msgs
+ geographic_msgs
+ rclcpp
+ eagleye_msgs
+ geographic_msgs
+ rclcpp
+ eagleye_msgs
+ geographic_msgs
+
+ ament_lint_auto
+ ament_lint_common
+
+ tf2_geometry_msgs
+
+
+ ament_cmake
+
+
diff --git a/eagleye_util/geo_pose_fusion/src/geo_pose_fusion.cpp b/eagleye_util/geo_pose_fusion/src/geo_pose_fusion.cpp
new file mode 100644
index 00000000..d365c082
--- /dev/null
+++ b/eagleye_util/geo_pose_fusion/src/geo_pose_fusion.cpp
@@ -0,0 +1,165 @@
+// Copyright (c) 2019, Map IV, Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of the Map IV, Inc. nor the names of its contributors
+// may be used to endorse or promote products derived from this software
+// without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+/*
+ * geo_pose_fusion.cpp
+ * Author MapIV Sekino
+ */
+
+#include "rclcpp/rclcpp.hpp"
+#include
+#include
+#include
+#include
+#include
+#include
+#ifdef ROS_DISTRO_GALACTIC
+#include
+#else
+#include
+#endif
+#include
+
+rclcpp::Clock _ros_clock(RCL_ROS_TIME);
+
+static eagleye_msgs::msg::Rolling _eagleye_rolling;
+static eagleye_msgs::msg::Pitching _eagleye_pitching;
+static eagleye_msgs::msg::Heading _eagleye_heading;
+static geometry_msgs::msg::Quaternion _quat;
+
+rclcpp::Publisher::SharedPtr _pub;
+static geographic_msgs::msg::GeoPoseWithCovarianceStamped _geo_pose_with_covariance;
+
+bool _fix_only_publish = false;
+int _fix_judgement_type = 0;
+double _fix_std_pos_thres = 0.1; // [m]
+
+std::string _node_name = "eagleye_geo_pose_fusion";
+
+void heading_callback(const eagleye_msgs::msg::Heading::ConstSharedPtr msg)
+{
+ _eagleye_heading = *msg;
+}
+
+void rolling_callback(const eagleye_msgs::msg::Rolling::ConstSharedPtr msg)
+{
+ _eagleye_rolling = *msg;
+}
+
+void pitching_callback(const eagleye_msgs::msg::Pitching::ConstSharedPtr msg)
+{
+ _eagleye_pitching = *msg;
+}
+
+void fix_callback(const sensor_msgs::msg::NavSatFix::ConstSharedPtr msg)
+{
+ bool fix_flag = false;
+ if(_fix_judgement_type == 0)
+ {
+ if(msg->status.status == 0 && _eagleye_heading.status.enabled_status) fix_flag = true;
+ }
+ else if(_fix_judgement_type == 1)
+ {
+ if(msg->position_covariance[0] < _fix_std_pos_thres * _fix_std_pos_thres && _eagleye_heading.status.enabled_status) fix_flag = true;
+ }
+ else
+ {
+ RCLCPP_ERROR(rclcpp::get_logger(_node_name), "fix_judgement_type is not valid");
+ rclcpp::shutdown();
+ }
+
+ if(_fix_only_publish && !fix_flag)
+ {
+ return;
+ }
+
+ double eagleye_heading = 0;
+ tf2::Quaternion localization_quat;
+ if (_eagleye_heading.status.enabled_status)
+ {
+ // NOTE: currently geo_pose_fusion ignores roll and pitch for robust estimation results.
+ eagleye_heading = fmod((90* M_PI / 180)-_eagleye_heading.heading_angle,2*M_PI);
+ localization_quat.setRPY(0, 0, eagleye_heading);
+ }
+ else
+ {
+ tf2::Matrix3x3(localization_quat).setRPY(0, 0, 0);
+ }
+ _quat = tf2::toMsg(localization_quat);
+
+
+ _geo_pose_with_covariance.header = msg->header;
+ _geo_pose_with_covariance.header.frame_id = "map";
+ _geo_pose_with_covariance.pose.pose.position.latitude = msg->latitude;
+ _geo_pose_with_covariance.pose.pose.position.longitude = msg->longitude;
+ _geo_pose_with_covariance.pose.pose.position.altitude = msg->altitude;
+ _geo_pose_with_covariance.pose.pose.orientation = _quat;
+
+ // TODO(Map IV): temporary value
+ double std_dev_roll = 100; // [rad]
+ double std_dev_pitch = 100; // [rad]
+ double std_dev_yaw = 100; // [rad]
+ if(_eagleye_rolling.status.enabled_status) std_dev_roll = 0.5 / 180 * M_PI;
+ if(_eagleye_pitching.status.enabled_status) std_dev_pitch = 0.5 / 180 * M_PI;
+ if(_eagleye_heading.status.enabled_status) std_dev_yaw = std::sqrt(_eagleye_heading.variance);
+
+ // Covariance in NavSatFix is in ENU coordinate while the one in GeoPoseWithCovariance is in Lat/Lon/Alt coordinate.
+ // In order to be consistent with the msg definition, we need to swap the covariance of x and y.
+ _geo_pose_with_covariance.pose.covariance[0] = msg->position_covariance[4];
+ _geo_pose_with_covariance.pose.covariance[7] = msg->position_covariance[0];
+ _geo_pose_with_covariance.pose.covariance[14] = msg->position_covariance[8];
+
+ _geo_pose_with_covariance.pose.covariance[21] = std_dev_roll * std_dev_roll;
+ _geo_pose_with_covariance.pose.covariance[28] = std_dev_pitch * std_dev_pitch;
+ _geo_pose_with_covariance.pose.covariance[35] = std_dev_yaw * std_dev_yaw;
+ _pub->publish(_geo_pose_with_covariance);
+}
+
+int main(int argc, char** argv)
+{
+ rclcpp::init(argc, argv);
+ auto node = rclcpp::Node::make_shared(_node_name);
+
+ node->declare_parameter("fix_only_publish", _fix_only_publish);
+ node->declare_parameter("fix_judgement_type", _fix_judgement_type);
+ node->declare_parameter("fix_std_pos_thres", _fix_std_pos_thres);
+
+ node->get_parameter("fix_only_publish", _fix_only_publish);
+ node->get_parameter("fix_judgement_type", _fix_judgement_type);
+ node->get_parameter("fix_std_pos_thres", _fix_std_pos_thres);
+
+ std::cout<< "fix_only_publish "<< _fix_only_publish<create_subscription("eagleye/heading_interpolate_3rd", 1000, heading_callback);
+ auto sub3 = node->create_subscription("eagleye/fix", 1000, fix_callback);
+ auto sub4 = node->create_subscription("eagleye/rolling", 1000, rolling_callback);
+ auto sub5 = node->create_subscription("eagleye/pitching", 1000, pitching_callback);
+ _pub = node->create_publisher("eagleye/geo_pose_with_covariance", 1000);
+ rclcpp::spin(node);
+
+ return 0;
+}