Linux 下轻量级显示程序imgui+ros

传感器过多的情况下,ros命令检测比较麻烦,直接运行显示界面,可直观查看传感器状态。

 依赖:ros+imgui 下载

下载:GitHub - ocornut/imgui at v1.81

 整体程序框架

程序源码

#include "imgui.h"
#include "imgui_impl_glfw.h"
#include "imgui_impl_opengl3.h"
#include <stdio.h>
#include <GL/gl3w.h>            // Initialize with gl3wInit()
// Include glfw3.h after our OpenGL definitions
#include <GLFW/glfw3.h>
#include <fstream>
#include "ros/ros.h"    //包含了使用ROS节点的必要文件
#include "std_msgs/String.h"    //包含了使用的数据类型
#include "std_msgs/UInt8MultiArray.h"
#include "std_msgs/MultiArrayDimension.h"
#include "std_msgs/Int8.h" //包含了使用的数据类型
#include "std_msgs/Int16MultiArray.h"
#include "std_msgs/Bool.h"
#include <sstream>
#include <geometry_msgs/TwistStamped.h>
#include <mutex> //定义了C++11标准中的一些互斥访问的类与方法
#include <image_transport/image_transport.h>
#include <sensor_msgs/PointCloud2.h>
#include "sensor_msgs/NavSatFix.h"
#include <cv_bridge/cv_bridge.h>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgcodecs.hpp>
#include <pcl_ros/transforms.h>
#include <pcl_ros/point_cloud.h>
#include <pcl/point_types.h>
#include <sensor_msgs/Imu.h>
std::mutex loc_mutex;
typedef union{
    struct Pst{
            float rtk_x;
            float rtk_y;
            float rtk_z;
            float x;
            float y;
            float z;
            float roll;
            float pitch;
            float yaw;
    }Pst_data;
    uint8_t detail[36];
}Pst_union;
Pst_union loc_pst={0};
bool      is_camera_connected    = false;
bool      is_lidar_connected     = false;
bool      is_realsense_connected = false;
bool      is_odometry_connected  = false;
ros::Time lidar_callback_time;
ros::Time camera_callback_time;
ros::Time realsense_callback_time;
ros::Time odometry_callback_time;
float     cutgo_linear_x = 0;
float     cutgo_imu_acc_z= 0;

double    odom_hz=0;
const int odom_fps_data_num=100;
double    odom_fps[odom_fps_data_num+1]={0};
int       odom_fps_num=0;

double    rgb_hz=0;
const int rgb_fps_data_num=30;
double    rgb_fps[odom_fps_data_num+1]={0};
int       rgb_fps_num=0;

double    lidar_hz=0;
const int lidar_fps_data_num=30;
double    lidar_fps[odom_fps_data_num+1]={0};
int       lidar_fps_num=0;

double    realsense_hz=0;
const int realsense_fps_data_num=30;
double    realsense_fps[odom_fps_data_num+1]={0};
int       realsense_fps_num=0;

float rtk_x=0.00,rtk_y=0.00,rtk_rcv_x=0.00,rtk_rcv_y=0.00;
float rtk_pos[300][9]={0};
int count=-1,before_count=0;
static int e = 0;
std::ofstream Out_dirStream;

static void glfw_error_callback(int error, const char* description)
{
    fprintf(stderr, "Glfw Error %d: %s\n", error, description);
}

void Loc_Callback(const std_msgs::UInt8MultiArray::ConstPtr &msg){
    if(msg->data.size()>0)
    {  
      loc_mutex.lock();
      for(int i = 0; i < msg->data.size();i++){  //vec_loc size is 12
        loc_pst.detail[i]=msg->data[i];
      }
      loc_mutex.unlock();
      //std::cout<<"rtk_x position"<<loc_pst.Pst_data.rtk_x<<std::endl;
    } 
}

void imageCallback(const sensor_msgs::ImageConstPtr &msg) {
    ros::Time time_now     = ros::Time::now();
    if(rgb_fps_num<rgb_fps_data_num)
    {      
       rgb_fps_num++;
    }
    else
    {
        rgb_fps_num=0;
    }
    rgb_fps[rgb_fps_num]=(time_now - camera_callback_time).toSec();
    double fps_average=0;
    for(int i=0;i<rgb_fps_data_num;i++)
    {
        fps_average=fps_average+rgb_fps[i]/rgb_fps_data_num;
    }
    rgb_hz = 1.0 / fps_average;
    camera_callback_time = time_now;
    try {
        cv::Mat img = cv_bridge::toCvShare(msg, "bgr8")->image;
        //*if img exist, then show it
        if (img.data) {
            is_camera_connected = true;
        } else {
            is_camera_connected = false;
        }
    } catch (cv_bridge::Exception &e) {
        ROS_ERROR("Could not convert from '%s' to 'bgr8'.", msg->encoding.c_str());
    }
}

