2022年9月30日金曜日

換気

会社で環境測定です。

「在宅ワーク、なにそれ?」「換気?ああ、アナウンスが流れてるね」状態で人の集まるフロアーです。ひょっとするとセンサーが反応して音が鳴るかも?と思いながら計測してみました。閾値は昨夜と同じ TVOC 100ppb 。

室外でキャリブレーションを行い、 SGP30 を持って入った次の瞬間に鳴り出しました。あ、これは失敗。薬品庫のある部屋でした。感度が良い。

気を取り直し、再測定。
鳴らないですね。室内はタバコ臭よりマシでした。
と思った数分後に鳴り出しました。うーん。タバコと同じレベルか。数字にするとキツイ。オジサンたちが集まって何を出しているのか。うーんキツイ。

換気、大事です。

2022年9月29日木曜日

Ambient の制限

Ambient からデータをダウンロードしてみると、4~6秒毎の蓄積、最小時間単位が秒になっています。1Hzで発信しているので、Wi-Fiかサーバー側の問題ですね。次はMEMSで振動を計測しようと考えていましたが、これではダメかな。

バッテリー電圧は、Ambient側では小数点以下2桁まで保存されていました。LCD表示は整数です。これは CO2濃度と同様に drawNumber を使用していたのが原因。

M5.Lcd.drawNumber(vbat, 120, 110, 4);

下2桁まで表示するにするには、カーソルを合わせてから print。

M5.Lcd.setCursor(96, 110, 4);
M5.Lcd.print(vbat);

drawNumber のx座標は中央配置用の指定になっています。setCursorは左端指定でした。


テストをクリアする最小限の実装が終わったので、いよいよ実験開始。
風上の窓をほんの少し開けて、その隙間風を計測できるよう、窓の鍵にUSBケーブルをかけてセンサーをぶら下げておきました。USBケーブルは数年前に100均で購入していたモバイルバッテリーにつないでおきます。

22:46 にスタートして流していると、1時前に反応がありました。外から入ってきたタバコでした。匂うよりも先にM5StickC-Plus の発する音と光で気づきました。音が小さいので昼間に別の部屋にいると気づかないかも。これは要改善点です。

※窓全開で換気中です。

窓際に立つと、外から入ってきたタバコの匂いがします。が、部屋全体には広がっていません。屋内にセンサーを設置する関係上、これ以上は早く感知できないでしょうね。窓を全開にしている流入量が多くてと使い物にならないか?流速が小さくなって同程度?
ま、いきなりタバコに反応するということが確認できただけでも収穫です。いったい、タバコには何が入っているのでしょうね。

翌朝、バッテリーが切れてM5は停止していました。
Ambient側の記録を見ると 4:30 までのデータが保存されていました。バッテリー電圧は降下していましたが、3.7V でしたのでまだ動くはず。おかしいなあと思い確認してみると、データ数制限のようでした。

https://ambidata.io/refs/spec/

  • 送信から次の送信まではチャネルごとに最低5秒空ける必要があります。それより短い間隔で送信したものは無視されます。
  • 1チャネルあたり1日3,000件までデーターを登録できます。平均すると28.8秒に1回のペースです。
  • 件数のカウントは0時に0クリアされます。
  • チャネルデーターを削除しても1日の登録件数のカウントは0クリアされません。

0時以降、3363件のデータが保存されていました。4~6秒毎も同様に制限に引っかかっていたのですね。これ、有料版だと50Hzサンプリングの記録をミリ秒単位で保存できるのでしょうか?
https://ambidata.io/samples/vibration/vibration/

電圧降下開始が4:08でしたので、そこから40分稼働するとすると、モバイルバッテリー追加で6時間稼働する事がわかりました。

初回から良い結果を得られたのですが、閾値を低くしていたので誤検知も多くなっている状態かと思われます。Ambient の限界?もわかりました。代替えクラウドを探してみましょうか。

あとは、RTCを使ったセンサー側の時刻付与、観測時のディスプレーoff(Aボタン押下で切り替え)、Bボタン押下で音と点滅の停止、余計な電力消費のカット、マルチモーダル化(音の取り込み)、そして閾値の調整(誤検知軽減)ですかね。コツコツ実装してまいりましょう。

M5.begin()

続きです。

まず、ソースを確認。

