c++ Cmake工程(4) opevslam ros工程模式

MKT-porter發表於2024-09-01

0 自己編寫ros節點引用opemvslam

0-1 首先將openvslam 正常cmake編譯一遍 得到build資料夾

0-2 進入自帶的ros資料夾例子 cakin_make,這一步要用到上一步的build的庫

openvslam 節點 測試建圖和定位(後期複製到自己的ros工程裡當基準用來改造)

publisher是影像釋出和影片釋出節點 非必須

0-3 自己任意地方建立一個ros工程 假設ros_cgg

複製openvslam 的檔案同級目錄

這個目錄是由cmakelist決定的 可以修改 相當於cmakelist上面三級目錄地址

message(STATUS "   當前編譯編譯目錄: ${PROJECT_SOURCE_DIR}")

get_filename_component(DEFAULT_OpenVSLAM_DIR ${PROJECT_SOURCE_DIR} DIRECTORY)
get_filename_component(DEFAULT_OpenVSLAM_DIR ${DEFAULT_OpenVSLAM_DIR} DIRECTORY)
get_filename_component(DEFAULT_OpenVSLAM_DIR ${DEFAULT_OpenVSLAM_DIR} DIRECTORY)

set(OpenVSLAM_ROOT ${DEFAULT_OpenVSLAM_DIR} CACHE STRING "Root directory of OpenVSLAM")
message(STATUS "Root directory of OpenVSLAM: ${OpenVSLAM_ROOT}")

  

ros_cgg/src下建立使用節點 複製原工程openvslam的ros測試節點

(其他倆資料夾是其他專案 和這個沒有關係 沒有也可以)

原版本自帶的直接複製過來

編譯

最後

簡單一點 的,不要這麼多複製,直接在原工程自帶的ros檔案裡修改新增自己編寫的檔案就完事了,或者把camkalist路徑改一下引導過去。

上面這幾個方法是完全重新建立了一個,為了理解ros工程結構,都依賴了哪些原始檔和組織關係。

關鍵點

1 -1 openvslamde 原始碼部分是如何被CMakeLists引用的?

引用的ros節點

編譯的CMakeLists

透過get_filename_component 指令連續三次上一級目錄,找到相對位置的總工程根目錄

get_filename_component 是 CMake 的一個命令,用於從路徑字串中提取特定的元件。它可以提取以下內容:

目錄(DIRECTORY):從路徑中獲取目錄部分。
檔名(NAME):從路徑中獲取檔名部分。
副檔名(EXT):從路徑中獲取副檔名部分。
基本名(NAME_WE):從路徑中獲取不帶副檔名的檔名部分。
例如,如果你有一個路徑 "/home/user/project/file.txt",使用 get_filename_component 可以分別提取 "/home/user/project/" 作為目錄、"file.txt" 作為檔名、".txt" 作為副檔名,以及 "file" 作為基本名。

  

1-2 openvslamde 原始碼部分是如何被呼叫檔案引用的

openvslam先編譯安裝到 usr/local/include/ 然後再是編譯ros節點。

ros節點檔案直接從系統目錄找的"openvslam/system.h"。 然後才是從CMakeLists給定的目錄查詢。

#include <ros/ros.h>
//#include "openvslam/system.h" // 優先從 usr/local/include/下查詢 然後才是自己指定的目錄

  

2 相對路徑

# 自己寫的依賴庫檔案目錄
message(STATUS "當前CMakeLists路徑: ${PROJECT_SOURCE_DIR}")
set(VSLAM_ROOT "${PROJECT_SOURCE_DIR}/../../../src" )
message(STATUS "自己寫的依賴庫檔案目錄: ${VSLAM_ROOT}")

include_directories( 
  ${catkin_INCLUDE_DIRS}
  ${OpenCV_INCLUDE_DIRS}
  ${Boost_INCLUDE_DIRS}
  "/usr/local/include/eigen3"
  ${VSLAM_ROOT} #自己寫的依賴庫檔案目錄
)

從而可以直接使用

#include "vslam/system.h" // 等同於 ${VSLAM_ROOT}/vslam/system.h

  

其中

set(VSLAM_ROOT "${PROJECT_SOURCE_DIR}/../../../src" )
可以參考openvslam類似寫法代替
# digging into the root directory of OpenVSLAM
get_filename_component(DEFAULT_OpenVSLAM_DIR ${PROJECT_SOURCE_DIR} DIRECTORY)
get_filename_component(DEFAULT_OpenVSLAM_DIR ${DEFAULT_OpenVSLAM_DIR} DIRECTORY)
get_filename_component(DEFAULT_OpenVSLAM_DIR ${DEFAULT_OpenVSLAM_DIR} DIRECTORY)