void realsenseCallback(const sensor_msgs::ImageConstPtr &msg) {
    ros::Time time_now     = ros::Time::now();
    if(realsense_fps_num<realsense_fps_data_num)
    {      
       realsense_fps_num++;
    }
    else
    {
        realsense_fps_num=0;
    }
    realsense_fps[realsense_fps_num]=(time_now - realsense_callback_time).toSec();
    double fps_average=0;
    for(int i=0;i<realsense_fps_data_num;i++)
    {
        fps_average=fps_average+realsense_fps[i]/realsense_fps_data_num;
    }
    realsense_hz = 1.0 / fps_average;
    realsense_callback_time = time_now;
    try {
        cv::Mat img = cv_bridge::toCvShare(msg, "bgr8")->image;
        if (img.data) {
            is_realsense_connected = true;
        } else {
            is_realsense_connected = false;
        }
    } catch (cv_bridge::Exception &e) {
        ROS_ERROR("Could not convert from '%s' to 'bgr8'.", msg->encoding.c_str());
    }
}

void lidarCallback(const sensor_msgs::PointCloud2ConstPtr &msg) {
    ros::Time time_now     = ros::Time::now();
    if(lidar_fps_num<lidar_fps_data_num)
    {      
       lidar_fps_num++;
    }
    else
    {
        lidar_fps_num=0;
    }
    lidar_fps[lidar_fps_num]=(time_now - lidar_callback_time).toSec();
    double fps_average=0;
    for(int i=0;i<lidar_fps_data_num;i++)
    {
        fps_average=fps_average+lidar_fps[i]/lidar_fps_data_num;
    }
    lidar_hz = 1.0 / fps_average;
    lidar_callback_time = time_now;
    pcl::PointCloud<pcl::PointXYZ>::Ptr mSphereCloud(new pcl::PointCloud<pcl::PointXYZ>);
    pcl::fromROSMsg(*msg, *mSphereCloud);
    if (mSphereCloud->points.size() > 0||lidar_hz>5) {
        is_lidar_connected = true;
    } else {
        is_lidar_connected = false;
    }
}

void imu_callback(const sensor_msgs::ImuConstPtr &imu_msg)
{
    cutgo_imu_acc_z = imu_msg->linear_acceleration.z;
}

