優(yōu)化算法應(yīng)用(一)路徑規(guī)劃

重點(diǎn):

  1. 如何建立模型:問題—》數(shù)學(xué)模型—》代碼實(shí)現(xiàn)许饿。
  2. 優(yōu)化算法如何處理解空間內(nèi)的無效區(qū)域阳欲。
  3. 問題模型每一維不是一個(gè)數(shù)值,優(yōu)化算法如何處理米辐。

一. 問題描述

如題胸完,只給出了路徑規(guī)劃的目的,其余條件全靠腦補(bǔ)翘贮。

  1. 既然有路徑赊窥,那么必然存在起點(diǎn)和終點(diǎn)。
  2. 既然需要規(guī)劃路徑狸页,那么肯定不是所有位置都能經(jīng)過锨能,或者經(jīng)過速度(代價(jià))不一樣,那么一定會有障礙物芍耘。
  3. 既然路徑能夠規(guī)劃址遇,那么,地圖一定是明確的斋竞,不會出現(xiàn)有未知的區(qū)域倔约。
    那么現(xiàn)在可以總體描述一下問題:在一個(gè)已知的區(qū)域內(nèi),選擇一條最合適的路徑坝初,連通起點(diǎn)到終點(diǎn)浸剩,使付出的代價(jià)最小。

二. 模型建立

根據(jù)問題描述可以確定模型中的幾個(gè)要素:
1. 起點(diǎn)鳄袍,終點(diǎn)
起點(diǎn)和終點(diǎn)為地圖中的兩個(gè)頂點(diǎn)绢要;在地圖中使用綠色區(qū)域表示。

2. 障礙物位置拗小,范圍
障礙物將分為兩種:
a. 可以通過的區(qū)域重罪,圓形,但是通過會有一定代價(jià),距離障礙物中心越近剿配,代價(jià)越大搅幅;在地圖中使用紅色區(qū)域表示。
b. 不可通過的區(qū)域呼胚,矩形盏筐,該區(qū)域任何位置都不允許通過;在地圖中使用灰色區(qū)域表示砸讳。

3. 地圖范圍
為了簡化模型,地圖范圍為一個(gè)矩形區(qū)域界牡,路徑上的所有點(diǎn)必須在該區(qū)域內(nèi)簿寂。

4. 路徑
連接起點(diǎn)至終點(diǎn)的曲線;在地圖中使用藍(lán)色曲線表示宿亡。

模型地圖如下圖所示:

圖1

  為了能使用優(yōu)化算法對路徑進(jìn)行優(yōu)化常遂,該模型的輸入應(yīng)是路徑,輸出應(yīng)該是一個(gè)數(shù)值挽荠,該數(shù)值將表示輸入的路徑的優(yōu)劣克胳。
  為了簡化問題,將路徑上的關(guān)鍵點(diǎn)作為模型的輸入圈匆,關(guān)鍵點(diǎn)之間的路徑為該兩個(gè)關(guān)鍵點(diǎn)的連線,路徑如圖2所示漠另。

圖2

  一般來說,路徑是越短越好跃赚,故我們求的是該模型的最小值笆搓。
  路徑評價(jià)函數(shù) = 路徑長度+通過障礙的代價(jià)。
  由于矩形障礙是無法通過的纬傲,在通過矩形障礙時(shí)直接給與一個(gè)無窮大的代價(jià)即可满败,所以我們只需要確定如何計(jì)算進(jìn)過圓形障礙的代價(jià)。

圖3

  如圖叹括,圓形障礙的半徑為R,關(guān)鍵點(diǎn)A距圓心O的距離AO=r<R,那么路徑通過點(diǎn)A所需的代價(jià)可以使用如下公式計(jì)算:



  其中a為該障礙物的代價(jià)系數(shù)算墨,a>0,a的值越大汁雷,其經(jīng)過該障礙的代價(jià)越大净嘀。


  f表示該模型的適應(yīng)度函數(shù),d為路徑的長度摔竿,p為路徑通過障礙的代價(jià)面粮。
  其中路徑的長度d比較好計(jì)算,順序計(jì)算兩個(gè)點(diǎn)之間的距離再累加即可继低。那么如何計(jì)算路徑通過障礙的代價(jià)呢熬苍?
  線段是由無數(shù)個(gè)點(diǎn)組成的,所有無法計(jì)算每個(gè)點(diǎn)的代價(jià)在累加。這時(shí)需要對路徑進(jìn)行采樣柴底,得到數(shù)個(gè)采樣點(diǎn)取計(jì)算其代價(jià)婿脸。
  如果不使用采樣點(diǎn)則可能出現(xiàn)路徑穿過障礙物卻沒有代價(jià)。

