2017年11月30日木曜日

MEDEVAC

 調べ物してたらた偶然見つけたので、ちょっと調べてみた。


 MEDEVACはMEDical EVAcuationの略で、負傷者を移動する手段、みたいなのを指すらしい。ヘリに限らず、車とかでもいい。

 基本的に9行(9種類)のパラメーターで交信するが、場合によっては最初の5行だけでもいい、という感じ?

 各パラメータはこのページに書いてある。
 9 Line MEDEVAC Request (ArmyStudyGuide.com)

Line 1:位置(MGRS:2桁のアルファベットと8桁の数字)
Line 2:周波数とコールサイン
Line 3:負傷者の状態と数
Line 4:必要な機材
Line 5:負傷者の状態
Line 6:周辺の安全状態
Line 7:マーキング方法
Line 8:負傷者の国籍
Line 9:汚染状況

 Line 1:位置
 位置は、そのままの意味。どこにヘリが来てほしいか、という位置。

 Line 2:周波数とコールサイン
 周波数とコールサインは、自分の物を伝える。
 要請に使っている周波数は戦闘地域全体からMEDEVACを要請するためのものだから、回収に来たヘリコプターと話す場合は別の周波数を使う必要がある。このため自分たちが使っている周波数とコールサインを伝える必要がある。
 動画では、相手・自分共にコールサインは3桁の英数を使っている。どちらもアルファベット・数字・アルファベットの並びだが、すべての組み合わせだと6760通りになるから、多分3文字で足りるんであろう。ただし、部隊内で一つの周波数を使うから、搬送用のために接尾辞を追加して、計5文字となる。サフィックスは数字2桁っぽい。

 Line 3:負傷者の状態と数
 負傷者の状態はAからEに分類され、Aは緊急、Bは外科治療が必要、Cは優先的、といった感じらしい。
 ナショジオのPJ番組で「n CAT Alpha」とか言ってるのは、この部分。「ワン キャット アルファ、ツー キャット ブラボー」ならカテゴリーA(緊急)が1人とカテゴリーB(手術が必要)が2人、といった感じの意味。

 Line 4必要な機材
 機材は、ホイストが必要か、とか、人工呼吸器が必要か、とか、そういう情報。今だと人工呼吸器くらいは初期装備な気もするけど、60年代前後とかならこういう機材を備えていたヘリも少なかったんだろう。

 Line 5:負傷者の状態
 自力で歩けるか否か。Aなら担架が必要、Bなら不要。

 Line 6:周辺の安全状態
  N:エリア内に敵兵はいない
  P:エリア内に敵がいる可能性がある(慎重に接近せよ)
  E:エリア内に敵がいる(慎重に接近せよ)
  X:エリア内に敵がいる(武装が必要)
 他に症状を伝えたりするらしい?

 Line 7:マーキング方法
 自分の居場所を知らせる手段。Aなら蛍光色の布を広げる。Bならフレア(信号弾)を使う。Cならスモークを炊く。Dはマーキングなし。Eはその他の手段。

 Line 8:負傷者の国籍
 Aなら米国籍の軍人。Bなら米国籍の民間人。Cは米国籍以外の軍人。Dは米国籍以外の民間人。Eなら敵の捕虜。

 Line 9:汚染状況
 特別な防護が必要かどうか。Nなら放射能で汚染されている。Bなら生物兵器で汚染されている。Cなら化学兵器で汚染されている。
 他に着陸地点の地形等の情報も伝える。そこが湖なのか、山なのか、市街地なのか、みたいな。


 予めホワイトボードみたいなチェックリストがあって、交信を始める前にこれらの情報を書き込んでおく。
 交信する際はまず相手のコールサインを呼び、その後自分のコールサインを言う。そしてMEDEVACを要請することを伝える。
 相手はこちらのコールサインを復唱し、自分のコールサインも言う。これが正しければ、自分と相手で意思疎通ができていることがわかる。
 通信が確立できれば、Line1からLine9までを、何行目かも含めて順に伝えていく。

 動画では、9Lineを伝えた後に、相手は復唱していない。通信状態が明瞭でノイズが少なく、また聞き間違えた可能性もない場合は、そのまま交信を終了する。


 あとはヘリが近くまでくれば、Line2で伝えた周波数とコールサインで通信が来るので、Line7で伝えた方法で自分の場所を示す。
 順調に行けば、負傷者は治療施設まで運んでもらうことができる。

***

 米軍はいろいろな部分で交信内容のフォーマットが決まってるっぽい。言い間違え、聞き間違え等を防ぐこともできるが、文章フォーマットが決まってるなら文字列で送ることもできる。最近の米軍は様々な交信を文字列で行うらしい。文字列ならデータとして残しやすいし、検索もできるし、特定のキーワードに反応してアラームを鳴らしたりもできるし、ということで、音声より扱いやすいんだろう。でも場合によっては銃弾が飛び交う中でチャットをやらなきゃいけないから、なかなか大変そう。
 レッドプラトーンでもチャットを使うシーンが出てくる。ローンサバイバーでもチャットで情報を送ってた気がする(途中でノートPCをぶち壊して、その後はイリジウムを使ってたが)。


 軍の救難ヘリを要請する交信の方法を知ってても一般生活では何の役にも立たないが、サバゲのルールに組み込んでみたりとかするとどうだろうか。
 例えば運営に対して9Lineを送信すればスタッフがやってきて、セーフティーまで連れて帰り、9Lineの内容が正しければ復活できる、とか。すっげー面倒くさいことになりそうだけど。

CASごっこ

 制服の上にリブリーザーを着用して、H&Kが製造したHK417(水鉄砲)とM320(水風船弾)、HK USP(水鉄砲)で武装し、LUCIE初め様々なガチ装備をしたミーちゃんが水路から潜入してくる、という電波を受信。
 水路潜入ならRATt感染の心配が少ない。はず。


 ミーちゃんが拳銃構えてる銃だけで買った価値が…うーん、もうひと押し…。
 キャラ絵オンリーな感じで、メカ類のレンダリングは無し。ファンブックと違い、テキストもほぼ無し。
 リング綴じは手で持って読むのは大変だけど、机において読むとかなら読みやすい。付属カバーもあって、好きなページを開いて置いておけるので、イラスト集とかにはいいと思う。


2017年11月29日水曜日

MS FSXのF/A-18のオートパイロット


 F/A-18のオートパイロットの使い方。

 戦闘機のAPなので、旅客機のそれとは全く別物。あくまで「人間の操縦がメインで、他の作業(交信とか)の合間だけ操縦する手段」というシロモノ。

 基本的にHUD直下のパネルだけで操作できるが、ヘディングを設定するノブだけ、左ラダーペダルのところにある。

 パネル下段には、A/PやILS、ON/OFFというボタンが有る。
 左端のA/Pを押せばオートパイロット設定に入ることができる。右端のON OFFボタンを押せばAPをON/OFFできるが、個人的には使い勝手が悪いと思った(使わなくてもON/OFFできる)。

 AP設定では、パネル右側の5段のディスプレイに、上からATTH, HSEL, BALT, RALT, CPLが表示される。
 ATTHは姿勢保持(Attitude Hold)、HSELは進路保持(Heading Select)、BALTは気圧高度維持(Barometer Altitude hold)、RALTは電波高度維持(Radar Altitude hold)の略だと思う。CPLは不明。
 この内、CPLの使い方は把握できていない。RALTは未実装らしい。

