DEKI/ENGINE ドキュメント
Deki 0.19.0
組み込みディスプレイとデスクトップのためのモジュール式 C++ 2D エンジン
読み取り中…
検索中…
一致する文字列を見つけられません
単位

単位を書き記しているのはここだけです。 このエンジンの数値に単位があるなら、それはこのページに載っています。

ルール

保存される値は SI です。必ず。 メートル、ラジアン、秒、キログラム、セルシウス度。コンポーネント、シーンファイル、パッケージの API にある float は、このページが示す単位です。例外も、プロジェクトごとの違いもありません。

変換が行われる境界はただ 1 つ、表示です。インスペクターは距離をピクセルで、角度を度で、温度を華氏で表示してもかまいません。シーンファイルと計算に届くのは SI です。

これは書き方の好みではありません。これがないと 3 つのことが壊れます。

  1. シリアライズされたシーンが曖昧になります。 保存した人によってメートルにもピクセルにもなりうる width: 4.0 は、確実に読み戻せません。
  2. 計算で尺度が黙って混ざります。 px/s の速度をメートルの位置に加えるコードはコンパイルが通り、もっともらしい間違った答えを出します。
  3. パッケージ同士が連携できなくなります。 deki-2d と物理パッケージは、互いに問い合わせることなく float の意味について合意していなければなりません。

保存されるもの

量 保存形式 PhysicalUnit インスペクターでの表示
距離 メートル Distance px (× pixelsPerMeter) または m
速度 メートル毎秒 Velocity px/s または m/s
加速度 メートル毎秒毎秒 Acceleration px/s² または m/s²
角度 ラジアン Angle 常に度
角速度 ラジアン毎秒 AngularVelocity 常に度/s
温度 セルシウス度 Temperature °C または °F
シミュレーションの時間 秒、float で - -
期間、タイムアウト ミリ秒、整数で - -
周波数 ヘルツ - -
データサイズ バイト - -
質量 キログラム - 予約済み。まだ何も使っていません

PhysicalUnit は表示のヒントであり、保存形式を示すものではありません。省略するとインスペクターは単位なしの数値を表示しますが、値の意味が変わることはありません。

時間に 2 つの決まりがある理由

どちらも意図したもので、どちらなのかは型でわかります。

秒単位の float はシミュレーションの差分、つまり 1 フレームでワールドの時間がどれだけ進むかです。秒を使うと数値が float の精度が最も高い 1.0 付近に保たれ、積分のステップで掛ける値でもあります。

ミリ秒単位の整数は実時間です。タイムアウト、アニメーションのフレームの長さ、タイムスタンプなどです。正確で、積分ではなく比較に使われ、たいていミリ秒を扱うプラットフォームの API を通ります。

名前が Ms で終わるなら、ミリ秒の整数です。時間を表す単なる float は秒です。

データシートは SI を使わないが、それで問題ない

センサーのデータシートは g や度毎秒で値を示します。それらを返す API が間違っているわけではありません。間違っているのは、名前にそれが表れていないメソッドから返す API です。IDekiIMU がそのパターンを示しています。

// SI, and the only virtual: this is what the engine stores
virtual DekiVec3f ReadGyroRadiansPerSecond() const = 0;
// the datasheet's unit, derived and NOT virtual, so a driver cannot make
// the two disagree
DekiVec3f ReadGyroDegreesPerSecond() const;

どちらの名前にも単位が含まれているので、どちらも読み違えようがありません。チップの ±245 dps という値と照らし合わせてデバッグするときはデータシートの表記を使い、読み取り値を積分するものはすべて SI を使います。変換はドライバーのスケール定数の 1 か所にあり、式の中にはデータシートの値がそのまま見えています。

float m_GyroScale = (245.0f / 32768.0f) * Deki::Math::kDegToRad; // LSB -> rad/s

ReadAccelMetersPerSecondSquared() と ReadAccelG() も同様です。

センサーの API を追加するときは、メソッド名に単位を入れてください。 単なるベクトルを返す ReadGyro() こそ、このルールが防ぐためにあるものです。エンジンのほかの角度の値がすべてラジアンだったのに、これは dps と文書化されていました。誤った前提で読み取り値を回転に入れると、57.3 倍ずれます。

表示の変換

すべて deki-editor/src/core/Units.h にあります。1 つのファイルなので、単位の追加は 1 か所の編集で済みます。

  • GetUnitDisplay(unit) - 乗数、オフセット、printf の書式、ドラッグの速度。
  • ToDisplay(stored, ud) / FromDisplay(shown, ud) - 逆変換の組で、まとめて置かれています。どの変換も単純な掛け算だった間は、呼び出し側がその場で逆変換できました。華氏のオフセットがあると、その場で書いた shown / multiplier は 32 度ずれ、それでももっともらしく見えます。
  • CanonicalUnitSymbol(unit) - 値が*保存されている* SI の記号で、機械で読む出力に使います。表示の設定には影響されません。メタデータのダンプに "px" と書くと、ダンプが嘘になってしまいます。
  • SnapMetersToPixel / ShouldSnapToPixel - 距離のみ、ピクセルモードのみ。

これを左右するプロジェクト設定で、すべて表示専用です。

設定 効果
inspectorUnit 距離の系統を Pixels または Meters で表示
pixelsPerMeter px↔m の係数、デフォルトは 16
temperatureUnit Celsius または Fahrenheit

どれを変更しても、ディスク上やメモリ上のものは何も変わりません。

プロパティに単位を付ける

DEKI_EXPORT
DEKI_UNIT(Distance)
float width; // metres, like every other Distance