圖4

  如圖4柄驻,A和B為關(guān)鍵點(diǎn)狐树,如果只計(jì)算關(guān)鍵點(diǎn),則AB連線即為路徑鸿脓,但實(shí)際上AB穿過了不可以通過的障礙物抑钟,該路徑無效。
  對線段采樣的方式很多野哭,這里我選擇使用指定步長來對線段進(jìn)行采樣在塔。如,若AB長為11拨黔,步長為2蛔溃,則將AB等分為6段(11/2后向上取整),其中共有6個(gè)采樣點(diǎn)篱蝇,我們計(jì)算這6個(gè)采樣點(diǎn)和AB兩個(gè)關(guān)鍵點(diǎn)的代價(jià)即可贺待。
  步長越小,結(jié)果越接近真實(shí)零截,但是計(jì)算的復(fù)雜程度越高麸塞;步長越大,計(jì)算起來越快瞻润,但是會有一定程度失真喘垂。

圖5

  如上圖5,由于步長較大绍撞,線段中有3個(gè)采樣點(diǎn)正勒,路徑依然穿越了障礙區(qū)域酗洒,卻沒有計(jì)算代價(jià)扶关,實(shí)際上,由于路徑AB穿過了不可通過的障礙區(qū)域闺魏,其代價(jià)應(yīng)為無窮大非洲。
  對于一個(gè)擁有k個(gè)圓形障礙的地圖鸭限,若路徑不穿過方形區(qū)域,由m個(gè)關(guān)鍵點(diǎn)組成两踏,有n個(gè)采樣點(diǎn)败京,其最終代價(jià)計(jì)算如下:


  其中d為路徑的長度,p由公式(2)計(jì)算得出梦染,r為采樣點(diǎn)距圓心的距離赡麦。
  同時(shí)朴皆,由于計(jì)算路徑時(shí)需要先知道其關(guān)鍵點(diǎn)數(shù)量。故計(jì)算之前需要先確定m的值泛粹。但由于m的值越大遂铡,路徑的計(jì)算越復(fù)雜也越慢,而我們無法得知m的最小值晶姊。故在計(jì)算完后我們需要計(jì)算路徑中是否有多余的關(guān)鍵點(diǎn)扒接。這個(gè)步驟其實(shí)可以省略,但是有多余的點(diǎn)時(shí)計(jì)算量會比較大们衙,算法需要更長時(shí)間才能得出結(jié)果钾怔。

圖6

  如上圖6,在得出路徑A-K1-K2-K3-K4-B后蒙挑,我們可以依次去掉各關(guān)鍵點(diǎn)蒂教,計(jì)算其代價(jià):即A-K2-K3-K4-B,A-K1-K3-K4-B脆荷,A-K1-K2-K4-B,A-K1-K2-K3-B這四條路徑的代價(jià)懊悯,如果其中有一條路徑的代價(jià)小于原路徑蜓谋,則可以將m-1后重新進(jìn)行計(jì)算。

三. 模型代碼實(shí)現(xiàn)

根據(jù)上面的模型炭分,我們可以將模型代碼劃分為三塊:地圖以及兩只障礙物桃焕。
  路徑是模型的輸入,代價(jià)是模型的輸出捧毛。
  由于下面需要使用優(yōu)化算法來對模型進(jìn)行優(yōu)化观堂,之前優(yōu)化算法matlab實(shí)現(xiàn)中,適應(yīng)度函數(shù)的輸入時(shí)一個(gè)向量呀忧,而這里模型的輸入時(shí)一個(gè)關(guān)鍵點(diǎn)序列师痕,故需要將關(guān)鍵點(diǎn)序列與向量相互轉(zhuǎn)化:


  如上公式(4),左邊為m個(gè)二維點(diǎn)的坐標(biāo)而账,右邊為模型的輸入序列胰坟,在計(jì)算代價(jià)時(shí),需要將右邊的序列轉(zhuǎn)化為左邊的點(diǎn)去計(jì)算泞辐,而在優(yōu)化算法中則使用右邊的序列去進(jìn)行笔横。
  代碼文件列表如下:
