独立ステアリング機構の操縦性を向上させるクラスです。
数式から得られた独立ステアの出力値は操縦性に問題があります。以下の最適化処理が含まれています。
車輪が動作中でない場合に旋回角度を維持する
車輪の旋回範囲を無限にする
式から得られた旋回角度は、±π の範囲で得られます。この範囲を無限に拡張します。
ゆっくりモジュールを旋回しようとした場合、次のような挙動をします。最適化しない場合 π と -π の境界を超える時に、逆方向に旋回してしまいます。
車輪の回転方向の最適化
90 度以上の旋回が必要な場合、目標旋回角度を 180 度回転させ、車輪の回転方向を逆転させます。目標角度へ最短で到達できるようになります。
個別インクルード
全車輪最適化
SteerOptimizer
クラスを用います。このクラスには車輪数を指定するためのテンプレート引数があります。下記の例では 4 つの車輪を使用しています。operator()
を通すことで最適値を得られます。
void setup()
{
...
}
void loop()
{
std::array<Udon::Polar, 4> raw = pos.
toSteer();
std::array<Udon::Polar, 4> optimized = optimizer(raw);
for (auto&& polar : optimized)
{
Serial.print(polar.r);
Serial.print(" ");
Serial.print(polar.theta);
Serial.print(" ");
}
Serial.println();
}
独立ステアリング機構最適化クラス
Definition SteerOptimizer.hpp:130
ロボットの位置
Definition Position.hpp:26
std::array< Udon::Polar, WheelCount > toSteer(uint8_t powerLimit=255, uint8_t turnPowerLimit=255) const
独立ステアリング機構のタイヤ出力値、旋回角を取得する
Definition Position.hpp:204
本クラスは最適化のみを行うため、事前に最適化前の値を求めておく必要があります。上記の例では Udon::Pos::toSteer()
で求めています。
最適化前の値要件:
r
[ -π ~ π ] ラジアン値
theta
[ 自由 ]
最適化後の値:
r
[ -∞ ~ ∞ ] ラジアン値
theta
[ ± 最適化前 theta
]
車輪ごとに最適化
実は、車輪の最適化は独立して計算されます(車輪間で影響し合わない)。そのため、SteerModuleOptimizer
クラスを使用することで、各車輪ごとに最適化を行えます。車輪ごとをクラスで管理している場合、こちらを使用すると便利です。
独立ステアリング機構の各モジュール最適化クラス
Definition SteerOptimizer.hpp:21
極座標系
Definition Polar.hpp:21
Sample
CAN 通信経由のコントローラーの値からステアモジュールの値を得る例を次の示します。
Udon::CanBus~~~ bus;
Udon::CanPadPS5 pad { bus, 10 };
void setup()
{
bus.begin();
}
void loop()
{
bus.update();
const auto optimized = optimizer(pad.getMoveInfo().toSteer());
}
OpenSiv3D でシミュレートする
Visual Studio への UdonLibrary の追加方法は 追加方法: Visual Studio を参照してください。
#include <Siv3D.hpp>
void Main()
{
while (System::Update())
{
const RectF frame { Arg::center = Scene::CenterF(), 300, 300 };
frame.drawFrame();
const auto stretchedFrame = frame.stretched(-50);
const auto lines = Array{
Line{ stretchedFrame.point(1), Arg::angle = optimized.at(0).
theta, optimized.at(0).
r + 0.000000001 },
Line{ stretchedFrame.point(2), Arg::angle = optimized.at(1).
theta, optimized.at(1).
r + 0.000000001 },
Line{ stretchedFrame.point(3), Arg::angle = optimized.at(2).
theta, optimized.at(2).
r + 0.000000001 },
Line{ stretchedFrame.point(0), Arg::angle = optimized.at(3).
theta, optimized.at(3).
r + 0.000000001 }
};
for (auto&& line : lines)
{
RectF{ Arg::center = line.begin, 30, 60 }
.rotated(line.vector().getAngle())
.drawFrame();
line.drawArrow();
}
}
}
void update(int deadZone=20) noexcept
更新
Definition PadPS5.hpp:144
Stick getMoveInfo() const noexcept
ロボットの移動に必要なスティックの情報 Udon::Stick オブジェクト {{x,y},turn} を取得
Definition PadPS5.hpp:140
PadPS5< Impl::SivPadPS5Reader > SivPadPS5
OpenSiv3D用 PS5コントローラー
Definition SivPadPS5.hpp:81
ValueType theta
角度
Definition Polar.hpp:29
ValueType r
中心からの距離
Definition Polar.hpp:26