|
@@ -11,10 +11,11 @@
|
|
|
|
|
|
#include <glog/logging.h>
|
|
|
|
|
|
+
|
|
|
+
|
|
|
#include <geometry_msgs/TransformStamped.h>
|
|
|
#include <geometry_msgs/PoseWithCovarianceStamped.h>
|
|
|
|
|
|
-
|
|
|
hdl_backend* instance = nullptr;
|
|
|
|
|
|
|
|
@@ -33,7 +34,7 @@ int main(int argc, char* argv[]) {
|
|
|
void hdl_backend::init() {
|
|
|
map_frame_id = "map";
|
|
|
odom_frame_id = "odom";
|
|
|
- map_cloud_resolution = 0.05;
|
|
|
+ map_cloud_resolution = 0.01;
|
|
|
trans_odom2map.setIdentity();
|
|
|
max_keyframes_per_update = 10;
|
|
|
keyframe_updater.reset(new hdl_graph_slam::KeyframeUpdater(nh));
|
|
@@ -68,8 +69,8 @@ void hdl_backend::init() {
|
|
|
|
|
|
read_until_pub = nh.advertise<std_msgs::Header>("/hdl_graph_slam/read_until", 32);
|
|
|
odom_pub = nh.advertise<geometry_msgs::PoseStamped>("/opt_odom", 32);
|
|
|
-
|
|
|
-
|
|
|
+
|
|
|
+ save_map_service_server = nh.advertiseService("/hdl_graph_slam/save_map", &hdl_backend::save_map_service, this);
|
|
|
|
|
|
graph_updated = false;
|
|
|
|
|
@@ -79,8 +80,6 @@ void hdl_backend::init() {
|
|
|
|
|
|
map_publish_timer = nh.createWallTimer(ros::WallDuration(map_cloud_update_interval), &hdl_backend::map_points_publish_timer_callback, this);
|
|
|
|
|
|
- map_cloud_resolution = 0.05;
|
|
|
-
|
|
|
pcl::RadiusOutlierRemoval<PointT>::Ptr rad(new pcl::RadiusOutlierRemoval<PointT>());
|
|
|
rad->setRadiusSearch(0.8);
|
|
|
rad->setMinNeighborsInRadius(1);
|
|
@@ -92,6 +91,9 @@ void hdl_backend::init() {
|
|
|
ros::spin();
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
|
|
|
* @brief 这个函数将队列中的所有数据添加到姿势图中,然后优化姿势图
|
|
|
* @param event
|
|
@@ -198,34 +200,31 @@ void hdl_backend::optimization_timer_callback() {
|
|
|
LOG(INFO) << "end()";
|
|
|
}
|
|
|
|
|
|
-
|
|
|
void hdl_backend::publishMatrixAsPose(ros::Publisher& publisher, const Eigen::Matrix4f& matrix) {
|
|
|
-
|
|
|
- Eigen::Vector3f translation = matrix.block<3, 1>(0, 3);
|
|
|
-
|
|
|
-
|
|
|
- Eigen::Matrix3f rotation_matrix = matrix.block<3, 3>(0, 0);
|
|
|
- Eigen::Quaternionf quaternion(rotation_matrix);
|
|
|
-
|
|
|
-
|
|
|
- geometry_msgs::PoseStamped pose_msg;
|
|
|
- pose_msg.header.stamp = ros::Time
|
|
|
- ::now();
|
|
|
- pose_msg.header.frame_id = "odom";
|
|
|
-
|
|
|
- pose_msg.pose.position.x = translation.x();
|
|
|
- pose_msg.pose.position.y = translation.y();
|
|
|
- pose_msg.pose.position.z = translation.z();
|
|
|
- pose_msg.pose.orientation.x = quaternion.x();
|
|
|
- pose_msg.pose.orientation.y = quaternion.y();
|
|
|
- pose_msg.pose.orientation.z = quaternion.z();
|
|
|
- pose_msg.pose.orientation.w = quaternion.w();
|
|
|
-
|
|
|
-
|
|
|
- publisher.publish(pose_msg);
|
|
|
+
|
|
|
+ Eigen::Vector3f translation = matrix.block<3, 1>(0, 3);
|
|
|
+
|
|
|
+
|
|
|
+ Eigen::Matrix3f rotation_matrix = matrix.block<3, 3>(0, 0);
|
|
|
+ Eigen::Quaternionf quaternion(rotation_matrix);
|
|
|
+
|
|
|
+
|
|
|
+ geometry_msgs::PoseStamped pose_msg;
|
|
|
+ pose_msg.header.stamp = ros::Time ::now();
|
|
|
+ pose_msg.header.frame_id = "odom";
|
|
|
+
|
|
|
+ pose_msg.pose.position.x = translation.x();
|
|
|
+ pose_msg.pose.position.y = translation.y();
|
|
|
+ pose_msg.pose.position.z = translation.z();
|
|
|
+ pose_msg.pose.orientation.x = quaternion.x();
|
|
|
+ pose_msg.pose.orientation.y = quaternion.y();
|
|
|
+ pose_msg.pose.orientation.z = quaternion.z();
|
|
|
+ pose_msg.pose.orientation.w = quaternion.w();
|
|
|
+
|
|
|
+
|
|
|
+ publisher.publish(pose_msg);
|
|
|
}
|
|
|
|
|
|
-
|
|
|
|
|
|
* @brief generate map point cloud and publish it
|
|
|
* @param event
|
|
@@ -234,7 +233,7 @@ void hdl_backend::map_points_publish_timer_callback(const ros::WallTimerEvent& e
|
|
|
|
|
|
|
|
|
if(!graph_updated) {
|
|
|
-
|
|
|
+
|
|
|
return;
|
|
|
}
|
|
|
|
|
@@ -261,7 +260,7 @@ void hdl_backend::map_points_publish_timer_callback(const ros::WallTimerEvent& e
|
|
|
std::vector<hdl_graph_slam::KeyFrameSnapshot::Ptr> snapshot;
|
|
|
snapshot = keyframes_snapshot;
|
|
|
|
|
|
- LOG(INFO) << "keyframes_snapshot.size() = " << keyframes_snapshot.size();
|
|
|
+
|
|
|
auto cloud = map_cloud_generator->generate(snapshot, map_cloud_resolution);
|
|
|
if(!cloud) {
|
|
|
return;
|
|
@@ -273,7 +272,7 @@ void hdl_backend::map_points_publish_timer_callback(const ros::WallTimerEvent& e
|
|
|
pcl::toROSMsg(*cloud, *cloud_msg);
|
|
|
|
|
|
map_points_pub.publish(*cloud_msg);
|
|
|
- LOG(INFO) << "点云数据发布完成";
|
|
|
+
|
|
|
|
|
|
|
|
|
}
|
|
@@ -325,7 +324,9 @@ void hdl_backend::cloud_callback(const nav_msgs::OdometryConstPtr& odom_msg, con
|
|
|
filtered = outlier_removal(filtered);
|
|
|
|
|
|
|
|
|
- if(!keyframe_updater->update(odom)) {
|
|
|
+ double delta_time = 1000;
|
|
|
+ if(keyframe_queue.size() != 0) delta_time = (stamp - keyframe_queue.back()->stamp).toSec();
|
|
|
+ if(!keyframe_updater->update(odom, delta_time)) {
|
|
|
|
|
|
|
|
|
if(keyframe_queue.empty()) {
|
|
@@ -344,6 +345,8 @@ void hdl_backend::cloud_callback(const nav_msgs::OdometryConstPtr& odom_msg, con
|
|
|
|
|
|
hdl_graph_slam::KeyFrame::Ptr keyframe(new hdl_graph_slam::KeyFrame(stamp, odom, accum_d, filtered));
|
|
|
|
|
|
+
|
|
|
+
|
|
|
|
|
|
keyframe_queue.push_back(keyframe);
|
|
|
|
|
@@ -415,8 +418,8 @@ bool hdl_backend::flush_keyframe_queue() {
|
|
|
graph_slam->add_robust_kernel(edge, "NONE", 1.0);
|
|
|
|
|
|
|
|
|
- std::cout << "keyframe->node = \n" << keyframe->node->estimate().matrix() << std::endl;
|
|
|
- std::cout << "prev_keyframe->node = \n" << prev_keyframe->node->estimate().matrix() << std::endl;
|
|
|
+
|
|
|
+
|
|
|
}
|
|
|
|
|
|
std_msgs::Header read_until;
|
|
@@ -430,6 +433,47 @@ bool hdl_backend::flush_keyframe_queue() {
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+ * @brief save map data as pcd
|
|
|
+ * @param req
|
|
|
+ * @param res
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ bool hdl_backend::save_map_service(hdl_graph_slam::SaveMapRequest& req, hdl_graph_slam::SaveMapResponse& res) {
|
|
|
+ std::cout << "get in save_map_service !!!" << std::endl;
|
|
|
+ std::vector<hdl_graph_slam::KeyFrameSnapshot::Ptr> snapshot1;
|
|
|
+
|
|
|
+
|
|
|
+ snapshot1 = keyframes_snapshot;
|
|
|
+
|
|
|
+
|
|
|
+ auto cloud = map_cloud_generator->generate(snapshot1, req.resolution);
|
|
|
+ if(!cloud) {
|
|
|
+ res.success = false;
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ if(zero_utm && req.utm) {
|
|
|
+ for(auto& pt : cloud->points) {
|
|
|
+ pt.getVector3fMap() += (*zero_utm).cast<float>();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ cloud->header.frame_id = "map";
|
|
|
+ cloud->header.stamp = snapshot1.back()->cloud->header.stamp;
|
|
|
+
|
|
|
+ if(zero_utm) {
|
|
|
+ std::ofstream ofs(req.destination + ".utm");
|
|
|
+ ofs << boost::format("%.6f %.6f %.6f") % zero_utm->x() % zero_utm->y() % zero_utm->z() << std::endl;
|
|
|
+ }
|
|
|
+
|
|
|
+ int ret = pcl::io::savePCDFileBinary(req.destination, *cloud);
|
|
|
+ res.success = ret == 0;
|
|
|
+
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
|
|
|
* @brief create visualization marker
|
|
|
* @param stamp
|