optimization algorithm\application_path_planning為該應(yīng)用根目錄

文件名 說明
Obstacle_Rect.m 矩形障礙區(qū)域。
Obstacle_Circle.m 圓形障礙區(qū)域咐吼。
Map_Model.m 地圖模型吹缔。

其實(shí)現(xiàn)如下:
optimization algorithm\application_path_planning\Obstacle_Rect.m
矩形區(qū)域:判斷是否有點(diǎn)在該區(qū)域內(nèi)

% 障礙區(qū)域:矩形,不可通過
classdef Obstacle_Rect    
    properties
        % 數(shù)值較大的頂點(diǎn)锯茄,類似于左下頂點(diǎn)
        point_low;
        % 數(shù)值較大的頂點(diǎn)厢塘,類似于右上頂點(diǎn)
        point_up;

    end
    
    methods
        % 構(gòu)造函數(shù)
        function self = Obstacle_Rect(point_low,point_up)
           self.point_low = point_low;
           self.point_up = point_up;
        end
        
        % 懲罰函數(shù)
        function value = get_penalty(self,path_point)
            
            % 如果>成立,I,J的對應(yīng)維度值為1俗冻,否則為0
            I = self.point_up > path_point;
            J = path_point > self.point_low;
            % 如果I,J的所有維值均為1礁叔,則說明路點(diǎn)在該矩形內(nèi)
            if sum(I.*J) == length(path_point)
                % 由于該障礙無法通過,故懲罰數(shù)值為最大
                value = realmax('double');
            else
                value = 0;
            end
        end
    end
    
end

optimization algorithm\application_path_planning\Obstacle_Circle.m
圓形區(qū)域:判斷點(diǎn)與圓心的距離迄薄,計(jì)算代價(jià)

% 障礙區(qū)域:圓形琅关,可以通過,但會受到一定懲罰
classdef Obstacle_Circle
    
    properties
        % 中心點(diǎn)的坐標(biāo)讥蔽,2維或者3維的點(diǎn)(長度為2或者3的向量)
        point;
        % 區(qū)域半徑涣易,數(shù)值
        radius;
        % 系數(shù),用于計(jì)算懲罰函數(shù)冶伞,數(shù)值新症,默認(rèn)為1
        coefficient = 1;
    end
    
    methods
        % 構(gòu)造函數(shù)
        function self = Obstacle_Circle(point,radius,coefficient)
           self.point = point;
           self.radius = radius;
           self.coefficient = coefficient;
        end
        
        % 懲罰函數(shù)
        function value = get_penalty(self,path_point)
            % 計(jì)算路點(diǎn)到障礙中心的距離
            dist = sqrt(sum((path_point - self.point).^2));
            if dist < self.radius
                % 將路點(diǎn)距中心的距離系數(shù)作為懲罰系數(shù)
                % 即距離中越近,懲罰系數(shù)越大
                value = self.coefficient*(1-dist/self.radius);
            else
                value = 0;
            end
        end
    end
        
end

optimization algorithm\application_path_planning\Map_Model.m
地圖模型:
1.設(shè)定障礙區(qū)域响禽,地圖邊界
2.關(guān)鍵點(diǎn)序列與向量轉(zhuǎn)換
3.根據(jù)關(guān)鍵點(diǎn)和步長得到采樣點(diǎn)
4.根據(jù)關(guān)鍵點(diǎn)徒爹,采樣點(diǎn)計(jì)算代價(jià)
5.繪制地圖和路徑