***

 簡単に使えるのは、ATTHモードで、「現在の姿勢を維持する」というモード。アフターバーナを燃やして急上昇しながらATTHをONにしてエンジンを絞れば、失速するまで姿勢を維持する。姿勢を維持するだけなので、例えば200ktでATTHをONにすれば、速度を下げれば降下率が増えるし、速度を上げれば上昇率が増える。
 姿勢維持ではあるが、バンクについてはゆっくりと水平に戻してくれるので、数十秒くらいの期間で見れば上昇率/進路保持となる。

 BALTモードは気圧高度を維持するだけで、進路は維持されない。ある程度の高度を保ちつつ、進路は自分で調整するといった用途。

 HSELは進路保持セレクタで指定した進路を維持する。高度は維持されないので、自分で調整する必要がある。

 使う際は、使用したいモードの左にあるボタンを押せば文字の左側に点々が表示されて、そのモードが動いていることを示す。もう一度ボタンを押せばOFFにできる。
 排他動作の場合は、他のモードがOFFになる。例えばATTHモードが有効なときにBALTを有効にすると、ATTHは無効になる。
 BALTとHSELは同時に使用可能で、両方共ONにすれば高度と進路を維持してくれる。


 使い分けとしては、一時的(無線交信や地図の確認等の合間)な場合はATTHを使い、ある程度の長距離を移動するならBALT/HSELを使う、という感じだと思う。
 BALT/HSELでは進路セレクタを設定する必要があるので、気軽に、という訳にはいかない。レーダーの設定だとか、地図の確認といった、短時間で済む程度の自動操縦ならATTHのほうが便利。

 すべてのモードで、速度は調整されないので、スロットルについてはすべて人間が責任を持つ必要がある。

***

 ILSの使い方。
 ILSボタンを押すと周波数入力モードになるので、テンキーで5桁の周波数を打ち込む(0.01MHzの単位まで)。受信できれば数字ディスプレイにONと表示される。
 ILSをHUDに表示するには、右側のディスプレイの右上にあるILSボタンを押してILSモードを選択する必要がある。
 
***

 せっかくなので、ついでにレーダーの説明も。

 起動時には右の画面に進路等の情報が表示され、左にエンジンの情報が表示されている。基本的に左右どちらも同じ用途で使うことができる。下段中央のMENUボタンを押せばモードを切り替えることができ、HSIなら進路、ENGならエンジンの情報、HUDなら姿勢、RDRならレーダーを表示できる。

 レーダーを使う場合、どちらかの画面でレーダーモードを呼び出す。本物の戦闘機パイロットだと、空対空戦闘と空対地戦闘で表示する場所を変える、といったことをするらしい。ただFSXではせいぜいレーダーを表示するくらいしか戦闘機らしいことが無いので、今回はレーダーを左側に表示する。


 レーダーにはいくつかの設定があるが、上の画像では左上から時計回りに6B、80、IUP、TDN、4833、140、M 0.8、544、といった表示がある。

 順に説明していくと、6Bはレーダーの「6Bar」という動作モードで、80は表示距離が80海里(約150km)、4833は自機の気圧高度(ft)、80はスキャン幅が80度、M 0.8は自機のマッハ数が0.8、544は自機のノット数、という意味。

 また画面の中央あたりに0.3と17、それと四角と直線などの明るいシンボルがあるが、これはレーダーで捕捉した目標を示し、0.3は目標がM0.3で飛んでいて、高度は17000ftということを意味している。
 直線は飛行方向を示していて、この場合は奥から手前に向けて、若干自機の左側に向かって飛んでいる、という状態。
 他に薄い3本の横線がいくつかあるが、これが他の目標の位置を示していて、TUP, TDNで切り替えることができる。


 レーダーを起動すると2バー、40海里、40度のモードになっていると思う。
 とりあえず空域を自機だけでスキャンするなら、6バー、80海里、80度くらいがいいと思う。これは上下方向で20度、横方向で80度の三角錐をスキャンするモード。
 バーは1,2,4,6を切り替えることができ、バーが多いほうが上下方向のスキャンが広い。代わりに、1回あたりのスキャンに余計時間がかかる。
 横方向は20,40,60,80,140から選ぶことができ、数字が大きいほど広い範囲をスキャンできるが、時間が長くかかる。
 距離は5,10,20,40,80から選ぶことができる。

 正直、FSXではバーのシミュレーションはやってないんじゃないかな、という気がする。なので、設定としてはスキャン幅と距離だけで十分。


 面白そうなレーダーシグネチャがあれば接近してみよう。レーダーに表示された目標の高度と速度、進路で会敵位置を予測してそこに接近していく。基本的に、相手の後方下側から接近する。後方から接近する場合は自機のほうが早いので、うまく速度を落とさないと相手の前に出てしまう。下から接近すると、ある程度近づいたところで上昇すれば、速度エネルギーを位置エネルギーに変換して減速することができる。どれくらいの差で近づいて、どのあたりで引き起こすか、というのはかなり難しい。
 退官した空自パイロットがフライトシミュを飛ばす動画がyoutubeにあるけど、感動的なまでにピタッと吸い付いて接近する。プロってすごい。


 うまくすれば、数百mくらいまでは接近できる。目視距離になるとレーダーは使わない(or使えない)ので、レーダーの代わりにHUDを表示するのがおすすめ。
 TrackIRとかを使うなら別だが、PoVスイッチで視点を動かす場合、あっという間に空間失調に陥ってしまう。それを防ぐために、HUDで自分の姿勢を確認しながら操縦する。
 また、引き起こしを掛ける前に目標の速度を確認しておけば、モニタに表示された速度を確認しながら、スロットルを調整できる、という利点もある。

***

 F/A-18には他にもキャノピーハンドルや主翼の格納を始めとした、様々な機能がある。とはいえ、それらを説明すると長くなりすぎるだろうし、僕自身もよくわかっていない部分があるので、とりあえず今回はここまで。

Visual Studio 2015 forWDでSimConnect

 SimConnectはウィンドウハンドルが必要なので、コンソールアプリは作れない、orかなり面倒。Formで作るべし。

 フォームのプロジェクトを作ったら、ソリューションエクスプローラーからプロジェクトのプロパティを開いて、"アプリケーション"タブにある、対象のフレームワークを.Net Framework 2.0にする。"ビルド"タブにある、プラットフォームターゲットをAny CPUからx86に変更する。
 いくつかの参照はリンクが切れているので、警告マークが出た参照は削除しておく。
 Form1.csとProgram.csのusingも、リンク切れを削除しておく。

 C:\Program Files (x86)\Microsoft Games\Microsoft Flight Simulator X SDK\SDK\Core Utilities Kit\SimConnect SDK\lib\managed\Microsoft.FlightSimulator.SimConnect.dllを参照に追加する。

 Microsoft.FlightSimulator.SimConnectとSystem.Runtime.InteropServicesのusingを追加する。


 ソースコードは長い(400行以上ある)ので、続きでどうぞ。

 とりあえず、FSXの情報を取り出すサンプルが2種類と、FSXにコマンドを送るサンプルが1個と、オマケにもう1種類。

 情報を取り出すのは、ギアハンドルが操作されたらFormに表示する、というサンプルと、常に位置情報を取り出して表示する、というサンプルの2種類。
 コマンドを送るのは、フォームからの操作でギアハンドルの位置を変える操作を行う。
 オマケは、SendInputでWin Alt PrintScreenを押す、という動作。

 ちなみにプリントスクリーンだけで120行くらいあるので、SimConnectだけでは300行くらい。
 キャプチャはGeForce ExperienceのAlt F1だと楽なんだけど、WinゲームバーだとWinキーが必要で、これはSendKeys.Sendでうまく送れないので、Win32APIを叩く必要がある。


 SimConnectでできることを網羅した、というには程遠いが、ある程度のことはこのサンプルを改造するだけでできるはず。

 値の名前とか単位とかはLockheed MartinのWebページが詳しいのでそちらを参照のこと。ただしFSXとP3Dでは使える要素に違いがあると思うので、そのあたりはMicrosoftのドキュメントも参照。

