sweet ai rviz panel
This commit is contained in:
parent
9b80189710
commit
dffea57921
|
|
@ -0,0 +1,74 @@
|
|||
cmake_minimum_required(VERSION 3.5)
|
||||
project(sweet_rviz_panel)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
find_package(ament_cmake REQUIRED)
|
||||
find_package(rclcpp REQUIRED)
|
||||
find_package(rviz_common REQUIRED)
|
||||
find_package(rviz_rendering REQUIRED)
|
||||
find_package(pluginlib REQUIRED)
|
||||
find_package(geometry_msgs REQUIRED)
|
||||
find_package(tf2 REQUIRED)
|
||||
find_package(Qt5 REQUIRED COMPONENTS Widgets)
|
||||
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
|
||||
set(HEADERS
|
||||
include/sweet_rviz_panel/sweet_rviz_panel.hpp
|
||||
)
|
||||
|
||||
set(SOURCES
|
||||
src/sweet_rviz_panel.cpp
|
||||
)
|
||||
|
||||
add_library(${PROJECT_NAME} SHARED
|
||||
${SOURCES}
|
||||
${HEADERS}
|
||||
)
|
||||
|
||||
target_include_directories(${PROJECT_NAME}
|
||||
PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
||||
$<INSTALL_INTERFACE:include>
|
||||
)
|
||||
|
||||
ament_target_dependencies(${PROJECT_NAME}
|
||||
rclcpp
|
||||
rviz_common
|
||||
rviz_rendering
|
||||
pluginlib
|
||||
geometry_msgs
|
||||
tf2
|
||||
)
|
||||
|
||||
target_link_libraries(${PROJECT_NAME}
|
||||
Qt5::Widgets
|
||||
)
|
||||
|
||||
pluginlib_export_plugin_description_file(
|
||||
rviz_common
|
||||
plugin_description.xml
|
||||
)
|
||||
|
||||
install(
|
||||
TARGETS ${PROJECT_NAME}
|
||||
ARCHIVE DESTINATION lib
|
||||
LIBRARY DESTINATION lib
|
||||
RUNTIME DESTINATION bin
|
||||
)
|
||||
|
||||
install(
|
||||
DIRECTORY include/
|
||||
DESTINATION include
|
||||
)
|
||||
|
||||
install(
|
||||
FILES plugin_description.xml
|
||||
DESTINATION share/${PROJECT_NAME}
|
||||
)
|
||||
|
||||
ament_package()
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
#ifndef SWEET_RVIZ_PANEL_HPP
|
||||
#define SWEET_RVIZ_PANEL_HPP
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <QLabel>
|
||||
#include <QPushButton>
|
||||
#include <QVBoxLayout>
|
||||
#include <QHBoxLayout>
|
||||
|
||||
#include <rviz_common/panel.hpp>
|
||||
|
||||
#include <rclcpp/rclcpp.hpp>
|
||||
#include "geometry_msgs/msg/twist.hpp"
|
||||
#include "geometry_msgs/msg/pose.hpp"
|
||||
#include <rviz_common/display_context.hpp>
|
||||
#include <rviz_common/ros_integration/ros_node_abstraction_iface.hpp>
|
||||
|
||||
namespace sweet_rviz_panel
|
||||
{
|
||||
|
||||
class SweetRvizPanel : public rviz_common::Panel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit SweetRvizPanel(QWidget *parent = nullptr);
|
||||
|
||||
protected:
|
||||
void onInitialize() override;
|
||||
|
||||
private Q_SLOTS:
|
||||
void onStart();
|
||||
void onStop();
|
||||
|
||||
private:
|
||||
void poseCallback(
|
||||
const geometry_msgs::msg::Pose::SharedPtr msg);
|
||||
void velCmdCallback(
|
||||
const geometry_msgs::msg::Twist::SharedPtr msg);
|
||||
QLabel *x_label_;
|
||||
QLabel *y_label_;
|
||||
QLabel *yaw_label_;
|
||||
QLabel *status_label_;
|
||||
|
||||
QLabel *vel_cmd_label_;
|
||||
QLabel *yaw_cmd_label_;
|
||||
|
||||
QPushButton *start_button_;
|
||||
QPushButton *stop_button_;
|
||||
|
||||
rclcpp::Node::SharedPtr node_;
|
||||
std::shared_ptr<
|
||||
rviz_common::ros_integration::RosNodeAbstractionIface> node_ptr_;
|
||||
rclcpp::Subscription<geometry_msgs::msg::Pose>::SharedPtr pose_sub_;
|
||||
rclcpp::Subscription<geometry_msgs::msg::Twist>::SharedPtr twist_cmd_sub_;
|
||||
|
||||
bool running_;
|
||||
};
|
||||
|
||||
} // namespace sweet_rviz_panel
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
<?xml version="1.0"?>
|
||||
<package format="3">
|
||||
|
||||
<name>sweet_rviz_panel</name>
|
||||
<version>0.0.1</version>
|
||||
<description>Sweet RViz2 vehicle debug panel</description>
|
||||
|
||||
<maintainer email="sweetai@example.com">sweetai</maintainer>
|
||||
<license>Apache-2.0</license>
|
||||
|
||||
<buildtool_depend>ament_cmake</buildtool_depend>
|
||||
|
||||
<depend>rclcpp</depend>
|
||||
<depend>rviz_common</depend>
|
||||
<depend>rviz_rendering</depend>
|
||||
<depend>pluginlib</depend>
|
||||
<depend>geometry_msgs</depend>
|
||||
|
||||
<export>
|
||||
<build_type>ament_cmake</build_type>
|
||||
<rviz_common plugin="${prefix}/plugin_description.xml"/>
|
||||
</export>
|
||||
|
||||
</package>
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<library path="sweet_rviz_panel">
|
||||
<class
|
||||
name="sweet_rviz_panel/SweetRvizPanel"
|
||||
type="sweet_rviz_panel::SweetRvizPanel"
|
||||
base_class_type="rviz_common::Panel">
|
||||
<description>
|
||||
Sweet Robot RViz2 debug panel.
|
||||
</description>
|
||||
</class>
|
||||
</library>
|
||||
|
|
@ -0,0 +1,176 @@
|
|||
#include "sweet_rviz_panel/sweet_rviz_panel.hpp"
|
||||
|
||||
#include <cmath>
|
||||
#include <QGroupBox>
|
||||
#include <tf2/LinearMath/Quaternion.h>
|
||||
#include <tf2/LinearMath/Matrix3x3.h>
|
||||
|
||||
#include <pluginlib/class_list_macros.hpp>
|
||||
|
||||
namespace sweet_rviz_panel
|
||||
{
|
||||
|
||||
SweetRvizPanel::SweetRvizPanel(QWidget *parent)
|
||||
: rviz_common::Panel(parent),
|
||||
x_label_(nullptr),
|
||||
y_label_(nullptr),
|
||||
yaw_label_(nullptr),
|
||||
status_label_(nullptr),
|
||||
start_button_(nullptr),
|
||||
stop_button_(nullptr),
|
||||
vel_cmd_label_(nullptr),
|
||||
yaw_cmd_label_(nullptr),
|
||||
running_(false)
|
||||
{
|
||||
auto *main_layout = new QVBoxLayout;
|
||||
// vehicle pose
|
||||
auto *pose_box = new QGroupBox("Vehicle Pose");
|
||||
auto *pose_layout = new QVBoxLayout;
|
||||
|
||||
x_label_ = new QLabel("X: 0.000 m");
|
||||
y_label_ = new QLabel("Y: 0.000 m");
|
||||
yaw_label_ = new QLabel("Yaw: 0.000 rad");
|
||||
|
||||
pose_layout->addWidget(x_label_);
|
||||
pose_layout->addWidget(y_label_);
|
||||
pose_layout->addWidget(yaw_label_);
|
||||
|
||||
pose_box->setLayout(pose_layout);
|
||||
// command
|
||||
auto *vel_cmd_box = new QGroupBox("Command Info");
|
||||
auto *vel_cmd_layout = new QVBoxLayout;
|
||||
vel_cmd_label_ = new QLabel("Velocity Command: 0.00 m/s");
|
||||
yaw_cmd_label_ = new QLabel("Yaw Command: 0.00 rad/s");
|
||||
|
||||
vel_cmd_layout->addWidget(vel_cmd_label_);
|
||||
vel_cmd_layout->addWidget(yaw_cmd_label_);
|
||||
vel_cmd_box->setLayout(vel_cmd_layout);
|
||||
// other buttons
|
||||
auto *button_layout = new QHBoxLayout;
|
||||
|
||||
start_button_ = new QPushButton("Start");
|
||||
stop_button_ = new QPushButton("Stop");
|
||||
|
||||
button_layout->addWidget(start_button_);
|
||||
button_layout->addWidget(stop_button_);
|
||||
|
||||
status_label_ = new QLabel("Status: STOPPED");
|
||||
|
||||
main_layout->addWidget(pose_box);
|
||||
main_layout->addWidget(vel_cmd_box);
|
||||
main_layout->addLayout(button_layout);
|
||||
main_layout->addWidget(status_label_);
|
||||
main_layout->addStretch();
|
||||
|
||||
setLayout(main_layout);
|
||||
|
||||
connect(
|
||||
start_button_,
|
||||
SIGNAL(clicked()),
|
||||
this,
|
||||
SLOT(onStart()));
|
||||
|
||||
connect(
|
||||
stop_button_,
|
||||
SIGNAL(clicked()),
|
||||
this,
|
||||
SLOT(onStop()));
|
||||
}
|
||||
|
||||
void SweetRvizPanel::onInitialize()
|
||||
{
|
||||
node_ = std::make_shared<rclcpp::Node>("sweet_rviz_panel");
|
||||
node_ptr_= getDisplayContext()->getRosNodeAbstraction().lock();
|
||||
if (!node_ptr_) {
|
||||
RCLCPP_ERROR(
|
||||
rclcpp::get_logger("SweetRvizPanel"),
|
||||
"Failed to get RViz ROS node");
|
||||
|
||||
return;
|
||||
}
|
||||
auto node = node_ptr_->get_raw_node();
|
||||
|
||||
pose_sub_ = node->create_subscription<
|
||||
geometry_msgs::msg::Pose>(
|
||||
"/rtk_pose",
|
||||
10,
|
||||
std::bind(&SweetRvizPanel::poseCallback,this,std::placeholders::_1));
|
||||
|
||||
twist_cmd_sub_ = node->create_subscription<
|
||||
geometry_msgs::msg::Twist>(
|
||||
"/twist_cmd_vel",
|
||||
10,
|
||||
std::bind(&SweetRvizPanel::velCmdCallback,this,std::placeholders::_1));
|
||||
|
||||
running_ = true;
|
||||
status_label_->setText("Status: RUNNING");
|
||||
}
|
||||
|
||||
void SweetRvizPanel::poseCallback(
|
||||
const geometry_msgs::msg::Pose::SharedPtr msg)
|
||||
{
|
||||
if (!running_) {
|
||||
return;
|
||||
}
|
||||
|
||||
const double x = msg->position.x;
|
||||
const double y = msg->position.y;
|
||||
|
||||
const auto &q = msg->orientation;
|
||||
|
||||
tf2::Quaternion quaternion(
|
||||
q.x,
|
||||
q.y,
|
||||
q.z,
|
||||
q.w);
|
||||
|
||||
double roll;
|
||||
double pitch;
|
||||
double yaw;
|
||||
|
||||
tf2::Matrix3x3(quaternion).getRPY(
|
||||
roll,
|
||||
pitch,
|
||||
yaw);
|
||||
|
||||
x_label_->setText(
|
||||
QString("X: %1 m").arg(x, 0, 'f', 3));
|
||||
|
||||
y_label_->setText(
|
||||
QString("Y: %1 m").arg(y, 0, 'f', 3));
|
||||
|
||||
yaw_label_->setText(
|
||||
QString("Yaw: %1 rad").arg(yaw, 0, 'f', 3));
|
||||
}
|
||||
|
||||
void SweetRvizPanel::velCmdCallback(
|
||||
const geometry_msgs::msg::Twist::SharedPtr msg)
|
||||
{
|
||||
if (!running_) {
|
||||
return;
|
||||
}
|
||||
|
||||
vel_cmd_label_->setText(
|
||||
QString("Velocity Command: %1 m/s").arg(msg->linear.x, 0, 'f', 3));
|
||||
|
||||
yaw_cmd_label_->setText(
|
||||
QString("Yaw Command: %1 rad/s").arg(msg->angular.z, 0, 'f', 3));
|
||||
}
|
||||
|
||||
void SweetRvizPanel::onStart()
|
||||
{
|
||||
running_ = true;
|
||||
status_label_->setText("Status: RUNNING");
|
||||
}
|
||||
|
||||
void SweetRvizPanel::onStop()
|
||||
{
|
||||
running_ = false;
|
||||
status_label_->setText("Status: STOPPED");
|
||||
}
|
||||
|
||||
} // namespace sweet_rviz_panel
|
||||
|
||||
PLUGINLIB_EXPORT_CLASS(
|
||||
sweet_rviz_panel::SweetRvizPanel,
|
||||
rviz_common::Panel)
|
||||
Loading…
Reference in New Issue