Untitled
unknown
plain_text
5 months ago
9.9 kB
13
No Index
/* A bare-bones example node demonstrating the use of the Monocular mode in ORB-SLAM3 Author: Azmyin Md. Kamal Date: 01/01/24 REQUIREMENTS * Make sure to set path to your workspace in common.hpp file */ //* Includes #include "ros2_orb_slam3/common.hpp" #include <queue> #include <mutex> std::queue<sensor_msgs::msg::Imu> imuBuffer; // IMU message buffer std::mutex imuMutex; // Mutex for thread safety //* Constructor MonocularMode::MonocularMode() :Node("mono_node_cpp") { // Declare parameters to be passsed from command line // https://roboticsbackend.com/rclcpp-params-tutorial-get-set-ros2-params-with-cpp/ //* Find path to home directory homeDir = getenv("HOME"); // std::cout<<"Home: "<<homeDir<<std::endl; // std::cout<<"VLSAM NODE STARTED\n\n"; RCLCPP_INFO(this->get_logger(), "\nORB-SLAM3-V1 NODE STARTED"); this->declare_parameter("node_name_arg", "not_given"); // Name of this agent this->declare_parameter("voc_file_arg", "file_not_set"); // Needs to be overriden with appropriate name this->declare_parameter("settings_file_path_arg", "file_path_not_set"); // path to settings file //* Watchdog, populate default values nodeName = "not_set"; vocFilePath = "file_not_set"; settingsFilePath = "file_not_set"; //* Populate parameter values rclcpp::Parameter param1 = this->get_parameter("node_name_arg"); nodeName = param1.as_string(); rclcpp::Parameter param2 = this->get_parameter("voc_file_arg"); vocFilePath = param2.as_string(); rclcpp::Parameter param3 = this->get_parameter("settings_file_path_arg"); settingsFilePath = param3.as_string(); // rclcpp::Parameter param4 = this->get_parameter("settings_file_name_arg"); //* HARDCODED, set paths if (vocFilePath == "file_not_set" || settingsFilePath == "file_not_set") { pass; vocFilePath = homeDir + "/" + packagePath + "orb_slam3/Vocabulary/ORBvoc.txt.bin"; settingsFilePath = homeDir + "/" + packagePath + "orb_slam3/config/Monocular-Inertial/"; } // std::cout<<"vocFilePath: "<<vocFilePath<<std::endl; // std::cout<<"settingsFilePath: "<<settingsFilePath<<std::endl; //* DEBUG print RCLCPP_INFO(this->get_logger(), "nodeName %s", nodeName.c_str()); RCLCPP_INFO(this->get_logger(), "voc_file %s", vocFilePath.c_str()); // RCLCPP_INFO(this->get_logger(), "settings_file_path %s", settingsFilePath.c_str()); subexperimentconfigName = "/mono_py_driver/experiment_settings"; // topic that sends out some configuration parameters to the cpp ndoe pubconfigackName = "/mono_py_driver/exp_settings_ack"; // send an acknowledgement to the python node subImgMsgName = "/mono_py_driver/img_msg"; // topic to receive RGB image messages subTimestepMsgName = "/mono_py_driver/timestep_msg"; // topic to receive RGB image messages subImuMsgName = "/mono_py_driver/imu_msg"; //* subscribe to python node to receive settings expConfig_subscription_ = this->create_subscription<std_msgs::msg::String>(subexperimentconfigName, 1, std::bind(&MonocularMode::experimentSetting_callback, this, _1)); //* publisher to send out acknowledgement configAck_publisher_ = this->create_publisher<std_msgs::msg::String>(pubconfigackName, 10); //* subscribe to receive the timestep subTimestepMsg_subscription_= this->create_subscription<std_msgs::msg::Float64>(subTimestepMsgName, 1, std::bind(&MonocularMode::Timestep_callback, this, _1)); subImuMsg_subscription_= this->create_subscription<sensor_msgs::msg::Imu>(subImuMsgName, 1, std::bind(&MonocularMode::Imu_callback, this, _1)); //* subscrbite to the image messages coming from the Python driver node subImgMsg_subscription_= this->create_subscription<sensor_msgs::msg::Image>(subImgMsgName, 1, std::bind(&MonocularMode::Img_callback, this, _1)); RCLCPP_INFO(this->get_logger(), "Waiting to finish handshake ......"); } //* Destructor MonocularMode::~MonocularMode() { // Stop all threads // Call method to write the trajectory file // Release resources and cleanly shutdown pAgent->Shutdown(); pass; } //* Callback which accepts experiment parameters from the Python node void MonocularMode::experimentSetting_callback(const std_msgs::msg::String& msg){ // std::cout<<"experimentSetting_callback"<<std::endl; bSettingsFromPython = true; experimentConfig = msg.data.c_str(); // receivedConfig = experimentConfig; // Redundant RCLCPP_INFO(this->get_logger(), "Configuration YAML file name: %s", this->receivedConfig.c_str()); //* Publish acknowledgement auto message = std_msgs::msg::String(); message.data = "ACK"; std::cout<<"Sent response: "<<message.data.c_str()<<std::endl; configAck_publisher_->publish(message); //* Wait to complete VSLAM initialization initializeVSLAM(experimentConfig); } //* Method to bind an initialized VSLAM framework to this node void MonocularMode::initializeVSLAM(std::string& configString){ // Watchdog, if the paths to vocabular and settings files are still not set if (vocFilePath == "file_not_set" || settingsFilePath == "file_not_set") { RCLCPP_ERROR(get_logger(), "Please provide valid voc_file and settings_file paths"); rclcpp::shutdown(); } //* Build .yaml`s file path std::cout<<"setting: "<<settingsFilePath<<" "<<"hi"<<std::endl; //if (settingsFilePath == "/home/reefranger/ros2_test/src/ros2_orb_slam3/orb_slam3/config/Monocular-Inertial/") settingsFilePath = settingsFilePath.append(configString); settingsFilePath = settingsFilePath.append(".yaml"); // Example ros2_ws/src/orb_slam3_ros2/orb_slam3/config/Monocular/TUM2.yaml RCLCPP_INFO(this->get_logger(), "Path to settings file: %s", settingsFilePath.c_str()); // NOTE if you plan on passing other configuration parameters to ORB SLAM3 Systems class, do it here // NOTE you may also use a .yaml file here to set these values sensorType = ORB_SLAM3::System::IMU_MONOCULAR; enablePangolinWindow = true; // Shows Pangolin window output enableOpenCVWindow = true; // Shows OpenCV window output pAgent = new ORB_SLAM3::System(vocFilePath, settingsFilePath, sensorType, enablePangolinWindow); std::cout << "MonocularInertialMode node initialized" << std::endl; // TODO needs a better message } //* Callback that processes timestep sent over ROS void MonocularMode::Timestep_callback(const std_msgs::msg::Float64& time_msg){ // timeStep = 0; // Initialize timeStep = time_msg.data; } void MonocularMode::Imu_callback(const sensor_msgs::msg::Imu& msg) { std::lock_guard<std::mutex> lock(imuMutex); imuBuffer.push(msg); // Optionally limit buffer size to prevent memory issues if (imuBuffer.size() > 100) // Example limit { imuBuffer.pop(); } } //* Callback to process image message and run SLAM node void MonocularMode::Img_callback(const sensor_msgs::msg::Image& msg) { // Initialize cv_bridge::CvImagePtr cv_ptr; //* Does not create a copy, memory efficient //* Convert ROS image to openCV image try { //cv::Mat im = cv_bridge::toCvShare(msg.img, msg)->image; cv_ptr = cv_bridge::toCvCopy(msg); // Local scope // DEBUGGING, Show image // Update GUI Window // cv::imshow("test_window", cv_ptr->image); // cv::waitKey(3); } catch (cv_bridge::Exception& e) { RCLCPP_ERROR(this->get_logger(),"Error reading image"); return; } auto imuMeasurements = RetrieveIMUData(timeStep); // std::cout<<std::fixed<<"Timestep: "<<timeStep<<std::endl; // Debug //* Perform all ORB-SLAM3 operations in Monocular mode //! Pose with respect to the camera coordinate frame not the world coordinate frame Sophus::SE3f Tcw = pAgent->TrackMonocular(cv_ptr->image, timeStep,imuMeasurements); //* An example of what can be done after the pose w.r.t camera coordinate frame is computed by ORB SLAM3 //Sophus::SE3f Twc = Tcw.inverse(); //* Pose with respect to global image coordinate, reserved for future use } std::vector<ORB_SLAM3::IMU::Point> MonocularMode::RetrieveIMUData(double timeStep) { std::vector<ORB_SLAM3::IMU::Point> imuMeasurements; std::lock_guard<std::mutex> lock(imuMutex); while (!imuBuffer.empty()) //&& //rclcpp::Time(imuBuffer.front().header.stamp).seconds() + //imuBuffer.front().header.stamp.nanosec * 1e-9 <= timeStep) //while (!imuBuffer.empty() && rclcpp::Time(imuBuffer.front().header.stamp).seconds() <= timeStep) { const auto& imuMsg = imuBuffer.front(); double timestamp_imu = imuMsg.header.stamp.sec + imuMsg.header.stamp.nanosec * 1e-9; if (timestamp_imu > timeStep) { break; } RCLCPP_DEBUG(this->get_logger(), "Image time: %.9f, IMU buffer size: %lu", timeStep, imuBuffer.size()); std::cout << "Hello, World!" << timestamp_imu << " "<< timeStep << std::endl; // Convert IMU data to ORB-SLAM3 format cv::Point3f acc( imuMsg.linear_acceleration.x, imuMsg.linear_acceleration.y, imuMsg.linear_acceleration.z); cv::Point3f gyr( imuMsg.angular_velocity.x, imuMsg.angular_velocity.y, imuMsg.angular_velocity.z); //auto imuTime = imuMsg.header.stamp; //double timestamp_imu = imuTime.sec + imuTime.nanosec * 1e-9; //double timestamp_imu = rclcpp::Time(imuMsg.header.stamp).seconds(); imuMeasurements.push_back(ORB_SLAM3::IMU::Point(acc, gyr, timestamp_imu)); imuBuffer.pop(); // Remove processed IMU message } return imuMeasurements; }
Editor is loading...
Leave a Comment