PythonRobotics-扩展卡尔曼定位

原文链接

定位

扩展卡尔曼滤波定位(Extended Kalman Filter Localization)在这里插入图片描述在这里插入图片描述

蓝色的是真实轨迹
黑色的里程计推演轨迹
绿色的点是GPS数据,

==>>

红色线是EKF推演推演路径
红色圆圈是估计斜方差

扩展卡尔曼基本原理

参考链接

滤波器设计

仿真设计初始时间 t 时刻, 机器人状态如下
X t = [ x t , y t , ϕ t , v t ] X_t=[x_t,y_t,\phi_t,v_t] Xt=[xt,yt,ϕt,vt]
x,y 是2D位置, ϕ \phi ϕ 是方向,v 是速度

名称含义
x,y2D位置
ϕ \phi ϕ2D方向
v速度

代码中含义

名称含义
xEst状态向量(state vector)
P t P_t Pt状态协方差矩阵(covariace matrix of the state)
Q Q Q噪声协方差矩阵(covariance matrix of process noise)
R R Rt 时刻观测噪声协方差矩阵(covariance matrix of observation noise at time 𝑡)

机器人有速度传感器和陀螺仪传感器,所以每个周期输入向量

u t = [ v t , ω t ] u_t=[v_t,\omega_t] ut=[vt,ωt]
机器人有GNSS 或者GPS传感器,每个周期机器人观测位置如下
z t = [ x t , y t ] z_t=[x_t,y_t] zt=[xt,yt]

运动学模型建立

机器人模型
x ˙ = v ∗ c o s ( ϕ ) y ˙ = v ∗ s i n ( ϕ ) ϕ ˙ = ω \dot x = v*cos(\phi) \\ \dot y= v* sin(\phi) \\ \dot \phi = \omega x˙=vcos(ϕ)y˙=vsin(ϕ)ϕ˙=ω
运动学模型应该是
x t + 1 = F x t + B u t x_{t+1}=Fx_t+Bu_t xt+1=Fxt+But

预测-2个公式

x_t 当前时刻状态比如(x,y) u_t 控制量输入 比如机器人速度 v
状态预测公式
x p r e d = F x t + B u t x_{pred}=Fx_t+Bu_t xpred=Fxt+But
方差预测公式  Q: 运动过程噪声
P p r e d = J F P t J F T + Q P_{pred}=J_F P_t J_F^T+Q Ppred=JFPtJFT+Q
x t x_t xt : {x,y,yaw,v}
u t u_t ut : {v, w}
根据上文数学公式 dt是时间周期 假定机器人前向速度不会改变,那么当前速度就是等于历史速度
里程计推演公式
[ x p r e d y p r e d ϕ p r e d v p r e d ] = [ x t + ​ v ∗ c o s ( ϕ ) d t y t + v ∗ s i n ( ϕ ) d t ϕ t + w ∗ d t v t ] \begin{bmatrix} x_{pred} \\ y_{pred} \\ \phi_{pred} \\ v_{pred} \end{bmatrix}= \begin{bmatrix} x_{t}+​v*cos(ϕ)dt \\ y_{t}+v*sin(ϕ)dt \\ \phi_{t}+w*dt \\ v_{t} \end{bmatrix} xpredypredϕpredvpred=xt+vcos(ϕ)dtyt+vsin(ϕ)dtϕt+wdtvt
==>>
[ x p r e d y p r e d ϕ p r e d v p r e d ] = [ 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 ] [ x t y t ϕ t v t ] + [ c o s ( ϕ ) d t 0 s i n ( ϕ ) d t 0 0 d t 1 0 ] [ v t w ] \begin{bmatrix} x_{pred} \\ y_{pred} \\ \phi_{pred} \\ v_{pred} \end{bmatrix} =\begin{bmatrix} 1&0&0&0 \\ 0&1&0&0 \\ 0&0&1&0 \\ 0&0&0&0 \end{bmatrix} \begin{bmatrix} x_{t} \\ y_{t} \\ \phi_{t} \\ v_{t} \end{bmatrix} +\begin{bmatrix} cos(\phi)dt&0 \\ sin(\phi)dt&0 \\ 0&dt \\ 1&0 \end{bmatrix} \begin{bmatrix} v_t \\ w \end{bmatrix} xpredypredϕpredvpred=1000010000100000xtytϕtvt+cos(ϕ)dtsin(ϕ)dt0100dt0[vtw]

雅克比矩阵公式如下

