课程 19:Lesson 6 – SLAM

本文详细记录了课程中的SLAM学习内容,包括定位、规划、PID控制以及Graph SLAM的实现。重点讨论了PID控制器的CTE计算、参数调整,以及在Graph SLAM中矩阵和向量的处理,同时还涵盖了噪声和测量可信度在SLAM中的应用。
摘要由CSDN通过智能技术生成

Lesson 6 – SLAM

1.   Putting It All Together

2.   练习:Localization

3.   练习:Planning

算法名

是否在连续空间

是否会取得最优解(找到目标)

是否是通用性算法

是否仅是局部性算法

广度优先搜索

A*

动态规划

平滑(Smoothing)

 

4.   练习:PID

下表是对PID控制器中的子项及其作用的描述:

 

 

QUIZ

子项

避免超调

最小化误差

补偿漂移

PID

P

I

D

 

5.   Your Robot Car

 

6.   练习:Segmented CTE

一个编程的例子,主要是写控制部分,如何根据粒子提供的预测路径(由线段组成),来计算出横切距离(CTE)。

视频提供了个相关的计算公式:

u大于1时,表明已经进入了下一个线段的计算范围。这上面的图片是视频讲解图片,遗憾的是,又写错了。。。。汗

在网页的视频的下方写道:Note: theformula for CTE should actually take the square root of the denominator, i.e.(Ry dx - Rx dy) /sqrt(dx^2 + dy^2)

就是说 CTE = (Ry* dx – Rx* dy) /sqrt(dx^2 + dy^2)

视频代码的答案中,给出的计算cte,没有做sqrt操作。

对于u和cte的计算公式怎么来的,这里我没有去深究。

代码:

# -*- coding: utf-8 -*-

 

# -----------

# User Instructions

#

# Familiarize yourself with the code below. Most of it

# reproduces results that you have obtained at some

# point in this class. Once you understand the code,

# write a function, cte, in the run class that

# computes the crosstrack

# error for the case of a segmented path. You will

# need to include the equations shown in the video.

#

 

from math import *

import random

 

 

# don't change the noise paameters

 

steering_noise    = 0.1

distance_noise    = 0.03

measurement_noise = 0.3

 

 

class plan:

 

    # --------

    # init:

    #    creates an empty plan

    #

 

    def __init__(self, grid,init, goal, cost = 1):

        self.cost = cost

        self.grid = grid

        self.init = init

        self.goal = goal

       self.make_heuristic(grid, goal, self.cost)

        self.path = []

        self.spath = []

 

    # --------

    #

    # make heuristic functionfor a grid

 

    def make_heuristic(self,grid, goal, cost):

        self.heuristic = [[0for row in range(len(grid[0]))]

                          forcol in range(len(grid))]

        for i inrange(len(self.grid)):

            for j inrange(len(self.grid[0])):

               self.heuristic[i][j] = abs(i - self.goal[0]) + \

                    abs(j -self.goal[1])

 

 

 

    #------------------------------------------------

    #

    # A* for searching a pathto the goal

    #

    #

 

    def astar(self):

 

 

        if self.heuristic ==[]:

            raise(ValueError,"Heuristic must be defined to run A*")

 

        # internal motionparameters

        delta = [[-1,  0], # go up

                 [ 0,  -1], # go left

                 [ 1,  0], # go down

                 [ 0,  1]] # do right

 

 

        # open list elementsare of the type: [f, g, h, x, y]

 

        closed = [[0 for rowin range(len(self.grid[0]))]

                  for col inrange(len(self.grid))]

        action = [[0 for rowin range(len(self.grid[0]))]

                  for col inrange(len(self.grid))]

 

       closed[self.init[0]][self.init[1]] = 1

 

 

        x = self.init[0]

        y = self.init[1]

        h =self.heuristic[x][y]

        g = 0

        f = g + h

 

        open = [[f, g, h, x,y]]

 

        found  = False # flag that is set when searchcomplete

        resign = False # flagset if we can't find expand

        count  = 0

 

        while not found andnot resign:

 

            # check if westill have elements on the open list

            if len(open) == 0:

                resign = True

                print('######Search terminated without success')

 

            else:

                # remove nodefrom list

                open.sort()

                open.reverse()

                next =open.pop()

                x = next[3]

                y = next[4]

                g = next[1]

 

            # check if we aredone

 

            if x == goal[0]and y == goal[1]:

                found = True

                # print'###### A* search successful'

 

            else:

                # expandwinning element and add to new open list

                for i inrange(len(delta)):

                    x2 = x +delta[i][0]

                    y2 = y +delta[i][1]

                    if x2>= 0 and x2 < len(self.grid) and y2 >= 0 \

                           and y2 < len(self.grid[0]):

                        ifclosed[x2][y2] == 0 and self.grid[x2][y2] == 0:

                            g2= g + self.cost

                            h2= self.heuristic[x2][y2]

                            f2= g2 + h2

                           open.append([f2, g2, h2, x2, y2])

                           closed[x2][y2] = 1

                           action[x2][y2] = i

 

            count += 1

 

        # extract the path

 

 

 

        invpath = []

        x = self.goal[0]

        y = self.goal[1]

        invpath.append([x, y])

        while x !=self.init[0] or y != self.init[1]:

            x2 = x -delta[action[x][y]][0]

            y2 = y -delta[action[x][y]][1]

            x = x2

            y = y2

            invpath.append([x,y])

 

        self.path = []

        for i inrange(len(invpath)):

           self.path.append(invpath[len(invpath) - 1 - i])

 

 

 

 

    #------------------------------------------------

    #

    # this is the smoothingfunction

    #

 

 

 

 

    def smooth(self,weight_data = 0.1, weight_smooth = 0.1,

               tolerance =0.000001):

 

        if self.path == []:

            raise(ValueError,"Run A* first before smoothing path")

 

        self.spath = [[0 forrow in range(len(self.path[0]))] \

                           forcol in range(len(self.path))]

        for i inrange(len(self.path)):

            for j inrange(len(self.path[0])):

               self.spath[i][j] = self.path[i][j]

 

        change = tolerance

        while change >=tolerance:

            change = 0.0

            for i in range(1,len(self.path)-1):

                for j inrange(len(self.path[0])):

                    aux =self.spath[i][j]

 

                   self.spath[i][j] += weight_data * \

                       (self.path[i][j] - self.spath[i][j])

 

                   self.spath[i][j] += weight_smooth * \

                       (self.spath[i-1][j] + self.spath[i+1][j]

                         - (2.0 * self.spath[i][j]))

                    if i >=2:

                       self.spath[i][j] += 0.5 * weight_smooth * \

                           (2.0 * self.spath[i-1][j] - self.spath[i-2][j]

                             -self.spath[i][j])

                    if i <=len(self.path) - 3:

                       self.spath[i][j] += 0.5 * weight_smooth * \

                           (2.0 * self.spath[i+1][j] - self.spath[i+2][j]

                             -self.spath[i][j])

 

            change += abs(aux - self.spath[i][j])

 

 

 

 

 

 

 

