Found an issue with the book? Report it on Github.

속도 측정(Speed Measurement)

속도 측정(Speed Measurement)

베이스라인 시스템(Baseline System)

연속 동작과 불연속 동작 간의 상호 작용을 모델링해야 하는 많은 응용 프로그램이 있습니다. 이 섹션에서는 회전 샤프트의 속도를 측정하는 데 사용하는 기술을 살펴보겠습니다. 이전에 기본 방정식에 대해 논의한 기계 예제 를 재사용할 것입니다.

model SecondOrderSystem "A second order rotational system"
  type Angle=Real(unit="rad");
  type AngularVelocity=Real(unit="rad/s");
  type Inertia=Real(unit="kg.m2");
  type Stiffness=Real(unit="N.m/rad");
  type Damping=Real(unit="N.m.s/rad");
  parameter Inertia J1=0.4 "Moment of inertia for inertia 1";
  parameter Inertia J2=1.0 "Moment of inertia for inertia 2";
  parameter Stiffness c1=11 "Spring constant for spring 1";
  parameter Stiffness c2=5 "Spring constant for spring 2";
  parameter Damping d1=0.2 "Damping for damper 1";
  parameter Damping d2=1.0 "Damping for damper 2";
  Angle phi1 "Angle for inertia 1";
  Angle phi2 "Angle for inertia 2";
  AngularVelocity omega1 "Velocity of inertia 1";
  AngularVelocity omega2 "Velocity of inertia 2";
initial equation
  phi1 = 0;
  phi2 = 1;
  omega1 = 0;
  omega2 = 0;
equation
  // Equations for inertia 1
  omega1 = der(phi1);
  J1*der(omega1) = c1*(phi2-phi1)+d1*der(phi2-phi1);
  // Equations for inertia 2
  omega2 = der(phi2);
  J2*der(omega2) = c1*(phi1-phi2)+d1*der(phi1-phi2)-c2*phi2-d2*der(phi2);
end SecondOrderSystem;

모델에 extends 절을 추가하여 이 모델을 재사용 함으로써, 본질적으로 확장하려고 하고 있는 모델에서 모든 것을 가져옵니다. extends 절에 대해서는 나중에 패키지(Packages) 에 대해 논의할 때 더 자세히 이야기하겠습니다. 지금은 다른 모델의 내용을 현재 모델에 복사하는 것으로 생각하십시오.

SecondOrderSystem 모델에 대한 해는 다음과 같습니다.

/static/_images/SOSIP.svg

이 경우, 단순히 계산한 해를 선도로 표현 합니다. 그러나 실제 시스템에서는 샤프트의 회전 속도를 직접적으로 알 수 없으며, 대신 측정해야 합니다.측정은 오류를 발생시키고 각 측정 기술은 서로 다른 종류의 오차를 생성합니다. 이 섹션에서는 이와 관련한 다양한 종류의 측정 기술을 모델링하는 방법을 살펴보겠습니다.

샘플과 홀드(Sample and Hold)

검토할, 첫 번째 유형은 측정에 대한 샘플 앤 홀드 접근 방식입니다. 일부 속도 센서에는 시스템의 회전 속도를 측정하는 회로가 있습니다. 그러나 속도에 대한 연속적인 값을 제공하는 대신, 주어진 시점에서 샘플링한 다음에 어딘가에 저장합니다.이를 "샘플 앤 홀드"라고 합니다.다음 모델은 각속도 omega1 측정에 대한 샘플 앤 홀드 접근 방식을 구현하는 방법을 보여줍니다.

model SampleAndHold "Measure speed and hold"
  extends BasicEquations.RotationalSMD.SecondOrderSystem;
  parameter Real sample_time(unit="s")=0.125;
  discrete Real omega1_measured;
equation
  when sample(0,sample_time) then
    omega1_measured = omega1;
  end when;
end SampleAndHold;

omega1_measured 선언에 discrete 한정자가 있습니다.이 특수 한정자는 지정된 변수에 연속 해가 없음을 나타냅니다.대신, 이 변수의 값은 시뮬레이션 중에 급격한 이산적인 변화(만)을 만듭니다. discrete 키워드를 포함할 필요는 없지만 컴파일러가 확인할 수 있는 모델의 의도에 대한 추가 정보를 제공하기 때문에 유용합니다(예: 해당 변수의 파생적인 결과물을 요청하지 않도록 함).

이제 이 모델에서 생성된 해를 살펴보겠습니다.

/static/_images/SampleAndHold.svg