J = [ ∂ y 1 ∂ x 1 . . . ∂ y 1 ∂ x n . . . . . . . . . ∂ y n ∂ x 1 . . . ∂ y n ∂ x n ] J= \begin{bmatrix} \frac{\partial y1 }{\partial x1} &...& \frac{\partial y1 }{\partial xn} \\ ...& ... & ... \\ \frac{\partial yn }{\partial x1} &...& \frac{\partial yn }{\partial xn} \\ \end{bmatrix} J=x1y1...x1yn.........xny1...xnyn
这里方差的J_F为

J F = [ ∂ x p r e d ∂ x t ∂ x p r e d ∂ y t ∂ x p r e d ∂ ϕ t ∂ x p r e d ∂ v t ∂ y p r e d ∂ x t ∂ x y p r e d ∂ y t ∂ y p r e d ∂ ϕ t ∂ y p r e d ∂ v t ∂ ϕ p r e d ∂ x t ∂ ϕ p r e d ∂ y t ∂ ϕ p r e d ∂ ϕ t ∂ ϕ p r e d ∂ v t ∂ v p r e d ∂ x t ∂ v p r e d ∂ y t ∂ v p r e d ∂ ϕ t ∂ v p r e d ∂ v t ] J_F= \begin{bmatrix} \frac{\partial x_{pred} }{\partial x_t} & \frac{\partial x_{pred} }{\partial y_t} & \frac{\partial x_{pred} }{\partial \phi_t} & \frac{\partial x_{pred} }{\partial v_t} \\ \frac{\partial y_{pred} }{\partial x_t} & \frac{\partial xy{pred} }{\partial y_t} & \frac{\partial y_{pred} }{\partial \phi_t} & \frac{\partial y_{pred} }{\partial v_t} \\ \frac{\partial \phi_{pred} }{\partial x_t} & \frac{\partial \phi_{pred} }{\partial y_t} & \frac{\partial \phi_{pred} }{\partial \phi_t} & \frac{\partial \phi_{pred} }{\partial v_t} \\ \frac{\partial v_{pred} }{\partial x_t} & \frac{\partial v_{pred} }{\partial y_t} & \frac{\partial v_{pred} }{\partial \phi_t} & \frac{\partial v_{pred} }{\partial v_t} \\ \end{bmatrix} JF=xtxpredxtypredxtϕpredxtvpredytxpredytxypredytϕpredytvpredϕtxpredϕtypredϕtϕpredϕtvpredvtxpredvtypredvtϕpredvtvpred
=>>
雅克比矩阵的意思就是求偏导函数,对某个变量求偏导时,将其他变量设定为定值
∂ x p r e d ∂ x t \frac{\partial x_{pred} }{\partial x_t} xtxpred 就是对
x t + ​ v ∗ c o s ( ϕ ) d t x_{t}+​v*cos(ϕ)dt xt+vcos(ϕ)dt 求偏导数 x_t 的系数为1 则偏导为1
∂ x p r e d ∂ ϕ t \frac{\partial x_{pred} }{\partial \phi_t} ϕtxpred 就是对
x t + ​ v ∗ c o s ( ϕ ) d t x_{t}+​v*cos(ϕ)dt xt+vcos(ϕ)dt 求偏导数  ϕ \phi ϕ 的系数为 vcos( ϕ \phi ϕ) 则偏导为 -vsin( ϕ \phi ϕ)
J F = [ 1 0 − v s i n ( ϕ ) d t c o s ( ϕ ) d t 0 1 v c o s ( ϕ ) d t s i n ( ϕ ) d t 0 0 1 0 0 0 0 1 ] J_F= \begin{bmatrix} 1 & 0 & -vsin(\phi)dt & cos(\phi)dt \\ 0&1&vcos(\phi)dt&sin(\phi)dt \\ 0&0&1&0 \\ 0&0&0&1 \end{bmatrix} JF=10000100vsin(ϕ)dtvcos(ϕ)dt10cos(ϕ)dtsin(ϕ)dt01
Q为运动噪声,设定Q为

Q=np.diag([0.1, 0.1, np.deg2rad(1.0), 1.0])**2  # predict state covariance
Q=array([[  1.00000000e-02,   0.00000000e+00,   0.00000000e+00,
          0.00000000e+00],
       [  0.00000000e+00,   1.00000000e-02,   0.00000000e+00,
          0.00000000e+00],
       [  0.00000000e+00,   0.00000000e+00,   3.04617420e-04,
          0.00000000e+00],
       [  0.00000000e+00,   0.00000000e+00,   0.00000000e+00,
          1.00000000e+00]])

