CV学习日志:CV开发之常用库最简CMake配置及ROS2使用样例

         之前分两篇文章介绍了CV开发的常用开发库及其头文件。详见《CV学习日志:CV开发之常用库及其头文件》和《CV学习日志:CV开发之ROS2和Webots头文件及其自动提取》。

         本篇给出基于CV开发常用库的CMake配置模板,并给出使用了ROS2的样例。

         给出的CMake配置基于ubuntu20.04,开发库除Webots(Webots采用默认安装路径)外都是通过apt-get安装,详见《CV学习日志:CV开发之Ubuntu2004和WLS2环境搭建》。

         给出的CMake工程假设了一个自定义库,即基于ROS2自编译的库,colon编译安装路径是/root/app/ros2ex/out/install。

 

         以下是CMake模板的详细代码,尤其要注意配置了Threads和对QT5添加了特殊配置。

 1 ###I.Global####################################################################
 2 cmake_minimum_required(VERSION 3.5)
 3 project(aaron)
 4 set(CMAKE_CXX_STANDARD 14)
 5 set(CMAKE_CXX_STANDARD_REQUIRED True)
 6 set(LIBRARY_OUTPUT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/out)
 7 set(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/out)
 8 include_directories(${CMAKE_CURRENT_SOURCE_DIR}/header) #if header directory exists
 9 
