实际上,我要做的是以示例代码为例,使用ROS2 (found 这里)来设置和运行订阅者和发布者,并设置订阅者python脚本以使用KivyMD显示它从Publisher python脚本接收到的消息,方法是每秒钟用订阅者回调更新的变量更新一个简单的MDLabel文本(注意:我目前还没有代码尝试这样做,因为我的问题目前与它无关)。
我不知道这样做的“最佳实践”是什么,因为我找过但找不到做过这件事的人,除了一些用ROS做这件事的YouTube视频之外,但我需要使用ROS2,而他的教程对此没有帮助。所以我只是想把它挂起来。
当我尝试这样做的时候,我发现的问题是,它们都能工作,就其本身而言,但似乎一次只能工作一次?如果在脚本中,最后在MainApp() (KivyMD代码)之前运行main() (KivyMD代码),那么当我在单独的终端中运行订阅服务器和发布服务器文件时,ROS2功能可以正常工作。发布服务器的消息到达订阅服务器。但是,弹出的KivyMD窗口没有填充该消息。
相反,如果我切换main()和MainApp()的位置,并在ROS2代码之前运行KivyMD代码,则KivyMD窗口将显示并填充占位符文本(在.kv文件中),但订阅服务器不会听到发布服务器的声音。
这个问题可能是显而易见的,但我就是看不到,而且我可能花了很长时间才意识到这个问题。有人能帮忙吗?
以下是订阅节点的python脚本:
import rclpy
from rclpy.node import Node
from std_msgs.msg import String
from kivy.lang import Builder
from kivymd.app import MDApp
from kivy.clock import Clock
global textOutput
textOutput = ""
class MainApp(MDApp):
def on_start(self):
Clock.schedule_interval(self.update_text, 1)
def build(self):
self.theme_cls.theme_style = "Dark"
self.theme_cls.primary_palette = "BlueGray"
return Builder.load_file('/home/cobot/dev_ws/src/py_pubsub/py_pubsub/ros_gui.kv')
def update_text(self, event):
global textOutput
self.root.ids.textOutputDisplay.text = textOutput
class MinimalSubscriber(Node):
def __init__(self):
super().__init__('minimal_subscriber')
self.subscription = self.create_subscription(
String,
'topic',
self.listener_callback,
10)
self.subscription # prevent unused variable warning
def listener_callback(self, msg):
global textOutput
textOutput = 'Test'
self.get_logger().info('I heard: "%s"' % msg.data)
def main(args=None):
rclpy.init(args=args)
minimal_subscriber = MinimalSubscriber()
rclpy.spin(minimal_subscriber)
# Destroy the node explicitly
# (optional - otherwise it will be done automatically
# when the garbage collector destroys the node object)
# minimal_subscriber.destroy_node()
rclpy.shutdown()
if __name__ == '__main__':
main()
MainApp().run()下面是我为KivyMD使用的KivyMD文件的代码:
MDScreen:
MDBoxLayout:
padding: dp(4), dp(4)
spacing: dp(4)
MDLabel:
id: textOutputDisplay
text: 'Output Text'
font_style: 'H1'
halign: 'center'发布于 2022-07-27 09:35:49
我最近遇到了和你类似的问题,但我用的是Tkinter而不是Kivy。
当您调用main()函数时,程序在rclpy.spin()函数中循环,不断侦听新消息。因此,您的Kivy接口没有得到更新。
相反,当您交换main()调用和MainApp().run()调用的位置时。在本例中,Kivy接口首先启动并侦听用户输入或输出,因此线程被阻塞,ROS2 2-功能没有启动。
可能有帮助的是在单独的线程中并行运行两个调用。
最简单的方法是导入threading包:
import threading然后,您可以为ROS2 2函数启动一个新线程,然后像往常一样在主线程中启动Kivy-接口:
process_thread = threading.Thread(target=main)
process_thread.start()
MainApp().run()在这里设置target=main而不是target=main()是很重要的。否则,您将立即运行main函数,将其传递给threading.Thread。
希望我能帮上忙!
https://stackoverflow.com/questions/72974005
复制相似问题