電磁石がほしい

 久しぶりにFSXで遊んだ(って、定期的にどっかに書いてるな。長続きしない)。

 やはり視点操作が結構面倒。気軽にやろうとするとFreeTrackだけど、FreeTrackが入ってるとArma 3を起動できない。三日坊主の自分には、TrackIRはコスパが悪い。
 SDKを使えば、FSXの視点を変更することができるが、そのためのソースをどうするか。
 前々から気になってた、OpenPoseを試してみようと思ったが、かなり要求リソースが高い。調べてみると、どうやら機械学習を使っているらしい。さもありなん。4kでフライトシミュをやりながら、その裏で機械学習の処理も行う。無理ゲーっぽい。

 自分で画像処理を作るのは、マーカーを使ったとしても、結構面倒な気がする。あと、画像処理はCPUリソースが大量に必要になる。
 ってことで、CPUリソースをあまり使わない方法が必要になる。
 一番手っ取り早いのは、加速度・角速度センサを使って頭の位置を計算すること。ただし、これだと積分する際に誤差も積み重なる。

 本物ではどうやっているのか。
 例えばJHMCSでは交流磁界を使った位置・角度の検出を行っている。ただし、この方式では磁界を邪魔する物が無い環境でしか使用することができない。F-22では、磁界を邪魔する物があるためにJHMCSが使用できないらしい。
 JHMCS IIでは別の方式となり、ジャイロやら光学系やらを使うらしい。
 ユーロファイター・タイフーンの場合は、ヘルメットに大量の赤外線LEDが埋め込まれて、これを画像解析するらしい。

 JHMCSでは、環境が良ければ交流磁界の周波数でリフレッシュレートが制限されると思われる。
 JHMCS IIでは慣性を使ってるので、慣性センサのサンプリングレートに制限される。ただし、戦闘機では最大10G程度の重力加速度があるから、高G環境でも正確にサンプリングできる慣性センサが必要になる(MEMSジャイロは高Gに弱い)。また機体自体の運動と、頭の運動を切り分ける必要もある(結局角度は機体の外に対してだから、切り分けは不要?)。
 タイフーンの場合はカメラのフレームレートと、画像処理の速度に制限される。

 タイフーンはかなりゴリ押し感がある。
 JHMCS II方式は、固定された椅子に座って使う分には、電子工作的に作りやすそう(ドリフトを考えなければ)。
 JHMCS方式の場合は、積分が無いので、誤差が少ない。ただし磁力を扱ったりとか、いろいろ面倒な気がする。


 気軽に作れるとなると、JHMCS II方式かなぁ。ドリフト対策をどうするか。角度の誤差は地磁気で補正できるかもしれないけど、位置の補正は9DoFでは不可能。数-数十Hzの交流磁界を外部で作って、加速度角速度で位置を計算し、地磁気センサで誤差を補正する、みたいな折衝案はできるかも。

 拾い物のPDFによると、送信コイルが直径5cm、受信コイルが2cmで、距離80cmにおいて位置誤差2cm、角度誤差2.5度くらいらしい。10年以上前のPDFなので、信号処理部が結構でかい。今だと手のひらサイズだろうなぁ。

 固定側で送信、ヘッドセットに受信コイルをつければいいかな、という気がするけど、すぐ横でヘッドセットのスピーカーが動くから、磁気式は厳しいかもしれない。ヘッドセットを送信にすれば、スピーカーからの磁気の影響は防げるかもしれないけど、逆に異音が聞こえてくる可能性もある。
 件のトラッカは100Hzで出るそうで、9軸(3x3軸)の計測を時分割で行うらしい。1msec以内に検出しなきゃいけないから、周波数は少なくとも50kHzから200kHzくらいだろうか。となると超音波の領域だから、スピーカーへの干渉は問題にならないかな?

 もしかしたら、ヘッドセットの入力から外部においた受信コイルの波形と相関を取って、送信コイルレスで6軸検出ができるようなソリューションがあるのかもしれない。このあたりはVRのトラッキングで使われそうな技術だから、調べれば出てきそう。


 で、結局どの方式を使うか。いまいち決めきれない。
 まぁ今回もFSXはすぐ飽きるだろうから、頭の体操程度にもうちょっと考えてみる。

2017年11月28日火曜日

C#でフルスクリーン

 C#のFormをフルスクリーンにするクラス。

 .NET TIPS:Windowsアプリケーションをフルスクリーンで表示するには? - @IT

 基本的にこのページのコピペだが、フルスクリーン/ウィンドウを切り替えるとFormサイズが変化してしまう不具合の部分だけ、修正してある。

 コンストラクタとメソッド3個しかないので、説明しなくても使えるはず。内容もそんなに大変じゃないはず。動作が知りたいなら上記リンクを参照。

public partial class Form1 : Form
{
    readonly Full_screen_controller full_screen;

    public Form1()
    {
        InitializeComponent();

        full_screen = new Full_screen_controller(this);
    }

    private void button1_Click(Object sender, EventArgs e)
    {
        full_screen.toggle_screen_mode();
    }

    private void button2_Click(Object sender, EventArgs e)
    {
        full_screen.to_full_screen();
    }

    private void button3_Click(Object sender, EventArgs e)
    {
        full_screen.to_window();
    }
}

class Full_screen_controller
{
    private readonly Form form = null;
    public bool is_full_screen_mode { get; private set; } = false;
    private FormWindowState previous_form_state;
    private FormBorderStyle previous_form_style;
    private Size previous_form_size;

    public Full_screen_controller(Form form)
    {
        this.form = form;
    }

    public void to_full_screen()
    {
        if (!is_full_screen_mode)
        {
            is_full_screen_mode = true;
            previous_form_state = form.WindowState;
            previous_form_style = form.FormBorderStyle;

            if (form.WindowState == FormWindowState.Maximized)
            {
                form.WindowState = FormWindowState.Normal;
            }

            previous_form_size = form.Size;

            form.FormBorderStyle = FormBorderStyle.None;
            form.WindowState = FormWindowState.Maximized;
        }
    }

    public void to_window()
    {
        if (is_full_screen_mode)
        {
            is_full_screen_mode = false;

            if (previous_form_state == FormWindowState.Maximized)
            {
                form.WindowState = FormWindowState.Normal;
            }
            else
            {
                form.Size = previous_form_size;
            }

            form.FormBorderStyle = previous_form_style;
            form.WindowState = previous_form_state;
        }
    }

    public void toggle_screen_mode()
    {
        if (!is_full_screen_mode)
        {
            to_full_screen();
        }
        else
        {
            to_window();
        }
    }
}


 そういえば、いちおうJSF++に則った雰囲気の書き方?だけど、JSF++だと大文字と小文字で区別しちゃいけないんだよな。ということで、「型名の最初の1文字は常に大文字」+「インスタンスは常に小文字」で区別するのはルール違反のはず。もっとも、基本的にクラス名とインスタンス名を間違えても、大抵はコンパイラでエラーになるので、バグにつながる危険性は少なそう。
 このあたりは実際の使用例を見てみないとなんとも。とはいえF-35のソースコードってオープンソースになってる部分とかあるんだろうか?機密的に言えば、単なる算術ライブラリとかは全く機密には当たらないけど、各国の税金で作ったものを(仮想敵国も含めた)全世界で共有する、というのは無いだろうなぁ。

2017年11月27日月曜日

むしゃくしゃしてやった。後悔はしていない。


 OSを入れ直して、地味に困ったのが、Picasaが終了してしまったことです。
 画像ビューアとしてはとても優秀だったのに。。。

 Windows 10のフォトを始め、様々な画像ビューアがありますが、Picasaほど使いやすいビューアには出会ったことがありません。
 ということで、簡易的なモノを作ってみました。

 最低限欲しい機能は、キー入力で同じフォルダの画像を表示することです。
 Picasaでは矢印キーで隣の画像を表示できますが、フォトではこれができません。Webブラウザも画像ビューアとしては使用できますが、同様に他の画像を見るには、いちいちウインドウを閉じてファイルをダブルクリックしたりする必要がありました。

 ということで、横の画像への移動は実装してあります。
 とはいえ、Picasaのような、エクスプローラーに表示された順番を得るのは、かなり大変な雰囲気です。なので、今回は自然数ソートのコードをもらってきました。
 C# 自然順で文字列をソートする - Qiita

 Picasaは、背景がすりガラス風だった気がしますが、これをC#で実装しようとするとかなり大変です。そもそもGraphics系ではフィルタリングができないので、自分でガウシアンフィルタなりを実装する必要がありますが、解像度が増えれば実用に耐えないほど遅くなってしまいます。特に僕は4k液晶を使っているので、かなり厳しいです。
 という理由と、すりガラス風にする利点がほとんど思い浮かばないので、今回は単色の背景にしました。

 そういえば昔、Win7のスクリーンセーバーのバブルが、ウインドウそのままでセキュリティ的に良くない、ってことでフィルタを実装した記憶がありますが、起動するのに数秒かかった気がする(しかもマルチスレッドで処理してるので、スクリーンセーバー起動時にCPUファンが唸りを上げる)。

 写真の加工はもっぱらLightroomを使っているので、ビューアとしては、本当に画像表示の機能しか必要ありません。印刷や、ましてやシェアなんて全く不要な機能です。ということで、僕の要求を満足するビューアは、かなり簡単につくれました。
 あとは暫定のプログラムに設定すれば完了だねっ!


 もうちょっと最適化は必要そうですが、気長にやっていこうと思います。

