|
@@ -11,6 +11,10 @@
|
|
|
|
|
|
#include <glog/logging.h>
|
|
|
|
|
|
+#include <geometry_msgs/TransformStamped.h>
|
|
|
+#include <geometry_msgs/PoseWithCovarianceStamped.h>
|
|
|
+
|
|
|
+
|
|
|
hdl_backend* instance = nullptr;
|
|
|
|
|
|
|
|
@@ -34,7 +38,7 @@ void hdl_backend::init() {
|
|
|
max_keyframes_per_update = 10;
|
|
|
keyframe_updater.reset(new hdl_graph_slam::KeyframeUpdater(nh));
|
|
|
points_topic = "/velodyne_points";
|
|
|
- graph_slam.reset(new hdl_graph_slam::GraphSLAM("lm_var"));
|
|
|
+ graph_slam.reset(new hdl_graph_slam::GraphSLAM("lm_var_cholmod"));
|
|
|
|
|
|
|
|
|
auto voxelgrid = new pcl::VoxelGrid<PointT>();
|
|
@@ -48,7 +52,9 @@ void hdl_backend::init() {
|
|
|
anchor_edge = nullptr;
|
|
|
odom_sub.reset(new message_filters::Subscriber<nav_msgs::Odometry>(nh, "/laser_odom", 256));
|
|
|
|
|
|
- cloud_sub.reset(new message_filters::Subscriber<sensor_msgs::PointCloud2>(nh, "/filtered_points", 32));
|
|
|
+
|
|
|
+ cloud_sub.reset(new message_filters::Subscriber<sensor_msgs::PointCloud2>(nh, "/filtered_points", 32));
|
|
|
+
|
|
|
|
|
|
|
|
|
|
|
@@ -61,7 +67,8 @@ void hdl_backend::init() {
|
|
|
map_points_pub2 = nh.advertise<sensor_msgs::PointCloud2>("/hdl_graph_slam/map_points2", 1, true);
|
|
|
|
|
|
read_until_pub = nh.advertise<std_msgs::Header>("/hdl_graph_slam/read_until", 32);
|
|
|
-
|
|
|
+ odom_pub = nh.advertise<geometry_msgs::PoseStamped>("/opt_odom", 32);
|
|
|
+
|
|
|
|
|
|
|
|
|
graph_updated = false;
|
|
@@ -107,7 +114,7 @@ void hdl_backend::optimization_timer_callback() {
|
|
|
}
|
|
|
if(!keyframe_updated) {
|
|
|
|
|
|
-
|
|
|
+
|
|
|
|
|
|
usleep(30000);
|
|
|
continue;
|
|
@@ -122,10 +129,8 @@ void hdl_backend::optimization_timer_callback() {
|
|
|
Eigen::Isometry3d relpose(loop->relative_pose.cast<double>());
|
|
|
Eigen::MatrixXd information_matrix = inf_calclator->calc_information_matrix(loop->key1->cloud, loop->key2->cloud, relpose);
|
|
|
auto edge = graph_slam->add_se3_edge(loop->key1->node, loop->key2->node, relpose, information_matrix);
|
|
|
- graph_slam->add_robust_kernel(edge, "Tukey", 0.05);
|
|
|
+ graph_slam->add_robust_kernel(edge, "Huber", 2);
|
|
|
|
|
|
-
|
|
|
-
|
|
|
}
|
|
|
std::copy(new_keyframes.begin(), new_keyframes.end(), std::back_inserter(keyframes));
|
|
|
new_keyframes.clear();
|
|
@@ -139,7 +144,7 @@ void hdl_backend::optimization_timer_callback() {
|
|
|
|
|
|
}
|
|
|
|
|
|
- int num_iterations = 10000000;
|
|
|
+ int num_iterations = 5000;
|
|
|
|
|
|
|
|
|
|
|
@@ -185,12 +190,42 @@ void hdl_backend::optimization_timer_callback() {
|
|
|
markers_pub.publish(markers);
|
|
|
|
|
|
|
|
|
+ publishMatrixAsPose(odom_pub, keyframes[keyframes.size() - 1]->node->estimate().matrix().cast<float>());
|
|
|
+
|
|
|
usleep(30000);
|
|
|
}
|
|
|
|
|
|
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);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
|
|
|
* @brief generate map point cloud and publish it
|
|
|
* @param event
|
|
@@ -198,7 +233,8 @@ void hdl_backend::optimization_timer_callback() {
|
|
|
void hdl_backend::map_points_publish_timer_callback(const ros::WallTimerEvent& event) {
|
|
|
|
|
|
|
|
|
- if(!map_points_pub.getNumSubscribers() || !graph_updated) {
|
|
|
+ if(!graph_updated) {
|
|
|
+
|
|
|
return;
|
|
|
}
|
|
|
|
|
@@ -242,7 +278,6 @@ void hdl_backend::map_points_publish_timer_callback(const ros::WallTimerEvent& e
|
|
|
|
|
|
}
|
|
|
|
|
|
-
|
|
|
|
|
|
* @brief downsample a point cloud
|
|
|
* @param cloud input cloud
|
|
@@ -271,22 +306,12 @@ pcl::PointCloud<PointT>::ConstPtr hdl_backend::outlier_removal(const pcl::PointC
|
|
|
return filtered;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
|
|
|
* @brief 接收点云数据并放到 keyframe_queue 中
|
|
|
* @param odom_msg 前端的激光里程计数据
|
|
|
* @param cloud_msg 前端滤波后的点云数据
|
|
|
*/
|
|
|
void hdl_backend::cloud_callback(const nav_msgs::OdometryConstPtr& odom_msg, const sensor_msgs::PointCloud2::ConstPtr& cloud_msg) {
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
const ros::Time& stamp = cloud_msg->header.stamp;
|
|
|
Eigen::Isometry3d odom = hdl_graph_slam::odom2isometry(odom_msg);
|
|
|
|
|
@@ -299,7 +324,6 @@ void hdl_backend::cloud_callback(const nav_msgs::OdometryConstPtr& odom_msg, con
|
|
|
auto filtered = downsample(cloud);
|
|
|
filtered = outlier_removal(filtered);
|
|
|
|
|
|
-
|
|
|
|
|
|
if(!keyframe_updater->update(odom)) {
|
|
|
|
|
@@ -362,19 +386,20 @@ bool hdl_backend::flush_keyframe_queue() {
|
|
|
|
|
|
|
|
|
if(keyframes.empty() && new_keyframes.size() == 1) {
|
|
|
- if(nh.param<bool>("fix_first_node", false)) {
|
|
|
- Eigen::MatrixXd inf = Eigen::MatrixXd::Identity(6, 6);
|
|
|
- std::stringstream sst(nh.param<std::string>("fix_first_node_stddev", "1 1 1 1 1 1"));
|
|
|
- for(int i = 0; i < 6; i++) {
|
|
|
- double stddev = 1.0;
|
|
|
- sst >> stddev;
|
|
|
- inf(i, i) = 1.0 / stddev;
|
|
|
- }
|
|
|
-
|
|
|
- anchor_node = graph_slam->add_se3_node(Eigen::Isometry3d::Identity());
|
|
|
- anchor_node->setFixed(true);
|
|
|
- anchor_edge = graph_slam->add_se3_edge(anchor_node, keyframe->node, Eigen::Isometry3d::Identity(), inf);
|
|
|
+
|
|
|
+ Eigen::MatrixXd inf = Eigen::MatrixXd::Identity(6, 6);
|
|
|
+
|
|
|
+ std::stringstream sst("10 10 10 1 1 1");
|
|
|
+
|
|
|
+ for(int i = 0; i < 6; i++) {
|
|
|
+ double stddev = 1.0;
|
|
|
+ sst >> stddev;
|
|
|
+ inf(i, i) = 1.0 / stddev;
|
|
|
}
|
|
|
+ anchor_node = graph_slam->add_se3_node(Eigen::Isometry3d::Identity());
|
|
|
+ anchor_node->setFixed(true);
|
|
|
+ anchor_edge = graph_slam->add_se3_edge(anchor_node, keyframe->node, Eigen::Isometry3d::Identity(), inf);
|
|
|
+
|
|
|
}
|
|
|
|
|
|
if(i == 0 && keyframes.empty()) {
|
|
@@ -389,6 +414,9 @@ bool hdl_backend::flush_keyframe_queue() {
|
|
|
auto edge = graph_slam->add_se3_edge(keyframe->node, prev_keyframe->node, relative_pose, information);
|
|
|
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;
|