更新

–6个公式
求观测函数H
z p r e d = H x p r e d z_{pred}=Hx_{pred} zpred=Hxpred
因为我们的观测只有GPS,x 和y的位置
因此
[ Z x p r e d Z y p r e d ] = [ 1 0 0 0 0 1 0 0 ] [ x p r e d y p r e d ϕ p r e d v p r e d ] \begin{bmatrix} Zx_{pred} \\ Zy_{pred} \end{bmatrix} =\begin{bmatrix} 1&0&0&0 \\ 0&1&0&0 \end{bmatrix} \begin{bmatrix} x_{pred} \\ y_{pred} \\ \phi_{pred} \\ v_{pred} \end{bmatrix} [ZxpredZypred]=[10010000]xpredypredϕpredvpred
H = [ 1 0 0 0 0 1 0 0 ] J H = [ 1 0 0 0 0 1 0 0 ] H =\begin{bmatrix} 1&0&0&0 \\ 0&1&0&0 \end{bmatrix} \\ J_H =\begin{bmatrix} 1&0&0&0 \\ 0&1&0&0 \end{bmatrix} H=[10010000]JH=[10010000]
观测与运动推测的
误差= 观测值 - 预测值
e r r o r = z − z p r e d error=z-z_{pred} error=zzpred
求卡尔曼增益 记住此公式即可
S = J H P p r e d J H T + R K = P p r e d J H T S − 1 S=J_HP_{pred}J_H^T+R \\ K=P_{pred}J_H^TS^{-1} S=JHPpredJHT+RK=PpredJHTS1
更新新的位置和方差
x t + 1 = x p r e d + K ∗ e r r o r P t + 1 = ( I − K J H ) P p r e d x_{t+1} = x_{pred}+K*error \\ P_{t+1}=(I-KJ_H)P_{pred} xt+1=xpred+KerrorPt+1=(IKJH)Ppred
R为观测方差
此处记录为

R = np.diag([1.0, 1.0])**2  # Observation x,y position covariance

代码链接
PythonRobotics/extended_kalman_filter.py at master · AtsushiSakai/PythonRobotics

"""
Extended kalman filter (EKF) localization sample
author: Atsushi Sakai (@Atsushi_twi)
"""

import numpy as np
import math
import matplotlib.pyplot as plt

# Estimation parameter of EKF diag 生成以对角线为数值生成矩阵 deg2rad角度转弧度
Q = np.diag([1.0, 1.0])**2  # Observation x,y position covariance
R = np.diag([0.1, 0.1, np.deg2rad(1.0), 1.0])**2  # predict state covariance

#  Simulation parameter
Qsim = np.diag([0.5, 0.5])**2
Rsim = np.diag([1.0, np.deg2rad(30.0)])**2

DT = 0.1  # time tick [s]
SIM_TIME = 50.0  # simulation time [s]

show_animation = True


def calc_input():
    v = 1.0  # [m/s]
    yawrate = 0.1  # [rad/s]
    u = np.array([[v, yawrate]]).T
    return u


def observation(xTrue, xd, u):


    # 这是仿真里面准确的位置
    xTrue = motion_model(xTrue, u)
    # add noise to gps x-y
    zx = xTrue[0, 0] + np.random.randn() * Qsim[0, 0]
    zy = xTrue[1, 0] + np.random.randn() * Qsim[1, 1]
    #在准确位置上加入一定噪声仿真GPS数据
    z = np.array([[zx, zy]])

    # 仿真实际的速度反馈,实际的速度加入一定噪声
    ud1 = u[0, 0] + np.random.randn() * Rsim[0, 0]
    ud2 = u[1, 0] + np.random.randn() * Rsim[1, 1]
    ud = np.array([[ud1, ud2]]).T

   #获得航迹
    xd = motion_model(xd, ud)

    return xTrue, z, xd, ud


def motion_model(x, u):

    F = np.array([[1.0, 0, 0, 0],
                  [0, 1.0, 0, 0],
                  [0, 0, 1.0, 0],
                  [0, 0, 0, 0]])

    B = np.array([[DT * math.cos(x[2, 0]), 0],
                  [DT * math.sin(x[2, 0]), 0],
                  [0.0, DT],
                  [1.0, 0.0]])

    x = F.dot(x) + B.dot(u)

    return x


def observation_model(x):
    #  Observation Model
    H = np.array([
        [1, 0, 0, 0],
        [0, 1, 0, 0]
    ])

    z = H.dot(x)

    return z