2017年11月25日土曜日

台形制御

 ステッピングモータで台形制御を試している。とりあえず動くようになってきたのでメモ。



 横軸が時間(秒)で、縦軸は右が位置、左が速度。
 位置は25600ステップで1回転分。速度は約67.11で1step/secとなる。ただし速度は200stepで1回転(ドライバの仕様)なので、約13422step/secで1rev/secとなる。2000step/secでリミットしてるので、1rev/6.7secくらい。0.5回転の移動に3秒ほどなので、だいたい計算通り。

 とりあえず秒20回制御してる。printfで位置や速度を出力しているのでこのレートだが、実際はもうちょっと細かく制御したい。


 台形制御というのは、速度が台形になる制御であり、位置が台形になる制御ではないのであしからず(位置が台形になるのはON/OFF制御)。

 指令値と実測値の差が少ない領域(速度が0に近い時)の操作を作ってないので、そのあたりでは発振してしまっているが、とりあえず台形制御にはなっている。


 台形制御は、低速域を除けば、「加速するか、減速するか、それが問題だ」みたいな制御になる。「この速度だと目標を追い越すぞ」となれば減速し、それ以外では常に加速し続ける。ただしあまりに加速してしまうとモーターの限界を超えてしまうので、そこはリミットする。
 ざっくり言えば、制御的には三角制御を行っているが、山の高さをある程度に制限することにより、結果的に台形になる、みたいな感じだろうか。

 減速するかどうかの判定は、
 現在位置 + (速度 * (abs(速度) / 加速度) / アップデートレート) > 目標位置
 がtrueの場合は速度から加速度を引き、falseの場合は速度に加速度を足す。
 こうすると、現在位置と目標位置の関係にかかわらず、うまく制御できる。
 あとは速度のリミットや、低速時の挙動を処理すれば、うまく動く気がする。

 まぁ、他にももっと計算コストの低い、あるいは簡単な実装がありそうな気がする。


 とりあえず、台形制御が動きそうな雰囲気はしてきたので、この方向でもうちょっと進めてみる。
 でも今回のは速度をPID制御したほうが向いてる気がするなぁ。。。

2017年11月23日木曜日

メモ:フェーズドアレイ

 遅延量の計算は以下ページの下の方の図がわかりやすい。
Radar Basics - Phased Array Antenna

 平面(焦点が無限遠)の合成波を作りたい場合、アンテナ面からの角度をθ、素子間隔をdとして、d sin θで遅延量が計算できる(開口が線上にある場合)。
 比較的近い距離に焦点を結びたい場合の計算は書いてない気がするが、焦点から開口までの距離を波長で割った余りが遅延量となる。

 ざっくりと計算してみたけど、意外とサイドローブが多い印象。もっとも、無指向性の開口で計算してるから、半値角90°くらいの開口なら、ある程度サイドローブは減らせそう。
 簡単な計算だと、2次元でしか表示できないので、平面に置こうとすると、開口は1次元にしか作れない。2次元平面に開口を置いた計算をやってみたいけど、かなり面倒そう。

 超音波素子で開口合成をやったら楽しいかな、と思ってた。レーダーだと法的に厳しいし、高周波扱うの面倒だし、光速の計測は大変だし、ということで、遊びでやるなら超音波が楽かな~と思った次第。

 すでに、開口数百素子の超音波フェーズドアレイ素子ってのを作ってる研究室があるらしい。これはもっぱら非接触で物体を操作するための物。
 受粉を機械的に行う、とか応用が書いてあって面白い。現在でも植物(果物、野菜、etc)の受粉は風や蜜蜂任せだが、自然相手なので扱いづらい。特に蜜蜂は使用できる農薬等の制限が厳しいらしい(うろおぼえ)。植物工場とかだと、ほぼ無菌状態で栽培できるので、農薬が一切不要、かつ出荷時・出荷後の洗浄が不要、という利点があるが、蜜蜂等を持ち込むとその利点がなくなってしまう。そういう環境では、多少高コストな機材が必要でも、うまく付加価値をつけれればちゃんとやっていけそう。


 マイコンでフェーズドアレイをやるのはどうやれば低コストでできるかな、と考えてみても、いまいちいい方法が思いつかない。
 STBee F4miniだとFPUがあるので、位相計算は楽だけど、せいぜい32素子くらいしか扱えない。それに外部回路もかなり大量に必要になる。データレートもかなり必要になるので、そのあたりも不安。
 件の研究室でも、やはり小型化・低コスト化がネックっぽい。超音波AESAだと計算量はそれほど多くない気がするけど、ピン数がかなり大量に必要になる(数百~)。こういうのはFPGAでやるより、ASICで量産したほうが低コスト化できそう。基準クロックと位相シフト量を与えればいいだけなので、それほど頻繁に回路を書き換えるわけでもないし、頻繁に変わる部分はFPGAにしちゃえばいいし。


 AESAの計算のついでに、FRESCANも試してみた。並べた開口に、順番に波を入れれば、d=n wavelengthの場合はまっすぐに波が合成されるが、周波数を変えると、d != n wavelengthで、合成波が斜めになる、というタイプ。
 古くは対空レーダーや、最近では車載レーダーに使われてるらしい。メリットはRF周りの低コストさ。パッシブフェーズドアレイでも増幅器は必要だし、移相器も必要になる。アクティブフェーズドアレイも言わずもがな。FRESCANは送受信機が1個で済み、周波数を変えるだけでスキャンできるという利点がある。
 一方で(軍用レーダーでは致命的なことだが)、開口の周期で周波数が固定されてしまう、というデメリットが有る。これは敵からすれば、周波数を見るだけでレーダーがどっちを向いているかがわかってしまう。周波数と角度の関係がわかれば、特定の周波数を入れれば、特定の角度に偽像を表示することができる。他にも色々ありそう。
 FRESCANは電磁波(光速に近い伝搬速度)には便利だが、超音波でやろうとすると、とても面倒なことになる。ということで、この方向は見込み無しということで、あんまりちゃんと確認してない。


 対空ミサイルの仕組みを調べると結構面白いし、レーダーの仕組みも面白いし、F-35Bとかも面白そうだし、こういうの作ってみたいなぁ、とは思うけど。
 ミサイルはモデルロケットで、ターゲットはPhantomでも借りれば、誘導の実験くらいはできるかもしれないが。
 レーダーは法的につらい。超音波で首振りくらいならできそうな気もするけど、あんまりおもしろくなさそう。
 ラジコン飛行機はやってみたい分野だけど、アレもお金かかるからなぁ。2.4GHz化で一気にアビオニクスの値段が上がってしまった感じがある。一昔のラジコン飛行機は安かったのになぁ(10年位前の話。入門用の1.5mくらいのEP機がフルセット1.5万円だった)。

 対空ミサイルは、レーダー誘導ならアンテナでどうにかしてるんだろうなーって気がするし、赤外線誘導もなんとなく想像できるし、GPS誘導爆弾は作れそうな気もするけど、レーザー誘導爆弾は全く想像できない。シーカーってどうなってるんだろうか。


 最近、気力ゲージの減り方がヤバイ。寒いからかなぁ。でも夏は夏で暑いと言って似たような感じだし、いつもこんなもんな気もする。