# ------------------------------------------------

#

# this is the robot class

#

 

class robot:

 

    # --------

    # init:

    #    creates robot and initializes location/orientation to 0, 0, 0

    #

 

    def __init__(self, length= 0.5):

        self.x = 0.0

        self.y = 0.0

        self.orientation = 0.0

        self.length = length

       self.steering_noise    = 0.0

       self.distance_noise    = 0.0

        self.measurement_noise= 0.0

        self.num_collisions    = 0

        self.num_steps         = 0

 

    # --------

    # set:

    #    sets a robot coordinate

    #

 

    def set(self, new_x,new_y, new_orientation):

 

        self.x = float(new_x)

        self.y = float(new_y)

        self.orientation =float(new_orientation) % (2.0 * pi)

 

 

    # --------

    # set_noise:

    #    sets the noise parameters

    #

 

    def set_noise(self,new_s_noise, new_d_noise, new_m_noise):

        # makes it possible tochange the noise parameters

        # this is often usefulin particle filters

       self.steering_noise     =float(new_s_noise)

       self.distance_noise    =float(new_d_noise)

        self.measurement_noise= float(new_m_noise)

 

    # --------

    # check:

    #    checks of the robot pose collides with anobstacle, or

    # is too far outside theplane

 

    def check_collision(self,grid):

        for i inrange(len(grid)):

            for j inrange(len(grid[0])):

                if grid[i][j]== 1:

                    dist =sqrt((self.x - float(i)) ** 2 +

                               (self.y - float(j)) ** 2)

                    if dist< 0.5:

                       self.num_collisions += 1

                        returnFalse

        return True

 

    def check_goal(self, goal,threshold = 1.0):

        dist =  sqrt((float(goal[0]) - self.x) ** 2 +(float(goal[1]) - self.y) ** 2)

        return dist <threshold

 

    # --------

    # move:

    #    steering = front wheel steering angle,limited by max_steering_angle

    #    distance = total distance driven, most benon-negative

 

    def move(self, grid,steering, distance,

             tolerance =0.001, max_steering_angle = pi / 4.0):

 

        if steering >max_steering_angle:

            steering =max_steering_angle

        if steering <-max_steering_angle:

            steering =-max_steering_angle

        if distance < 0.0:

            distance = 0.0

 

 

        # make a new copy

        res = robot()

        res.length            = self.length

       res.steering_noise    =self.steering_noise

       res.distance_noise    =self.distance_noise

        res.measurement_noise= self.measurement_noise

       res.num_collisions    =self.num_collisions

        res.num_steps         = self.num_steps + 1

 

        # apply noise

        steering2 =random.gauss(steering, self.steering_noise)

        distance2 =random.gauss(distance, self.distance_noise)

 

 

        # Execute motion

        turn = tan(steering2)* distance2 / res.length

 

        if abs(turn) <tolerance:

 

            # approximate bystraight line motion

 

            res.x = self.x +(distance2 * cos(self.orientation))

            res.y = self.y +(distance2 * sin(self.orientation))

            res.orientation =(self.orientation + turn) % (2.0 * pi)

 

        else:

 

            # approximatebicycle model for motion

 

            radius = distance2/ turn

            cx = self.x -(sin(self.orientation) * radius)

            cy = self.y +(cos(self.orientation) * radius)

            res.orientation =(self.orientation + turn) % (2.0 * pi)

            res.x = cx +(sin(res.orientation) * radius)

            res.y = cy -(cos(res.orientation) * radius)

 

        # check for collision

        #res.check_collision(grid)

 

        return res

 

    # --------

    # sense:

    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值