https://github.com/m5stack/M5StickC-Plus/blob/master/src/M5StickCPlus.cpp
void M5StickCPlus::begin(bool LCDEnable, bool PowerEnable, bool SerialEnable) {
    //! UART
    if (SerialEnable) {
        Serial.begin(115200);//省略
}
    // Power
    if (PowerEnable) {
        Axp.begin();
    }
    // LCD INIT
    if (LCDEnable) {
        Lcd.begin();
    }

https://github.com/m5stack/M5StickC-Plus/blob/master/src/AXP192.cpp
void AXP192::begin(void) {
    // Set LDO2 & LDO3(TFT_LED & TFT) 3.0V

今は M5.begin(true,false,false)。AXP が begin されないと、各種電源関係が初期化されません。これでしょう。そもそも、false はどのようなケースで使用するのでしょうか?

M5.begin() = デフォ true*3 だと、電源を落とせます。USBケーブルでPCや電源につなぐと、自動で起動します。そういう仕様なのでしょう。
M5.begin(true,true,false)でも同様です。

調べてみると、M5.begin()の引数 はM5シリーズ内で異なるようです。純正のサンプルコードが誤っているのでしょうか?ま、意図したように電源が動作するようになったので解決です。

さらに続く。


M5StickC Plus + SGP30 + Ambient

続きです。
Ambient を使用するコードを転送。

書き込めましたが、Wi-Fiがダメ。
アクセス先の 5GHzを 2.4GHz に切り替えるとつながりました。M5Stick 側で 5GHz を指定する方法はないのでしょうか?後回しにして、進めます。

サンプルコードを足しただけですので、動きました。TVOC, eCO2, 電圧が1秒毎に更新されます。バッテリー電圧の表示が一桁なのは御愛嬌。この修正も後回し。

Ambient を確認。
測定できています。グラフが書かれています。時間が経つと更新されます。素晴らしい。
この部分はPython並みにライブラリ依存ですので、間違いようがないのでしょう。

そのまま測定を継続すると、開始後40分で電圧が急降下し始め、電源が切れました。ほぼデフォで1時間持ちませんでした。残念。ま、粗々の流れは確認できましたので、良しとしましょう。

安心して再起動すると、LCDが暗いまま。
あれ?転送中の問題じゃなかった?

つづく。

2022年9月28日水曜日

M5StickC Plus + SGP30

今回購入したモノ

※イヤホンは購入していません。サイズ比較用です。小さい!

1.マイクロボード: M5StickC Plus
https://shop.m5stack.com/collections/m5-controllers/products/m5stickc-plus-esp32-pico-mini-iot-development-kit
このサイズで3軸加速度センサー、ブザー、マイク、Wi-Fi、LCDなどの欲しい機能が一通り実装されています。そして、この価格。さすが中国発。まさかの手作り?
https://wirelesswire.jp/2019/08/71960/

2.測定モジュール: TVOC/eCO2 Gas Sensor Unit (SGP30)
https://shop.m5stack.com/products/tvoc-eco2-gas-unit-sgp30
TVOCセンサーはいくつかありますが、SGP30 の感度が良さそうでした。https://www.jaredwolff.com/finding-the-best-tvoc-sensor-ccs811-vs-bme680-vs-sgp30/
価格が安く、ケーブル付きで繋ぐだけ。電圧調整も不要な M5 純正ユニットを選択。ケースに入っている分だけ反応は弱くなりそうですが。これらの組み合わせはネットでもいくつか紹介されています。
eCO2 への換算式は載っていません。テストがエタノールと水素ですので、測定された H2 と TVOC=エタノールとみなして C2H6O+3O2→3H2O+2CO2 から推定しているのかもしれません。おまけみたいなモノと捉えておきましょう。
https://m5stack.oss-cn-shenzhen.aliyuncs.com/resource/docs/datasheet/unit/Sensirion_Gas_Sensors_SGP30_Datasheet.pdf

電源を入れるとFactoryTest が 始まるようです。ボタンを押すと、ジャイロ?による立方体の表示や音声のFFTが切り替わります。
用意していたHellowWorldの表示コード、加速度の表示コードでも正常動作を確認できました。
初期不良はないようです。一安心。

SGP30を使用するコードをコンパイルし、転送。
動きました。SGP30も大丈夫みたいですね。

次に Ambient を使用するコードを転送。
と思いきや、転送途中でラップトップの電源が切れました。M5はどうなった?
電源をoff にした後、起動しなくなりました。ありゃ。

異なるラップトップにつなぐと認識します。ディスプレーがoffってるだけでしょうか?

再度、FactoryTestを転送すると、動きました。
USBケーブルを外して、もう一度電源 off, on。大丈夫です。

危なかった。


2022年9月27日火曜日

Arduino IDE その2

Arduino IDE で SGP30 のライブラリを検索すると、3つ引っかかりました。M5社のサンプルコードでは"Adafruit_SGP30.h"が使用されていますので、これをインストール。https://github.com/m5stack/M5StickC-Plus/blob/master/examples/Unit/TVOC_SGP30/TVOC_SGP30.ino

サンプルコードをコンパイルできるか?
通りました。問題ないようです。

次は Wifi に繋いで、Ambientにデータをアップする部分。
図書に記載してあるので、常套手段なのでしょう。Ambient さんのサンプルコードを利用します。https://github.com/AmbientDataInc/Ambient_ESP8266_lib/blob/master/examples/M5Stack_ESP32/Ambient_BME680/Ambient_BME680.ino
Arudino IDE では、Ambient_ESP32_ESP8266_lib をインストール。これでインクルードできました。

コンパイルできるか?
ダメ。wifiで引っかかります。
原因は私の記載ミス。WiFi.h を Wifi.h と記載していたので、どのライブラリを入れても認識してくれしなかっただけ。何も追加する必要はなく、素直にコピペしておけば最初から通っていました。これを修正すれば、通りました。

ひとまず、環境構築は終了。後追いだとサンプルコードが豊富にあるので楽ですね。

2022年9月24日土曜日

Arduino IDE

Arduino の開発環境です。
Arduino IDE
公式:https://docs.m5stack.com/en/quick_start/m5stickc_plus/arduino

まずは driver。これはリンクから exe 版を利用しました。

次に Arduino IDE。
インストール後に追加のURLを設定すると、依存関係を含むボード特有のライブラリを引っ張ってきてくれます。この点が支持される理由でしょう。

ボードマネージャーからボードを指定、必要なファイルをインストール。

ライブラリマネージャーも同様。GitHub から検索しているようです。引っかかったので、install を押しました。が、途中でエラー発生。

Error: 13 INTERNAL: Library install failed: moving extracted archive to destination

作成されたフォルダが読み取り専用になっていたため解除。IDE 再起動後にもう一度インストールで成功。https://github.com/arduino/arduino-cli/issues/723

この IDE では、sketchという単位でコードを管理するようです。inoファイルができていましたが、c++もインクルードされています。

'Hellow World' を sketch として保存、再読み込み、ボードを指定して検証・コンパイル。OKです。

つづく。

Autodesk Tinkercad

Arduino はイタリア発とのこと。

マイコンボードとしてはかなり売れているのでしょう。設計がOpen なので互換機もたくさん出ています。
今回は購入しなかったのですが、ちょっと試してみたい。そのような時に、思い出したのがコレ↓
Autodesk Tinkercad
https://www.autodesk.co.jp/solutions/circuit-design-software

回路作成シミュレーションが可能な web アプリです(以前は異なる名前でした)。これに Arudino が含まれています。Ardino やブレッドボード、センサー類を配置し配線することで、動きをシミュレーションできます。配置だけである程度のコードが作成されるのもありがたい。

センサーが豊富というわけではないので作成したいものをシミュレートできるわけではないのですが、使い方を把握するには手軽で便利です。


2022年9月23日金曜日

電子工作

MEMS センサーを扱ってから、電子工作に興味が出てきました。

RasPi や M5stack などにセンサーを付けるだけで(精度ははともかく)独立した計測器ができてしまします。機械学習済みのモデルを入れると、エッジAIカメラとしても使えるようですね。ネットや書店では数年前からよく見かけていましたが、これまで惹かれることがありませんでした。
が、この季節、窓を開けると時折風に乗ってくる匂いに迷惑を被っています。窓に臭気センサーかマイクを付けて、Arduino に接続してプログラムを組んでしまえば検知できるなあ、警報機はできるよね、できちゃうわ。ということで、ポチ。注文しました。ひとまずやってみようと。

パーツが届くまでにプログラムの組み方やクラウドへのデータ転送、表示の方法などを調べました。書籍にも記載されているくらい、メジャーなようです。AWS もサービスを供給していました。何とでもなりそうです。

言語は Python or C風の「Arduino言語」とのこと(by Wiki、私にはC++との違いが判りません)。後者の方が情報が多く、購入したセンサーの利用例もすぐに見つかりました。後追いは楽ですね。

ネットでは、実用化というよりもおもちゃとして作成されている方が多いように見えます。スマート農業におけるIoT機器の一躍を担っているので、すべてがおもちゃと片づけるわけにはいかないのですが、入り口が低くなってファンが増えているのは確かなようです。古参からすれば薄い「にわか」でしょうが。

MEMS を触って、C に触れた今がちょうど良いタイミングだったということでしょうね。
ま、おもちゃでも役に立つかもしれないなら試してみましょう。


2022年9月20日火曜日

3D display

3D display のデモがありました。

知らなかったのですが、既に2年以上前から裸眼での 3D display が販売されていたようです。いくつかの表示方式があるようですね。今日はそれらの中から最新版を体験。

驚きました。
画面から飛び出しているように見えます。VR ゴーグルを使わなくても、立体視ができます。面白い。

先輩が FBX のデータを持ち込まれました。
これは面白かった。トイカメラを覗いているようで、建物、橋、車が立体的に見えます。広い範囲を映したり、極手前にオブジェクトが来るような配置だと 3D 映像が崩れてしまいますが、そこそこの距離を保てば立体感抜群でした。

1枚の写真データからでも 3D 化できるということでしたの、地形の写真も試しました。が、これはダメ。専用ソフトのアルゴリズムがあっていなかったようで、高さがチグハグでした。2枚の写真で空中写真判読をする時のように並べると、正しく表示してくれるのかもしれません。

面白いのですが、仕事に有効かといわれると ???。
地形がダメでしたので、VR の代用くらいしか思いつきません。もう少し安ければ FPS 用に買えますが、まだまだお高い。

展示用に1台ですかね。 


2022年9月11日日曜日

open.intel

OSS の領域に Intel さんが参戦していたとは知りませんでした。

open.intel
https://github.com/intel

色々あります。
intel-extension-for-pytorch は気になりますね。当然ながら、CPU をうまく使うアプローチです。既存のGPU版とどちらが早いのでしょうか。

Intel Extension for Scikit-learn はありがたい。
https://github.com/intel/scikit-learn-intelex
https://medium.com/intel-analytics-software/save-time-and-money-with-intel-extension-for-scikit-learn-33627425ae4

(Note: The extension contains scikit-learn optimizations that were originally in the daal4py package, but it was decided to extract them into a separate Python package: scikit-learn-intelex. All future updates for scikit-learn will be available only in Intel Extension for Scikit-learn. We recommend using scikit-learn-intelex instead of daal4py.)

Intel oneAPI Data Analytics Library を使うとも書かれています。
https://github.com/oneapi-src/oneDAL

conda install scikit-learn-intelex を打ち込めば、 daal4py, dal も同時に install されました。daal4py が必要なのは説明と異なるようにも思えましたが、完全分離とまではいかなかったのでしょう。共通する部分は daal4py に残しているのかもしれません。

早速 SVC の example を動かしてみました。
が、import error を吐きます。
issue で検索すると、2021.6から修正されているようです。pip には上がっていますが、conda にはまだ上がってないとのこと。18日前の情報なので、これでしょう。issue 内の対応通り Scikit-learn を 1.0.2 に downgrade したら読めました。 conda に登録されたら、すべて update しましょう。

結果は歴然。学習時間は約1/9になっています。
extentionなし:877.6s
extentionあり:98.5s

予測が12倍。これは嬉しい。
extentionなし:13.4s
extentionあり:1.1s


xgboost, LightGBM も高速化されているようです。https://www.xlsoft.com/jp/blog/intel/2021/08/05/improve-the-performance-of-xgboost-and-lightgbm-inference/

これらは速いので、恩恵は Scikit-learn よりもかなり小さいでしょうね。いずれ、試してみましょう。


2022年9月10日土曜日

pybind11

手は動かしていませんが、忘れそうなのでメモ ( ..)φ

pybind11
https://github.com/pybind/pybind11

pybind11 is a lightweight header-only library that exposes C++ types in Python and vice versa, mainly to create Python bindings of existing C++ code. Its goals and syntax are similar to the excellent Boost.

C++ 側の書き込みは最低限で、私のような初心者でもわかりやすいのがgood!
ネットの書き込みを見ていますと、Python 側の list は C++ 側の vector や list に変換してもらえるとのこと。オーバーヘッドも Cython より小さくなりやすいと評価される方もいらっしゃいました。

本当ならありがたい。まずはこれらから確認してみましょう。。


2022年9月8日木曜日

カメラの位置推定

後輩君がマネージャーからの指示で点群を触っていました。

マネージャーがうまくビジョンを伝えられていないようで、指示を受けた内容に対し手を動かして少しづつ進んでいる状態のようでした。私も何度かマネージャーから話を聞きましたが、着地点から逆算できるような筋の通った説明は得られませんでした。これだとルートを考えられないので、指示をこなすしかありません。どちらかというと、後輩君の方が問題の本質と解決手段を理解しているような印象を受けましたが。

その中で、sfm の逆のように点群と画像からカメラ位置と角度を推定したいという要望を聞きました。これ、知らなかったのですが PnP 問題と呼んでいるそうです。
この辺とか https://daily-tech.hatenablog.com/entry/2018/01/21/185633 この辺が https://daily-tech.hatenablog.com/entry/2018/03/22/022218 わかりやすい。

ひずみを取る、既知点の座標を 2D & 3D から指定するという手作業が発生しますので、完全に機械化はできないのでしょう。簡単なモデルだと自動でできるようですが、限られているでしょうね。

OpenCVでは実装されているようです。種類が多い。https://docs.opencv.org/4.x/d5/d1f/calib3d_solvePnP.html

ま、後輩君なら大丈夫でしょう。


ArcGIS Proに入れない

朝、後輩君から「ArcGIS Pro に入れません」と報告を受けました。

画面を覗くと、サブスクリプション関連のエラーが吐かれています。
そういえば、全社でライセンスを統合すると聞いていました。

社内外の担当に調べてもらって理由がわかったのがその日の夕刻。
原因は米国ESRIの統合時の処理方法でした。ライセンス統合作業を進めるために 日本ESRI と ユーザー側に連絡なしにアカウントを使えない状態にしてしまったとのこと。日本ではありえないのですが、海外なら普通にあるかもと思わせる出来事でした。

新しくアカウントを作り直せば入れるように設定できるため、後輩君にはそれで対処してもらいました。

試行錯誤を1日続けていたため、特に担当の方々はお疲れだったと思います。
ま、今後も起こるであろう問題への対処法をつかめただけ、良しとしましょう。


2022年9月7日水曜日

QGIS のリレーション

QGIS からは PostgreSQL 内のリレーションが見えませんでした。

が、それらを全く扱えないわけではないようです。https://docs.qgis.org/3.22/ja/docs/user_manual/working_with_vector/attribute_table.html#creating-one-or-many-to-many-relations

QGIS 内であらためてキーを設定することで、リンク先の情報まで地物情報に表示されるようになりました。

簡単ですが、惜しいですね。もう少しです。


2022年9月6日火曜日

QGIS + PostgreSQL + 日本語

一息ついたので、QGIS + PostgreSQL を実践しています。

用意したのはガッツリ日本語の入った csv。
以前購入していた図書を参考に、PostgreSQL が日本語にどこまで対応しているのか知りたいというのと、QGIS から PostgreSQL へデータを取り込む方法のトレースが目的です。後者は図書を読むまで知らなかったんですよね。

まずはSQL。
ジオメトリ作成は日本語 out。””ナシだとエラー。”緯度”というように””で囲むとエラーはかからなかったのですが、ジオメトリとして認識されませんでした。日本語でカラムを指定する方法がわからず、Lat, Lon で csv を書き換え。
csvを取り込む際に小文字変換のチェックがあったのですが、大文字だと引っかかるみたいですね。ま、キホン英数小文字というのはわかるのですが、何か日本語を通す書き方はあるのだと思います。
ALTER TABLE s_aaa.tb_bbb ADD geom GEOMETRY(POINT,4612);
UPDATE s_aaa.tb_bbb SET geom=ST_GeometryFromText('SRID=4612;POINT('||lat||' '||lon||')');
※この後、空間インデックス作成

型変換は日本語カラムOK。
ALTER TABLE s_aaa.tb_bbb
ALTER COLUMN "あああ" TYPE int4
USING "あああ"::int4
ただし、Python と異なって、nan を含む場合は float にも変換できませんでした。これも何かコツがあるのでしょう。

キーの指定は日本語OK。テーブル名、カラム名ともに日本語でも問題ありませんでした。


次にQGIS
csv を shpにするとカラム名が半角8文字でぶつ切りにされます。が、csv を PostgreSQL に取り込むと、問題ナシ。SQL でジオメトリを作ってから QGIS に持っていくと、長い日本語カラムでも欠かすことなく取り込めました。

QIS からは geometry を持つテーブルしか見えません。オブジェクトをクリックするとその属性が pop up され、さらに外部キーから参照テーブルの情報を表示させる、といった機能はなさそうです。これに期待していたので、もう少し探してみようと思います。

一通り触ってみましたが、QGIS の機能の多さにあらためて驚き。
SQL は使わないかな。QGIS 側で地理情報のみの表示であれば、Python で作ってしまった方が柔軟かつ速いと思います。

2022年9月4日日曜日

Infraworks2023でPLATEAU その2

続きです。

1) のテキスト置換を Python で組んだのですが、配布しても使えない方が多い。
ということで、C++で作ってみました。

といっても、C++ は初心者。既存のコードを読んだりコンパイルしたりしたことはありますが、書いたことはありません。久しぶりにプログラミングの入門書を買ってきました。
読んでみると、独学で振り落としてきた重要なパーツがちらほら。半分ほど読んでみましたが、勉強になりました。

で、ネットでコードを拾いながら3日かかって完成(Python なら1時間かからないのに)。特にパスの型が難しかった。意外と、欲しい情報がなかったので、図書を買ったのは正解でした。

python も C++ も、バッチファイルを書いて 2) の投影変換と連携させました。ダブルクリックで1)2)を済ませてくれます。できれば C++ で Java まで取り込みたかったのですが、今は実力不足。いずれ整理しましょう。いえ、そのころには PLATAEU で 全都市 FBX が整備されているでしょうね。

