| 
6 | 6 | 
  | 
7 | 7 | """  | 
8 | 8 | 
 
  | 
9 |  | -#  import math  | 
10 |  | -#  import numpy as np  | 
11 |  | -#  import matplotlib.pyplot as plt  | 
 | 9 | +import math  | 
 | 10 | +import numpy as np  | 
 | 11 | +import matplotlib.pyplot as plt  | 
 | 12 | + | 
 | 13 | +#  % 点をランダムでばら撒く(t-1の時の点群)  | 
 | 14 | +#  data1=fieldLength*rand(2,nPoint)-fieldLength/2;  | 
 | 15 | + | 
 | 16 | +#  % data2= data1を移動させる & ノイズ付加  | 
 | 17 | +#  % 回転方向 & ノイズ付加  | 
 | 18 | +#  theta=toRadian(motion(3))+toRadian(thetaSigma)*rand(1);  | 
 | 19 | +#  % 並進ベクトル & ノイズ付加  | 
 | 20 | +#  t=repmat(motion(1:2)',1,nPoint)+transitionSigma*randn(2,nPoint);  | 
 | 21 | +#  % 回転行列の作成  | 
 | 22 | +#  A=[cos(theta) sin(theta);-sin(theta) cos(theta)];  | 
 | 23 | +#  % data1を移動させてdata2を作る  | 
 | 24 | +#  data2=t+A*data1;  | 
 | 25 | + | 
 | 26 | +#  % ICPアルゴリズム data2とdata1のMatching  | 
 | 27 | +#  % R:回転行列 t:併進ベクトル  | 
 | 28 | +#  % [R,T]=icp(data1,data2)  | 
 | 29 | +#  [R,T] = ICPMatching(data2,data1);  | 
 | 30 | + | 
 | 31 | +#  function [R, t]=ICPMatching(data1, data2)  | 
 | 32 | +#  % ICPアルゴリズムによる、並進ベクトルと回転行列の計算を実施する関数  | 
 | 33 | +#  % data1 = [x(t)1 x(t)2 x(t)3 ...]  | 
 | 34 | +#  % data2 = [x(t+1)1 x(t+1)2 x(t+1)3 ...]  | 
 | 35 | +#  % x=[x y z]'  | 
 | 36 | + | 
 | 37 | +#  R=eye(2);%回転行列  | 
 | 38 | +#  t=zeros(2,1);%並進ベクトル  | 
 | 39 | + | 
 | 40 | +#  while ~(dError < EPS)  | 
 | 41 | +#  count=count+1;  | 
 | 42 | + | 
 | 43 | +#  [ii, error]=FindNearestPoint(data1, data2);%最近傍点探索  | 
 | 44 | +#  [R1, t1]=SVDMotionEstimation(data1, data2, ii);%特異値分解による移動量推定  | 
 | 45 | +#  %計算したRとtで点群とRとtの値を更新  | 
 | 46 | +#  data2=R1*data2;  | 
 | 47 | +#  data2=[data2(1,:)+t1(1) ; data2(2,:)+t1(2)];  | 
 | 48 | +#  R = R1*R;  | 
 | 49 | +#  t = R1*t + t1;  | 
 | 50 | + | 
 | 51 | +#  dError=abs(preError-error);%エラーの改善量  | 
 | 52 | +#  preError=error;%一つ前のエラーの総和値を保存  | 
 | 53 | + | 
 | 54 | +#  if count > maxIter %収束しなかった  | 
 | 55 | +#  disp('Max Iteration');return;  | 
 | 56 | +#  end  | 
 | 57 | +#  end  | 
 | 58 | +#  disp(['Convergence:',num2str(count)]);  | 
 | 59 | + | 
 | 60 | +#  function [index, error]=FindNearestPoint(data1, data2)  | 
 | 61 | +#  %data2に対するdata1の最近傍点のインデックスを計算する関数  | 
 | 62 | +#  m1=size(data1,2);  | 
 | 63 | +#  m2=size(data2,2);  | 
 | 64 | +#  index=[];  | 
 | 65 | +#  error=0;  | 
 | 66 | + | 
 | 67 | +#  for i=1:m1  | 
 | 68 | +#  dx=(data2-repmat(data1(:,i),1,m2));  | 
 | 69 | +#  dist=sqrt(dx(1,:).^2+dx(2,:).^2);  | 
 | 70 | +#  [dist, ii]=min(dist);  | 
 | 71 | +#  index=[index; ii];  | 
 | 72 | +#  error=error+dist;  | 
 | 73 | +#  end  | 
 | 74 | + | 
 | 75 | +#  function [R, t]=SVDMotionEstimation(data1, data2, index)  | 
 | 76 | +#  %特異値分解法による並進ベクトルと、回転行列の計算  | 
 | 77 | + | 
 | 78 | +#  %各点群の重心の計算  | 
 | 79 | +#  M = data1;  | 
 | 80 | +#  mm = mean(M,2);  | 
 | 81 | +#  S = data2(:,index);  | 
 | 82 | +#  ms = mean(S,2);  | 
 | 83 | + | 
 | 84 | +#  %各点群を重心中心の座標系に変換  | 
 | 85 | +#  Sshifted = [S(1,:)-ms(1); S(2,:)-ms(2);];  | 
 | 86 | +#  Mshifted = [M(1,:)-mm(1); M(2,:)-mm(2);];  | 
 | 87 | + | 
 | 88 | +#  W = Sshifted*Mshifted';  | 
 | 89 | +#  [U,A,V] = svd(W);%特異値分解  | 
 | 90 | + | 
 | 91 | +#  R = (U*V')';%回転行列の計算  | 
 | 92 | +#  t = mm - R*ms;%並進ベクトルの計算  | 
 | 93 | + | 
 | 94 | + | 
 | 95 | +def ICP_matching(pdata, data):  | 
 | 96 | +    R = 0.0  # rotation matrix  | 
 | 97 | +    T = 0.0  # translation vector  | 
 | 98 | + | 
 | 99 | +    #  ICP  | 
 | 100 | +    #  EPS = 0.0001  | 
 | 101 | +    #  maxIter = 100  | 
 | 102 | + | 
 | 103 | +    #  preError = 0  | 
 | 104 | +    #  loopcount = 0  | 
 | 105 | +    #  dError = 1000.0  | 
 | 106 | + | 
 | 107 | +    return R, T  | 
12 | 108 | 
 
  | 
13 | 109 | 
 
  | 
14 | 110 | def main():  | 
15 | 111 |     print(__file__ + " start!!")  | 
16 | 112 | 
 
  | 
 | 113 | +    # simulation parameters  | 
 | 114 | +    nPoint = 10  | 
 | 115 | +    fieldLength = 50.0  | 
 | 116 | +    motion = [0.5, 1.0, math.radians(-40.0)]  # movement [x[m],y[m],yaw[deg]]  | 
 | 117 | +    #  transitionSigma=0.01;%並進方向の移動誤差標準偏差[m]  | 
 | 118 | +    #  thetaSigma=1;   %回転方向の誤差標準偏差[deg]  | 
 | 119 | + | 
 | 120 | +    # previous point data  | 
 | 121 | +    px = (np.random.rand(nPoint) - 0.5) * fieldLength  | 
 | 122 | +    py = (np.random.rand(nPoint) - 0.5) * fieldLength  | 
 | 123 | + | 
 | 124 | +    cx = [math.cos(motion[2]) * x - math.sin(motion[2]) * y + motion[0]  | 
 | 125 | +          for (x, y) in zip(px, py)]  | 
 | 126 | +    cy = [math.sin(motion[2]) * x + math.cos(motion[2]) * y + motion[1]  | 
 | 127 | +          for (x, y) in zip(px, py)]  | 
 | 128 | + | 
 | 129 | +    plt.plot(px, py, ".b")  | 
 | 130 | +    plt.plot(cx, cy, ".r")  | 
 | 131 | +    plt.plot(0.0, 0.0, "xr")  | 
 | 132 | +    plt.axis("equal")  | 
 | 133 | +    plt.show()  | 
 | 134 | + | 
17 | 135 | 
 
  | 
18 | 136 | if __name__ == '__main__':  | 
19 | 137 |     main()  | 
0 commit comments