% 原文鏈接:http://www.reibang.com/p/70252c42b37d
% 地圖模型
classdef Map_Model

    properties
        
        % 地圖維度,2芋类,表示為平面地圖
        dim = 2;
        
        % 插值步長
        step_size = 0.5;
        
        % 地圖上界
        bound_up = [100,100];
        % 地圖下界
        bound_low = [0,0];
        
        % 起點(diǎn)x=5,y=90
        point_start = [5,90];
        % 終點(diǎn)x=90,y=5
        point_end =  [90,5];
        
        % 不可通過的障礙列表
        obstacle_rect_list=[Obstacle_Rect([5,20],[20,30]),Obstacle_Rect([30,45],[50,60])];
    
        % 懲罰性質(zhì)的障礙列表
        % 中心為(55,70)隆嗅,半徑為8,懲罰系數(shù)為5
        % 中心為(65,40)侯繁,半徑為10胖喳,懲罰系數(shù)為5
        obstacle_circle_list=[Obstacle_Circle([55,70],8,5),Obstacle_Circle([65,45],10,5),Obstacle_Circle([20,55],7,5),Obstacle_Circle([40,30],8,5)];;
    end
    
    methods
        % 構(gòu)造函數(shù)
        function self = Map_Model()
        end
        
        % 輸入為向量,輸出為適應(yīng)度值
        function value = fit_function(self,x) 
            % 將向量x,轉(zhuǎn)化為數(shù)個(gè)關(guān)鍵點(diǎn)坐標(biāo)
            key_point_list = self.get_point_from_vector(x);
            value = self.get_path_value(key_point_list);
        end
        
        % 從輸入的向量中獲取點(diǎn)的坐標(biāo)
        function key_point_list = get_point_from_vector(self,x)
            % 加入起點(diǎn)
            key_point_list = [self.point_start];
            for i = 1:(length(x)/self.dim)
                % x中相鄰數(shù)個(gè)值組成一個(gè)點(diǎn)
                path_point = x((i-1)*self.dim+1:i*self.dim);
                % 將該點(diǎn)加入列表
                key_point_list = [key_point_list;path_point];
            end
            % 加入終點(diǎn)
            key_point_list = [key_point_list;self.point_end];
        end
        
        % 輸入路徑關(guān)鍵點(diǎn)贮竟,計(jì)算其評價(jià)值
        function value = get_path_value(self,key_point_list)
            value = 0;
            for i = 2:length(key_point_list)
                cur_point = key_point_list(i,:);
                last_point = key_point_list(i-1,:);
                % 計(jì)算兩點(diǎn)之間的距離
                dist = sqrt(sum((last_point-cur_point).^2));
                % 累加兩點(diǎn)之間的距離丽焊,作為適應(yīng)度函數(shù)的一部分
                value = value + dist;
            end
            % 獲取采樣點(diǎn)
            sampling_point_list = self.get_sampling_point_list(key_point_list);
            
            % 遍歷每個(gè)點(diǎn)采樣點(diǎn),計(jì)算懲罰系數(shù)
            for i = 1:size(sampling_point_list,1)
                % 計(jì)算長方形區(qū)域的懲罰
                for j = 1:length(self.obstacle_rect_list)
                    value = value + self.obstacle_rect_list(j).get_penalty(sampling_point_list(i,:));
                end
                
                % 計(jì)算圓形區(qū)域的懲罰
                for j = 1:length(self.obstacle_circle_list)
                    penalty = self.obstacle_circle_list(j).get_penalty(sampling_point_list(i,:));
                    value = value + penalty;
                end
            end
        end
        
        % 計(jì)算路徑中的采樣點(diǎn)
        function sampling_point_list = get_sampling_point_list(self,key_point_list)
            % 加入起點(diǎn)
            sampling_point_list = [key_point_list(1,:)];
            for i = 2:length(key_point_list)
                % 獲取當(dāng)前點(diǎn)
                path_point = key_point_list(i,:);
                % 計(jì)算該點(diǎn)和上一個(gè)點(diǎn)之間的中間點(diǎn)
                middle_point_list = self.get_middle_point(sampling_point_list(end,:),path_point);
                % 將中間點(diǎn)加入列表
                sampling_point_list = [sampling_point_list;middle_point_list];
                % 將該點(diǎn)加入列表
                sampling_point_list = [sampling_point_list;path_point];
            end
        end
        
        % 計(jì)算兩個(gè)關(guān)鍵點(diǎn)之間的插值點(diǎn)
        function middle_point_list = get_middle_point(self,path_point_start,path_point_end)
            % step_size 為插值步長咕别,步長越小技健,插入的中間點(diǎn)越多
            % 計(jì)算兩點(diǎn)之間的距離
            dist = sqrt(sum((path_point_start-path_point_end).^2));
            % 計(jì)算插值點(diǎn)數(shù)
            middle_num = floor(dist/self.step_size)+1;
            middle_point_list = [];
            if middle_num > 0
                % 如果插值點(diǎn)數(shù)大于0
                for i = 1:middle_num
                    middle_point = (i*path_point_end+(middle_num+1-i)*path_point_start)/(middle_num+1);
                    middle_point_list = [middle_point_list;middle_point];
                end
            end
        end
        
        % 判斷是否有多余的點(diǎn)
        function has_surplus = get_surplus_point_num(self,x)
            has_surplus = 0;
            % 將向量x,轉(zhuǎn)化為數(shù)個(gè)關(guān)鍵點(diǎn)坐標(biāo)
            key_point_list = self.get_point_from_vector(x);
            % 計(jì)算當(dāng)前值
            value = self.get_path_value(key_point_list);
            
            for i = 2:(length(key_point_list)-1)
                % 去除一個(gè)關(guān)鍵點(diǎn)計(jì)算其值
                temp_point_list = [key_point_list(1:i-1,:);key_point_list(i+1:end,:)];
                % 計(jì)算去除一個(gè)點(diǎn)后的適應(yīng)度值
                new_value = get_path_value(self,temp_point_list);
                % 如果去除一個(gè)點(diǎn)的值更好則直接返回1
                if new_value < value
                    has_surplus = 1;
                    break;
                end
            end
            
        end
        
        % 繪制地圖
        function draw_map(self,input,num)
            % 繪制圖像

            for i = 1:length(self.obstacle_circle_list)
                %圓心坐標(biāo)為point,半徑為radius,輪廓顏色為紅色
                x = self.obstacle_circle_list(i).point(1);
                y = self.obstacle_circle_list(i).point(2);
                r = self.obstacle_circle_list(i).radius;
                rectangle('Position',[x-r,y-r,2*r,2*r],'Curvature',[1,1],'edgecolor',[1 0.2 0.2],'FaceColor',[1 0.2 0.2]);
            end
            
            for i = 1:length(self.obstacle_rect_list)
                %rectangle('Position',[x,y,w,h],'PropertyName',propertyvalue)
                xy = self.obstacle_rect_list(i).point_low;
                wh = self.obstacle_rect_list(i).point_up - self.obstacle_rect_list(i).point_low;
                rectangle('Position',[xy,wh],'Linewidth',1,'LineStyle','-','EdgeColor',[0.5 0.5 0.5],'FaceColor',[0.5 0.5 0.5])
            end
            
            % 繪制起點(diǎn)
            rectangle('Position',[self.point_start-3,6,6],'Linewidth',1,'LineStyle','-','EdgeColor',[0.5 1 0.5],'FaceColor',[0.5 1 0.5]);
            % 繪制終點(diǎn)
            rectangle('Position',[self.point_end-3,6,6],'Linewidth',1,'LineStyle','-','EdgeColor',[0.5 1 0.5],'FaceColor',[0.5 1 0.5]);

            % 如果沒有有輸入關(guān)鍵點(diǎn)則返回惰拱,否則繪制路徑
            if isempty(x)
                return
            end
            hold on ;
            
            % 繪制路徑
            % 加入起點(diǎn)
            path_point_list = [self.point_start];
            for i = 1:(length(input)/self.dim)
                % x中相鄰數(shù)個(gè)值組成一個(gè)點(diǎn)
                path_point = input((i-1)*self.dim+1:i*self.dim);
                x = [path_point(1),path_point_list(end,1)];
                y = [path_point(2),path_point_list(end,2)];
                scatter(path_point(1),path_point(2),20,'b','filled');
                % 當(dāng)前點(diǎn)連接到上一個(gè)點(diǎn)
                plot(x,y,'b','linewidth',1.5);
                hold on ;
                path_point_list = [path_point_list;path_point];
            end
            hold on ;
            % 終點(diǎn)連接到上一個(gè)點(diǎn)
            x = [path_point_list(end,1),self.point_end(1)];
            y = [path_point_list(end,2),self.point_end(2)];
            plot(x,y,'b','linewidth',1.5);
            hold on;
            % 加入終點(diǎn)
            path_point_list = [path_point_list;self.point_end];
            text(90,100,num2str(num),'FontSize',20);
            
            % 繪制顯示區(qū)域
            axis([self.bound_low(1)-10 self.bound_up(1)+10 self.bound_low(2)-10 self.bound_up(2)+10]);
            
            axis equal;
            
            % 固定橫縱坐標(biāo)軸
            set(gca,'XLim',[self.bound_low(1)-10 self.bound_up(1)+10]);
            set(gca,'YLim',[self.bound_low(2)-10 self.bound_up(2)+10])
        end
        
    end
    