Infraworks2023でPLATEAU

Plateau のデータを WebGIS に載せるところまでは確認していましたが、それ以降、触っていませんでした。

少し面倒だったのであらためて手順を整理しておきたいと思っていたところ、社内でも同様の考えを持った方と遭遇。これを機に、整理してみました。

まずは Infraworks 等での利用。
fbx が配布されている場合は、迷わずそちらを選びましょう。
問題は、CityGMLしか配布されていない場合。以下の3手が必要です。

GML⇒
①GML内のアドレスを置換
②citygml-tools で直角平面に投影変換。
③FMEフリー版でIMXへ変換(axis=2,1,3)
⇒Infraworks

1)GML内のアドレス置換

3D都市モデルのデータ変換マニュアル
https://github.com/Project-PLATEAU/Data-Conversion-Manual-for-3D-City-Model

ただし、i-UR1.4は2021年9月にi-UR1.5に改定されました。これに伴い、URLが変更されました。そのため、本ソフトウェアの利用にあたり、3D都市モデル(CityGML形式)及びソフトウェアに記述された旧URLを新しいURLに更新する必要があります。具体的には以下の手順に従い、更新してください。

これは置換のみです。大量の GML データに対しては Python で処理しました。これを飛ばすと3)でエラーを吐きます。


2)citygml-tools で直角平面に投影変換

