//-------------------------------------------------------------------------- VertexPoseKeyFrame* VertexAnimationTrack::getVertexPoseKeyFrame(unsigned short index) const { if (mAnimationType != VAT_POSE) { OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Pose keyframes can only be created on vertex tracks of type pose.", "VertexAnimationTrack::getVertexPoseKeyFrame"); } return static_cast<VertexPoseKeyFrame*>(getKeyFrame(index)); }
//-------------------------------------------------------------------------- TransformKeyFrame* NodeAnimationTrack::getNodeKeyFrame(unsigned short index) const { return static_cast<TransformKeyFrame*>(getKeyFrame(index)); }
//-------------------------------------------------------------------------- NumericKeyFrame* NumericAnimationTrack::getNumericKeyFrame(unsigned short index) const { return static_cast<NumericKeyFrame*>(getKeyFrame(index)); }
void PoseGraph::updatePath() { m_keyframelist.lock(); list<KeyFrame*>::iterator it; for (int i = 1; i <= sequence_cnt; i++) { path[i].poses.clear(); } base_path.poses.clear(); posegraph_visualization->reset(); if (SAVE_LOOP_PATH) { ofstream loop_path_file_tmp(VINS_RESULT_PATH, ios::out); loop_path_file_tmp.close(); } for (it = keyframelist.begin(); it != keyframelist.end(); it++) { Vector3d P; Matrix3d R; (*it)->getPose(P, R); Quaterniond Q; Q = R; // printf("path p: %f, %f, %f\n", P.x(), P.z(), P.y() ); geometry_msgs::PoseStamped pose_stamped; pose_stamped.header.stamp = ros::Time((*it)->time_stamp); pose_stamped.header.frame_id = "world"; pose_stamped.pose.position.x = P.x() + VISUALIZATION_SHIFT_X; pose_stamped.pose.position.y = P.y() + VISUALIZATION_SHIFT_Y; pose_stamped.pose.position.z = P.z(); pose_stamped.pose.orientation.x = Q.x(); pose_stamped.pose.orientation.y = Q.y(); pose_stamped.pose.orientation.z = Q.z(); pose_stamped.pose.orientation.w = Q.w(); if((*it)->sequence == 0) { base_path.poses.push_back(pose_stamped); base_path.header = pose_stamped.header; } else { path[(*it)->sequence].poses.push_back(pose_stamped); path[(*it)->sequence].header = pose_stamped.header; } if (SAVE_LOOP_PATH) { ofstream loop_path_file(VINS_RESULT_PATH, ios::app); loop_path_file.setf(ios::fixed, ios::floatfield); loop_path_file.precision(0); loop_path_file << (*it)->time_stamp * 1e9 << ","; loop_path_file.precision(5); loop_path_file << P.x() << "," << P.y() << "," << P.z() << "," << Q.w() << "," << Q.x() << "," << Q.y() << "," << Q.z() << "," << endl; loop_path_file.close(); } //draw local connection if (SHOW_S_EDGE) { list<KeyFrame*>::reverse_iterator rit = keyframelist.rbegin(); list<KeyFrame*>::reverse_iterator lrit; for (; rit != keyframelist.rend(); rit++) { if ((*rit)->index == (*it)->index) { lrit = rit; lrit++; for (int i = 0; i < 4; i++) { if (lrit == keyframelist.rend()) break; if((*lrit)->sequence == (*it)->sequence) { Vector3d conncected_P; Matrix3d connected_R; (*lrit)->getPose(conncected_P, connected_R); posegraph_visualization->add_edge(P, conncected_P); } lrit++; } break; } } } if (SHOW_L_EDGE) { if ((*it)->has_loop && (*it)->sequence == sequence_cnt) { KeyFrame* connected_KF = getKeyFrame((*it)->loop_index); Vector3d connected_P; Matrix3d connected_R; connected_KF->getPose(connected_P, connected_R); //(*it)->getVioPose(P, R); (*it)->getPose(P, R); if((*it)->sequence > 0) { posegraph_visualization->add_loopedge(P, connected_P + Vector3d(VISUALIZATION_SHIFT_X, VISUALIZATION_SHIFT_Y, 0)); } } } } publish(); m_keyframelist.unlock(); }
void PoseGraph::addKeyFrame(KeyFrame* cur_kf, bool flag_detect_loop) { //shift to base frame Vector3d vio_P_cur; Matrix3d vio_R_cur; if (sequence_cnt != cur_kf->sequence) { sequence_cnt++; sequence_loop.push_back(0); w_t_vio = Eigen::Vector3d(0, 0, 0); w_r_vio = Eigen::Matrix3d::Identity(); m_drift.lock(); t_drift = Eigen::Vector3d(0, 0, 0); r_drift = Eigen::Matrix3d::Identity(); m_drift.unlock(); } cur_kf->getVioPose(vio_P_cur, vio_R_cur); vio_P_cur = w_r_vio * vio_P_cur + w_t_vio; vio_R_cur = w_r_vio * vio_R_cur; cur_kf->updateVioPose(vio_P_cur, vio_R_cur); cur_kf->index = global_index; global_index++; int loop_index = -1; if (flag_detect_loop) { TicToc tmp_t; loop_index = detectLoop(cur_kf, cur_kf->index); } else { addKeyFrameIntoVoc(cur_kf); } if (loop_index != -1) { //printf(" %d detect loop with %d \n", cur_kf->index, loop_index); KeyFrame* old_kf = getKeyFrame(loop_index); if (cur_kf->findConnection(old_kf)) { if (earliest_loop_index > loop_index || earliest_loop_index == -1) earliest_loop_index = loop_index; Vector3d w_P_old, w_P_cur, vio_P_cur; Matrix3d w_R_old, w_R_cur, vio_R_cur; old_kf->getVioPose(w_P_old, w_R_old); cur_kf->getVioPose(vio_P_cur, vio_R_cur); Vector3d relative_t; Quaterniond relative_q; relative_t = cur_kf->getLoopRelativeT(); relative_q = (cur_kf->getLoopRelativeQ()).toRotationMatrix(); w_P_cur = w_R_old * relative_t + w_P_old; w_R_cur = w_R_old * relative_q; double shift_yaw; Matrix3d shift_r; Vector3d shift_t; if(use_imu) { shift_yaw = Utility::R2ypr(w_R_cur).x() - Utility::R2ypr(vio_R_cur).x(); shift_r = Utility::ypr2R(Vector3d(shift_yaw, 0, 0)); } else shift_r = w_R_cur * vio_R_cur.transpose(); shift_t = w_P_cur - w_R_cur * vio_R_cur.transpose() * vio_P_cur; // shift vio pose of whole sequence to the world frame if (old_kf->sequence != cur_kf->sequence && sequence_loop[cur_kf->sequence] == 0) { w_r_vio = shift_r; w_t_vio = shift_t; vio_P_cur = w_r_vio * vio_P_cur + w_t_vio; vio_R_cur = w_r_vio * vio_R_cur; cur_kf->updateVioPose(vio_P_cur, vio_R_cur); list<KeyFrame*>::iterator it = keyframelist.begin(); for (; it != keyframelist.end(); it++) { if((*it)->sequence == cur_kf->sequence) { Vector3d vio_P_cur; Matrix3d vio_R_cur; (*it)->getVioPose(vio_P_cur, vio_R_cur); vio_P_cur = w_r_vio * vio_P_cur + w_t_vio; vio_R_cur = w_r_vio * vio_R_cur; (*it)->updateVioPose(vio_P_cur, vio_R_cur); } } sequence_loop[cur_kf->sequence] = 1; } m_optimize_buf.lock(); optimize_buf.push(cur_kf->index); m_optimize_buf.unlock(); } } m_keyframelist.lock(); Vector3d P; Matrix3d R; cur_kf->getVioPose(P, R); P = r_drift * P + t_drift; R = r_drift * R; cur_kf->updatePose(P, R); Quaterniond Q{R}; geometry_msgs::PoseStamped pose_stamped; pose_stamped.header.stamp = ros::Time(cur_kf->time_stamp); pose_stamped.header.frame_id = "world"; pose_stamped.pose.position.x = P.x() + VISUALIZATION_SHIFT_X; pose_stamped.pose.position.y = P.y() + VISUALIZATION_SHIFT_Y; pose_stamped.pose.position.z = P.z(); pose_stamped.pose.orientation.x = Q.x(); pose_stamped.pose.orientation.y = Q.y(); pose_stamped.pose.orientation.z = Q.z(); pose_stamped.pose.orientation.w = Q.w(); path[sequence_cnt].poses.push_back(pose_stamped); path[sequence_cnt].header = pose_stamped.header; if (SAVE_LOOP_PATH) { ofstream loop_path_file(VINS_RESULT_PATH, ios::app); loop_path_file.setf(ios::fixed, ios::floatfield); loop_path_file.precision(0); loop_path_file << cur_kf->time_stamp * 1e9 << ","; loop_path_file.precision(5); loop_path_file << P.x() << "," << P.y() << "," << P.z() << "," << Q.w() << "," << Q.x() << "," << Q.y() << "," << Q.z() << "," << endl; loop_path_file.close(); } //draw local connection if (SHOW_S_EDGE) { list<KeyFrame*>::reverse_iterator rit = keyframelist.rbegin(); for (int i = 0; i < 4; i++) { if (rit == keyframelist.rend()) break; Vector3d conncected_P; Matrix3d connected_R; if((*rit)->sequence == cur_kf->sequence) { (*rit)->getPose(conncected_P, connected_R); posegraph_visualization->add_edge(P, conncected_P); } rit++; } } if (SHOW_L_EDGE) { if (cur_kf->has_loop) { //printf("has loop \n"); KeyFrame* connected_KF = getKeyFrame(cur_kf->loop_index); Vector3d connected_P,P0; Matrix3d connected_R,R0; connected_KF->getPose(connected_P, connected_R); //cur_kf->getVioPose(P0, R0); cur_kf->getPose(P0, R0); if(cur_kf->sequence > 0) { //printf("add loop into visual \n"); posegraph_visualization->add_loopedge(P0, connected_P + Vector3d(VISUALIZATION_SHIFT_X, VISUALIZATION_SHIFT_Y, 0)); } } } //posegraph_visualization->add_pose(P + Vector3d(VISUALIZATION_SHIFT_X, VISUALIZATION_SHIFT_Y, 0), Q); keyframelist.push_back(cur_kf); publish(); m_keyframelist.unlock(); }
void PoseGraph::optimize6DoF() { while(true) { int cur_index = -1; int first_looped_index = -1; m_optimize_buf.lock(); while(!optimize_buf.empty()) { cur_index = optimize_buf.front(); first_looped_index = earliest_loop_index; optimize_buf.pop(); } m_optimize_buf.unlock(); if (cur_index != -1) { printf("optimize pose graph \n"); TicToc tmp_t; m_keyframelist.lock(); KeyFrame* cur_kf = getKeyFrame(cur_index); int max_length = cur_index + 1; // w^t_i w^q_i double t_array[max_length][3]; double q_array[max_length][4]; double sequence_array[max_length]; ceres::Problem problem; ceres::Solver::Options options; options.linear_solver_type = ceres::SPARSE_NORMAL_CHOLESKY; //ptions.minimizer_progress_to_stdout = true; //options.max_solver_time_in_seconds = SOLVER_TIME * 3; options.max_num_iterations = 5; ceres::Solver::Summary summary; ceres::LossFunction *loss_function; loss_function = new ceres::HuberLoss(0.1); //loss_function = new ceres::CauchyLoss(1.0); ceres::LocalParameterization* local_parameterization = new ceres::QuaternionParameterization(); list<KeyFrame*>::iterator it; int i = 0; for (it = keyframelist.begin(); it != keyframelist.end(); it++) { if ((*it)->index < first_looped_index) continue; (*it)->local_index = i; Quaterniond tmp_q; Matrix3d tmp_r; Vector3d tmp_t; (*it)->getVioPose(tmp_t, tmp_r); tmp_q = tmp_r; t_array[i][0] = tmp_t(0); t_array[i][1] = tmp_t(1); t_array[i][2] = tmp_t(2); q_array[i][0] = tmp_q.w(); q_array[i][1] = tmp_q.x(); q_array[i][2] = tmp_q.y(); q_array[i][3] = tmp_q.z(); sequence_array[i] = (*it)->sequence; problem.AddParameterBlock(q_array[i], 4, local_parameterization); problem.AddParameterBlock(t_array[i], 3); if ((*it)->index == first_looped_index || (*it)->sequence == 0) { problem.SetParameterBlockConstant(q_array[i]); problem.SetParameterBlockConstant(t_array[i]); } //add edge for (int j = 1; j < 5; j++) { if (i - j >= 0 && sequence_array[i] == sequence_array[i-j]) { Vector3d relative_t(t_array[i][0] - t_array[i-j][0], t_array[i][1] - t_array[i-j][1], t_array[i][2] - t_array[i-j][2]); Quaterniond q_i_j = Quaterniond(q_array[i-j][0], q_array[i-j][1], q_array[i-j][2], q_array[i-j][3]); Quaterniond q_i = Quaterniond(q_array[i][0], q_array[i][1], q_array[i][2], q_array[i][3]); relative_t = q_i_j.inverse() * relative_t; Quaterniond relative_q = q_i_j.inverse() * q_i; ceres::CostFunction* vo_function = RelativeRTError::Create(relative_t.x(), relative_t.y(), relative_t.z(), relative_q.w(), relative_q.x(), relative_q.y(), relative_q.z(), 0.1, 0.01); problem.AddResidualBlock(vo_function, NULL, q_array[i-j], t_array[i-j], q_array[i], t_array[i]); } } //add loop edge if((*it)->has_loop) { assert((*it)->loop_index >= first_looped_index); int connected_index = getKeyFrame((*it)->loop_index)->local_index; Vector3d relative_t; relative_t = (*it)->getLoopRelativeT(); Quaterniond relative_q; relative_q = (*it)->getLoopRelativeQ(); ceres::CostFunction* loop_function = RelativeRTError::Create(relative_t.x(), relative_t.y(), relative_t.z(), relative_q.w(), relative_q.x(), relative_q.y(), relative_q.z(), 0.1, 0.01); problem.AddResidualBlock(loop_function, loss_function, q_array[connected_index], t_array[connected_index], q_array[i], t_array[i]); } if ((*it)->index == cur_index) break; i++; } m_keyframelist.unlock(); ceres::Solve(options, &problem, &summary); //std::cout << summary.BriefReport() << "\n"; //printf("pose optimization time: %f \n", tmp_t.toc()); /* for (int j = 0 ; j < i; j++) { printf("optimize i: %d p: %f, %f, %f\n", j, t_array[j][0], t_array[j][1], t_array[j][2] ); } */ m_keyframelist.lock(); i = 0; for (it = keyframelist.begin(); it != keyframelist.end(); it++) { if ((*it)->index < first_looped_index) continue; Quaterniond tmp_q(q_array[i][0], q_array[i][1], q_array[i][2], q_array[i][3]); Vector3d tmp_t = Vector3d(t_array[i][0], t_array[i][1], t_array[i][2]); Matrix3d tmp_r = tmp_q.toRotationMatrix(); (*it)-> updatePose(tmp_t, tmp_r); if ((*it)->index == cur_index) break; i++; } Vector3d cur_t, vio_t; Matrix3d cur_r, vio_r; cur_kf->getPose(cur_t, cur_r); cur_kf->getVioPose(vio_t, vio_r); m_drift.lock(); r_drift = cur_r * vio_r.transpose(); t_drift = cur_t - r_drift * vio_t; m_drift.unlock(); //cout << "t_drift " << t_drift.transpose() << endl; //cout << "r_drift " << Utility::R2ypr(r_drift).transpose() << endl; it++; for (; it != keyframelist.end(); it++) { Vector3d P; Matrix3d R; (*it)->getVioPose(P, R); P = r_drift * P + t_drift; R = r_drift * R; (*it)->updatePose(P, R); } m_keyframelist.unlock(); updatePath(); } std::chrono::milliseconds dura(2000); std::this_thread::sleep_for(dura); } return; }
void PoseGraph::loadKeyFrame(KeyFrame* cur_kf, bool flag_detect_loop) { cur_kf->index = global_index; global_index++; int loop_index = -1; if (flag_detect_loop) loop_index = detectLoop(cur_kf, cur_kf->index); else { addKeyFrameIntoVoc(cur_kf); } if (loop_index != -1) { printf(" %d detect loop with %d \n", cur_kf->index, loop_index); KeyFrame* old_kf = getKeyFrame(loop_index); if (cur_kf->findConnection(old_kf)) { if (earliest_loop_index > loop_index || earliest_loop_index == -1) earliest_loop_index = loop_index; m_optimize_buf.lock(); optimize_buf.push(cur_kf->index); m_optimize_buf.unlock(); } } m_keyframelist.lock(); Vector3d P; Matrix3d R; cur_kf->getPose(P, R); Quaterniond Q{R}; geometry_msgs::PoseStamped pose_stamped; pose_stamped.header.stamp = ros::Time(cur_kf->time_stamp); pose_stamped.header.frame_id = "world"; pose_stamped.pose.position.x = P.x() + VISUALIZATION_SHIFT_X; pose_stamped.pose.position.y = P.y() + VISUALIZATION_SHIFT_Y; pose_stamped.pose.position.z = P.z(); pose_stamped.pose.orientation.x = Q.x(); pose_stamped.pose.orientation.y = Q.y(); pose_stamped.pose.orientation.z = Q.z(); pose_stamped.pose.orientation.w = Q.w(); base_path.poses.push_back(pose_stamped); base_path.header = pose_stamped.header; //draw local connection if (SHOW_S_EDGE) { list<KeyFrame*>::reverse_iterator rit = keyframelist.rbegin(); for (int i = 0; i < 1; i++) { if (rit == keyframelist.rend()) break; Vector3d conncected_P; Matrix3d connected_R; if((*rit)->sequence == cur_kf->sequence) { (*rit)->getPose(conncected_P, connected_R); posegraph_visualization->add_edge(P, conncected_P); } rit++; } } /* if (cur_kf->has_loop) { KeyFrame* connected_KF = getKeyFrame(cur_kf->loop_index); Vector3d connected_P; Matrix3d connected_R; connected_KF->getPose(connected_P, connected_R); posegraph_visualization->add_loopedge(P, connected_P, SHIFT); } */ keyframelist.push_back(cur_kf); //publish(); m_keyframelist.unlock(); }