def jacobF(x, u):
    """
    Jacobian of Motion Model
    motion model
    x_{t+1} = x_t+v*dt*cos(yaw)
    y_{t+1} = y_t+v*dt*sin(yaw)
    yaw_{t+1} = yaw_t+omega*dt
    v_{t+1} = v{t}
    so
    dx/dyaw = -v*dt*sin(yaw)
    dx/dv = dt*cos(yaw)
    dy/dyaw = v*dt*cos(yaw)
    dy/dv = dt*sin(yaw)
    """
    yaw = x[2, 0]
    v = u[0, 0]
    jF = np.array([
        [1.0, 0.0, -DT * v * math.sin(yaw), DT * math.cos(yaw)],
        [0.0, 1.0, DT * v * math.cos(yaw), DT * math.sin(yaw)],
        [0.0, 0.0, 1.0, 0.0],
        [0.0, 0.0, 0.0, 1.0]])

    return jF


def jacobH(x):
    # Jacobian of Observation Model
    jH = np.array([
        [1, 0, 0, 0],
        [0, 1, 0, 0]
    ])

    return jH


def ekf_estimation(xEst, PEst, z, u):

    """
    假设当前推演值是x_t 观测值是z_t 这了里程计是推测值,GPS是观测值
    那么ekf_x估计位置是 
    ekf_t= x_t+ k(z_t-x_t) 
    ekf滤波值=里程计值+k*(GPS位置-里程计位置)
    ekf 主要目的是为了求k值
    假如k=0 那么ekf估计值就是推测值
    假如k=1 那么ekf估计值就是观测值
    
    """
    #  Predict 预测位置
    xPred = motion_model(xEst, u)
    # 得到运动学模型雅克比矩阵
    jF = jacobF(xPred, u)
    # R预测值的协方差
    PPred = jF.dot(PEst).dot(jF.T) + R

    #  Update
    #得到观测位置
    zPred = observation_model(xPred)
    
    jH = jacobH(xPred)
    y = z.T - zPred
    S = jH.dot(PPred).dot(jH.T) + Q
    K = PPred.dot(jH.T).dot(np.linalg.inv(S))
    xEst = xPred + K.dot(y)
    PEst = (np.eye(len(xEst)) - K.dot(jH)).dot(PPred)

    return xEst, PEst


def plot_covariance_ellipse(xEst, PEst):
    Pxy = PEst[0:2, 0:2]
    eigval, eigvec = np.linalg.eig(Pxy)

    if eigval[0] >= eigval[1]:
        bigind = 0
        smallind = 1
    else:
        bigind = 1
        smallind = 0

    t = np.arange(0, 2 * math.pi + 0.1, 0.1)
    a = math.sqrt(eigval[bigind])
    b = math.sqrt(eigval[smallind])
    x = [a * math.cos(it) for it in t]
    y = [b * math.sin(it) for it in t]
    angle = math.atan2(eigvec[bigind, 1], eigvec[bigind, 0])
    R = np.array([[math.cos(angle), math.sin(angle)],
                  [-math.sin(angle), math.cos(angle)]])
    fx = R.dot(np.array([[x, y]]))
    px = np.array(fx[0, :] + xEst[0, 0]).flatten()
    py = np.array(fx[1, :] + xEst[1, 0]).flatten()
    plt.plot(px, py, "--r")


def main():
    print(__file__ + " start!!")

    time = 0.0

    # State Vector [x y yaw v]' 估计位置状态矩阵 4行1列
    xEst = np.zeros((4, 1))
    # 真实位置状态矩阵 4行1列
    xTrue = np.zeros((4, 1))
    #协方差矩阵
    PEst = np.eye(4)
	# 里程计
    xDR = np.zeros((4, 1))  # Dead reckoning

    # history
    hxEst = xEst
    hxTrue = xTrue
    hxDR = xTrue
    hz = np.zeros((1, 2))

    while SIM_TIME >= time:
        time += DT
        # 假定真实固定的速度输入
        u = calc_input()
     # 输入上次的准确位置 里程计数据 和速度
     # 返回得到模拟真实轨迹 不准确的GPS数据 里程计数据 不准确的速度向量 
        xTrue, z, xDR, ud = observation(xTrue, xDR, u)
     # 输入推算位置 协方差 带噪声的GPS位置 带噪声的速度输入
        xEst, PEst = ekf_estimation(xEst, PEst, z, ud)

        # store data history
        hxEst = np.hstack((hxEst, xEst))
        hxDR = np.hstack((hxDR, xDR))
        hxTrue = np.hstack((hxTrue, xTrue))
        hz = np.vstack((hz, z))

        if show_animation:
            plt.cla()
            plt.plot(hz[:, 0], hz[:, 1], ".g")
            plt.plot(hxTrue[0, :].flatten(),
                     hxTrue[1, :].flatten(), "-b")
            plt.plot(hxDR[0, :].flatten(),
                     hxDR[1, :].flatten(), "-k")
            plt.plot(hxEst[0, :].flatten(),
                     hxEst[1, :].flatten(), "-r")
            plot_covariance_ellipse(xEst, PEst)