日本のデータの変換について
https://github.com/tokyo-digitaltwin/citygml-tools

現在、CityJSON-Tools が利用する空間参照系ライブラリでは、3D空間参照系間の参照系変換のための十分な環境整備ができていません。そのため、空間参照系の変換を行う際は、該当する2D空間参照系を利用して変換を行います。高さ方向は一般的に変換による差が小さいため、実用上変換は不要であるとして、垂直方向では元となるデータの値を変換後もそのまま利用します。以下で具体的なコマンドを上げて、変換方法を説明します。

投影変換にcitygml-tools を利用します。Javaの実行環境(JDKのインストール)が必要です。コマンドプロンプトから以下のコマンドを打つだけで変換してくれます。マニュアル通りにXYを入れ替えてもOK。

citygml-tools reproject --source-crs=6668 --target-crs=6677 --lenient-transform *.gml

※6677はEPSGコード。東京⇒JGD2011-9系⇒EPSG:6677

3)FMEフリー版

CityGML Importer for Autodesk
https://www.safe.com/citygml-importer/

メールが送られてきます。
・インストーラーは有料版と同じ。
・ライセンスファイルをリンク先から落として記載の位置に入れる。
・ワークスペースをリンク先から落として記載の位置に入れる。
・FME Quick Translator を起動。

記載の手順でRun。
Axis は「2, 1, 3」。
2)citygml-toolsで投影変換と同時に軸を入れ替えた場合は「1, 2, 3」


これでIMXファイルの完成です。
あとは Infraworks に取り込むだけ、ですが時間がかかります。
配布されている都市単位で1)2)が10分程度、3)が20分程度、Infraworksの取り込みが1.5時間かかりました。再表示も30分以上かかります。
取り込んでも建物全体が見えない地域もありました。変換ファイル数を少なくしてもダメな場合があり、変換かInfraworks 側かわかりませんが、まだノウハウがあるのでしょう。
それは追々。