end

模型建立完了凫乖,我給地圖中隨機(jī)添加了幾個(gè)障礙物,現(xiàn)在來看看地圖的樣子弓颈。
optimization algorithm\application_path_planning\Test.m
測試腳本

%% 清理之前的數(shù)據(jù)
% 清除所有數(shù)據(jù)
clear all;
close all;
% 清除窗口輸出
clc;

% 初始化模型
model = Map_Model();
% 繪制無路徑地圖帽芽,無編號
% 第一個(gè)參數(shù)為算法輸出的結(jié)果,第二個(gè)參數(shù)為編號翔冀,繪制動態(tài)圖用
model.draw_map([],'');
圖7

  這是當(dāng)前的地圖模型导街,下面將使用優(yōu)化算法在該地圖中尋找一條代價(jià)最小的路徑連接起點(diǎn)和終點(diǎn)。

四. 優(yōu)化算法計(jì)算路徑

這里將使用差分進(jìn)化算法來求解路徑纤子,差分進(jìn)化算法實(shí)現(xiàn)可以看優(yōu)化算法matlab實(shí)現(xiàn)(七)差分進(jìn)化算法matlab實(shí)現(xiàn)搬瑰。如果想使用其他優(yōu)化算法款票,則引入相關(guān)的優(yōu)化算法路徑后,實(shí)例化即可泽论。
  由于不知道需要多少個(gè)關(guān)鍵點(diǎn)才能確定路徑艾少,故先計(jì)算5個(gè)關(guān)鍵點(diǎn)的路徑,如果有多余的關(guān)鍵點(diǎn)翼悴,后面減少關(guān)鍵點(diǎn)后再次計(jì)算缚够。5個(gè)關(guān)鍵點(diǎn),每個(gè)關(guān)鍵點(diǎn)有x,y兩個(gè)坐標(biāo)鹦赎,對于優(yōu)化算法來說其維度為10維谍椅。