メモ

 とりあえず無事にWin10をクリーンインストールすることができた。

 インストール時はシリアルナンバーとかプロダクトキーとか入れなくてもインストールできる。まだライセンス云々のメッセージは何も出てきてない。

 11月20日にダウンロードしたWindows 10 x64のISOをDVDに焼いたが、OSバージョン1709、ビルド16299.15で、Fall Creators Update適用済みっぽい。
 見た目は何も変わってないが、タスクマネージャにGPUのグラフが追加されてるので、FCU適用済みだと思う。

 回線が細いので、オンラインでインストーラーを落としてこなければならないソフトウェアはほとんど入ってない。
 来月になれば回線の制限も解除されるので、来月になるのを待ってからOS入れ直せばよかったなぁ、と後悔。


 MBはASUSのB85-PLUSだが、UEFI BIOSでSerial ATAの設定からホットプラグを有効にすると、OSでHDDをリムーバブルドライブとして使うことができる。
 ケースの上面にSATAの3.5インチ?5インチ?が刺さるような部分がある。そこに裸のHDDを刺せば、リムーバブルドライブとして使えた。
 昔、HDDを刺すとOSが落ちる、というのが頻発して、トラウマになってた。なのでほとんどこの機能を使ってなかった。調べてみると、電源が弱いPCでは突入電流でクラッシュするらしい。さもありなん。当時はPCを安く組むために、安い電源を使ってたはず。その後、かなり余裕のある電源に交換したので、HDDの挿抜に耐えられるようになったのではないか、と予想。


 Lightroom5はHDDをコピーしてくるだけで問題なかった。カタログとか全部がひとつのHDDに入ってるので、HDDをまるっとコピーするだけ。
 ドライブレターさえ合わせておけば、カタログの問題は特にない。


 いままでArma3を起動するときに、初回インストールが毎回コケてたのだけど、今回はちゃんと入った。でも相変わらずレーザー測距/誘導ができない。これはバックアップから復元してるから、ファイルが破損してるのかなぁ。来月になったらインストールし直してみよう。
 FPSは相変わらず4kで60fpsくらい出る。でもGeForce Experienceの最適化ができない(設定ファイルを読み込めない)。最適化しなくても60fpsくらい出るので、いいかなという気もするけど。


 今のところ、Cドライブ(4TB)の空き容量が1.87B、データドライブ(6TB)の空き容量が2.2TBほど。写真を撮るペースにもよるけど、2年は持たないかも。Cドライブはこれから色々インストールするけど、それでも1TBは使わないはず。


 試しにVS Codeを入れてみたけど、相変わらずドキュメントのフォーマットができない。何のためにOS入れ直したんだかw(データドライブの容量/寿命が主目的)。ま、オートフォーマットはAStyleでやるので、VS Codeはどうでもいい。

 いくつかバックアップを忘れているファイルがあるので、いつか取ってこなければ。
 今回はドキュメント・ピクチャ・ミュージック・ビデオ・ダウンロードあたりをHDDに丸ごとコピーしてきたけど、プログラムの設定データとかはコピーできてない。
 AppDataとか移動すればいいのかもしれないけど、あんまり古い環境を大量に持ってくると、せっかくクリーンインストールで安定した環境が戻っちゃうからなぁ。


 というあたりで、遅々として進まないダウンロードのプログレスバーを睨みながら、今回はここまで。

2017年11月22日水曜日

メモ:Mk 41 VLS

 セルのハッチの横についてる、穴の空いた小さい四角柱状の突起物って何のためかなぁ、と気になってたんだけど、どうやらstrike down module(日本語版wikipediaでの名称/英語版wikipediaでは"strikedown crane")で、セルを交換するときに使う部品を固定する穴らしい。
 確かに、Flight II以前のStrikedownクレーン搭載艦では突起があるし、Flight IIA以降のStrikedownクレーン非搭載艦では突起が見られない。


フライトI相当の海上自衛隊護衛艦きりしまのVLS付近
Kirishima 06


フライトIIA相当の海上自衛隊護衛艦あたごのVLS付近
JS Atago(DDG-177) Mk.41 Mod20 VLS in Tenpouzan Port 20140426


 どういうときに使う部品かというと、水平状態に置いてあるセルを、クレーンで垂直に立ち上げる際に、支点となる部品らしい。これがあることにより、立ち上げ時の不安定なときにも不用意に動く危険が減らせる。
 同様のモノは地上でVLSの装填を行う際にも使われる。
US Navy 111108-N-BE353-060 Sailors aboard the submarine tender USS Frank Cable prepare to load a training Tomahawk vertical launch system container

 地上だと置くだけなので大きめの部品。セルを置いておく台も兼ねてそう。
 一方、艦載型は固定して使えるので、もう少し小型になってる(wikimediaで画像が見つからなかった/下記リンク参照)。

 Strikedown craneはこういうもの。
020805-N-XP218-008 USS Hopper VLS Strikedown Crane

110909-N-XQ375-035 USS Mitscher VLS Strikedown Crane folded

 ミサイルは水平の状態で移動する。
USS Frank Cable activity 121018-N-UE250-082

 装填するときは、もちろん垂直。
Flickr - Official U.S. Navy Imagery - USS Winston S. Churchill loads missiles.


 艦載のモジュールの写真は以下リンクで。
 Technical Discussions On International Military Equipments Doctrines Tactics Etc - Foreign Affairs (192) - Nigeria
 右下の茶色い服の人の肩の高さにある。
 VLS8セルの中央付近に支点があるので、設置する側と位置を移動することにより、8セルのどの位置にでも挿入することができる。
 画像右下にも別の部品があり、この2個1組で水平に置いたセルを支えて置くらしい。

 Stikedown craneが入っているセルにも固定用の金具がついているので、クレーン周辺の5セルにも挿入可能。
VLS MK41 СG-70 Lake Erie20080218


 蛇足だが、こういう釣り上げるときの支点を使う方法は、長物を扱うときは共通らしい。これは原子力巡航ミサイル潜水艦に搭載するトマホークミサイルの例。
Flickr - Official U.S. Navy Imagery - to load a Tomahawk aboard USS Michigan.

 旧来、潜水艦からトマホークミサイルを発射する場合は、魚雷発射管から水平に発射されていたが、巡航ミサイル潜水艦では垂直に発射することになる。そのため、装填も垂直に行うことになる。


 大きさは違うが、シースパローミサイルだともうちょっと簡単な装填方法になる。

US Navy 061022-N-2970T-003 Fire Controlmen lock a RIM-7 missile into the missile loader while Chief Fire Controlman Jesse Souza stands by as the safety observer

 シースパローは重量230kg程度と、かなりの重さではあるが、軍人数人程度がいれば人力で移動することができる重量となる。航空母艦なら重量のある物を移動するためのドーリーもあるだろうから、複雑な機械等はなるべく使わずに装填できるように設計されている。
 シースパローの発射機はそれなりの高さにあるので、人間が持ち上げるのはかなり大変。ということで、ランチャーの後ろにレールを追加し、ランチャーが仰角をとるとレールが俯角をとり、レール後端が下がって、甲板に置いたミサイルに近くなる、というわけ。

***

 ちょっと気になって調べてただけだけど、かなり時間がかかってしまった。これでも文字列検索ができるオンラインだからこの時間で済んだわけで、20年くらい前の紙ベースの資料を漁ることになったら、いったいどれだけの時間がかかることか。でもまぁ誰か詳しい人に聞いたらこんなこと一瞬で教えてくれるんだろうなぁ。
 そしてこの知識が役に立つときは来るのだろうか。「VLSのハッチの横にある突起って何なの?」とか聞かれるシチュエーションが想像できない。
 ま、知識なんて自己満足なんだから、知りたいことを調べればそれで十分なのだ。


 Wikimedia、意外と色々と画像があるけど、検索性が悪い。Wikiでタグ付けできるようになってたり、機械学習で関連するタグも検索してきたり、できれば便利なんだけど。

