デバイス時刻の推定
ExecAt や GpioOut::SysTimeEq などでは, デバイスの時刻を指定する必要がある.
ホストは PTP に参加していないので, デバイスの時刻を直接知ることはできない.
そのため, DeviceClock は, ホストの送信/受信時刻とデバイスの送信/受信時刻を記録して, それらの情報から, ホスト時刻に対応するデバイス時刻を推定する.
デバイスの時刻 (ETHSW のタイマ) は, open 時に GM (ID 0 のデバイス) が SetTime で指定した値 ( 0 ) から GM のクロックでカウントする.
slave は PTP で GM に追従するので, GM の時刻だけを推定すればいい.
ホスト時刻とデバイス時刻
Section titled “ホスト時刻とデバイス時刻”時刻にはホストの時計で測ったもの (ホスト時刻) と, デバイスの時計で測ったもの (デバイス時刻) の 2 種類がある.
以下, ある出来事をホストの時計で測った時刻を
ホスト時刻を基準にして, 両者の差を offset
となる.
任意のホスト時刻
デバイスの時計はホストの時計とは独立しており, 水晶振動子の誤差等により微妙にクロック周波数は指定値とは異なる.
そのため
で近似する.
1 往復から得られる上下限
Section titled “1 往復から得られる上下限”GM へ送った Frame / Heartbeat の 1 往復に関して, 以下の 4 つの時刻を記録する.
: ホストが要求を送る直前のホスト時刻 : GM が要求を受信したデバイス時刻 : GM が返信を組んだデバイス時刻 : ホストが返信を受信したホスト時刻
GM が要求を受信した時, および, 返信を組んだ時のホスト時刻
となる.
ただし,
往路について, 観測される
となる.
が成り立つ.
ここで,
復路も同様に,
となり,
そこで 1 往復から 2 種類のサンプル (ホスト時刻, offset の限界) を作る.
- 上限:
- 下限:
以下, 上限のサンプルを
上の議論から, 全てのサンプルで
である.
offset の推定
Section titled “offset の推定”真の直線
となる.
ここで,
とすし, 真の傾きで
真の値を
と書ける.
である.
傾きを
したがって,
となり,
である.
ここで, 遅れは経路で決まる一定の遅れに, 混雑や処理待ちなどによる余分な遅れが加わったものと考え,
とおく.
となる.
である.
となる.
となる.
どちらの場合も, 選んだ
となり, 真の傾き
また,
となる. 誤差の小さいサンプル同士が窓の中で離れているほど傾きの推定は正確になる.
切片は, 傾き
とし, ホスト時刻
なので,
となる.
したがって, 切片の真の値とのずれは
アルゴリズム
Section titled “アルゴリズム”ここでは,
まず,
まず, 上限側の
サンプル
となる.
この右辺は
よって,
下限に関しても同様の議論が成り立ち, 下限のサンプルのなかで, 上側凸包の頂点のみによって
したがって,
以上の議論に従って, 以下のアルゴリズムで
-
下限・上限の列がどちらも 1 s 以上にわたり, かつ
を満たすとする. これが満たされない場合は2に進む
1-1. 下限の列から上側凸包, 上限の列から下側凸包を Andrew’s Monotone Chain Algorithm で作る
1-2. 2 つの凸包の各辺の傾きを候補
とする 1-3. 各候補について, 天井と床を
で求める (
は凸包の頂点だけ走査する) 1-4.
が最大の候補 を選び, , とする. -
1 の条件を満たさず, 最新の下限と最新の上限のホスト時刻の差が 1 s 未満のとき, 傾きを 0 として
とする (open 直後など, サンプルがまだ少ない間). -
どちらでもなければ, 推定しない.
サンプルの収集
Section titled “サンプルの収集”- GM 宛てにフレームを送るたびに, その
msg_idと送信直前のホスト時刻を記録する - GM の返信を受け取るたびに,
- 返信時刻
が載っていれば, 下限のサンプル を加える. - 要求の受信時刻
が載っていて, 同じ msg_idのが記録されていれば, 上限のサンプル を加える.
- 返信時刻
- open 時の
SetTimeでは, デバイス時刻が送信直前のホスト時刻と応答受信時のホスト時刻 の間に 0 になるので, 上限 と下限 を加える. - ホスト時刻
は, 最初に記録した時刻 (最初の送信または最初の返信) からの経過時間 [ns] とする.
間引きと区間窓
Section titled “間引きと区間窓”後々の走査の計算量を減らすため, サンプルは間引きと区間窓で整理する.
- ホスト時刻を 100 ms ごとの区間に区切り, 各区間でサンプルを 1 つだけ残す.
下限は
が最大のもの, 上限は が最小のものを残す. 直前の区間より古い区間のサンプルが届いたら捨てる. - 下限・上限のどちらかで最新のサンプルから 10 s より古いサンプルを, 両方の列から捨てる.
これにより各列のサンプルは高々 101 個で, ホスト時刻順に並ぶ.
凸包の頂点は高々 101 個なので, 候補は高々 200 個, 1 回の推定は高々 4 万回程度の積和で済む.
推定は DeviceClock::now のたびに行い, 凸包も毎回作り直す.
なお, 上限の下側凸包は, 符号を反転させて下限の上側凸包と同じアルゴリズムで作る.
候補の傾きは, 凸包の辺の両端の差
のまま, 整数の組
また, 最後に
を用いる.
この時,
となる.
最後に, 選んだ候補
で