參數(shù)
維度 10(5個(gè)關(guān)鍵點(diǎn))
種群 50
最大迭代 1000
范圍 [(0,0),(100,100)]
步長 0.5

實(shí)現(xiàn)代碼如下:
optimization algorithm\application_path_planning\Test.m

%% 清理之前的數(shù)據(jù)
% 清除所有數(shù)據(jù)
clear all;
close all;
% 清除窗口輸出
clc;

%% 添加目錄
% 將上級目錄中的frame文件夾加入路徑
addpath('../frame')
% 引入差分進(jìn)化算法
addpath('../algorithm_differential_evolution')

% 初始化模型
model = Map_Model();
% 預(yù)設(shè)關(guān)鍵點(diǎn)數(shù)
point_num = 5;
% 重新計(jì)算每一維的取值范圍
% 將(100,200)轉(zhuǎn)化為(100,200,100,200,100,200,100,200....)
range_max = repmat(model.bound_up, 1, point_num);
range_max = reshape(range_max, 1, numel(range_max));
range_min = repmat(model.bound_low, 1, point_num);
range_min = reshape(range_min, 1, numel(range_min));

%% 算法實(shí)例
dim = model.dim*point_num;
% 種群數(shù)量
size = 50;
% 最大迭代次數(shù)
iter_max = 1000;
% 取值范圍上界
range_max_list = range_max;
% 取值范圍下界
range_min_list = range_min;

% 實(shí)例化差分進(jìn)化算法類
base = DE_Impl(dim,size,iter_max,range_min_list,range_max_list);
base.is_cal_max = false;
% 確定適應(yīng)度函數(shù)
base.fitfunction = @model.fit_function;
% 運(yùn)行
base.run();
disp(['復(fù)雜度',num2str(base.cal_fit_num)]);

%% 下面繪制動態(tài)圖
% 繪制每一代的路徑
for i = 1:length(base.position_best_history)
    model.draw_map(base.position_best_history(i,:),i);
    % 每0.01繪制一次
    pause = 0.01;
    %下面是保存為GIF的程序
    frame=getframe(gcf);
    % 返回單幀顏色圖像
    imind=frame2im(frame);
    % 顏色轉(zhuǎn)換
    [imind,cm] = rgb2ind(imind,256);
    filename = ['path_planning_',num2str(point_num),'.gif'];
    if i==1
         imwrite(imind,cm,filename,'gif', 'Loopcount',inf,'DelayTime',1e-4);
    else
         imwrite(imind,cm,filename,'gif','WriteMode','append','DelayTime',pause);
    end

    if i <length(base.position_best_history)
        % 如果不是最后一張圖就清除窗口
        clf;
    end
