About this site
このサイトは、航空・宇宙コンピュータ電子工作といった時代の最先端のことから、登山といった文明生活から遥かにかけ離れたことまで、思うがままに書いてあります。写真も大好きです。
興味がある方にしかおもしろくないと思いますが、どうぞ楽しんでいってください。あと、MovableTypeのカスタマイズ情報を提供しています。

If you are interested in "Super Sylphide", an autopilot system for small UAVs, please visit this page.

Super Sylphide猫カメラGPSロガーXBee電力計


最後に、はてなアンテナやRSSリーダーで読む場合はこちらからどうぞ。
Entries @ recently

June 07, 2026

numru/fftw3とnumo/fftwをGithub actionsで使う

頭の体操を兼ねて、FFT(Fast Fourier Transform)の代表的なアルゴリズムであるCooley-Tukey(素因数分解して高速化)Bluestein(2のべき乗になるようゼロ埋め)をRubyのgemであるgps_pvtFFT.hとして実装してみました。正しく実装が行われているか比較するためにFFTライブラリとして著名なFFTWとの比較をしようと思い、Rubyのnumru/fftw3(パッケージ名はruby-fftw3)、およびその近代化版であるnumo/fftw(同numo-fftw)と比較をしてみることにしました。Rspec上にてfft_spec.rbでFFT結果の比較をしてみています。

対応するGithub Actions用のCIスクリプトも作りました。テストをパスさせるうえでいくつか嵌った点があるので、ここに書き残しておこうと思います。

まずGithub Actions上でnumru/fftw3とnumo/fftwを標準的なRubyインストールアクションであるruby/setup-ruby@v1にてbundle installさせるために、少々ビルドを外から助けてあげる必要がありました。CIスクリプト上でBUNDLE_BUILD_XXXという環境変数を設定することで、共有ライブラリのパスやファイル名(-l:narray.soとすると標準(=libnarray.so)でないファイル名のライブラリにリンクできる、ldのmanの-lオプションに記載)、コンパイルオプション(narrayは古いのでgcc-15以降でもビルドするには-std=c17が必要)を教えてあげるようにしています。この環境変数はbundle config setでのビルド設定と同様の効果をもたらします。またこの環境変数の命名規則ですが、_(アンダースコア)が2個で.(ドット)に、_が3個で-(ハイフン)になるという仕様があり、ドキュメントに書いてある(Credentials For Gem Sourcesの最後のほう)ものの、気が付くのに時間がかかりました。

次の嵌りポイントはWindows環境におけるFFTWライブラリの調達です。pacmanを使っても良いのですが、最新版を追えてなさそうなのでvcpkgでセルフビルドするようにしました。ビルドを毎回しなくてよいよう、TAServers/vcpkg-cache@v3にてキャッシュも効かせてあります。

最後にWindowsでの嵌りポイントです。numru/fftw3はnarrayパッケージのnarray.soを、numo/fftwはnumo/narrayのnarray.soを参照します。同時に使おうとすると、共有ライブラリ(.so)の内部が違うにもかかわらず、同じ名前(Windowsではパス全体ではなくファイル名しか見てくれない)によりシンボル解決ができず、死にます。gdbで動きをおってみた(こちらのリンクにあるsls(Show Loader Snaps)のビットを立てると十分なログが取れる)ところ、下記のようなエラーがでていました。

warning: 144f4:b6b8 @ -1382925171 - LdrpNameToOrdinal - WARNING: Procedure "na_data_type" could not be located in DLL at base 0x00007FFFD1280000.
warning: 144f4:b6b8 @ -1382925156 - LdrpReportError - ERROR: Locating export "na_data_type" for DLL "C:\Tools\Ruby\Ruby34-x64\lib\ruby\gems\3.4.0\bundler\gems\numo-fftw-d89821146b5c\lib\numo\fftw.so" failed with status: 0xc0000139.

仕方がないので、ライブラリごとにプロセスを分けて比較をします。といってもWindows環境にはforkがないので、別プロセスをopen3(内部的にはspawn)で立ち上げて、drbで通信をしてFFTの結果だけ取り出すことにしました。

技術的に色々細かいこと(特にWindowsの共有ライブラリまわり)を知れたのが良かったです。

00:05 fenrir が投稿 : 固定リンク | | このエントリーを含むはてなブックマーク | コメント ←ここから投稿できます!! | トラックバック (0)
このエントリーのトラックバックURL: https://fenrir.naruoka.org/mt/mt-tb.cgi/965

August 11, 2025

Ruby 3.5のRactorでyield/takeを復活させる

Ruby 3.5(現時点では3.5-dev)で並列実行機構であるRactorの仕様が大きく変わりましたRactor::Portという通信経路が定義され、別実行されるRactorの外から中への内向き通信経路がRactor#default_portでとりだせるRactor::Portで管理されるようになりました。従来からあるpush型の通信関数であるRactor#sendRactor.receiveもdefault_portと紐づけられています。

