小乌龟案例实现二

Subscriber整合

1. 添加subscriber创建

poseTopicName = "/turtle1/pose"
rospy.Subscriber(poseTopicName, Pose, self.poseCallback)

2. 添加订阅回调

def poseCallback(self, msg):
    print msg

3. 调试

与C++不同,调试结果为可以正常接收到订阅的消息。但是关于窗体关闭事件方面只能通过关闭QT界面来关闭进程,不同通过命令行来。

Python可以正常接收到订阅消息的原因,在于Python采用的SIP方式进行操作QT的界面UI的中间是一套异步策略。

但是为了更好的优化体验,我们也是可以和C++实现的代码逻辑想通的。

接管渲染:

updateTimer = QTimer(self)
updateTimer.setInterval(16)
updateTimer.start()

updateTimer.timeout.connect(self.onUpdate)

渲染逻辑:

def onUpdate(self):
    self.update()
    if rospy.is_shutdown():
        self.close()

完整示例代码

MainWindow

#!/usr/bin/env python
# coding: utf-8

from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
import rospy
from geometry_msgs.msg import Twist
from turtlesim.msg import Pose
from math import radians, degrees


class MainWindow(QWidget):
    def __init__(self):
        super(MainWindow, self).__init__()

        # 自定义刷新
        updateTimer = QTimer(self)
        updateTimer.setInterval(16)
        updateTimer.start()

        updateTimer.timeout.connect(self.onUpdate)

        # 设置title
        self.setWindowTitle("小乌龟控制")
        self.resize(400, 120)

        # 设置布局
        layout = QFormLayout()
        self.setLayout(layout)

        # 添加控件
        self.editLinear = QLineEdit("0")
        layout.addRow("线速度", self.editLinear)

        self.editAngular = QLineEdit("0")
        layout.addRow("角速度", self.editAngular)

        self.labelX = QLabel()
        layout.addRow("当前X坐标", self.labelX)

        self.labelY = QLabel()
        layout.addRow("当前Y坐标", self.labelY)

        self.labelLinear = QLabel()
        layout.addRow("当前线速度", self.labelLinear)

        self.labelAngular = QLabel()
        layout.addRow("当前角速度", self.labelAngular)

        self.labelDegrees = QLabel()
        layout.addRow("当前角度", self.labelDegrees)

        self.btnSend = QPushButton("发送")
        layout.addRow(self.btnSend)

        # 添加事件
        self.btnSend.clicked.connect(self.clickSend)

        # 创建publisher
        topicName = "/turtle1/cmd_vel"
        self.publisher = rospy.Publisher(topicName, Twist, queue_size=1000)

        poseTopicName = "/turtle1/pose"
        rospy.Subscriber(poseTopicName, Pose, self.poseCallback)

    def clickSend(self):
        linearX = float(self.editLinear.text())
        angularZ = radians(float(self.editAngular.text()))

        # 构建消息
        twist = Twist()
        twist.linear.x = linearX
        twist.angular.z = angularZ
        # 发布
        self.publisher.publish(twist)

    def poseCallback(self, msg):
        if not isinstance(msg, Pose):
            return
        self.labelX.setText(str(msg.x))
        self.labelY.setText(str(msg.y))
        self.labelLinear.setText(str(msg.linear_velocity))
        self.labelAngular.setText(str(msg.angular_velocity))
        self.labelDegrees.setText(str(degrees(msg.theta)))

    def onUpdate(self):
        self.update()

        if rospy.is_shutdown():
            self.close()