10 ###II.UNIX####################################################################
11 if(UNIX)
12 set(THREADS_PREFER_PTHREAD_FLAG ON)
13 find_package(Threads REQUIRED)
14 message("Platform: UNIX

Platform: UNIX

Platform: UNIX

Platform: UNIX

Platform: UNIX

Platform: UNIX

")
15 
16 #1.Qt5
17 include_directories(/usr/include/x86_64-linux-gnu/qt5)
18 file(GLOB Qt5_LIBS /usr/lib/x86_64-linux-gnu/libQt5*.so.5) #remove Qt5Bootstrap and Qt5Debug if they exist
19 add_compile_definitions(QT_WIDGETS_LIB) #Add QT_NO_VERSION_TAGGING if installing Qt manually
20 add_compile_options(-fPIC)
21 
22 #2.OpenCV
23 include_directories(/usr/include/opencv4)
24 file(GLOB OpenCV_LIBS /usr/lib/x86_64-linux-gnu/libopencv*.so)
25 
26 #3.Eigen3 Gflags Glog Ceres Spdlog
27 include_directories(/usr/include)
28 include_directories(/usr/include/eigen3)
29 file(GLOB Gflags_LIBS /usr/lib/x86_64-linux-gnu/libgflags*.so)
30 file(GLOB Glog_LIBS /usr/lib/x86_64-linux-gnu/libglog*.so)
31 file(GLOB Ceres_LIBS /usr/lib/libceres*.so)
32 
33 #4.ROS2 ROS2EX Webots
34 include_directories(/opt/ros/foxy/include /root/app/ros2ex/out/install/include)
35 include_directories(/usr/local/webots/include/controller/cpp /usr/local/webots/include/controller/c)
36 file(GLOB ROS2_LIBS LIST_DIRECTORIES false /opt/ros/foxy/lib/*.so)
37 file(GLOB ROS2EX_LIBS LIST_DIRECTORIES false /root/app/ros2ex/out/install/lib/*.so)
38 file(GLOB Webots_LIBS LIST_DIRECTORIES false /usr/local/webots/lib/controller/*.so)
39 
40 #5.Octomap
41 include_directories(/usr/include)
42 file(GLOB Octomap_LIBS /usr/lib/x86_64-linux-gnu/liboctom*.so)#octomap&octomath
43 set(Octomap_LIBS ${Octomap_LIBS} /usr/lib/x86_64-linux-gnu/liboctovis.so)
44 set(Octomap_LIBS ${Octomap_LIBS} /usr/lib/x86_64-linux-gnu/libdynamicedt3d.so)
45 
46 #8.AllLibs
47 set(ALL_LIBS ${Qt5_LIBS} ${OpenCV_LIBS} ${ROS2_LIBS} ${ROS2EX_LIBS} ${Webots_LIBS}
48 ${Gflags_LIBS} ${Glog_LIBS} ${Ceres_LIBS} ${Octomap_LIBS})
49 link_libraries(${ALL_LIBS})
50 message("ALL_LIBS: ${ALL_LIBS}")
51 
52 ###9.2ROSTest
53 set(rostestcpp ${CMAKE_SOURCE_DIR}/rostest.cpp)
54 add_executable(rostest ${rostestcpp})
55 target_link_libraries(rostest Threads::Threads)
56 endif(UNIX)
View Code

         以下是ROS2使用样例的详细代码,依赖于C++14、OpenCV4.x、Spdlog及Foxy

 1 #include "cvheaders.h" //write this file based on previous articles
 2 
 3 #ifndef ns1970
 4 #define ms1970 chrono::time_point_cast<chrono::milliseconds>(chrono::system_clock::now()).time_since_epoch().count()
 5 #define us1970 chrono::time_point_cast<chrono::microseconds>(chrono::system_clock::now()).time_since_epoch().count()
 6 #define ns1970 chrono::time_point_cast<chrono::nanoseconds>(chrono::system_clock::now()).time_since_epoch().count()
 7 #endif
 8 
 9 class RosTestCore
10 {
11 public:
12     static void AirRobot(int argc = 0, char **argv = 0)
13     {
14         //0.InitROS
15         rclcpp::init(argc, argv);
16 
17         //1.PreROS
18         int64 nPubFrame = 0;
19         rclcpp::Node::SharedPtr nodAirRobot = rclcpp::Node::make_shared("airRobot", "acv");
20         rclcpp::Publisher<ssrmsg::Image>::SharedPtr pubRawFrame = nodAirRobot->create_publisher<ssrmsg::Image>("rawFrame", 2);
21         rclcpp::TimerBase::SharedPtr TimerTimestamp = nodAirRobot->create_wall_timer(200ms, [&]()->void
22             {
23                 //1.PrepareData
24                 int64 ts = ns1970;
25                 ssrmsg::Image::UniquePtr ima = make_unique<ssrmsg::Image>();
26                 ima->header.frame_id = std::to_string(++nPubFrame);
27                 ima->header.stamp.sec = ts / 1000000000;
28                 ima->header.stamp.nanosec = ts % 1000000000;
29                 ima->width = 640;
30                 ima->height = 480;
31                 ima->step = 3 * ima->width;
32                 ima->is_bigendian = 0;
33                 ima->encoding = CV_8UC3;
34                 ima->data.assign(ima->step * ima->height, 128);
35                 cv::putText(Mat_<Vec3b>(ima->height, ima->width, (Vec3b*)ima->data.data()), ima->header.frame_id, Point(300, 220), FONT_HERSHEY_PLAIN, 4, Scalar(255, 0, 0), 4);
36 
37                 //2.PublishData
38                 pubRawFrame->publish(std::move(ima));
39 
40                 //3.PrintDetails
41                 spdlog::info("nPubFrame: {}", nPubFrame);
42                 spdlog::info("	Node::get_name: {}", nodAirRobot->get_name());
43                 spdlog::info("	Node::get_namespace: {}", nodAirRobot->get_namespace());
44                 spdlog::info("	Node::get_sub_namespace: {}", nodAirRobot->get_sub_namespace());
45                 spdlog::info("	Node::get_effective_namespace: {}", nodAirRobot->get_effective_namespace());
46                 spdlog::info("	Node::get_fully_qualified_name: {}", nodAirRobot->get_fully_qualified_name());
47             });
48 
49         //2.SpinROS
50         rclcpp::spin(nodAirRobot);
51 
52         //3.StopROS
53         rclcpp::shutdown();
54     }
55 
56 public:
57     static void LandRobot(int argc = 0, char **argv = 0)
58     {
59         //0.InitROS
60         rclcpp::init(argc, argv);
61 
62         //1.PreROS
63         int64 nSubRawFrame = 0;
64         rclcpp::Node::SharedPtr nodLandRobot = rclcpp::Node::make_shared("landRobot", "acv");
65         rclcpp::Subscription<ssrmsg::Image>::SharedPtr subRawFrame = nodLandRobot->create_subscription<ssrmsg::Image>("rawFrame", 2, [&](ssrmsg::Image::UniquePtr frame)
66             {
67                 cv::imshow("RawFrame", Mat_<Vec3b>(frame->height, frame->width, (Vec3b*)frame->data.data()));
68                 cv::waitKey(10);
69                 spdlog::info("nSubRawFrame: {}", ++nSubRawFrame);
70                 spdlog::info("	Node::get_name: {}", nodLandRobot->get_name());
71                 spdlog::info("	Node::get_namespace: {}", nodLandRobot->get_namespace());
72                 spdlog::info("	Node::get_sub_namespace: {}", nodLandRobot->get_sub_namespace());
73                 spdlog::info("	Node::get_effective_namespace: {}", nodLandRobot->get_effective_namespace());
74                 spdlog::info("	Node::get_fully_qualified_name: {}", nodLandRobot->get_fully_qualified_name());
75             });
76 
77         //2.SpinROS
78         rclcpp::spin(nodLandRobot);
79 
80         //3.StopROS
81         rclcpp::shutdown();
82     }
83 };
84 
85 int main(int argc, char** argv)
86 {
87     if (argc < 2){ spdlog::critical("appName nodeName(airRobot/landRobot)"); return -1; }
88 
89     if (strcmp(argv[1], "airRobot") == 0) RosTestCore::AirRobot(argc, argv);
90     else if (strcmp(argv[1], "landRobot") == 0) RosTestCore::LandRobot(argc, argv);
91 
92     return 0;
93 }
View Code

         打开两个终端执行source /opt/ros/foxy/setup.bash后,再分别执行以下命令可查看效果。

         1)终端一:./rostest airRobot

         2)终端二:./rostest landRobot

 

原文地址:https://www.cnblogs.com/dzyBK/p/13894015.html