set(OpenVSLAM_ROOT "${DEFAULT_OpenVSLAM_DIR}/src" CACHE STRING "Root directory of OpenVSLAM")
message(STATUS "Root directory of OpenVSLAM: ${OpenVSLAM_ROOT}")

  

CMakeLists.txt

cmake_minimum_required(VERSION 3.0.2)
project(test_node)

find_package(catkin REQUIRED COMPONENTS
  roscpp
  geometry_msgs
  sensor_msgs
  cv_bridge
  message_filters # 訊息同步
  image_transport
)

find_package(OpenCV REQUIRED)
find_package(Boost REQUIRED COMPONENTS filesystem)
find_package(Eigen3 REQUIRED)

catkin_package(
  CATKIN_DEPENDS roscpp geometry_msgs sensor_msgs cv_bridge
  DEPENDS Boost
)


# 自己寫的依賴庫檔案目錄
message(STATUS "當前CMakeLists路徑: ${PROJECT_SOURCE_DIR}")
set(VSLAM_ROOT "${PROJECT_SOURCE_DIR}/../../../src" )
message(STATUS "自己寫的依賴庫檔案目錄: ${VSLAM_ROOT}")

include_directories( 
  ${catkin_INCLUDE_DIRS}
  ${OpenCV_INCLUDE_DIRS}
  ${Boost_INCLUDE_DIRS}
  "/usr/local/include/eigen3"
  ${VSLAM_ROOT} #自己寫的依賴庫檔案目錄
)

# 編譯自己寫的依賴庫
add_library(openvslam_system
   ${VSLAM_ROOT}/vslam/system.cc
)

# 編譯釋出節點
add_executable(run_slam src/run_slam.cc)
target_link_libraries(run_slam 
  ${catkin_LIBRARIES}
  ${OpenCV_LIBRARIES}
  ${Boost_LIBRARIES}
  openvslam_system)

  

package.xml

<?xml version="1.0"?>
<package format="2">
  <name>test_node</name>
  <version>0.0.1</version>
  <description>
    A package to publish and subscribe to images and GPS data using ROS.
  </description>

  <!-- Maintainer of the package -->
  <maintainer email="your_email@example.com">Your Name</maintainer>

  <!-- License of the package -->
  <license>MIT</license>

  <!-- Build tool required to build this package -->
  <buildtool_depend>catkin</buildtool_depend>

  <!-- Dependencies of the package during build and runtime -->
  <build_depend>roscpp</build_depend>
  <build_depend>sensor_msgs</build_depend>
  <build_depend>cv_bridge</build_depend>
  <build_depend>eigen</build_depend>
  <build_depend>geometry_msgs</build_depend>
  <build_depend>message_filters</build_depend>
  <build_depend>image_transport</build_depend>

  
  
  <exec_depend>roscpp</exec_depend>
  <exec_depend>sensor_msgs</exec_depend>
  <exec_depend>cv_bridge</exec_depend>
  <exec_depend>eigen</exec_depend>
  <exec_depend>geometry_msgs</exec_depend>
  <exec_depend>message_filters</exec_depend>
  <exec_depend>image_transport</exec_depend>

  <!-- Declare additional dependencies required for building this package -->
  <build_export_depend>roscpp</build_export_depend>
  <build_export_depend>sensor_msgs</build_export_depend>
  <build_export_depend>cv_bridge</build_export_depend>
  <build_export_depend>eigen</build_export_depend>
  <build_export_depend>geometry_msgs</build_export_depend>
  <build_export_depend>message_filters</build_export_depend>
  <build_export_depend>image_transport</build_export_depend>

  <!-- Export information, can be used by other packages -->
  <export>
    <!-- Export any specific information here -->
  </export>
</package>

  

run_slam.cc

#include <ros/ros.h>
//#include "openvslam/system.h" // 優先從 usr/local/include/下查詢 然後才是自己指定的目錄
#include "vslam/system.h" // 等同於 ${VSLAM_ROOT}/vslam/system.h


int main(int argc, char** argv) {
    ros::init(argc, argv, "run_slam_node");
    ros::NodeHandle nh;

    // Create an instance of SLAMSystem
    SLAMSystem slam_system;
    slam_system.initialize();

    ros::spin();  // Enter a loop, waiting for callbacks
    return 0;
}

  

依賴庫

system.h

#ifndef OPENVSLAM_SYSTEM_H
#define OPENVSLAM_SYSTEM_H

#include <iostream>


class SLAMSystem {
public:
    SLAMSystem();
    void initialize();
};

#endif // OPENVSLAM_SYSTEM_H

  

system.cc

#include "system.h"

SLAMSystem::SLAMSystem() {
    // Constructor implementation
}

void SLAMSystem::initialize() {
    std::cout << "SLAMSystem initialized." << std::endl;
}

  

相關文章