end

% 判斷是否有多余的點(diǎn)
has_surplus = model.get_surplus_point_num(base.position_best);
if has_surplus
    disp('包含多余的點(diǎn),將point_num減1后重新測試')
end
% 原文鏈接:http://www.reibang.com/p/70252c42b37d

最終結(jié)果如下
程序顯示有多余的點(diǎn)古话,接下來會測一測關(guān)鍵點(diǎn)為4,3,2,1時(shí)的情況雏吭。

關(guān)鍵點(diǎn)數(shù) 運(yùn)行時(shí)間(秒) 代價(jià) 是否有多余點(diǎn)
5 1106 127.428
4 928 125.98
3 783 127.7271
2 760 128.0267
1 719 133.5343

迭代圖像如下:

↑關(guān)鍵點(diǎn)5
↑關(guān)鍵點(diǎn)4
↑關(guān)鍵點(diǎn)3
↑關(guān)鍵點(diǎn)2
↑關(guān)鍵點(diǎn)1

  從最終結(jié)果可以看出,上述模型至少需要2個(gè)關(guān)鍵點(diǎn)(可以看有4個(gè)關(guān)鍵點(diǎn)的動態(tài)圖陪踩,有兩個(gè)多余的點(diǎn))但是卻在有4個(gè)關(guān)鍵點(diǎn)時(shí)得到了整個(gè)結(jié)果中的最優(yōu)解杖们。畢竟優(yōu)化算法是概率算法,不保證一定能得到最優(yōu)解肩狂,所以需要多進(jìn)行幾次試驗(yàn)選取最優(yōu)的結(jié)果才行胀莹,上面只進(jìn)行了一次試驗(yàn),所以是一個(gè)正常的結(jié)果婚温。
  試驗(yàn)的耗時(shí)隨著維度的增加而增加,但是這個(gè)增加并不明顯媳否。關(guān)鍵點(diǎn)的數(shù)量對計(jì)算模型代價(jià)所耗時(shí)并不直接栅螟。模型計(jì)算耗時(shí)的最關(guān)鍵因素是:關(guān)鍵點(diǎn)數(shù)量+采樣點(diǎn)數(shù)量。所以步長越大篱竭,路徑越短力图,耗時(shí)也就越少。在步長一定掺逼,且當(dāng)關(guān)鍵點(diǎn)數(shù)量較多時(shí)吃媒,解空間搜索范圍較大,出現(xiàn)較長路徑的概率很大吕喘,所以耗時(shí)會相對較多赘那。
  下面在確定關(guān)鍵點(diǎn)為3時(shí),測試下步長為0.1氯质, 1.0募舟,2.0時(shí)的結(jié)果。
  最終結(jié)果如下

步長 運(yùn)行時(shí)間(秒) 代價(jià) 是否有多余點(diǎn)
2 188 123.2993
1 411 123.7047
0.5 783 127.7271
0.1 3188 127.7327
↑關(guān)鍵點(diǎn)3闻察,步長2.0
↑關(guān)鍵點(diǎn)3拱礁,步長1.0
↑關(guān)鍵點(diǎn)3琢锋,步長0.1

從表格可得知,步長越大呢灶,所需計(jì)算時(shí)間越少吴超,但結(jié)果卻越好,這是因?yàn)槿狱c(diǎn)較少鸯乃,路徑代價(jià)計(jì)算有一定失真鲸阻。看圖可以看出飒责,當(dāng)步長為1.0和2.0時(shí)赘娄,路徑其實(shí)有掠過不可通過的障礙,但是由于步長較大宏蛉,沒有取樣點(diǎn)在該障礙區(qū)域內(nèi)遣臼,所以計(jì)算時(shí)認(rèn)為該路徑有效。

五. 總結(jié)