def main():
    print(__file__ + " start!!")

    time = 0.0

    # State Vector [x y yaw v]' 估计位置状态矩阵 4行1列
    xEst = np.zeros((4, 1))
    # 真实位置状态矩阵 4行
  • 4
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Design, simulate, and program interactive robots Key Features Design, simulate, build, and program an interactive autonomous mobile robot Leverage the power of ROS, Gazebo, and Python to enhance your robotic skills A hands-on guide to creating an autonomous mobile robot with the help of ROS and Python Book Description Robot Operating System (ROS) is one of the most popular robotics software frameworks in research and industry. It has various features for implement different capabilities in a robot without implementing them from scratch. This book starts by showing you the fundamentals of ROS so you understand the basics of differential robots. Then, you'll learn about robot modeling and how to design and simulate it using ROS. Moving on, we'll design robot hardware and interfacing actuators. Then, you'll learn to configure and program depth sensors and LIDARs using ROS. Finally, you'll create a GUI for your robot using the Qt framework. By the end of this tutorial, you'll have a clear idea of how to integrate and assemble everything into a robot and how to bundle the software package. What you will learn Design a differential robot from scratch Model a differential robot using ROS and URDF Simulate a differential robot using ROS and Gazebo Design robot hardware electronics Interface robot actuators with embedded boards Explore the interfacing of different 3D depth cameras in ROS Implement autonomous navigation in ChefBot Create a GUI for robot control Who this book is for This book is for those who are conducting research in mobile robotics and autonomous navigation. As well as the robotics research domain, this book is also for the robot hobbyist community. You're expected to have a basic understanding of Linux commands and Python. Table of Contents Getting started with ROS Understanding basics of differential robots Modeling the Differential Drive Robot Simulating a Differential Drive Robot Using ROS Designing ChefBot Hardware and Circuits Interfacing Actuators and Sensors to the Robot Controller Interfacing Vision Sensors with ROS Building ChefBot Hardware and the Integration of Software Designing a GUI for a Robot Using Qt and Python Assessments 设计,模拟和编程交互式机器人 主要特征 设计,模拟,构建和编程交互式自主移动机器人 利用ROS,Gazebo和Python的强大功能来增强您的机器人技能 在ROS和Python的帮助下创建自主移动机器人的实用指南 书说明 机器人操作系统(ROS)是研究和工业中最流行的机器人软件框架之一。它具有各种功能,可以在机器人中实现不同的功能而无需从头开始实现。 本书首先向您展示ROS的基础知识,以便您了解差分机器人的基础知识。然后,您将学习机器人建模以及如何使用ROS设计和模拟它。继续,我们将设计机器人硬件和接口执行器。然后,您将学习使用ROS配置和编程深度传感器和激光雷达。最后,您将使用Qt框架为您的机器人创建GUI。 在本教程结束时,您将清楚地了解如何将所有内容集成并组装到机器人中以及如何捆绑软件包。 你会学到什么 从头开始设计差速机器人 使用ROS和URDF建模差分机器人 使用ROS和Gazebo模拟差分机器人 设计机器人硬件电子 带嵌入式板的接口机器人执行器 探索ROS中不同3D深度相机的接口 在ChefBot中实现自主导航 为机器人控制创建GUI 这本书的用途是谁 本书适用于从事移动机器人和自主导航研究的人员。除了机器人研究领域,本书也适用于机器人爱好者社区。您应该对Linux命令和Python有基本的了解。 目录 ROS入门 了解差分机器人的基础知识 差动驱动机器人的建模 使用ROS模拟差分驱动机器人 设计ChefBot硬件和电路 将执行器和传感器连接到机器人控制器 将视觉传感器与ROS连接 构建ChefBot硬件和软件集成 使用Qt和Python为机器人设计GUI 评估

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值