Avoiding drift while creating angular rotation with variable degree increments

조회 수: 2 (최근 30일)
Hello,
With the following code, I am trying to create a variable "deg" which should have small degree increments (ddeg_min) for deg<=angle and large increments (ddeg_max) for rest of a complete revolution. I want to repeat the same increments after completion of each revolution. For example, the increment should be 0.1 for 0<=deg<=16.0 and it should repeat the same thing after 360 degrees i.e. incr should be 0.1 for 360.1<=deg<=316.0. But, I am getting a drift in values e.g. 16.1 for first revolution and 366.1 for next revolution and so on.
It was hard to explain but I tried to make it as comprehendible as possible. Waiting for your kind suggestions, Thx.
close all
clear all
clc
phi=90;
angle=16;
ddeg_min=0.1;
ddeg_max=10;
deg(1)=0;
d_deg(1)=ddeg_min;
i=1;
while (1)
i=i+1;
revol_n=floor(deg(i-1)/360);
kkk=deg(i-1)-revol_n*360;
if (kkk >= 0 && kkk < angle)
d_deg(i)=ddeg_min;
deg(i)=deg(i-1)+d_deg(i);
else
d_deg(i)=ddeg_max;
deg(i)=deg(i-1)+d_deg(i);
end
if deg(i)>=1070
break
end
end

채택된 답변

Jan
Jan 2021년 11월 24일
편집: Jan 2021년 11월 24일
Let's start with a simplification of the code:
phi = 90;
angle = 16;
ddeg_min = 0.1;
ddeg_max = 10;
deg(1) = 0;
d_deg(1) = ddeg_min;
i = 1;
while deg(i) < 1070
kkk = rem(deg(i), 360);
if kkk < angle
deg(i + 1) = deg(i) + ddeg_min;
else
deg(i + 1) = deg(i) + ddeg_max;
end
i = i + 1;
end
Or:
phi = 90;
angle = 16;
ddeg = [0.1, 10];
deg = 0;
i = 1;
while deg(i) < 1070
deg(i + 1) = deg(i) + ddeg(1 + rem(deg(i), 360) < angle);
i = i + 1;
end
What is the problem now?
"the increment should be 0.1 for 0<=deg<=16.0"
"I am getting a drift in values e.g. 16.1"
Yes, of course. Welcome to the world of numerical maths.
0.1 + 0.1 + 0.1 == 0.3 % FALSE !!!
0.1 + 0.1 + 0.1 - 0.3 % This is 5.551115123125783e-17
Most floating point values cannot be represented accurately as binary numbers. Therefore you have to consider a rounding effekt. Your loop does not stop at the wanted value, because it does not reach 16, but 15.99999999999996. This must be considered either by using a specific range:
if abs(kkk - angle) < 100 * eps(angle)
But in ypour case it is easier to create the output by a constructive apporach:
deg = [0:0.1:16, 26:10:360];
deg = [deg, deg + 360, deg + 720];
deg = deg(deg < 1070);
  댓글 수: 1
Waseem Akhtar
Waseem Akhtar 2021년 11월 24일
@Jan Thank you for your reply. I think you got to the root of the problem!
The constructive appraoch you gave seems simple and better. I am trying to implement it for the real case in which I have four 90 degree intervals of small increments in each revoltion i.e. 0:0.1:16, 90:0.1:106, 180:0.1:196 and 270:0.1:286
At the same time, I would love to know how this problem can be addressed the other way i.e. by controling the numerical variations (as you highlighted). It would be great if you could correct my code. tbh I'm not a computational expert, I would like to learn handling such situations.
Thank you once again!

댓글을 달려면 로그인하십시오.

추가 답변 (1개)

Mathieu NOE
Mathieu NOE 2021년 11월 24일
hello
why make things so complicated ?
this way you can generate the pattern for the first revolution . if you want to have it for multiple revolutions simply add 360 for each rev
close all
clear all
clc
phi=90;
angle=16;
ddeg_min=0.1;
ddeg_max=10;
% one revolution pattern
deg1 = (0:ddeg_min:angle);
deg2 = (angle+ddeg_max:ddeg_max:360);
deg = [deg1 deg2];
  댓글 수: 6

댓글을 달려면 로그인하십시오.

제품


릴리스

R2021b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by