本文主要使用優(yōu)化算法解決了路徑規(guī)劃問題拾并。這個(gè)問題不算太復(fù)雜揍堰,優(yōu)化算法也不用修改,只需要將問題建立模型嗅义,然后使用優(yōu)化算法去計(jì)算結(jié)果即可屏歹。也就是說,只要問題模型建立好之碗,使用任何一個(gè)優(yōu)化算法來求解都是相同的步驟蝙眶。
  對于更加復(fù)雜的問題模型,可能需要對指定的優(yōu)化算法進(jìn)行針對性的修改來提高計(jì)算效率和準(zhǔn)確度褪那。不過大多數(shù)使用通用算法即可幽纷,不需要定制。
對于開頭的問題博敬,可以參考下面的做法:
  1如何建立模型:問題—》數(shù)學(xué)模型—》代碼實(shí)現(xiàn)友浸。
  因?yàn)樾枰褂脙?yōu)化算法來求解,所以問題模型的核心是一個(gè)函數(shù)偏窝,其輸入是所需要的解收恢,其輸出是該解的評價(jià)函數(shù)。只要滿足這兩點(diǎn)祭往,函數(shù)內(nèi)如何計(jì)算伦意,根據(jù)實(shí)際情況處理即可。
  2優(yōu)化算法如何處理解空間內(nèi)的無效區(qū)域硼补∧福  
  當(dāng)該解(個(gè)體位置)到達(dá)無效區(qū)域時(shí),直接返回一個(gè)極差值括勺。本問題中就是返回一個(gè)極大值缆八,這樣到達(dá)該區(qū)域的個(gè)體將會直接被淘汰曲掰。缺點(diǎn)是當(dāng)無效區(qū)域占解空間比例很大時(shí),會很費(fèi)時(shí)奈辰。如果要規(guī)避栏妖,就要對優(yōu)化算法的算子進(jìn)行修改了,也比較麻煩奖恰。
  3問題模型每一維不是一個(gè)數(shù)值吊趾,優(yōu)化算法如何處理。
  將模型的輸入轉(zhuǎn)化為一個(gè)一維的向量瑟啃,例如這里一個(gè)二維點(diǎn)可以轉(zhuǎn)換為一個(gè)2維的向量论泛,5個(gè)二維點(diǎn)就是一個(gè)10維的向量。雖然這樣做維度會比較高蛹屿,但是處理起來比較簡單屁奏。直接將5個(gè)點(diǎn)傳入優(yōu)化算法進(jìn)行迭代也不是不行,比較勉強(qiáng)错负,算法實(shí)現(xiàn)需要修改不少坟瓢,好在matlab這種動態(tài)語言沒聲明變量類型,需要處理的部分不太多犹撒,但還是有不少bug需要解決折联,就不勉強(qiáng)了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末识颊,一起剝皮案震驚了整個(gè)濱河市诚镰,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌祥款,老刑警劉巖清笨,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異镰踏,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)沙合,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進(jìn)店門奠伪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人首懈,你說我怎么就攤上這事绊率。” “怎么了究履?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵滤否,是天一觀的道長。 經(jīng)常有香客問我最仑,道長藐俺,這世上最難降的妖魔是什么炊甲? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮欲芹,結(jié)果婚禮上卿啡,老公的妹妹穿的比我還像新娘。我一直安慰自己菱父,他們只是感情好颈娜,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著浙宜,像睡著了一般官辽。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上粟瞬,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天同仆,我揣著相機(jī)與錄音,去河邊找鬼亩钟。 笑死乓梨,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的清酥。 我是一名探鬼主播扶镀,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼焰轻!你這毒婦竟也來了臭觉?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤辱志,失蹤者是張志新(化名)和其女友劉穎蝠筑,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體揩懒,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡什乙,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了已球。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片臣镣。...
    茶點(diǎn)故事閱讀 40,040評論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖智亮,靈堂內(nèi)的尸體忽然破棺而出忆某,到底是詐尸還是另有隱情,我是刑警寧澤阔蛉,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布弃舒,位于F島的核電站,受9級特大地震影響状原,放射性物質(zhì)發(fā)生泄漏聋呢。R本人自食惡果不足惜苗踪,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望坝冕。 院中可真熱鬧徒探,春花似錦、人聲如沸喂窟。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽磨澡。三九已至碗啄,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間稳摄,已是汗流浹背稚字。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留厦酬,地道東北人胆描。 一個(gè)月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像仗阅,于是被迫代替她去往敵國和親昌讲。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評論 2 355

推薦閱讀更多精彩內(nèi)容