一方、pull型通信であるRactor.yieldRactor#take(3.4のドキュメントへのリンク)がなくなってしまいました。いちおうtakeは3.5でも残されているのですが、2025/8に除去します、と警告が表示され、また対になるyieldがないので並列実行途中(終了時ではなく)に出したメッセージを取得してくれません。

調べてみたところ、Ractor::Portの提案には3.5でも動くとされる代替策(Ractor.yield and Ractor#take with channel ractor)が記述されているのですが、これが実装ミスでうまく動きません。主な原因として、Ractorのインスタンス生成がinitializeを呼び出さずnewだけで定義されていることによるものと思われます。

そこでRactor.yieldとRactor#takeを3.5でも動くようにしてみました。newされるときに外向きの通信経路をRactor::Portで新たに追加してあげています。またRactor#monitorで終了を監視するようにしました。

上記で手元ではRuby 3.4までのコードをそのまま使うことができています。

08:56 fenrir が投稿 : 固定リンク | | このエントリーを含むはてなブックマーク | コメント ←ここから投稿できます!! | トラックバック (0)
このエントリーのトラックバックURL: https://fenrir.naruoka.org/mt/mt-tb.cgi/964

July 14, 2025

RubyでRactor::Selectorを使う(C APIをRubyから呼び出す)

Rubyで並列処理をするにあたってRuby3から導入されたRactor(日本語のドキュメントが見つからなかったので英語版で…)を使ってみています。まだ試験的導入(Ractor入りのスクリプトを実行すると warning: Ractor is experimental, and the behavior may change in future versions of Ruby! Also there are many implementation issues.とでる)であるため、日々改良が重ねられているようですが、つーすを読んでみると隠し機能があることがわかりました。

Ractor間の通信があったことを補足するRactor::select(*ractors)という関数があるのですが、複数のRactorのメッセージを全て完了するのに、一つずつ減らしながらselectを何度も呼び出すのはオーバーヘッドが大きそうだということに気が付きました。内部的にはRuby 3.3, 3.4ではRactor::Selectorというクラスのインスタンスを生成して、そこにractorsを登録するような仕組みになっていますので、selectを呼ぶためにRactor::Selectorを作ります。もしRactor::Selectorが再利用できれば、オーバーヘッドを少しでも減らせそうです。

しかし残念ながらRactor::Selectorを直接RubyからいじるにはRubyをビルドする時にUSE_RACTOR_SELECTORをdefineする必要がありました。一方よく見てみると、rb_init_ractor_selector()というRactor::SelectorをRubyから見えるようにする関数も公開されていることがわかりました(Ruby 3.4では2567行目付近、3.3も同様の定義です)。

Rubyをビルドしなおすのも少々面倒なので、ここからはサブタイトルになっているRubyのC API(今回でいうとrb_init_ractor_selector)を呼び出すことを考えます。C関数を呼び出せるFFIまたはFiddleを使うことにしました。下記のコードで達成できます。Using Ruby's C API inside Rubyが参考になりました。

最後にもともとのRactor::selectの効率化ですがRactor::Selector#wait, #removeなどが定義されていますので、これを使って実現しました。

00:33 fenrir が投稿 : 固定リンク | | このエントリーを含むはてなブックマーク | コメント ←ここから投稿できます!! | トラックバック (0)
このエントリーのトラックバックURL: https://fenrir.naruoka.org/mt/mt-tb.cgi/963

July 24, 2024

HDL-AAX2 シャットダウンスクリプト

自宅NASのIO-DATA HDL-AAX2ですが、リモートでシャットダウンする必要があり、方法を検討しました。少し古い機種のHDL2-Aのシャットダウンスクリプトが見つかったのですが、それをそのまま適用することはできなかったので、少し改造して使うことにしました。

出来上がったのが以下のRubyスクリプトです。

mechanizeというwebの自動巡回を可能とするgem(クローラ)を使うことで実現しています。少し古いRuby(< 2.6.0)でも簡潔に書けるよう、Kernel#thenがない場合に備えて自己定義しています(古いRubyに最新の機能を入れ込むbackports gemKernel#yield_selfのコードを参考にしました)。

00:12 fenrir が投稿 : 固定リンク | | このエントリーを含むはてなブックマーク | コメント ←ここから投稿できます!! | トラックバック (0)
このエントリーのトラックバックURL: https://fenrir.naruoka.org/mt/mt-tb.cgi/962

July 04, 2024

曜日を求める(8bit範囲で)

マイコンを使って年月日から曜日を求めたいケースがありました。普通の環境ならC言語を前提とすれば<time.h>にあるmktime関数とlocaltime関数を使うことで実現できます。

裏では曜日を求めるアルゴリズム(色々あります)のどれかを使って求めていると思います。


今回は対象がマイコンということもあり、機能を限定することでコンパクトなアルゴリズムに改変してみました。

sakamoto's methodを元にしました。日時範囲はGPS時刻を前提とすることで1980年以降とし、また2099年まで使えればよい割り切りをしています。すると、うるう年の計算が100で割り切れて400で割り切れない年を考慮する必要がなくなり、簡略化されました。また型を最小のunsigned charで統一してみました。


検証はRubyのRspecでやってみています。

上記CコードとRubyでのDate#wdayとの一致を見ています。なおテストの実装にあたっては、RubyInlineを使ってRubyの中でC言語コードを直接扱ってみました。

11:40 fenrir が投稿 : 固定リンク | | このエントリーを含むはてなブックマーク | コメント ←ここから投稿できます!! | トラックバック (0)
このエントリーのトラックバックURL: https://fenrir.naruoka.org/mt/mt-tb.cgi/961

April 02, 2024

Assisted GPS (A-GPS)クライアントの実装

GPS関係の処理をRubyから使えるようにしたgps_pvt gemは色々なストリームやファイル、シリアルポート(GPSデバイス直結)から情報を読み込めるようにしてあります。このたびv0.10で初期測位を早めるためのAssisted GPS (A-GPS)に対応しました。単独測位をするのであればgemをインストール後に以下のコマンドで例えばAndroidなどて使われているGoogleのサーバから情報を取得してA-GPSを利用できます。

$ gps_pvt supl://supl.google.com/ (Ntrip等のリアルタイムストリームを指定)

生データに近い物が見たければ、以下のコマンドでJSON形式でエフェメリス等が得られます。

$ gps_get supl://supl.google.com/

エフェメリス(軌道情報)を読み込む程度なので実装は簡単かなと思って始めたのですが、結果的に色々調べる必要がありました。羅列ですが、調べたものを残しておこうと思います。

SUPL
Secure user plane location。A-GPSの事実上の標準実装(という理解)。プロトコル名としてはUserPlane Location Protocol(ULP)。表面を覆っているのがULPで、中身のペイロードにはLPPやRRLPといった別のプロトコルが使われる。実装例が少ない中、tajuma/suplgoogle/supl-clientが参考になった。
LPP (TS 37.355)
LTE Positioning Protocol。エフェメリスなどの定義がある。GPS以外の定義もしっかりされている。
RRLP (TS 44.031)
Radio Resource Location service Protocol。LPP同様エフェメリスなどの定義があるが古めの規格。プロトコルとしてはGPS以外も使えそうに見えるが、GoogleのSUPLサーバに問い合わせてもGPSのエフェメリスしかくれない模様。
ASN.1 (X.680)
Abstract Syntax Notation One。ULP, LPP, RRLPなどの文法は全てこれで書かれている。Rubyにも主にSSL証明書をパースする目的でOpenSSL::ASN1の実装があるが、機能が限定的で今回は使わなかった。代わりにRubyの構文解析ツールであるRaccを使う前提で文法asn1.yを定義し、asn.1形式の文法ファイルをパースできるようにした。asn.1をasn1.y(から作ったRubyコード)で事前にJSONに変換(upl.json.gz)して本番では利用している(rake upl.json)。Samayou Oharikuiの和文解説Gusztáv ADAMISさん(ERICSSON)のスライド(PDF)がとても参考になった。OSS NokalvaObjective Systemsも参考にした。
PER (X.691)
Packed Encoding Rules。SUPLではバイナリで情報がやり取りされるが、その時のエンコーディングルールにBasic Unaligned PERが指定されている。前述の参考資料にも解説あり。RSpecで(asn.1から変換した)JSONとPER間のテストを書いて検証した。

最後におまけとなりますが、SUPLサーバに対しては携帯のようにIMEIを渡すわけではなく、問い合わせホストのGlobal IPを渡すようにしてみています。

22:39 fenrir が投稿 : 固定リンク | | このエントリーを含むはてなブックマーク | コメント ←ここから投稿できます!! | トラックバック (0)
このエントリーのトラックバックURL: https://fenrir.naruoka.org/mt/mt-tb.cgi/960

March 17, 2024

HDL-AAX2の修理

自宅NASのIO-DATA HDL-AAX2から少し異音がしていたので確認してみたところ、ファンから異音が出ていました。そこで修理をしてみることにしました。

HDL-AAX_fan_before_Sunon.jpg

元々ついていたファンはSunonのHA40101V4-1Q01C-F99というファンでした。残念ながら全く同じ型番のファンを見つけることができませんでしたが、DC12Vで40mm角の10mm厚、回転パルス出力付きのものであれば交換可能だろうということで、違うものに変えてみました。選んだのはAINEX CFY-40SAです。

HDL-AAX_fan_after_AINEX.jpg

ぴったりはまりました。コネクタだけは加工する必要があって、秋月電子千石電商などで買えるJST XHシリーズの3ピンコネクタ(ハウジング:XHP-3, コンタクト:SXH-001T-P0.6)に付け替えています。

23:36 fenrir が投稿 : 固定リンク | | このエントリーを含むはてなブックマーク | コメント ←ここから投稿できます!! | トラックバック (0)
このエントリーのトラックバックURL: https://fenrir.naruoka.org/mt/mt-tb.cgi/959