Main Content

meanrot

쿼터니언 평균 회전

R2019b 이후

설명

예제

quatAverage = meanrot(quat)는 크기가 1이 아닌 첫 번째 배열 차원을 따라 quat 요소의 평균 회전을 반환합니다.

  • quat가 벡터인 경우 meanrot(quat)는 요소의 평균 회전을 반환합니다.

  • quat가 행렬인 경우 meanrot(quat)는 각 열의 평균 회전이 포함된 행 벡터를 반환합니다.

  • quat가 다차원 배열인 경우 mearot(quat)는 크기가 1이 아닌 첫 번째 배열 차원을 따라 연산을 수행하며, 요소를 벡터로 처리합니다. 이 차원은 1이 되며, 다른 모든 차원의 크기는 동일하게 유지됩니다.

meanrot 함수는 입력 쿼터니언 quat를 정규화한 다음에 평균을 계산합니다.

quatAverage = meanrot(quat,dim)은 차원 dim을 따라 평균 회전을 반환합니다. 예를 들어 quat가 행렬인 경우 meanrot(quat,2)는 각 행의 평균이 포함된 열 벡터입니다.

quatAverage = meanrot(___,nanflag)는 위에 열거된 구문을 사용하여 계산할 때 NaN 값을 포함할지 아니면 생략할지를 지정합니다. meanrot(quat,"includenan")은 모든 NaN 값을 포함하고 mean(quat,"omitnan")은 모두 무시합니다.

예제

모두 축소

오일러 각의 세 집합에 해당하는 쿼터니언으로 구성된 행렬을 만듭니다.

eulerAngles = [40 20 10; ...
               50 10 5; ...
               45 70 1];

quat = quaternion(eulerAngles,"eulerd","ZYX","frame");

쿼터니언으로 표현되는 평균 회전을 결정합니다. 가독성을 위해 평균 회전을 오일러 각(단위: 도)으로 변환합니다.

quatAverage = meanrot(quat)
quatAverage = quaternion
      0.88863 - 0.062598i +  0.27822j +  0.35918k

eulerAverage = eulerd(quatAverage,"ZYX","frame")
eulerAverage = 1×3

   45.7876   32.6452    6.0407

meanrot를 쿼터니언 시퀀스에 사용하여 가산성 잡음의 평균을 구합니다.

dist 함수의 정의에 따라 쿼터니언(1,0,0,0)으로부터의 거리가 정규분포를 이루도록 1e6개의 쿼터니언으로 구성된 벡터를 만듭니다. 잡음이 있는 쿼터니언 벡터에 해당하는 오일러 각을 플로팅합니다.

nrows = 1e6;
ax = 2*rand(nrows,3) - 1;   
ax = ax./sqrt(sum(ax.^2,2));
ang = 0.5*randn(size(ax,1),1);
q = quaternion(ax.*ang ,"rotvec");

noisyEulerAngles = eulerd(q,"ZYX","frame");

figure(1)

subplot(3,1,1)
plot(noisyEulerAngles(:,1))
title("Z-Axis")
ylabel("Rotation (degrees)")
hold on

subplot(3,1,2)
plot(noisyEulerAngles(:,2))
title("Y-Axis")
ylabel("Rotation (degrees)")
hold on

subplot(3,1,3)
plot(noisyEulerAngles(:,3))
title("X-Axis")
ylabel("Rotation (degrees)")
hold on

주어진 쿼터니언 벡터에 대해 meanrot를 사용하여 평균 쿼터니언을 구합니다. 오일러 각으로 변환하고 결과를 플로팅합니다.

qAverage = meanrot(q);

qAverageInEulerAngles = eulerd(qAverage,"ZYX","frame");

figure(1)

subplot(3,1,1)
plot(ones(nrows,1)*qAverageInEulerAngles(:,1))
title("Z-Axis")

subplot(3,1,2)
plot(ones(nrows,1)*qAverageInEulerAngles(:,2))
title("Y-Axis")

subplot(3,1,3)
plot(ones(nrows,1)*qAverageInEulerAngles(:,3))
title("X-Axis")

meanrot 알고리즘

meanrot 함수는 회전 행렬 간 차이의 제곱 프로베니우스 노름을 최소화하는 쿼터니언을 출력합니다. 다음과 같은 쿼터니언이 두 개 있다고 가정합니다.

  • q0은 무회전을 표현합니다.

  • q90x축 중심의 90도 회전을 표현합니다.

q0 = quaternion([0 0 0],"eulerd","ZYX","frame");
q90 = quaternion([0 0 90],"eulerd","ZYX","frame");

x축을 중심으로 0도에서 180도까지의 회전을 나타내는 쿼터니언 스윕 qSweep을 만듭니다.

eulerSweep = (0:1:180)';
qSweep = quaternion([zeros(numel(eulerSweep),2),eulerSweep], ...
    "eulerd","ZYX","frame");