해에서 주목해야 할 중요한 사항은, 측정된 값이 구간(조각난) 상수인지 여부입니다. omega1_measured 값은 when 문이 활성화될 때만 설정되기 때문입니다. sample 함수는 첫 번째 인수(이 경우 0)에 의해 지정된 시간에 먼저 참이 되고,그 이후 일정한 간격으로 참이 되는 특별한 내장 함수입니다.이러한 규칙적인 간격의 연속 시간에 대한 설정은 두 번째 인수(이 경우 sample_time)로 표현 합니다.

구간 측정(Interval Measurement)

앞의 예제에서 실제로 속도를 추정하지 않고 단순히 특정 시간에만 변수 omega1 값을 전달 했습니다. 즉, omega1 을 샘플링한 순간의 값은 완전히 정확 한 것 입니다.다른말로 표현하면, 측정된 값을 그대로 "유지(hold)"함으로써(omega1 을 계속 추적하는 대신) 측정에 약간의 인위적인 조작이 이루어졌을 뿐입니다.

나머지 예제에서는, 회전축의 속도를 추정하는 기술에 중점을 둘 것입니다. 이 경우, 측정 시 시뮬레이션에서 계산한 실제 속도를 직접 사용하지 않습니다. 대신 물리적 시스템에서 생성된 이벤트에 응답하고 이러한 이벤트를 사용하여 회전 속도의 추정치를 재구성하려고 시도합니다.

응답할 이벤트는 회전축에 부착된 개별 요소에 의해 생성됩니다. 예를 들어 이러한 이벤트를 생성하는 일반적인 방법은 "회전식 광학 엔코더(톱니 바퀴 모양으로 위치를 측정할 수 있는 구조의 인코더)"를 사용하는 것입니다. 톱니바퀴 엔코더에는 회전축에 기어가 포함되어 있습니다. 기어 양쪽에 광원과 광 센서를 배치합니다. 기어 이빨이 광원 앞을 지나갈 때 빛을 차단하게 되고, 그 결과 구형파 형태의 광 센서 신호를 생성합니다.이 구형파의 상승 엣지(rising edge, leading edge)에 이벤트로 반응합니다.

검토할 첫 번째 추정 방법은 각 이벤트의 사이를 통과하는 시간 간격을 측정하여 샤프트의 속도를 계산 하는것 입니다.샤프트가 정해진 각도 \Delta heta 만큼 회전할 때마다 이벤트가 발생한다는 것을 알기 때문에 다음과 같이 속도를 추정할 수 있습니다.

\hat{\omega} = \frac{\Delta\theta}{\Delta t}

This technique for speed estimation can be represented in Modelica as:

model IntervalMeasure "Measure interval between teeth"
  extends BasicEquations.RotationalSMD.SecondOrderSystem;
  parameter Integer teeth=200;
  parameter Real tooth_angle(unit="rad")=2*3.14159/teeth;
  Real next_phi, prev_phi;
  Real last_time;
  Real omega1_measured;
initial equation
  next_phi = phi1+tooth_angle;
  prev_phi = phi1-tooth_angle;
  last_time = time;
equation
  when {phi1>=pre(next_phi),phi1<=pre(prev_phi)} then
    omega1_measured = tooth_angle/(time-pre(last_time));
    next_phi = phi1+tooth_angle;
    prev_phi = phi1-tooth_angle;
    last_time = time;
  end when;
end IntervalMeasure;

여기서 tooth_angle \Delta heta 를 나타냅니다. tooth_angle 은 사용자가 지정해야 하는 항목이 아니며,대신 사용자는 teeth parameter를 사용하여 톱니의 이빨 수를 지정합니다. tooth_angle 파라미터는 teeth 값을 사용하여 계산 합니다. (여기서는 pi 값을 직접 작성하였는데, 상수(Constants) 에 대해 이야기할 때 다시 다루겠습니다.)

이 모델의 when 문을 자세히 살펴보겠습니다.

equation
  when {phi1>=pre(next_phi),phi1<=pre(prev_phi)} then
    omega1_measured = tooth_angle/(time-pre(last_time));
    next_phi = phi1+tooth_angle;
    prev_phi = phi1-tooth_angle;
    last_time = time;
  end when;

여기에서는 이전에 틩기는 공(Bouncing Ball) 예제에서 사용된 벡터 표현식 구문을 사용합니다.조건 중 하나라도 참이면 when 문이 활성화된다는 점을 기억하십시오.이 경우 각도 phi1next_phi 보다 크거나 prev_phi 보다 작으면 when 문이 활성화됩니다.