void odometryCallback(const geometry_msgs::TwistStampedConstPtr &msg) {
    ros::Time time_now     = ros::Time::now();
    if(odom_fps_num<odom_fps_data_num)
    {      
       odom_fps_num++;
    }
    else
    {
        odom_fps_num=0;
    }
    odom_fps[odom_fps_num]=(time_now - odometry_callback_time).toSec();
    double fps_average=0;
    for(int i=0;i<odom_fps_data_num;i++)
    {
        fps_average=fps_average+odom_fps[i]/odom_fps_data_num;
    }
    odom_hz = 1.0 / fps_average;
    odometry_callback_time = time_now;
    //printf("fps=%lf\n",odom_hz);
    if (odom_hz > 90) {
        is_odometry_connected = true;
    } else {
        is_odometry_connected = false;
    }
    cutgo_linear_x = msg->twist.linear.x;
}
void show_rtk_window()
{
    if(ImGui::Button("Add Point"))
        {
            count++;
            loc_mutex.lock();
            rtk_pos[count][0]=loc_pst.Pst_data.rtk_x;
            rtk_pos[count][1]=loc_pst.Pst_data.rtk_y;
            rtk_pos[count][2]=loc_pst.Pst_data.rtk_z;
            rtk_pos[count][3]=loc_pst.Pst_data.x;
            rtk_pos[count][4]=loc_pst.Pst_data.y;
            rtk_pos[count][5]=loc_pst.Pst_data.z;
            rtk_pos[count][6]=loc_pst.Pst_data.roll;
            rtk_pos[count][7]=loc_pst.Pst_data.pitch;
            rtk_pos[count][8]=loc_pst.Pst_data.yaw;
            loc_mutex.unlock();
        }
        ImGui::SameLine();
        if(ImGui::Button("Delete Point"))
        {
            count--;
        }
        ImGui::SameLine();
        if(ImGui::Button("Clear Points"))
        {
            count=0;
        }
        static char str0[128] = "/home/nvidia/positec/robot_logs/SLAM/shadow.txt";
        ImGui::SetNextItemWidth(500);
        ImGui::InputText("Input save path", str0, IM_ARRAYSIZE(str0));
        ImGui::PushItemWidth(500);
        std::string mSavePath;
        mSavePath = str0;
        // add a button; if click, save this test name
        if (ImGui::Button("save")) 
        {
            Out_dirStream.open(mSavePath, std::ios::out);
            Out_dirStream.close();
            Out_dirStream.open(mSavePath, std::ios::app);
            Out_dirStream.setf(std::ios::fixed,std::ios::floatfield);
            Out_dirStream.precision(9);
            for(int j=0;j<count+1;j++)
            {			
                Out_dirStream   << rtk_pos[j][0] << " " 
                                << rtk_pos[j][1] << " "
                                << rtk_pos[j][2] << " " 
                                << rtk_pos[j][3] << " "
                                << rtk_pos[j][4] << " " 
                                << rtk_pos[j][5] << " "
                                << rtk_pos[j][6] << " " 
                                << rtk_pos[j][7] << " "
                                << rtk_pos[j][8] << " "
                                << std::endl;		
            }
            Out_dirStream.close();
            std::cout << "mSavePath: " << mSavePath << std::endl;
        }
        loc_mutex.lock();
        ImGui::Text("Cur car pst %f %f %f %f %f %f %f %f %f",loc_pst.Pst_data.rtk_x,loc_pst.Pst_data.rtk_y,loc_pst.Pst_data.rtk_z,loc_pst.Pst_data.x,loc_pst.Pst_data.y,loc_pst.Pst_data.z,loc_pst.Pst_data.roll,loc_pst.Pst_data.pitch,loc_pst.Pst_data.yaw);
        ImGui::Text("-----------------------------------------------------------------------");
        loc_mutex.unlock();
        for(int i=0;i<count+1;i++)
        {
            ImGui::Text("points_num=%d,position %f %f %f %f %f %f %f %f %f",i, rtk_pos[i][0],rtk_pos[i][1],rtk_pos[i][2],rtk_pos[i][3],rtk_pos[i][4],rtk_pos[i][5],rtk_pos[i][6],rtk_pos[i][7],rtk_pos[i][8]);
        }
}
int main(int argc, char **argv)
{
    // Setup window
    glfwSetErrorCallback(glfw_error_callback);
    if (!glfwInit())
        return 1;
    // GL 3.0 + GLSL 130
    const char* glsl_version = "#version 130";
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
    // Create window with graphics context
    //glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
    GLFWwindow* window = glfwCreateWindow(1280, 720, "cut and go", NULL, NULL);
    if (window == NULL)
        return 1;
    glfwMakeContextCurrent(window);
    glfwSwapInterval(1); // Enable vsync

    // Initialize OpenGL loader
    bool err = gl3wInit() != 0;
    if (err)
    {
        fprintf(stderr, "Failed to initialize OpenGL loader!\n");
        return 1;
    }

    // Setup Dear ImGui context
    IMGUI_CHECKVERSION();
    ImGui::CreateContext();
    ImGuiIO& io = ImGui::GetIO(); (void)io;
    ImGui::StyleColorsDark();
    ImGui_ImplGlfw_InitForOpenGL(window, true);
    ImGui_ImplOpenGL3_Init(glsl_version);
    //ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
    ros::init(argc, argv, "node_gui");    //初始化ROS,节点名命名为node_a,节点名必须保持唯一
    ros::NodeHandle n;    //实例化节点, 节点进程句柄
    ros::Subscriber sub = n.subscribe("Fusion_pose_50hz", 1000, Loc_Callback);
    ros::Subscriber sub_camera = n.subscribe("/camera/rgb/image_raw", 1, imageCallback);
    ros::Subscriber sub_realsense = n.subscribe("/camera/color/image_raw", 1, realsenseCallback);
    ros::Subscriber sub_lidar = n.subscribe("/zvision_lidar_points", 1, lidarCallback);
    ros::Subscriber sub_odometry  = n.subscribe("/Ser_odom", 1000, odometryCallback);
    ros::Subscriber sub_imu = n.subscribe("/Ser_imu", 100,imu_callback);
    ros::Rate loop_rate(50);    //设置发送数据的频率为50Hz
    ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
    // Main loop
    while (!glfwWindowShouldClose(window)&&ros::ok())
    {
        glfwPollEvents();
        ImGui_ImplOpenGL3_NewFrame();
        ImGui_ImplGlfw_NewFrame();
        ImGui::NewFrame(); 
        ros::spinOnce();    //不是必须,若程序中订阅话题则必须,否则回掉函数不起作用。
        loop_rate.sleep();    //按前面设置的10Hz频率将程序挂起

        static float f = 0.0f;
        ImGui::Begin("RTK TEST");                          // Create a window called "Hello, world!" and append into it.
        if (abs(lidar_callback_time.toSec() - ros::Time::now().toSec()) < 1) 
        {
            if (!is_lidar_connected) 
            {
                ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(255, 0, 0, 255));
                ImGui::Text("Lidar connect fail");
                ImGui::PopStyleColor();

            } 
            else 
            {
                ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(0, 255, 0, 255));
                ImGui::Text("Lidar connect success");
                ImGui::PopStyleColor();
            }
        } 
        else 
        {
            ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(255, 0, 0, 255));
            ImGui::Text("Lidar connect fail");
            ImGui::PopStyleColor();
        }
        ImGui::SameLine();
        if (abs(camera_callback_time.toSec() - ros::Time::now().toSec()) < 1) {
            // is_camera_connected
            if (!is_camera_connected) {
                ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(255, 0, 0, 255));
                ImGui::Text(" ----- Camera connect fail");
                ImGui::PopStyleColor();
            } else {
                ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(0, 255, 0, 255));
                ImGui::Text(" ----- Camera connect success");
                ImGui::PopStyleColor();
            }
        } else {
            ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(255, 0, 0, 255));
            ImGui::Text(" ----- Camera connect fail");
            ImGui::PopStyleColor();
        }

        //* check back realsense is connected or not, two topics: /camera/color/image_raw /camera/depth/image_rect_raw
        ImGui::SameLine();
        if (abs(realsense_callback_time.toSec() - ros::Time::now().toSec()) < 1) {
            //* if is_realsense_connected false, show the text: realsense detection Failed
            if (!is_realsense_connected) {
                ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(255, 0, 0, 255));
                ImGui::Text(" ----- realsense connect fail");
                ImGui::PopStyleColor();
            } else {
                ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(0, 255, 0, 255));
                ImGui::Text(" ----- realsense connect success");
                ImGui::PopStyleColor();
            }
        } else {
            ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(255, 0, 0, 255));
            ImGui::Text(" ----- realsense connect fail");
            ImGui::PopStyleColor();
        }
        //* check odometry is connected or not, two topics: /Ser_odom
        ImGui::SameLine();
        if (abs(odometry_callback_time.toSec() - ros::Time::now().toSec()) < 1) {
            //* if is_odometry_connected false, show the text: odometry detection Failed
            if (!is_odometry_connected) {
                ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(255, 0, 0, 255));
                ImGui::Text(" ----- odometry connect fail");
                ImGui::PopStyleColor();
            } else {
                ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(0, 255, 0, 255));
                ImGui::Text(" ----- odometry connnect success");
                ImGui::PopStyleColor();
            }
        } else {
            ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(255, 0, 0, 255));
            ImGui::Text("   -----   odometry connect fail");
            ImGui::PopStyleColor();
        }
        ImGui::SameLine();
	    if (ImGui::Button("--Exit System--"))
	    {
	    	ros::shutdown();
	    }
        ImGui::Text(" ----- car    imu    fps %.3f", odom_hz);
        ImGui::Text(" ----- car   camera  fps %.3f", rgb_hz);
        ImGui::Text(" ----- car realsense fps %.3f", realsense_hz);
        ImGui::Text(" ----- car    lidar  fps %.3f", lidar_hz);
        ImGui::Text(" ----- car move  speed %.3f m/s", cutgo_linear_x);
        ImGui::Text(" ----- car imu  acc  z %.3f m2/s", cutgo_imu_acc_z);
        ImGui::Text("-------------------------------------------------------------------------------------------------------------");
        // bool ImGui::RadioButton(const char *label, int *v, int v_button);
        // IMGUI_DEMO_MARKER("Widgets/Basic/RadioButton");
        static int e = 0;
        ImGui::RadioButton("RTK_Shadow", &e, 0);
        ImGui::SameLine();
        ImGui::RadioButton("No Function", &e, 1);
        ImGui::Text("-------------------------------------------------------------------------------------------------------------");
        if (e == 0) {
            show_rtk_window();
        } else if (e == 1) {
            //show_dynamic_window();
        } 
        ImGui::End();
        // Rendering
        ImGui::Render();
        int display_w, display_h;
        glfwGetFramebufferSize(window, &display_w, &display_h);
        glViewport(0, 0, display_w, display_h);
        //glClearColor(clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w);
        glClear(GL_COLOR_BUFFER_BIT);
        ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
        glfwSwapBuffers(window);
    }
    // Cleanup
    ImGui_ImplOpenGL3_Shutdown();
    ImGui_ImplGlfw_Shutdown();
    ImGui::DestroyContext();
    glfwDestroyWindow(window);
    glfwTerminate();
    return 0;
}

 CMakeLists.txt