Win10クリーンインストールで2TBの壁

 Win10をクリーンインストールしようと思ったけど、4TBのHDDが2TBの壁に阻まれた。
 4TBくらいのパーティションを作ろうとしても、2TB(2047.5GB)くらいしか作れず、拡張しようとしても「新しいパーティションを作成できません」みたいなエラーが出て来る。
 調べてみると「必要ないストレージをはずせ」とか書いてあるけど、心当たりがない。

 どうやら、起動モードに問題があるらしい。

 起動時にBIOSを立ち上げて、ブートモードで光学ドライブの内、UEFIの併記があるドライブを選択する。そしてpress any keyとか出てきたところを見逃さず、キーを押す。
 押さなくてもOSインストール画面が出てくるが、起動モードが違うために2TBの壁に阻まれるらしい。

 僕もよくわかってないが、とりあえずこの方法で4TB近いパーティションを作ることができた。
 最初は2TBくらいしか作れないが、「拡張」をクリックすれば4TBくらいに広げることができる。


 OSのインストールなんて2年ぶりだからすっかり忘れちゃってるよ。
 このまま何事もなく進みますように。

2017年11月21日火曜日

2017年11月16日木曜日

うにおん

 要素の大きさが固定のキューで様々な情報をやり取りする際は、union(共用体)が役に立つ。
 1つの情報は構造体によりデータを持つが、複数の情報を排他で保持したい場合、それらの構造体をさらに構造体に入れるのは、メモリ効率の点で無駄が多い。

 構造体を使う場合、1回の操作に必要な情報をひとまとめにして渡すことができる、という利点がある。例えばキューが整数型1個(と内容を示す列挙型)しか扱えない場合、1回の設定で複数の変数を設定する必要がある場合、何回もキューに入れる操作が必要になる。

 共用体が使えるなら、複数の構造体を選んでキューに入れられるので、キュー1本で様々なデータを受け渡しすることができる。
 共用体を使わなくても、例えばキューの要素サイズを64バイトの固定長にする、といった方法で複数の構造体を入れることができる。しかし、後から要素数の大きい構造体を使おうと思った際に、保守が困難となる。共用体を使えば、コンパイラが自動的に要素サイズを設定してくれる。


 ということで、共用体を使いたいんだけど、コーディングルールで共用体が使えない。
 どうやってデータを渡そうかなーといろいろ考え中。

***

 最近、軽くスランプ気味。
 すっごい簡単な試作基板(コネクタ何個か乗ってて、ジュンフロン線数本という程度)を作っただけでも気力がゴッソリ削り取られた。コーディングもなかなか進まない。
 まぁ、いつもこんな感じな気もするけど。
 なんかぱーっと気分転換したい。

 そういえば、今季もアニメ1本も見てない気がする。いくつか録画はしてるけど、見る気が出ない。

2017年11月14日火曜日

ルームランナー

 某所でルームランナーに乗ってエアガンを撃ってきた。
 イメージはこんな感じ。


 この人すごい上手。

 でも意外となんとかなる。M4で、4km/hくらいなら5m先の直径20cmくらいにほとんど命中する。12km/hでも50cmくらいにほとんど命中する。リロードも特に問題なく可能だった。
 もしも相手が自分を撃ってでも確保したい、あるいは射殺したい、と思っているようであれば、走って逃げても絶対に逃げ切れない。
 サバゲだとどうだろう。こっちが走っていて、相手を撃つ状態。相手がカバー無しで見えてるなら当たるだろうけど、隠れてたらたぶん無理。逆に、相手はむき出しのこっちを撃てる。とはいえエアガンだと弾速が遅いので、リード射撃が必要。相手が距離や速度を見誤れば、撃たれずに移動できるかも。それにこっちは相手を壁の向こうに押し込めるし。とはいえ、それは1対1の状況で、相手が複数人だと誰かに撃たれる。

 ある人曰く、「相手を見てから撃つまでに、どんなに訓練しても3秒未満にはできない」らしいので、逃げるなら10m毎に遮蔽物があるルートを探すしか無いのかな。この遮蔽物は、弾が抜けない強度が必要。エアソフトならベニヤ板で十分だけど、実弾だと鉄筋コンクリート位ないと厳しい(ブロック塀や自動車くらいなら実弾は抜ける)。
 この3秒というの、たぶん正規軍のような統制が取れた組織での話なので、「動くものはすべて撃つ」というテロリストとかトリガーの軽いハンターみたいな相手だと、たぶんもっと早い。ローレディから挙銃して正面の的に撃つのもかなり早いから、3秒ってのはかなり条件が厳しそう。

 ランダムなタイミングで起き上がって、5発くらい撃ったら倒れる的、というのがあれば、ルームランナーの周りに10個くらい置いておけば、かなり楽しそう。5x5mくらいの部屋でも、かなり楽しめそうだ。うちにもルームランナーほしい。

2017年11月13日月曜日

暗黙の型変換

 なぞのきょどうに遭遇して結構ハマった。

#include 
#include 

int main(void)
{
    {
        int32_t v1 = -104;
        uint32_t v2 = 32768;
        int32_t v3 = 450869;
        int32_t v4 = v1 * v2 * 32 / v3;
        printf("1:%d\n", v4);
    }
    {
        int32_t v1 = -104;
        int32_t v2 = 32768;
        int32_t v3 = 450869;
        int32_t v4 = v1 * v2 * 32 / v3;
        printf("2:%d\n", v4);
    }

    return(0);
}


 というコード。最初のブロックは当初のコード、次のブロックは修正後のコード。値は実際に使われた値を書いている。
 どちらも、結果は-241を予想している。
 -104 * 32768 * 32 / 450869 = 約-241.870で、切り捨てて-241となる。関数電卓とかで計算しても、このような結果になる。
 しかし、実際には1では9284という結果になる。
 arm-none-eabi-gcc 4.9.3でも、WSLのgcc 4.8.4でも同じ結果。

 これは、符号ありと符号なしで演算を行う場合、符号なしに変換されて計算されるためらしい(よくわかってない)。
 -104はu32で0xFFFFFF98となる。これに32768を掛けると0x7FFFFFCC0000となるが、32bitに切り落とされるので0xFFCC0000となる。32を掛けて同0xF9800000、450869で割って9284となる。

 型変換が行われるのは、違う形で演算を行うためであり、同じ型同士であれば変換は行われない。ということで、v2をs32にすれば正しい結果となる。


 JSF++で、「符号付きおよび符号なしの値は、算術演算または比較演算で混在してはなりません(理論的根拠: 符号付き値と符号なし値を混在させると、演算が多数の算術変換および積分型昇格のルールに従うため、エラーが発生しやすくなります)」(AV Rule 162 shall not)というのがある。
 今回、身をもって実感した。
 ついこの間、JSF++を翻訳してたので、そう言えば混在しちゃいけないルールが有ったな、と思い出したけど、これを読んでなかったらもっと深みにハマってた気がする。


 このv2は、元のコードでは、ハードウェアの符号なし32bitレジスタから読み取った値なので、そのままu32に突っ込んでいた。実際に取りうる範囲は0x00000000-0x0000FFFFなので、s32でも足りたのだが。

2017年11月11日土曜日

