@@ -55,6 +55,7 @@ using namespace Eigen;
5555#include " NodeDataManager.h"
5656#include " PoseGraphSLAM.h"
5757#include " VizPoseGraph.h"
58+ #include " utils/RawFileIO.h"
5859
5960void periodic_print_len ( const NodeDataManager * manager )
6061{
@@ -352,6 +353,35 @@ void monitor_disjoint_set_datastructure( const NodeDataManager * manager, const
352353}
353354
354355
356+
357+ // set this to 0 to remove the gt code
358+ #define __CODE___GT__ 0
359+ // /////////////////
360+ #if __CODE___GT__
361+ std::map< ros::Time, Vector3d > gt_map;
362+ void ground_truth_callback ( const geometry_msgs::PointStamped::ConstPtr msg )
363+ {
364+ cout << TermColor::YELLOW () << " ground_truth_callback " << msg->header .stamp ;
365+ cout << " \t " << msg->point .x << " , " << msg->point .y << " , " << msg->point .z << " " ;
366+ cout << TermColor::RESET () << endl;
367+
368+ gt_map[ msg->header .stamp ] = Vector3d ( msg->point .x , msg->point .y , msg->point .z );
369+ }
370+
371+
372+ struct assoc_s
373+ {
374+ ros::Time node_timestamp;
375+ Matrix4d corrected_pose;
376+ Matrix4d vio_pose;
377+
378+ Vector3d gt_pose;
379+ ros::Time gt_pose_timestamp;
380+ };
381+ // ///////////////////
382+ #endif
383+
384+
355385// plots the corrected trajectories, different worlds will have different colored lines
356386
357387#define opt_traj_publisher_colored_by_world_LINE_COLOR_STYLE 10 // < color the line with worldID
@@ -389,6 +419,7 @@ void opt_traj_publisher_colored_by_world( const NodeDataManager * manager, const
389419 // ros::Rate loop_rate(5);
390420 map<int , vector<Matrix4d> > jmb;
391421 vector< Vector3d > lbm; // a corrected poses. Same index as the node. These are used for loopedges.
422+ vector< Matrix4d > lbm_fullpose;
392423 bool published_axis = true ;
393424 while ( ros::ok () )
394425 {
@@ -402,6 +433,7 @@ void opt_traj_publisher_colored_by_world( const NodeDataManager * manager, const
402433 // clear map
403434 jmb.clear ();
404435 lbm.clear ();
436+ lbm_fullpose.clear ();
405437
406438 // cerr << "[opt_traj_publisher_colored_by_world]i=0 ; i<"<< manager->getNodeLen() << " ; solvedUntil=" << slam->solvedUntil() <<"\n";
407439 int latest_pose_worldid = -1 ;
@@ -478,6 +510,7 @@ void opt_traj_publisher_colored_by_world( const NodeDataManager * manager, const
478510
479511 jmb[ world_id ].push_back ( w_T_c );
480512 lbm.push_back ( w_T_c.col (3 ).topRows (3 ) );
513+ lbm_fullpose.push_back ( w_T_c );
481514 latest_pose_worldid = world_id;
482515
483516 #ifdef __opt_traj_publisher_colored_by_world___print_on_file_exist
@@ -545,6 +578,7 @@ void opt_traj_publisher_colored_by_world( const NodeDataManager * manager, const
545578
546579 jmb[ world_id ].push_back ( w_TM_i );
547580 lbm.push_back ( w_TM_i.col (3 ).topRows (3 ) );
581+ lbm_fullpose.push_back ( w_TM_i );
548582 latest_pose_worldid = world_id;
549583
550584 #ifdef __opt_traj_publisher_colored_by_world___print_on_file_exist
@@ -659,6 +693,135 @@ void opt_traj_publisher_colored_by_world( const NodeDataManager * manager, const
659693 // cerr << "\nSLEEP\n";
660694 loop_rate.sleep ();
661695 }
696+
697+
698+ #if __CODE___GT__
699+
700+ // Set this to 1 to enable loggin of final poses,
701+ #define __LOGGING___LBM__ 1
702+ #if __LOGGING___LBM__
703+ // Log LMB
704+ vector<assoc_s> _RESULT_;
705+ cout << " ========[opt_traj_publisher_colored_by_world] logging ========\n " ;
706+ cout << " loop on gt_map\n " ;
707+ int _gt_map_i = 0 ;
708+ // ---a
709+ for ( auto it=gt_map.begin () ; it!= gt_map.end () ; it++ ) {
710+ cout << _gt_map_i++ << " : " << it->first << " : " << (it->second ).transpose () << endl;
711+ }
712+
713+ // /---b
714+ cout << " loop on lbm lbm.size() = " << lbm.size () << " lbm_fullpose.size= " << lbm_fullpose.size () <<" \n " ;
715+ assert ( lbm.size () == lbm_fullpose.size () );
716+ for ( auto k=0 ; k<lbm.size () ; k++ ) {
717+ ros::Time _t = manager->getNodeTimestamp (k);
718+ Matrix4d _viopose = manager->getNodePose (k);
719+ cout << k << " : " << _t << " : " << lbm[k].transpose () << " \t " ;
720+ cout << PoseManipUtils::prettyprintMatrix4d (lbm_fullpose[k]) << endl;
721+
722+
723+ assoc_s tmp;
724+ tmp.corrected_pose = lbm_fullpose[k];
725+ tmp.vio_pose = _viopose;
726+ tmp.node_timestamp = _t;
727+
728+
729+ // ---------------
730+ // loop through gt_map and find the gt_pose at this t.
731+ // search for `_t` in gt_map.
732+ {
733+ cout << " \t search for `_t`= " << _t << " in gt_map.\n " ;
734+ int it_i = -1 ;
735+ ros::Duration smallest_diff = ros::Duration ( 100000 );
736+ int smallest_diff_i = -1 ;
737+ auto gt_map_iterator = gt_map.begin ();
738+ bool found = false ;
739+ for ( auto it=gt_map.begin () ; it!= gt_map.end () ; it++ ) {
740+ it_i++;
741+ ros::Duration diff = it->first - _t;
742+ if ( diff.sec < 0 ) { diff.sec = - diff.sec ; diff.nsec = 1000000000 - diff.nsec ; }
743+ // cout << "\t\tit_i=" << it_i << " diff=" << diff.sec << " " << diff.nsec << " >>>>>> smallest_diff_i=" << smallest_diff_i << endl;
744+
745+ if ( diff.sec < smallest_diff.sec || (diff.sec == smallest_diff.sec && abs (diff.nsec ) < abs (smallest_diff.nsec ) ) ) {
746+ smallest_diff = diff;
747+ smallest_diff_i = it_i;
748+ gt_map_iterator = it;
749+ }
750+ if ( (diff.sec == 0 && abs (diff.nsec ) < 10000000 ) || (diff.sec == -1 && diff.nsec > (1000000000 -10000000 ) ) ) {
751+ // cout << "NodeDataManager::find_indexof_node " << i << " "<< diff.sec << " " << diff.nsec << endl
752+ cout << TermColor::GREEN () << " \t found " << it->first << " at idx=" << it_i << endl << TermColor::RESET ();
753+ found = true ;
754+
755+ tmp.gt_pose_timestamp = it->first ;
756+ tmp.gt_pose = it->second ;
757+ break ;
758+ }
759+
760+ }
761+
762+ if ( found == false ) {
763+ cout << TermColor::RED () << " \t NOT found, however, smallest_diff=" << smallest_diff << " at idx=" << smallest_diff_i;
764+ cout << endl << TermColor::RESET ();
765+ tmp.gt_pose_timestamp = gt_map_iterator->first ;
766+ tmp.gt_pose = gt_map_iterator->second ;
767+ }
768+ }
769+ // ---------
770+ // END of search onn gt_map
771+ // ---------
772+
773+
774+
775+ // Result:"
776+ _RESULT_.push_back ( tmp );
777+ cout << TermColor::CYAN () << " Result: \n " ;
778+ cout << " node_timestamp " << tmp.node_timestamp << endl;
779+ cout << " gt_pose_timestamp " << tmp.gt_pose_timestamp << endl;
780+ cout << " gt_pose " << (tmp.gt_pose ).transpose () << endl;
781+ cout << " vio_pose " << PoseManipUtils::prettyprintMatrix4d (tmp.vio_pose ) << endl;
782+ cout << " corrected_pose " << PoseManipUtils::prettyprintMatrix4d (tmp.corrected_pose ) << endl;
783+ cout << TermColor::RESET ();
784+
785+ }
786+
787+
788+ // write CSV:
789+ std::stringstream buffer_gt;
790+ std::stringstream buffer_corrected;
791+ std::stringstream buffer_vio;
792+
793+ for ( int j=0 ; j<_RESULT_.size () ; j++ )
794+ {
795+ // stamp, tx, ty, tz
796+ buffer_gt << long (_RESULT_[j].node_timestamp .toSec () * 1E9 ) << " ," << _RESULT_[j].gt_pose (0 ) << " ," << _RESULT_[j].gt_pose (1 )<< " ," << _RESULT_[j].gt_pose (2 ) <<endl;
797+
798+
799+ // stamp, tx, ty, tz, qw, qx, qy, qz
800+ buffer_corrected << long (_RESULT_[j].node_timestamp .toSec () * 1E9 ) << " ," << _RESULT_[j].corrected_pose (0 ,3 ) << " ," << _RESULT_[j].corrected_pose (1 ,3 )<< " ," << _RESULT_[j].corrected_pose (2 ,3 ) << " ," ;
801+ Matrix3d __R = _RESULT_[j].corrected_pose .topLeftCorner (3 ,3 );
802+ Quaterniond quat ( __R );
803+ buffer_corrected << quat.w () << " ," << quat.x () << " ," << quat.y () << " ," << quat.z () << endl;
804+
805+
806+ buffer_vio << long (_RESULT_[j].node_timestamp .toSec () * 1E9 ) << " ," << _RESULT_[j].vio_pose (0 ,3 ) << " ," << _RESULT_[j].vio_pose (1 ,3 )<< " ," << _RESULT_[j].vio_pose (2 ,3 ) << " ," ;
807+ Matrix3d __R2 = _RESULT_[j].vio_pose .topLeftCorner (3 ,3 );
808+ Quaterniond quat2 ( __R );
809+ buffer_vio << quat2.w () << " ," << quat2.x () << " ," << quat2.y () << " ," << quat2.z () << endl;
810+ }
811+ const string DATA_PATH = " /Bulk_Data/_tmp_posegraph/" ;
812+ RawFileIO::write_string ( DATA_PATH+" /gt.csv" , buffer_gt.str () );
813+ RawFileIO::write_string ( DATA_PATH+" /corrected.csv" , buffer_corrected.str () );
814+ RawFileIO::write_string ( DATA_PATH+" /vio_pose.csv" , buffer_vio.str () );
815+
816+
817+
818+ #endif // __LOGGING___LBM__
819+
820+ #endif // __CODE___GT__
821+
822+
823+
824+
662825}
663826
664827
@@ -685,14 +848,23 @@ int main( int argc, char ** argv)
685848 ros::Subscriber sub_loopclosure = nh.subscribe ( loopclosure_camera_rel_pose_topic, 1000 , &NodeDataManager::loopclosure_pose_callback, manager );
686849
687850
688- // -- TODO: Also subscribe to tracked features to know if I have been kidnaped.
851+ // -- subscribe to tracked features to know if I have been kidnaped. --//
689852 // False indicates -> I got kidnapped now
690853 // True indicates --> I got unkidnapped.
691854 string rcvd_kidnap_indicator_topic = string ( " /feature_tracker/rcvd_flag_header" );
692855 ROS_INFO ( " Subscribed to kidnap_indicator aka %s" , rcvd_kidnap_indicator_topic.c_str () );
693856 ros::Subscriber sub_kidnap_indicator = nh.subscribe ( rcvd_kidnap_indicator_topic, 100 , &NodeDataManager::rcvd_kidnap_indicator_callback, manager );
694857
695858
859+ #if __CODE___GT__
860+ // --- ground_truth_callback. Sometimes bags may contain GT data, ---//
861+ // this will associate the GT data to the pose graph for analysis.
862+ string ground_truth_topic = string ( " /leica/position" );
863+ ROS_INFO ( " Subscribed to ground_truth_topic: %s" , ground_truth_topic.c_str () );
864+ ros::Subscriber sub_gt_ = nh.subscribe ( ground_truth_topic, 100 , ground_truth_callback );
865+ #endif
866+
867+
696868
697869 // Setup publishers
698870 // --- Marker ---//
@@ -773,6 +945,18 @@ int main( int argc, char ** argv)
773945
774946 #define __LOGGING__ 0 // make this 1 to enable logging. 0 to disable logging. rememeber to catkin_make after this change
775947 #if __LOGGING__
948+ // Note: If using roslaunch to launch this node and when LOGGING is enabled,
949+ // roslaunch sends a sigterm and kills this thread when ros::ok() returns false ie.
950+ // when you press CTRL+C. The timeout is governed by roslaunch.
951+ //
952+ // If you wish to increase this timeout, you need to edit "/opt/ros/kinetic/lib/python2.7/dist-packages/roslaunch/nodeprocess.py"
953+ // then edit these two vars.
954+ // _TIMEOUT_SIGINT = 15.0 #seconds
955+ // _TIMEOUT_SIGTERM = 2.0 #seconds
956+ // ^^^^ Borrowed from : https://answers.ros.org/question/11353/how-to-delay-escalation-to-sig-term-after-sending-sig-int-to-roslaunch/
957+
958+
959+
776960 // /// Save Pose Graph for Debugging
777961 const string DATA_PATH = " /Bulk_Data/_tmp_posegraph/" ;
778962
0 commit comments