cmake_minimum_required(VERSION 3.0.2)
project(gui_rtk)
find_package(catkin REQUIRED COMPONENTS roscpp std_msgs cv_bridge   sensor_msgs
  image_transport pcl_ros)
catkin_package()
find_package(glfw3 REQUIRED)
find_package(OpenGL REQUIRED)
find_package(OpenCV REQUIRED)

include_directories(${catkin_INCLUDE_DIRS})
include_directories(${OPENGL_INCLUDE_DIR})
include_directories(${OpenCV_INCLUDE_DIRS})
include_directories(${PROJECT_SOURCE_DIR}/imgui-1.83
	${PROJECT_SOURCE_DIR}/imgui-1.83/backends
)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/imgui-1.83/examples/libs/gl3w)
add_definitions(-DIMGUI_IMPL_OPENGL_LOADER_GL3W)
file (GLOB PLATFORM_SRC
        ./imgui-1.83/examples/libs/gl3w/GL/gl3w.*
        ./imgui-1.83/backends/imgui_impl_glfw.*
        ./imgui-1.83/backends/imgui_impl_opengl3.*
)
file(GLOB SRC
    ./imgui-1.83/*.h
    ./imgui-1.83/*.cpp
)

add_executable(gui_rtk
    src/gui_rtk.cpp
    ${SRC} ${PLATFORM_SRC}
)
target_link_libraries(gui_rtk ${catkin_LIBRARIES}
    glfw
    ${OPENGL_gl_LIBRARY}
    GL
    dl
    ${OpenCV_LIBS}
    ${PCL_LIBRARIES}
)

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用Qt库、RViz和ROS进行点云显示界面设计是一种常见的做法。Qt是一个功能强大的跨平台界面开发框架,RViz是一个ROS包,用于可视化和分析ROS数据。 首先,我们需要在ROS环境中安装RViz包,并确保系统中安装了Qt库。然后,我们可以使用Qt的创作工具Qt Creator创建一个新的Qt项目。 在Qt Creator中,我们可以使用Qt的图形用户界面设计工具来设计点云显示界面的布局。可以选择合适的窗口大小、放置各种控件,如按钮、滑块和标签等,以及指定它们的位置。还可以设置界面的样式和主题,使其符合我们的需求。 然后,我们需要在Qt项目中引入RViz库,以便能够使用其点云显示功能。在Qt Creator的项目文件中,添加RViz库的依赖项,并将其包含到源代码中。通过RViz提供的接口,可以在界面中加载并显示点云数据。 接下来,要使界面与ROS通信,我们需要编写一些代码来连接ROS和Qt。可以使用ROSC++或Python API在Qt中订阅和发布ROS消息,从而实现与ROS节点的数据交互。通过订阅ROS节点发布的点云消息,可以将点云数据传递给RViz,并在界面上显示出来。 最后,我们可以将Qt项目构建为可执行文件,并在ROS系统中运行。在启动ROS节点后,打开设计好的界面,即可显示ROS系统中的点云数据。 总的来说,使用Qt库、RViz和ROS进行点云显示界面设计是一种灵活且功能强大的方法。通过合理布局界面、使用RViz的点云显示功能并与ROS进行数据交互,我们可以设计出易于使用且具有良好用户体验的点云显示界面。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值