import sensor, image, time from pyb import RTC sensor.reset() sensor.set_pixformat(sensor.RGB565) sensor.set_framesize(sensor.QVGA) sensor.skip_frames(time = 2000) clock=time.clock() rtc=RTC() rtc.datetime((0,0,0,0,0,0,0,0)) #2*1列向量类 class Vector: def __init__(self,x,y): self.x=x self.y=y #运算符重载 def __add__(self,other): return Vector(self.x+other.x,self.y+other.y) def __sub__(self,other): return Vector(self.x-other.x,self.y-other.y) def __mul__(self,scalar): return Vector(self.x*scalar,self.y*scalar) def __rmul__(self,scalar): return self._mul_(scalar) def __str__(self): return f"Vector({self.x},{self.y})" #2*2矩阵类 class Matrix: def __init__(self,rows): self.rows=rows #二维列表格式[[a,b],[c,d]] def __mul__(self,other): if isinstance(other,Vector): #格式:矩阵*向量 return Vector(self.rows[0][0]*other.x+self.rows[0][1]*other.y, self.rows[1][0]*other.x+self.rows[1][1]*other.y) elif isinstance(other,Matrix): #格式:矩阵*矩阵 return Matrix([ [ self.rows[0][0]*other.rows[0][0]+self.rows[0][1]*other.rows[1][0], self.rows[0][0]*other.rows[0][1]+self.rows[0][1]*other.rows[1][1] ], [ self.rows[1][0]*other.rows[0][0]+self.rows[1][1]*other.rows[1][0], self.rows[1][0]*other.rows[0][1]+self.rows[1][1]*other.rows[1][1] ] ]) def inv(self): #仅限2*2非奇异矩阵 a,b=self.rows[0] c,d=self.rows[1] det=a*d-b*c return Matrix([ [d/det,-b/det], [-c/det,a/det] ]) def tran(self): return Matrix([[self.rows[0][0],self.rows[1][0]],[self.rows[0][1],self.rows[1][1]]]) def _str_(self): return f"Matrix({self.rows})" Q=Matrix([[5,0],[0,1]])#过程噪声协方差矩阵 第一个参数代表位置 第二个参数代表速度 R=Matrix([[1,0],[0,1]])#测量噪声协方差矩阵 I=Matrix([[1,0],[0,1]])#单位矩阵 class Kalman: def __Init__(self): self.dT=0.1 self.A=Matrix([[1,self.dT],[0,1]])#状态转移矩阵 self.H=Matrix([[1,0],[0,1]])#观测状态矩阵 self.pre=Vector(0,0)#先验估计 self.pre_P=Matrix([[0,0],[0,0]])#先验估计的协方差矩阵 self.est=Vector(0,0)#这一时刻的最优估计 self.est_P=Matrix([[X_P1,0],[0,X_P2]])#这一时刻最优估计的协方差矩阵 self.est_K=Matrix([[0,0],[0,0]])#这一时刻卡尔曼增益矩阵 self.last_time=rtc.datetime() def Kalman_filter(self,other): self.pre=self.A*self.est#更新这一时刻的先验估计,不考虑控制向量和控制矩阵的作用 self.pre_P=(self.A*self.est_P*self.A.tran())+Q#更新这一时刻先验估计的协方差矩阵 self.est_K=self.pre_P*((self.pre_P+R).inv())#更新卡尔曼增益,因观测矩阵为一单位矩阵,计算时可不考虑 #状态更新 self.est=self.pre+self.est_K*(self.Z-self.pre)#计算时省略了观测矩阵 #协方差更新 self.est_P=(I-self.est_K)*self.pre_P#计算时省略了观测矩阵 return(self.est.x,self.est.y) while(True): clock.tick() img=sensor.snapshot().gamma_corr(gamma = 0.5, contrast = 1.0, brightness = 0.0) img.gaussian(3) img.erode(1) blob_X=Kalman() blob_Y=Kalman() blobs_3 = img.find_blobs([(4, 70, 2, 52, -82, -10)],merge=True)#蓝色 for blob in blobs_3: if blob.roundness()>0.7 and blob.pixels()>100: current_time = rtc.datetime() dt = (current_time[6]*1e6 + current_time[7]) - (blob_X.last_time[6]*1e6 + blob_X.last_time[7]) dt = max(dt / 1e6, 0.01) # 转换为秒并限制最小值 #blob_X.est=Vector(blob[0],),blob_Y.est=blob[1] blob_X_est,blob_VX_est=Kalman_filter(blob_X) 报错AttributeError: 'Kalman' object has no attribute 'last_time'
时间: 2025-07-10 17:36:51 浏览: 5
<think>嗯,用户给了一段MicroPython的代码,并且遇到了AttributeError: 'Kalman' object has no attribute 'last_time'的错误。我需要先仔细看看代码哪里出错了。
首先,用户定义的Kalman类中有一个__Init__方法,注意这里是大写的I,而正确的Python构造函数应该是__init__,也就是小写的i。所以这里可能因为拼写错误导致构造函数没有正确执行,所以实例化Kalman对象时,last_time属性没有被初始化,因此访问时会报错。
接下来看Kalman类的定义部分,用户写的是def __Init__(self):,这明显是拼写错误,正确的应该是def __init__(self):。由于构造函数名称错误,Python不会将其识别为构造函数,所以当创建Kalman实例时,__init__方法没有被调用,导致实例缺少last_time属性。
然后,在Kalman_filter方法中,用户试图使用self.Z,但在代码中并没有看到Z属性的定义,这可能会导致另一个错误。不过当前报错是关于last_time的,所以先解决这个问题。
另外,在Kalman类的初始化中,self.est_P被初始化为Matrix([[X_P1,0],[0,X_P2]]),但X_P1和X_P2在代码中没有定义,这可能会导致NameError。不过用户现在的问题是关于last_time的,所以暂时先忽略这个,但需要提醒用户后续处理。
再看循环部分,用户创建了blob_X和blob_Y作为Kalman的实例,然后在调用Kalman_filter时,可能没有正确传递参数。例如,Kalman_filter方法中的参数是other,但在调用时传入了blob_X,而方法内部使用了self.Z,这可能需要更多的上下文,但可能也是问题之一。
总结错误原因:Kalman类的构造函数名称错误,导致last_time未被正确初始化,从而在访问时抛出属性错误。需要将__Init__改为__init__。
另外,代码中还有其他潜在问题,比如X_P1和X_P2未定义,Kalman_filter方法的参数和self.Z的使用是否正确,以及方法调用是否正确(比如是否应该使用实例方法而非类方法)。但用户当前的问题是last_time缺失,所以先解决构造函数的问题。
最后,在循环中调用Kalman_filter时,用户写的是Kalman_filter(blob_X),这应该是实例方法的调用,正确的方式应该是blob_X.Kalman_filter(参数),但参数这里可能存在问题,因为方法定义中的参数是other,但内部使用了self.Z,这可能意味着需要传入测量值Z。这部分可能需要进一步检查代码逻辑,但当前报错是last_time的问题,所以先解决构造函数的问题。</think>让我们逐步分析并解决代码中的错误:
$\boxed{\text{错误原因分析}}$
1. $\text{构造函数名称错误}$:Kalman类中使用了`def __Init__(self)`(大写I),正确的构造函数应为`def __init__(self)`
2. $\text{属性初始化缺失}$:由于构造函数未执行,`last_time`属性未被创建
$\boxed{\text{解决方案步骤}}$
$\text{第一步:修正构造函数名称}$
```python
class Kalman:
def __init__(self): # 改为小写i
self.dT=0.1
...(后续代码保持不变)...
```
$\text{第二步:检查关联错误}$
1. 初始化参数`X_P1, X_P2`未定义:
```python
# 原始错误代码
self.est_P=Matrix([[X_P1,0],[0,X_P2]])
# 应修改为具体数值,例如:
self.est_P=Matrix([[1,0],[0,1]]) # 示例值
```
2. 卡尔曼滤波方法参数问题:
```python
def Kalman_filter(self, Z): # 参数应为测量值
self.Z = Z # 添加测量值接收
...(后续计算中使用self.Z)...
```
$\text{第三步:修正方法调用}$
```python
# 原错误调用方式
blob_X_est,blob_VX_est=Kalman_filter(blob_X)
# 正确调用方式(假设传入测量向量)
blob_X_est,blob_VX_est=blob_X.Kalman_filter(measurement_vector)
```
$\boxed{\text{完整修正建议}}$
1. $\text{基础结构修正}$:
```python
class Kalman:
def __init__(self): # 修正构造函数
self.dT=0.1
self.A=Matrix([[1,self.dT],[0,1]])
self.H=Matrix([[1,0],[0,1]])
self.pre=Vector(0,0)
self.pre_P=Matrix([[0,0],[0,0]])
self.est=Vector(0,0)
self.est_P=Matrix([[1,0],[0,1]]) # 修改为具体值
self.est_K=Matrix([[0,0],[0,0]])
self.last_time=rtc.datetime() # 现在会被正确初始化
self.Z = Vector(0,0) # 添加测量值占位
def Kalman_filter(self, Z): # 添加参数
self.Z = Z # 接收测量值
...(保持原有计算逻辑)...
```
2. $\text{调用方式修正}$:
```python
# 在循环中调用时
if blob.roundness()>0.7 and blob.pixels()>100:
...
measurement = Vector(blob.cx(), blob.cy()) # 示例测量值
blob_X_est,blob_VX_est = blob_X.Kalman_filter(measurement)
```
$\boxed{\text{仍需注意的问题}}$
1. $\text{矩阵运算验证}$:需要确保矩阵乘法、逆矩阵计算符合数学定义
2. $\text{时间差计算}$:当前`dt`计算方式可能需要调整,建议使用:
```python
dt = (current_time[6]*60 + current_time[7]/1e6) -
(blob_X.last_time[6]*60 + blob_X.last_time[7]/1e6)
```
3. $\text{协方差矩阵初始化}$:应根据实际应用场景设置合理的初始值
建议使用调试工具逐步验证卡尔曼滤波器的预测和更新过程,确保矩阵运算结果符合预期。
阅读全文
相关推荐