メモ:浮動小数点数

 浮動小数点数は誤差があるから使ってはいけないのだという。例として、「0.1ですら性格に表現できない」とか言われている。実際、JSF++でも浮動小数点数の演算は一部の例外を除き、明確に禁止されている。

 そもそもなぜ浮動小数点数は誤差を持つかというと、大抵の実数は2進数の有限長では表現できないためで、整数値の範囲であれば問題はない。例えば整数同士の加減乗は問題ない。除算の場合は、整数でも1.0/3.0=3.33...のように実数となり、また有限長の2進数では表現できない。

 じゃぁdoubleでも実数しか使わないなら問題ないね、ということになるが、それならint使ったほうが良いだろ、となってしまう。

 参考までに、浮動小数点数の表現範囲は、単精度が23bit、倍精度が52bit、4倍精度が112bitとなる(さらに符号ビットや指数がある)。
 23bitではfloor(log10(2^23))で 10進6桁分の精度がある。52bitでは15桁、112bitでは33桁となる(4倍精度はまだ一般的ではない感じだが)。
 ちなみに8bitから128bitまでだと、8bitで2桁、16bitで4桁、32bitで9桁、64bitで18桁、128bitで38桁を表現できる(符号ありで1bit少ない幅の場合)。
 浮動小数点でも整数でも、演算途中を含め、数値がこの桁数の範囲に収まるのであれば、誤差は発生しない。
 例えば1/128は0.0078125だが、これは有効数字5桁なので、単精度浮動小数点数型でも誤差は発生しない。しかし1/2048は0.00048828125で8桁が必用なので、単精度浮動小数点数型では表現できない。倍精度浮動小数点数型は15桁まで表現できるので、8桁なら問題なく表現できる。
 単精度浮動小数点数型は約6桁しか表現できないから、例えば12345678という数値も正しく表現できない。

 浮動小数点にかかわらず、プログラミングで変数を使う場合には、必要な精度を見極める必要がある。無闇矢鱈と大きな変数を使えば、丸め誤差は発生しないが、それではメモリを余計に使用してしまう。


 例えば、GPSの本によると、単精度では足りず、倍精度を使う必要があると書いてある。
 GPS衛星は約20,000kmの高度にいるから、単精度では100メートル単位でしか表現できない。これでは数百mの計算誤差を生じてしまう。倍精度ならマイクロメートルの単位まで表現することができる。
 実際にはGPSの位置情報は数メートルの誤差があるが、精密測量機器ではミリメートルの精度で計測できるし、汎用型でも誤差数百メートルは許容できないだろうから、倍精度が必用、というわけ。


 整数型で計算を行う場合、加減乗は範囲だけ気にすればいいので気が楽だが、除算はかなり面倒になる。例えば10/6は1.666を丸めた2を期待するが、整数型では切り捨てのために1となる。このあたりの誤差をどう処理するか、といった、本来の処理からは外れた部分を考える必要があるのが大変。
 STM32F4にはFPUが乗ってるんだし、多少誤差が有ったって問題ないんだから、浮動小数点を使ってもいいでしょ、とは思うのだが、一旦整数型縛りを始めるとなかなか。

2017年11月9日木曜日

メモ

 FreeRTOSのコルーチン。日本語ドキュメントだと「FreeRTOSではコルーチンを使用できます」くらいしか書いて無くて、どうやって使うのかが謎い。公式のページが一番わかりやすい。
 Example code creating scheduling and using RTOS co-routines
 Quick Co-routine Exampleの通り、簡単にわかる。

 FreeRTOSのコルーチンはRTOSによるスタックの割当は行われず、FreeRTOS外のスタック領域を使うらしい。またQueueとかも使えない気がする(詳細未確認)。デバッグメッセージをprintfからQueue経由でUARTに出そうとしたらハングアップした。

 基本的に、OSで管理するほどではないけど、ISRとかに書くには大きい、位の低レイヤ処理をターゲットにしてそう。サンプルだとLチカとかやってる。とはいえ、Lチカするにしたってその指令を出すのはタスクなわけで、じゃぁその間の橋渡しはどうやるんだ、という問題が有る。グローバル変数とか?

 今回はRTCの校正をコルーチンで行おう、と思っていた。処理自体はISRでもできないことはないくらいに小さいコードだけど、printfデバッグとかしたいので。ということで、printfが使えない?コルーチンも不可ということに。

***

 STM32F4RTCは、SSRの分解能を優先すると、キャリブレーションが面倒な感じになるっぽい。F4RTCはDIV_AとDIV_Sの2本のプリスケーラの積で1Hzを作るが、DIV_Aを小さくしてDIV_Sを大きくするとSSRの分解能が向上する。ただしDIV_Aが3未満の場合は正の方向にキャリブレーションできないらしい。
 対策として、わざとDIV_Sを外した値にして、キャリブレーションで負のレンジの真ん中に設定しておく、という感じにするらしい。キャリブレーションは9bitのレジスタと1bitの符号で10bit分の分解能があるが、DIV_S<3の場合は9bitの分解能しか得られない。
 ま、今試してるボードでは5bit+Signで足りてるので、9bitでも十分なのだけど。

***

 かなり面倒なことになってきてる。ステッピングモータで遊びたいだけだったのに、どうしてこうなった。

2017年11月8日水曜日

F4RTCメモ

 微妙に痒いところに手が届かない。
 例えばRTCの動作中は位相をモニタしたい。ということで1Hz出力を有効にする。すると、外部イベントによるタイムスタンプの記録ができなくなる。

 とりあえず、32.768kHzの水晶がそれなりに誤差が大きいらしい。といっても21ppmくらいなので、時計としては十分に高精度。だけどオシロで見るとどんどん位相が動いていく(GPS基準)。

 周期はCALR(キャリブレーションレジスタ)で調整する。CALIBRという似たようなレジスタが有るけど、こっちは互換性のために残している?らしい。約1ppm単位で調整ができる。調整幅が約488ppmを超えると、調整幅が倍になって分解能が4分の1になる。それでも調整しきれない場合は、さらに調整幅が倍になって分解能が4分の1になる。最大2000ppmくらいの範囲で8ppm単位、くらいかな。

 一方、位相の調整は、SHIFTR(シフトレジスタ)で調整する。デフォルトでは1/256秒(約4msec)の分解能で移動できる。
 リファレンスマニュアルによると、最大約30usecの分解能が得られるらしい。ただし「消費電力が増加する場合がある」と書いてある。ま、モーター制御に使ったりするなら誤差のレベルであろう。

 とりあえず、大まかな位相差はシフトで取り除き、それより細かい分解能ではキャリブレーションで移動すると良いかもしれない。
 ただし、キャリブレーション値を変化させたままでコアが停止した場合、そのままずーっと移動し続けてしまう。電源供給断で割り込みがかかるようにして、その後数十msec分の電力をキャパシタに入れておき、ISRの中でキャリブレーション値を戻す、みたいな工夫が必用そう。
 あるいは、シフトレジスタの分解能を限界まで上げてしまうか。これで30usecの精度で位相を合せられる。ただ、原因がわからないが、ジッターが100usecくらいある。なので30usecで合せてもあんまり意味がない。


 ま、とりあえず、今の用途なら50msec程度で十分なので、まずは1PPSから自動で位相を合せられるような処理を作らなければ。

 でも、これでもEXTIとISRを使う方法とか、タイムスタンプトリガを使う方法とか、いろいろやり方がある。
 精度を求めるならタイムスタンプだけど、EXTIだとデバッグが楽。そのあたりは追々。


 デスクトップ機のVS Codeが不調で、ドキュメントのフォーマットができない。症状としては、右クリックメニューが変更・切り取りコピー・貼り付け・コマンドの4個以外表示されない。PCを再起動したり、VS Codeを入れ直したりしてもダメだった。ショートカットキーも反応しないので、右クリックメニュー周りのバグではなく、コンポーネントの読み込みがされてないらしい。しかしショートカットキーリストにはフォーマットとかのキーコンフィグが出てる。

 とりあえずしょうがないので、ノートにリモートデスクトップ接続して、ノートからデスクトップ機のコードを置いてあるフォルダをVS Codeで開いて、ビルドと書き込みはデスクトップ機で、みたいなわけのわからないことになってる(ノートは解像度が低いので開発には向かない/ノートから4k液晶は30pしか出力できない/机の上にそもそも置くスペースがない/etc)。

