问题描述
每当触发回调时,我都会尝试更新一个占用网格图。以下代码显示了回调,该回调将激光扫描数据作为输入(使用rospy
),使用该数据更新占用网格图,然后为用户绘制网格图:
def lidar_callback(self,scan: LaserScan):
scan_parameters = [scan.angle_min,scan.angle_max,scan.angle_increment]
scan_ranges = np.array(scan.ranges)
self.mapper.update_map(self.pose,scan_ranges,scan.angle_min,scan.angle_increment)
fig = plt.figure()
ax = self.fig.add_subplot(111)
ax.matshow(self.mapper.probability_map(),cmap="Greys")
plt.draw()
对于一次迭代,占用栅格图的输出如下:
但是,以上代码在触发回调时 都会创建一个新图,而不是保留一个图并在处理新的激光雷达数据时对其进行更新。由于lidar_callback()
函数是更大的MapperNode
类的一部分,因此我试图通过将fig
变量移到__init__()
的{{1}}构造函数中来解决此问题。类,提供以下代码,
MapperNode
但是现在,在尝试定义class MapperNode:
def __init__(self,pose: Pose,mapper: Mapper):
self.pose = pose
self.mapper = mapper
rospy.Subscriber("scan",LaserScan,self.lidar_callback)
rospy.Subscriber("odom",odometry,self.odometry_callback)
self.fig = plt.figure()
def lidar_callback(self,scan: LaserScan):
scan_parameters = [scan.angle_min,scan.angle_increment]
scan_ranges = np.array(scan.ranges)
self.mapper.update_map(self.pose,scan.angle_increment)
ax = self.fig.add_subplot(111)
ax.matshow(self.mapper.probability_map(),cmap="Greys")
plt.draw()
时使用self.fig
时,出现以下错误:
ax = self.fig.add_subplot(111)
因此,似乎无法在构造函数中定义ax = self.fig.add_subplot(111)
AttributeError: 'MapperNode' object has no attribute 'fig'
对象,以后再在该类的另一个函数中使用它。有人知道我在尝试更新回调中的现有图形时犯什么错误吗?如果有更好的方法来显示/更新占用率网格图,我将非常高兴知道这一点。谢谢!
解决方法
您可以尝试一下
import matplotlib.pyplot as plt
import rospy
import tf
from sensor_msgs.msg import LaserScan
from tf.transformations import quaternion_matrix
import numpy as np
from matplotlib.animation import FuncAnimation
class Visualiser:
def __init__(self):
self.fig,self.ax = plt.subplots()
self.ln,= plt.plot([],[],'ro')
self.max_x = 300
self.max_y = 300
def plot_init(self):
self.ax.set_xlim(0,self.max_x)
self.ax.set_ylim(0,self.max_y)
return self.ln
def update_plot(self,frame):
# data_map = np.random.randint(60,size=(60,60))
# self.ax.matshow(data_map,cmap="Greys")
self.ax.matshow(self.mapper.probability_map(),cmap="Greys")
return self.ln
def lidar_callback(self,scan):
scan_parameters = [scan.angle_min,scan.angle_max,scan.angle_increment]
scan_ranges = np.array(scan.ranges)
self.mapper.update_map(self.pose,scan_ranges,scan.angle_min,scan.angle_increment)
rospy.init_node('lidar_visual_node')
vis = Visualiser()
sub = rospy.Subscriber('/scan',LaserScan,vis.lidar_callback)
ani = FuncAnimation(vis.fig,vis.update_plot,init_func=vis.plot_init)
plt.show(block=True)
注意:我为随机映射测试了self.max_x
和self.max_y
的正确值。让我知道这是否对您有用