q0, q90, qSweep을 회전 행렬로 변환합니다. 쿼터니언 스윕의 각 멤버에 대해 최소화하는 메트릭을 루프로 계산합니다. 결과를 플로팅하고 메트릭의 최솟값에 해당하는 오일러 스윕의 값을 반환합니다.

r0     = rotmat(q0,"frame");
r90    = rotmat(q90,"frame");
rSweep = rotmat(qSweep,"frame");

metricToMinimize = zeros(size(rSweep,3),1);
for i = 1:numel(qSweep)
    metricToMinimize(i) = norm((rSweep(:,:,i) - r0),"fro").^2 + ...
                          norm((rSweep(:,:,i) - r90),"fro").^2;
end

plot(eulerSweep,metricToMinimize)
xlabel("Euler Sweep (degrees)")
ylabel("Metric to Minimize")

[~,eulerIndex] = min(metricToMinimize);
eulerSweep(eulerIndex)
ans = 45

메트릭의 최솟값은 오일러 각 스윕의 45도에 해당합니다. 즉, meanrotquaterion([0 0 0],"ZYX","frame")quaternion([0 0 90],"ZYX","frame") 사이의 평균을 quaternion([0 0 45],"ZYX","frame")으로 정의합니다. q0q90과 함께 meanrot를 호출하여 결과가 동일한지 확인합니다.

eulerd(meanrot([q0,q90]),"ZYX","frame")
ans = 1×3

         0         0   45.0000

제한 사항

meanrot가 평균 회전을 구하기 위해 사용하는 메트릭은 상당히 멀리 떨어진 쿼터니언의 경우에는 고유하지 않습니다. 180도로 분리된 쿼터니언에 대해 위의 실험을 반복합니다.

q180 = quaternion([0 0 180],"eulerd","ZYX","frame");
r180 = rotmat(q180,"frame");

for i = 1:numel(qSweep)
    metricToMinimize(i) = norm((rSweep(:,:,i) - r0),"fro").^2 + ...
                          norm((rSweep(:,:,i) - r180),"fro").^2;
end

plot(eulerSweep,metricToMinimize)
xlabel("Euler Sweep (degrees)")
ylabel("Metric to Minimize")

[~,eulerIndex] = min(metricToMinimize);
eulerSweep(eulerIndex)
ans = 49

쿼터니언 평균은 일반적으로 서로 가까운 회전에 대해 계산되므로 이 예제에서 보이는 극단적인 경우는 실제 응용 사례에서 발생할 가능성이 적습니다. 상당히 멀리 떨어진 두 쿼터니언의 평균을 구하려면 slerp 함수를 사용하십시오. slerp를 사용하여 실험을 반복하고 반환된 쿼터니언 평균이 먼 거리에서 더 직관적인지 확인합니다.

qMean = slerp(q0,q180,0.5);
q0_q180 = eulerd(qMean,"ZYX","frame")
q0_q180 = 1×3

         0         0   90.0000

입력 인수

모두 축소

평균을 계산할 쿼터니언으로, quaternion 객체 또는 임의 차원의 quaternion 객체로 구성된 배열로 지정됩니다.

연산을 수행할 차원으로, 양의 정수 스칼라로 지정됩니다. 값이 지정되지 않는 경우 디폴트 값은 크기가 1이 아닌 첫 번째 배열 차원입니다.

차원 dim은 길이가 1로 감소하는 차원을 나타냅니다. size(quatAverage,dim)1이며, 다른 모든 차원의 크기는 동일하게 유지됩니다.

데이터형: double | single

NaN 조건으로, 다음 값 중 하나로 지정됩니다.

  • "includenan" –– 평균 회전을 계산할 때 NaN 값을 포함하며, 그 결과 NaN이 생성됩니다.

  • "omitnan" –– 입력값에서 모든 NaN 값을 무시합니다.

데이터형: char | string

출력 인수

모두 축소

쿼터니언 평균 회전으로, quaternion 객체 또는 quaternion 객체로 구성된 배열로 반환됩니다.

알고리즘

meanrot[1]에 따라 쿼터니언 평균 q¯를 구합니다. q¯는 다음과 같이 회전 행렬 간 차이의 제곱 프로베니우스 노름을 최소화하는 쿼터니언입니다.

q¯=argminqS3i=1nA(q)A(qi)F2

참고 문헌

[1] Markley, F. Landis, Yang Chen, John Lucas Crassidis, and Yaakov Oshman. "Average Quaternions." Journal of Guidance, Control, and Dynamics. Vol. 30, Issue 4, 2007, pp. 1193-1197.

확장 기능

C/C++ 코드 생성
MATLAB® Coder™를 사용하여 C 코드나 C++ 코드를 생성할 수 있습니다.

버전 내역

R2019b에 개발됨

참고 항목

함수

객체