Arma 3は異常終了しました


 こーゆーの。

 Touch Keyboard and Handwriting Panel Serviceというサービスが問題らしいので、ゲームプレイ時はそれを停止させる。


 タスクバーを右クリックして"タスクマネージャー"をクリック、タスクマネージャーを開いたら"サービス"タブを開いて下側の"サービス管理ツールを開く"をクリック、てきとーなサービス(歯車アイコンのリスト)をクリックし、"touch"とキーボードを入力。そうするとtouchで始まるサービス名が選択される。"Touch Keyboard and Handwriting Panel Service"というのがあるので、コレを右クリックして"停止"をクリック。これでArmaがクラッシュしなくなる。
 この手順はPCを再起動する毎に必用。「そもそもサービスを起動しないようにするべき(自動起動を停止)」という過激派も居るけど、必要があってサービスが起動している以上は、徹底的に殺すのはやりすぎだろ、という気がする。タッチパネルでキーボドを使うならこのサービスが必用。タッチパネルなんてつかわねーよ、という人は知らん。どうぞ勝手に。


 4k液晶でArma 3、Core i5 4570(第4世代/3.2GHz)とGeForce GTX950の組み合わせでも60fpsくらい出る。
 「総合品質」を一番低いクオリティに設定してから、必要に応じて高めていく、という手順。隠しパラメータでもあるのか、総合品質を高いところから各々落としていくと、あんまりFPS出ない。
 地形は低くすると草とかが生えない不毛の大地になる。最高以外では浮遊物体が発生してしまうけど、背に腹は代えられない。
 PIPはバックミラーとかバックモニタに使われる、Picture In Pictureという機能だが、コレがかなりのリソースを食う。2画面分とか3画面分のレンダリングをするわけだから、リソースがn倍という単位で必要になる。無効にするとかなりFPSが改善する。後ろが見えないけど、「バックモニタは故障中」ということで。
 視程はよほど大量のオブジェクトが無い限りは、2kmくらい表示するなら問題ない。あんまり短いと、車載火器の射程に視程外から狙われる(敵アルゴリズムで視程の切り落とししてるかな? 未確認)。ドローンが使えるフィールドとかで苦労するので、ある程度の視程は必須。

 4kになったからと言って状況認識が改善するかというと、微妙な感じ。完全に見通せるなら角分解能が高いほうが有利だけど、敵も木や草の影に隠れるから、あんまり角分解能は重要ではない。
 4kでフルクオリティのレンダリングをすればそりゃ綺麗だけど、1-3fps位しか出ない。移動もままならない。


 僕が使ってるDIGA DMR-BRW1000という機種。取説によると4kアップコンバートに対応しているらしい。再生中にサブメニューから24p/30p切り替えで30pとかにすれば、FHD60pから4k30p/4k24pに変換されて出力される。4k60pではないらしい。
 デジカメの4k出力も30pだしなぁ。まだ4k60pの動作確認ができてない。
 Xbox One Xの在庫、いつ入ってくるのかなぁ。1月中に買えると良いけど。


追記:2017/12/15
 最近になって、サービスを手動で停止しても、勝手に再び開始されてしまうようになった。当然、停止してからArma3(A3)を開始しても、プレイ中に開始され、A3がクラッシュする。
 スタートアップの種類を手動にしても自動で起動する。とりあえず、スタートアップの種類を無効にすれば自動起動は防げるが、今度はIMEが使えなくなるという大問題が出る。

 アプリケーションが起動中にTSIを動かせば、再び停止させた後でも、IMEの切り替えは問題なく行える。一方、TSIを停止してから起動したアプリケーションでは、IMEの切り替えが行えないものがある。
 また、TSI停止中では、スタートメニューを表示してキーを入力しても、文字入力ができなくなってしまっている。他にも、ロック画面でキー(any key)を押すと、通常であればPIN入力画面に移行するが、TSI停止中はそれも行えない(マウスボタン押下で遷移できるので、ログインは行える)。

 このあたりでOSからTSIに対する依存が発生して、死活チェックを追加した、みたいな流れな気がする。


 基本的に、「ゲーム専用マシン」として使うなら、今のところTSI停止中でも大きなデメリットはない気がする。頻繁にログインを繰り返すわけじゃないだろうし、大量のプログラムリストをフィルタリングする必要もないし。IME切り替えに関しては、むしろ不要な日本語入力が行われないので、好都合とも言える(ゲーム内チャットとかってどうやってるんだろうか。IMEが必要?)。

 いちいちゲームを行うたびにスタートアップの種類を変更して開始/停止させるのも面倒な気がする。scを使えばスタートアップの種類の変更もできるっぽいので、スタートアップを手動にしてサービスを停止する、スタートアップを自動にしてサービスを開始する、という2種類のバッチファイルを作れば便利になりそう。


 ちなみに、タブレット/タッチパネルがない環境ではTSIが起動していても問題ない模様。ゲーミングマシンでタブとかタッチパネル使うユーザーもそんなにいないだろうから、A3開発側でもfixする気はないんだろうなぁ。デベロッパーでどうにかなる問題なのか知らないが。

2017年11月7日火曜日

F4RTC

 STM32F4のリアルタイムクロックは高機能だ。F1の32bitカウンタとは比べ物にならないほど高機能だ。
 しかし、使いづらい。

 せっかく超高精度に時間を読み出せるのに、メーカー想定の使い方ではシステムリセット時に秒のプリスケーラがクリアされる。つまり、秒の信頼性が著しく低い。
 これをキャンセルする機能がある。しかし、それを使うにはユーザーが複雑なプログラムを書く必要がある。

 キャリブレーションも非常に使いづらい。リファレンスマニュアルによると「数秒の校正で0.95ppmの精度」だという。1秒で1usec程度の誤差ということだ。1ヶ月では2.5秒ほどの誤差だから、一般的な時計より1桁良い性能だ。
 しかしその方法が書いていない。

 基準クロックはどうだ。50Hzか60Hzを入れれば正確な1Hzを刻むのだという。しかしマイコンで時間を測りたいのに、わざわざコンセントに繋ぎっぱなしにしなければいけないのは面倒だ。
 それに50Hzか60Hzというのがいただけない。1Hzを基準にできれば、GPSモジュールを併用して、世界標準時と0.1マイクロ秒単位で正確に同期した時計を作れるというのに。


 どうにも、F4RTCは使いづらい。ま、F1よりは便利になったんだけどね。
 いまいち使い方がよくわかってないので、もうちょっと試行錯誤する必要がありそう。
 時計というか、時間処理系で、リアルタイムに動かさないとダメなモノだと、1箇所のパラメータの動作確認に5-10分程度かかることもザラ。カレンダ機能に至っては、数日間の連続動作を行わないとわからない、ということも有る。とても面倒くさい。


 結局のところ、EXTIで1Hzを監視して、それによって校正値を生成することにより、位相を合せたり、校正したり、というのを自前で用意する必要がありそう。
 ハードウェアで勝手にやってくれれば便利なんだけどねぇ。

2017年11月3日金曜日

論理(or/and)代入演算子が欲しい

 失敗時に0、成功時に0以外(不定/実装依存)を返す関数hoge,fugaが有ったとする。

int flag = 1;
flag &= hoge();
flag &= fuga();
if (flag)
{
}
else
{
}

 意図する処理は、双方ともに成功したらifを処理し、片方でも失敗したらelseを処理する、という流れ。
 しかし、これは上手く動かない。
 hogeが成功時に1を返し、fugaが成功時に2を返した場合、1&2は0になるからだ。この場合、期待通りの処理を行うには、ビットAND代入演算子(&=)ではなく、論理AND代入演算子(&&=)が必要になる。しかしそんなものはない。

flag = flag && hoge();
flag = flag && fuga();
 と書けば期待する処理になるが、なんとも冗長なコードになる。

 どうにかならんものか。


flag &= !!hoge();
flag &= !!fuga();
 というコードであれば、1回目のnotで反転し、2回目のnotで元の論理値に戻り、この際にコンパイラのfalse/true値に置き換わるので、コンパイラのtrue同士のANDとなり、うまく動く。でも、なんか綺麗じゃない。


 変数や配列やポインタの説明とか、関数の使い方とかじゃなくて、こういう小ネタが書いてある本を読みたい。