WSL中ROS节点实时单坐标点散点图及背景图全屏适配问题
解决方案
核心问题修复说明
1. 仅显示最新坐标点(解决卡顿)
原代码每次收到坐标就新建一个散点,历史点持续堆积导致渲染卡顿。我们改为初始化单个散点对象,仅更新其坐标数据,避免重复创建图形元素;同时用线程锁保证多线程下的变量安全。
2. 全屏适配修复
原代码混用plt.show()和Tkinter嵌入,导致窗口逻辑冲突。我们直接基于Tkinter实现全屏,让matplotlib画布填充整个窗口,同时调整背景图的显示逻辑,使其自适应窗口大小。
修改后的完整代码
from Tkinter import Canvas import Tkinter as Tk import rospy from std_msgs.msg import String import matplotlib.pyplot as plt from matplotlib.animation import FuncAnimation from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg from threading import Thread, Lock import numpy as np # 线程锁,保证坐标更新的线程安全 coord_lock = Lock() # 存储最新坐标 latest_x, latest_y = 0, 0 # 散点对象,用于后续更新 scatter_point = None def callback(data): global latest_x, latest_y received = data.data.split(',') x = int(float(received[0])) y = int(float(received[1])) # 线程安全更新坐标 with coord_lock: latest_x, latest_y = x, y def listener(): rospy.Subscriber('first', String, callback) rospy.spin() def animate(i): global scatter_point # 更新散点坐标 with coord_lock: if scatter_point is not None: scatter_point.set_offsets([[latest_x, latest_y]]) return [scatter_point] def visual(): global scatter_point root = Tk.Tk() root.title("Realtime plot") # 设置窗口全屏,按ESC退出 root.attributes('-fullscreen', True) root.bind('<Escape>', lambda e: root.destroy()) # 加载背景图 img = plt.imread("back.jpg") fig, ax = plt.subplots() # 显示背景图,取消固定宽高比让图自适应窗口 ax.imshow(img, extent=[0, 17947, -200, 5330], aspect='auto') # 初始化散点(初始坐标可按需调整) scatter_point = ax.scatter(latest_x, latest_y, color='red', s=50) # 将matplotlib画布嵌入Tkinter窗口并填充全屏 plotcanvas = FigureCanvasTkAgg(fig, root) plotcanvas.get_tk_widget().pack(fill=Tk.BOTH, expand=True) # 启动动画,blit=True仅更新变化区域提升效率 ani = FuncAnimation(fig, animate, interval=100, blit=True) Tk.mainloop() # 启动线程 t1 = Thread(target=visual) t1.start() listener() t1.join()
关键改动点
- 新增
coord_lock线程锁:解决ROS回调线程和matplotlib动画线程的坐标变量读写冲突 - 单个散点对象复用:仅初始化一次散点,后续通过
set_offsets更新坐标,避免图形元素堆积 - 移除
plt.show():取消独立matplotlib窗口,完全由Tkinter管理窗口逻辑 - Tkinter全屏设置:通过
attributes('-fullscreen', True)实现全屏,绑定ESC键快速退出 - 画布自适应窗口:
pack(fill=Tk.BOTH, expand=True)让matplotlib画布随窗口拉伸 aspect='auto':取消背景图固定宽高比,适配窗口大小blit=True:动画仅刷新变化区域,降低渲染压力
内容的提问来源于stack exchange,提问作者rebrid
相关产品推荐
相关产品推荐