주목해야 할 또 다른 사항은 when 문 안에서 pre 연산자를 사용한다는 것입니다. 모델에서 이벤트가 발생하면 일부 변수의 값이 불연속적으로 변할 가능성이 있습니다.이벤트의 결과로 모든 변수가 어떤 값을 가져야 하는지 확인하려고 시도할 때, pre 연산자를 사용하면 이벤트 이전 변수의 값을 참조할 수 있습니다. pre 연산자는 이 모델에서 next_phi , prev_philast_time 의 이전(먼저 발생한 이벤트) 값을 참조하는 데 사용합니다.``pre`` 연산자는 이러한 모든 변수가 when 문 내부의 구문에 의해 영향을 받습니다.예를 들어 last_time ( pre 연산자 없이)은 이벤트가 끝날 때 last_time 값을 참조하고 pre(last_time) 값은 이벤트가 발생하기 전의 last_time 을 참조하기 때문 입니다.

앞서 제시한 방식에서 추정하는 예상 속도를 보겠습니다.

/static/_images/IntervalMeasure.svg

결과에서 즉시 볼 수 있는, 이 추정 알고리즘의 두 가지 중요한 속성이 있습니다. 첫 번째는 추정치가 부호가 없다는 것입니다. 즉, 톱니바퀴 엔코더와 같은 장치에서는 축이 어느 방향 으로 회전하는지 알 수 없습니다.두번째는, 낮은 속도인 경우와 회전 방향이 변하는 경우에는 추정의 정확도를 크게 떨어뜨릴 수 있다는 것 입니다.결과 또한, 관련된 톱니의 수에 매우 민감합니다.``teeth`` 를 20으로 설정하여 인코더에 사용하는 톱니 수를 줄이면 매우 다른 결과를 얻게 됩니다.

/static/_images/IntervalMeasure_Coarse.svg

측정된 신호가 왜 그렇게 부정확한지 정확히 이해하려면, 각도 phi1 에 따른 인접한 두 톱니의 각도인 next_phiprev_phi 를 비교하는 다음 선도를 볼 필요가 있습니다.

/static/_images/IntervalMeasure_Coarse_phi.svg

이 선도를 통해, 상대적으로 낮은 속도와 속도의 방향 전환이 상당한 추정에서의 오류를 유발하는 불규칙한 이벤트를 생성하는 것을 명확하게 볼 수 있습니다.

펄스 카운팅(Pulse Counting)

위에서 언급한 간격을 측정하는 기술에서는 물리적으로 발생하는 인터럽트에 대한 속도 계산을 수행할 수 있는 하드웨어가 필요합니다.속도를 추정하는 또 다른 접근 방식은 주어진(고정된) 타임 스탭 내에서 발생하는 이벤트 수를 세고 이를 속도 추정치로 사용하는 것입니다. 이 방법을 사용하면 이벤트가 발생할 때 이벤트 합계만 집계하고, 계산은 정기적으로 예정된 시점으로 업데이트를 미루어 둘 수 있습니다.

이 섹션의 이전 예제를 기반으로, 다음은 이 추정 기법을 구현하는 모델을 만드는 자연스러운 방법을 보여 주겠습니다.

model Counter "Count teeth in a given interval"
  extends BasicEquations.RotationalSMD.SecondOrderSystem;
  parameter Real sample_time(unit="s")=0.125;
  parameter Integer teeth=200;
  parameter Real tooth_angle(unit="rad")=2*3.14159/teeth;
  Real next_phi, prev_phi;
  Integer count;
  Real omega1_measured;
initial equation
  next_phi = phi1+tooth_angle;
  prev_phi = phi1-tooth_angle;
  count = 0;
equation
  when {phi1>=pre(next_phi),phi1<=pre(prev_phi)} then
    next_phi = phi1+tooth_angle;
    prev_phi = phi1-tooth_angle;
    count = pre(count) + 1;
  end when;
  when sample(0,sample_time) then
    omega1_measured = pre(count)*tooth_angle/sample_time;
    count = 0 "Another equation for count?";
  end when;
end Counter;

그러나 이 모델에는 count 에 대한 방정식이 두 개 있다는 문제점이 있습니다. 이러한 모델을 컴파일하려고 하면 변수보다 방정식이 더 많은 상황이 발생합니다. 즉, 문제가 특이(singular) 합니다.

그래서 이러한 현상에 대해 어떻게 해결 할 수 있을까요? count 에 대한 업데이트가 서로 다른 이벤트에 대한 응답으로 발생하기 때문에 두 개의 서로 다른 방정식이 필요합니다. 그래서 다음과 같이 단일 when 문 아래 모든 것을 공식으로 표현 할 수 있습니다.

