ROS机器人GUI程序开发(蒋程杨)-一
Posted juzhango
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ROS机器人GUI程序开发(蒋程杨)-一相关的知识,希望对你有一定的参考价值。
title: ROS机器人GUI程序开发(蒋程杨)-一
date: 2020-07-12 08:35:59
tags: 记录
周末这两天完整的学了一下蒋程杨大佬做的ros的gui开发第二部分。简单做一下记录吧,以便以后能快速的复制粘贴??,里面包括一些信号和槽函数的链接,编辑回调函数和信号函数,订阅图像话题,实现快速指令。。。
按键速度控制
连接:
connect(ui.horizontalSlider_linear,SIGNAL(valueChanged(int)),this,SLOT(on_horizontalSlider_linear_valueChanged(int)));
connect(ui.horizontalSlider_raw,SIGNAL(valueChanged(int)),this,SLOT(on_horizontalSlider_raw_valueChanged(int)));
槽函数:
void robot_hmi::MainWindow::on_horizontalSlider_linear_valueChanged(int value)
{
ui.label_linear->setText(QString::number(value));
}
void robot_hmi::MainWindow::on_horizontalSlider_raw_valueChanged(int value)
{
ui.label_raw->setText(QString::number(value));
}
话题发布:
ros::Publisher cmd_vel_pub;
cmd_vel_pub = n.advertise<geometry_msgs::Twist>("/turtle1/cmd_vel",1000);
node与window接口:
public:
void set_cmd_vel(char k, float linear, float angular);
void QNode::set_cmd_vel(char k, float linear, float angular)
{
std::map<char, std::vector<float>> moveBindings
{
{‘i‘, {1, 0, 0, 0}},
{‘o‘, {1, 0, 0, -1}},
{‘j‘, {0, 0, 0, 1}},
{‘l‘, {0, 0, 0, -1}},
{‘u‘, {1, 0, 0, 1}},
{‘,‘, {-1, 0, 0, 0}},
{‘.‘, {-1, 0, 0, 1}},
{‘m‘, {-1, 0, 0, -1}},
{‘O‘, {1, -1, 0, 0}},
{‘I‘, {1, 0, 0, 0}},
{‘J‘, {0, 1, 0, 0}},
{‘L‘, {0, -1, 0, 0}},
{‘U‘, {1, 1, 0, 0}},
{‘<‘, {-1, 0, 0, 0}},
{‘>‘, {-1, -1, 0, 0}},
{‘M‘, {-1, 1, 0, 0}},
{‘t‘, {0, 0, 1, 0}},
{‘b‘, {0, 0, -1, 0}},
{‘k‘, {0, 0, 0, 0}},
{‘K‘, {0, 0, 0, 0}}
};
char key=k;
//计算是往哪个方向
float x = moveBindings[key][0];
float y = moveBindings[key][1];
float z = moveBindings[key][2];
float th = moveBindings[key][3];
// Update the Twist message
geometry_msgs::Twist twist;
twist.linear.x = x * linear;
twist.linear.y = y * linear;
twist.linear.z = z * linear;
twist.angular.x = 0;
twist.angular.y = 0;
twist.angular.z = th * angular;
// Publish it and resolve any remaining callbacks
cmd_vel_pub.publish(twist);
}
按钮:
connect(ui.pushButton_u,SIGNAL(clicked()),this,SLOT(on_pushButton_clicked()));
connect(ui.pushButton_i,SIGNAL(clicked()),this,SLOT(on_pushButton_clicked()));
connect(ui.pushButton_o,SIGNAL(clicked()),this,SLOT(on_pushButton_clicked()));
connect(ui.pushButton_j,SIGNAL(clicked()),this,SLOT(on_pushButton_clicked()));
connect(ui.pushButton_l,SIGNAL(clicked()),this,SLOT(on_pushButton_clicked()));
connect(ui.pushButton_m,SIGNAL(clicked()),this,SLOT(on_pushButton_clicked()));
connect(ui.pushButton_bb,SIGNAL(clicked()),this,SLOT(on_pushButton_clicked()));
connect(ui.pushButton_bc,SIGNAL(clicked()),this,SLOT(on_pushButton_clicked()));
void robot_hmi::MainWindow::on_pushButton_clicked()
{
QPushButton* btn = qobject_cast<QPushButton*> (sender());
char k = btn->text().toStdString()[0];
// 全向轮模式
bool is_all = ui.checkBox_is_all->isChecked();
float linear = ui.label_linear->text().toFloat()*0.01;
float angular = ui.label_raw->text().toFloat()*0.01;
switch (k) {
case ‘u‘:
qnode.set_cmd_vel(is_all?‘U‘:‘u‘,linear,angular);
break;
case ‘i‘:
qnode.set_cmd_vel(is_all?‘I‘:‘i‘,linear,angular);
break;
case ‘o‘:
qnode.set_cmd_vel(is_all?‘O‘:‘o‘,linear,angular);
break;
case ‘j‘:
qnode.set_cmd_vel(is_all?‘J‘:‘j‘,linear,angular);
break;
case ‘l‘:
qnode.set_cmd_vel(is_all?‘L‘:‘l‘,linear,angular);
break;
case ‘m‘:
qnode.set_cmd_vel(is_all?‘M‘:‘m‘,linear,angular);
break;
case ‘,‘:
qnode.set_cmd_vel(is_all?‘<‘:‘,‘,linear,angular);
break;
case ‘.‘:
qnode.set_cmd_vel(is_all?‘>‘:‘.‘,linear,angular);
break;
default:
break;
}
}
速度仪表盘
最小size 300*300
创建两个仪表盘:
CCtrlDashBoard* speed_x_dashBoard;
CCtrlDashBoard* speed_y_dashBorad;
//ui
speed_x_dashBoard = new CCtrlDashBoard(ui.widget_speed_x);
speed_y_dashBorad = new CCtrlDashBoard(ui.widget_speed_y);
speed_x_dashBoard->setGeometry(ui.widget_speed_x->rect());
speed_y_dashBorad->setGeometry(ui.widget_speed_y->rect());
speed_x_dashBoard->setValue(0);
speed_x_dashBoard->setValue(0);
添加订阅者
#include <turtlesim/Pose.h>
ros::Subscriber pose_sub;
// 添加信号
Q_SIGNALS:
void speed_vel(float linear_vel,float angular_vel);
void pose_callBack(const turtlesim::Pose& msg);
pose_sub = n.subscribe("/turtle1/pose",1000,&QNode::pose_callBack,this);
这里注意:emit 改成 Q_EMIT
void QNode::pose_callBack(const turtlesim::Pose& msg)
{
Q_EMIT speed_vel(msg.linear_velocity,msg.angular_velocity);
}
此时可以在MainWindow连接这个信号:
connect(&qnode,SIGNAL(speed_vel(float,float)),this,SLOT(on_update_dashBoard(float,float)));
void robot_hmi::MainWindow::on_update_dashBoard(float x,float y)
{
ui.label_dir_x->setText(x>=0?"forward":"backward");
ui.label_dir_y->setText(y>=0?"forward":"backward");
speed_x_dashBoard->setValue(abs(x*100));
speed_y_dashBoard->setValue(abs(y*100));
}
显示电池电量
添加一些图片
QNode:
void power_vel(float); //信号
ros::Subscriber power_sub;
void power_callBack(const std_msgs::Float32& msgs);
power_sub = n.subscribe("power",1000,&QNode::power_callBack,this);
void QNode::power_callBack(const std_msgs::Float32& msg)
{
float p = 90.012;
//Q_EMIT power_vel(msg.data);
Q_EMIT power_vel(p);
}
MainWindow:
void on_update_power(float);
connect(&qnode,SIGNAL(power_vel(float)),this,SLOT(on_update_power(float)));
void robot_hmi::MainWindow::on_update_power(float value)
{
ui.label_power_val->setText(QString::number(value).mid(0.5)+"V");
ui.progressBar->setValue(value);
}
订阅图像话题并显示
添加依赖
find_package(catkin REQUIRED COMPONENTS qt_build roscpp
sensor_msgs
cv_bridge
std_msgs
image_transport
)
添加头文件
#include <image_transport/image_transport.h>
#include <cv_bridge/cv_bridge.h>
#include <sensor_msgs/image_encodings.h>
#include <QImage>
UI设计
Label的黑框,Frame的分隔符
声明图像话题订阅者
包括回调函数,信号函数
void image_val(QImage); //信号哦函数
image_transport::Subscriber image_sub;
void image_callBack(const sensor_msgs::ImageConstPtr& msg);
QImage Mat2QImage(cv::Mat const& src); //转换算法
void QNode::image_callBack(const sensor_msgs::ImageConstPtr& msg)
{
cv_bridge::CvImageConstPtr cv_Ptr;
cv_Ptr=cv_bridge::toCvCopy(msg,msg->encoding);
QImage im = Mat2QImage((cv_Ptr->image));
Q_EMIT image_val(im);
}
void QNode::sub_image(QString topic_name)
{
ros::NodeHandle n;
image_transport::ImageTransport it_(n);
image_sub = it_.subscribe(topic_name.toStdString(),1000,&QNode::image_callBack,this);
}
QImage QNode::Mat2QImage(cv::Mat const& src)
{
QImage dest(src.cols, src.rows, QImage::Format_ARGB32);
const float scale = 255.0;
if (src.depth() == CV_8U) {
if (src.channels() == 1) {
for (int i = 0; i < src.rows; ++i) {
for (int j = 0; j < src.cols; ++j) {
int level = src.at<quint8>(i, j);
dest.setPixel(j, i, qRgb(level, level, level));
}
}
} else if (src.channels() == 3) {
for (int i = 0; i < src.rows; ++i) {
for (int j = 0; j < src.cols; ++j) {
cv::Vec3b bgr = src.at<cv::Vec3b>(i, j);
dest.setPixel(j, i, qRgb(bgr[2], bgr[1], bgr[0]));
}
}
}
} else if (src.depth() == CV_32F) {
if (src.channels() == 1) {
for (int i = 0; i < src.rows; ++i) {
for (int j = 0; j < src.cols; ++j) {
int level = scale * src.at<float>(i, j);
dest.setPixel(j, i, qRgb(level, level, level));
}
}
} else if (src.channels() == 3) {
for (int i = 0; i < src.rows; ++i) {
for (int j = 0; j < src.cols; ++j) {
cv::Vec3f bgr = scale * src.at<cv::Vec3f>(i, j);
dest.setPixel(j, i, qRgb(bgr[2], bgr[1], bgr[0]));
}
}
}
}
return dest;
}
链接信号
void on_update_image(QImage);
void on_sub_image();
connect(ui.pushButton_sub_image,SIGNAL(clicked()),this,SLOT(on_sub_image()));
void robot_hmi::MainWindow::on_update_image(QImage im)
{
ui.label_image->setPixmap(QPixmap::fromImage(im));
}
void robot_hmi::MainWindow::on_sub_image()
{
qnode.sub_image(ui.lineEdit_image->text());;
}
最后实现
没有图像话题,没有显示
运行终端命令实现快捷指令
ui设计
链接按钮信号和槽函数
void on_pushButton_turtlesim_clicked();//槽函数
void on_quick_output();
QProcess* turtlesim_cmd;
connect(ui.pushButton_turtlesim,SIGNAL(clicked()),this,SLOT(on_pushButton_turtlesim_clicked()));
ui添加回显
void robot_hmi::MainWindow::on_pushButton_turtlesim_clicked()
{
turtlesim_cmd = new QProcess;
// 运行系统命令行
turtlesim_cmd->start("bash");
turtlesim_cmd->write(ui.textEdit_turtlesim->toPlainText().toLocal8Bit()+"
");
connect(turtlesim_cmd,SIGNAL(readyReadStandardError()),this,SLOT(on_quick_output()));
connect(turtlesim_cmd,SIGNAL(readyReadStandardOutput()),this,SLOT(on_quick_output()));
}
void robot_hmi::MainWindow::on_quick_output()
{
ui.textEdit_quick_output->append("<font color="#FF0000">" + turtlesim_cmd->readAllStandardError() + "</font>");
ui.textEdit_quick_output->append("<font color="#FFFFFF">" + turtlesim_cmd->readAllStandardOutput() + "</font>");
}
最后效果:
!-->以上是关于ROS机器人GUI程序开发(蒋程杨)-一的主要内容,如果未能解决你的问题,请参考以下文章