MATLAB模拟退火算法优化包围盒(OBB)问题

MATLAB模拟退火算法优化包围盒(OBB)问题

一、实现效果

OBB效果图
在这里插入图片描述
在这里插入图片描述
注意:本文只涉及OBB坐标计算部分,图形显示由OpenGL处理,本文不作介绍

二、算法设计

众所周知,模拟退火算法的核心在于如何选择与更新解空间以及设计成本函数。确定了这几个部分,接下来只需要套用算法框架即可。

1、待优化参数(解空间)的确定

对于OBB问题,有两种参数选择方案:
一是,直接以包围盒三条邻边顶点及原点坐标为参数:
在这里插入图片描述
二是,在确定单位立方体的基础上将原点坐标、xyz三轴缩放、xyz三轴旋转作为参数
第一种 优点在于能直接得出最终结果(绝对坐标)不需要进行换算,但是问题在于每次随机更新坐标,都会使得ox、oy、oz向量不再相互垂直,需要添加额外的约束条件,浪费计算力。
第二种 的优点很明显,默认三轴垂直,不再需要考虑该约束条件,但是要求出绝对坐标还需要额外换算。
本文选择第二种方案作为解空间。
下面给出各参数的初始化代码:
init.m

clear all;
%% 模拟退火基本参数初始化
T=80;%初温
Tend=0.0001;%末温
searchCount=100;%单温内搜索次数
q=0.98;

%% 解空间初始化
O=[rand*2-1,rand*2-1,rand*2-1];%原点
    % 三轴缩放
Xzoom=abs(randn(1,1));
Yzoom=abs(randn(1,1));
Zzoom=abs(randn(1,1));
    % 三轴旋转
Xroll=randi(360);
Yroll=randi(360);
Zroll=randi(360);

%% 记录器初始化
log_count=1;
costLog=[];
OLog=[0,0,0];
xLog=[0,0,0];
yLog=[0,0,0];
zLog=[0,0,0];

2、更新解空间

模拟退火要获得较精确的解需要在高温时更新解的范围大,来跳出局部最优解;在低温时更新解的范围小,以找到精确的解。
由此可知,更新解的函数需要与温度有关,代码如下:
getNew.m

% z=[Xzoom,Yzoom,Zzoom]
% r=[Xroll,Yroll,Zroll]
function [o,zoom,roll] = getNew(O,z,r,T)
    % 获取新解
    o=[O(1)+(rand*2-1)*T,O(2)+(rand*2-1)*T,O(3)+(rand*2-1)*T];
    zoom=[abs(z(1)+randn(1,1)*T),abs(z(2)+randn(1,1)*T),abs(z(3)+randn(1,1)*T)];
    roll=[r(1)+(rand*2-1)*T,r(2)+(rand*2-1)*T,r(3)+(rand*2-1)*T];
end

3、成本函数

OBB问题要求包围盒尽可能小,尽可能贴近模型边界,于是选择用体积来表示成本。此外,还有一个重要的约束条件:模型的每个点都不能在包围盒的范围外。
在这里插入图片描述
其中f(x)为约束条件函数,当x满足约束条件,则无附加成本;当x不满足条件,则成本无穷大。
设模型中的任意点为P,x为OP在OX轴上的投影与|OX|的比值。若x在(0,1)之间,则表示P点在包围盒内。
在这里插入图片描述
其中O、X为包围盒原点和X轴顶点的绝对坐标。
但是我们计算的参数均为变换参数,需要将其转化为绝对坐标才能进行运算,下面是转换代码:
getVertex.m

function [O,vx,vy,vz] = getVertex(o,z,r)
    %变换->点
    vx0=[o(1)+z(1),o(2),o(3)];
    vy0=[o(1),o(2)+z(2),o(3)];
    vz0=[o(1),o(2),o(3)+z(3)];
    rx=[1,0,0 ; 0,cosd(r(1)),-sind(r(1)) ; 0,sind(r(1)),cosd(r(1))];%绕x轴旋转矩阵
    ry=[cosd(r(2)),0,sind(r(2)) ; 0,1,0 ; -sind(r(2)),0,cosd(r(2))];%绕y轴旋转矩阵
    rz=[cosd(r(3)),-sind(r(3)),0 ; sind(r(3)),cosd(r(3)),0 ; 0,0,1];%绕z轴旋转矩阵
    O=o*rx*ry*rz;
    vx=vx0*rx*ry*rz;
    vy=vy0*rx*ry*rz;
    vz=vz0*rx*ry*rz;
end

在获取了顶点坐标以后就可以计算通过上面的公式计算成本函数了,代码如下:(注意:模型点坐标保存在points矩阵中,这里不做展示)
goal.m

function [cost] = goal(o,x,y,z,points)
[row,~]=size(points);
cons=0;
for i= 1:row
    p=points(i,:);%提取第i行数据
    c1=isInLine(o,x,p);
    c2=isInLine(o,y,p);
    c3=isInLine(o,z,p);
    if c1 ~= 0 || c2 ~= 0 || c3 ~= 0 % 判断是否在OBB内部
        cons=1e10;
        break
    end
end
ox=norm(x-o); %取模
oy=norm(y-o);
oz=norm(z-o);
cost=ox*oy*oz+cons;

isInLine.m

%% 判断点是否在OBB内,在则返回0,不在则返回1
function [value] = isInLine(o,n,p)
o_p=p-o;
o_n=n-o;
o_n1=o_n/norm(n-o);
x=(dot(o_p,o_n1))/norm(n-o);
if x > 0 && x <1
    value=0;
else
    value=1;
end
end

三、模拟退火代码

main.m

run init;
[o0,zoom0,roll0]=getNew(O,[Xzoom,Yzoom,Zzoom],[Xroll,Yroll,Zroll],T);
[O0,x0,y0,z0]=getVertex(o0,zoom0,roll0);
cost0=goal(O0,x0,y0,z0,points);
cost_final=cost0;
while T>Tend
    for i=1:searchCount
        [oNew,zoomNew,rollNew] = getNew(o0,zoom0,roll0,T);
        [ONew,xNew,yNew,zNew]=getVertex(oNew,zoomNew,rollNew);
        cost=goal(ONew,xNew,yNew,zNew,points);
        if cost < cost0    % 如果新解成本值小于当前解的成本
            o0 = oNew; % 更新当前解为新解
            zoom0=zoomNew;
            roll0=rollNew;
            cost0 = cost;
        else
            p = exp(-(cost - cost0)/T); % 根据Metropolis准则计算一个概率
            if rand(1) < p 
                o0 = oNew; % 更新当前解为新解
                zoom0=zoomNew;
                roll0=rollNew;
                cost0 = cost;
            end
        end
        if cost<cost_final
            O_final=ONew;
            x_final=xNew;
            y_final=yNew;
            z_final=zNew;
            cost_final=cost;
            % 记录解
            costLog(log_count)=cost;
            OLog=cat(1,OLog,O_final);
            xLog=cat(1,xLog,x_final);
            yLog=cat(1,yLog,y_final);
            zLog=cat(1,zLog,z_final);
            log_count=log_count+1;
        end
    end
    T=T*q;
end
  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值