when {phi1>=pre(next_phi),phi1<=pre(prev_phi),sample(0,sample_time)} then
  if sample(0,sample_time) then
    omega1_measured := pre(count)*tooth_angle/sample_time;
    count :=0;
  else
    next_phi := phi1 + tooth_angle;
    prev_phi := phi1 - tooth_angle;
    count :=pre(count) + 1;
  end if;
end when;

하지만 이런 종류의 코드는 금방 읽기 어렵습니다.다행스럽게도 모든 when 문을 algorithm 섹션에 배치하여 이 상황을 해결할 수 있습니다.

algorithm 섹션의 특성은 그 안에 할당된 모든 변수에 대해 하나의 단일 방정식으로 취급 합니다.예를 들어 count 에 대한 다중 할당을 허용합니다. 그래서, algorithm 섹션을 사용할 때 할당의 순서 가 중요해진다는 것을 이해하는 것이 매우 중요합니다. 충돌이 발생하는 경우(예: 동일한 algorithm 섹션 내에서 변수에 두 개의 값이 할당되는 경우)는 마지막 값이 사용합니다. algorithm 섹션에 대해 주의해야 할 또 다른 사항은 일반 방정식을 작성할 수 없다는 것입니다. 그 대신 대입문 을 작성해야 합니다.

이런 식으로 algorithm 섹션은 대부분의 프로그래밍 언어가 작동하는 방식과 매우 유사합니다. 알고리즘 섹션의 명령문은 순서대로 실행되며 각 명령문은 방정식으로 해석되지 않고 변수에 표현식을 할당한 것으로 해석합니다. 모델리카의 방정식 지향적인 측면이 혼란스럽고 익숙하지 않은,프로그래밍 배경을 가진 사람들에게 할당문의 친숙함은 algorithm 섹션을 매력적으로 느끼게 할 수 있습니다. 그러나 algorithm 섹션을 피해야 하는 한 가지 큰 이유는 모델리카 컴파일러가 수행하는 기호 조작을 방해하기 때문입니다.이로 인해 시뮬레이션 성능이 저하되고 모델 구성 방식의 유연성이 저하될 수 있습니다.따라서 가능할 때마다 equation 섹션을 사용하는 것이 가장 좋습니다.

이 경우는 algorithm 섹션을 사용해도 큰 결과의 변화는 없습니다. 다음은 algorithm 섹션을 사용하여 이전에 보인 추정 알고리즘을 리팩터링하는 방법의 예입니다.

model CounterWithAlgorithm "Count teeth in a given interval using an algorithm"
  extends BasicEquations.RotationalSMD.SecondOrderSystem;
  parameter Real sample_time(unit="s")=0.125;
  parameter Integer teeth=200;
  parameter Real tooth_angle(unit="rad")=2*3.14159/teeth;
  Real next_phi, prev_phi;
  Integer count;
  Real omega1_measured;
initial equation
  next_phi = phi1+tooth_angle;
  prev_phi = phi1-tooth_angle;
  count = 0;
algorithm
  when {phi1>=pre(next_phi),phi1<=pre(prev_phi)} then
    next_phi := phi1 + tooth_angle;
    prev_phi := phi1 - tooth_angle;
    count := pre(count) + 1;
  end when;
  when sample(0,sample_time) then
    omega1_measured := pre(count)*tooth_angle/sample_time;
    count :=0;
  end when;
end CounterWithAlgorithm;

이 추정 기법의 시뮬레이션 결과는 다음 선도에서 볼 수 있습니다.

/static/_images/SpeedCounter.svg

다시 말하지만 이 접근 방식은 회전 방향을 결정할 수 없습니다. 다음 선도를 통해 각 샘플 간격 내에서 발생하는 이벤트 수를 파악할 수 있습니다.

/static/_images/SpeedCounter_count.svg

일반적으로 간격에서 카운트가 높을수록(저속일 수록) 추정치가 더 정확합니다.

결론(Conclusion)

이 섹션에서는 when 구성을 사용하여 시스템에서 발생하는 물리적 이벤트에 응답하는 방법을 보여줍니다.이러한 종류의 이벤트와 시스템에 미치는 영향은 이전에 다룬 연속 역학만큼이나 중요합니다.이러한 물리적 이벤트를 표현하고 이에 대응하는 기능은 모델리카가 전체 시스템을 모델링하는데 매우 적합한 중요한 이유중 하나 입니다.이러한 시스템에는 종종 연속 및 불연속 동작이 모두 포함되기 때문입니다.