2025年2月12日水曜日

小ネタ


 なんか最近Delta Forceラグいなーと思ったら、Visual Studioが複数起動していると、デバッグ中じゃなくても、PCのリソースがそっちに食われるのな。いくつかVS閉じたらだいぶ軽くなった。



 #にじ若手女子マイクラ - YouTube

 本鯖はスプロール現象の見本みたいな状況で、いでぃおすもみんな遠くに拠点を作ったから交流が少ないとか、やはり歴史のある鯖なりの欠点もあるし。若手鯖は更地から期間限定で始めたから、アクティブな人数も多いし、拠点が近いから交流も盛んだし。

 主に七瀬すず菜視点で見ているけど、年上の新人の距離感が結構好き。

 にじさんじ、30代くらいの新人入ってこないかなー。兄貴姉御枠。ある程度人生経験のある人が入ってくると最近の新人と違う方向性で面白くなりそう。最近の若い新人との距離感が難しそうではあるけど。



https://www.jstage.jst.go.jp/article/itej1978/46/5/46_5_559/_pdf

 1992年。赤外線カメラに関する話。

 実用化された画素だと三菱電機が1987年に作った512x512が実用的なものとしては最初のものらしい。カタログスペック。640x480とか1040x1040の製品、60fpsの製品とか。

 この時代にはセンサやコントローラを一体化した8kgの製品があって、Heスターリングサイクルを使った80K冷却器を採用。撮影した画像等の例。

 天文観測用の赤外線カメラ。可視光はすでに固体化が進んでいる。赤外線はダストの影響を受けづらいため、新しい知見が得られると期待している。デュワー内を液体N2で冷却し、センサを固体N2で60Kに冷却。ノイズ対策の話とか。このあたりになるとトランジスタの発光現象なんてものも問題になるらしい。LEDだってPN接合だし、トランジスタでも光くらい出すか…… ググっても出てこないので普通の用途で問題になるようなレベルではないんだろうけど(あるいは、画素メーカーが対策のノウハウを企業秘密として報告していないだけか)。

 今後の展望とか。


https://www.jstage.jst.go.jp/article/sicetr1965/27/11/27_11_1199/_pdf

 1991年

https://www.jstage.jst.go.jp/article/sicetr1965/30/10/30_10_1151/_pdf

 1994年

 上は製鉄所で使うためのレベル計の試作。下はそれを地中レーダに応用した例。

 m系列を使用し、アナログ系の処理でパルス圧縮を行うための手法の提案。127チップから1023チップ程度のm系列を使ってパルス圧縮を行う。LFSRを2つ並べてクロックに微妙な差を与えることで、クロック差に応じて応答信号を時間方向に拡大(今回の例では4万倍程度)できるので、見かけ上の掃引時間を長くできる。例えばレンジ1.5mでは20ns程度の時間を処理する必要があるが、4万倍に拡大すると400us程度の時間になる。送信用のLFSRと受信用のLFSRの周期がわずかに違うから、送信と受信で位相差ができて、それが距離方向の掃引となる。

 地中レーダは表面から照射して往復させる場合と、細い穴2本にゾンデを入れてその間を画像化する。ゾンデはアンテナの直前でO/E変換、E/O変換を行って、電源は外付け。かなり細い穴で良さそう。

 スペクトラムアナライザの掃引みたいに目的のウインドウ(上記方式の場合は距離ゲート)以外の情報は捨てているから、使用可能な情報を漏れなく使うような方式ではないけど、大きな情報を遅延線なりデジタルメモリに保存しておく必要がないのが利点。特に近距離の電磁波伝搬みたいに短時間の現象を小リソースで引き伸ばすことができる。


https://www.jstage.jst.go.jp/article/jsmst/7/2/7_2_1/_pdf/-char/ja

 1995年。海底の地殻変動を観測することを目的とした、音響測距技術に関する話題。数kmで1cm程度の精度がほしい。バーストでも指向性のトランスデューサを使えば実現できそう。パルス圧縮の方式がいくつか。海底対海底と、海底対水面の方式。GPSを使う方法の説明で、Pコードのキネマティック観測みたいな話が出てくる。


https://www.eri.u-tokyo.ac.jp/GIHOU/archive/05_065-073.pdf

 1999年。日本で開発中の水中測距の機材。m系列よりFMチャープのほうが精度が高い、とのこと。アップチャープとダウンチャープで送受信を分離するんだそうだ。


***


 夜中にワンセグドングルでダイレクトサンプリングしてフーリエ変換

 0.5MHz2.4Mspsで-0.7MHzから+1.7MHzの範囲が見えている。2^22ポイントなのでコヒーレント長約1.7秒、それを32回インコヒーレント積分している。0Hzと500kHzのピークはDCオフセット成分。500-1600kHzあたりに色々入ってそう。


 一部を拡大

 左側の一部だけでも、567kHz札幌100kW、585kHz釧路10kW、596kHz東京300kW、612kHz福岡100kW、621kHz旭川3kW、666kHz大阪100kW、693kW東京500kW、702kHz北見10kW、747kHz札幌500kW、774kHz秋田500kW、828kHz大阪300kW、864kHz旭川3kHz/室蘭3kHz/遠別1kHz、891kHz不明、900kHz函館5kW、945kHz室蘭3kW、等々、ラジオ放送は色々ある帯域だけど、とはいえ屋内のマグネチックループアンテナをダイレクトサンプリングして、搬送波だけとはいえこんなに受信できるものかな? 1kHzの整数倍のスプリアスなんてどっからでも入ってきそうだしなぁ。

 試しに747とか774とか828をSDR#で再生してみたら、いかにもNHK R2っぽい内容(中国語講座的な内容)が聞こえてきた。うーん、じゃあ受信できてるのか……


 試しに40kHz付近を拡大してみたり、SDR#で40kHzをCWで聴いてみても、何もなさそう。さすがに無理か。波長が1桁長い分でアンテナ利得も下がるし、rtl sdr blogドングルはbias-teeが入っているからDC付近では電源に吸い込まれるという点もあるし。


 久しぶりにSDR#(以前ダウンロードした、最新版よりは少し前のやつ)を使ったけど、やっぱりこのUIめちゃくちゃ使いづらいなー。機能的にも不便だし。


***


 13.333kHzの搬送波を振幅変調したWAVファイルを作成。電波時計に聞かせてみたらちゃんと同期した。AGC含め4分かかった(AGCは15秒くらいなので3分20秒程度あれば受信できる)。JJYタイムコードは時分にはパリティがあるけど、それ以外(年日曜等)にはパリティはないから、自分が持っている時刻と明らかに違う時刻を受信したときは、多数決を取って誤り訂正するようなアルゴリズムになっているんだと思う。普段の時刻の修正が1フレーム(1分)で済むのは、自分が持っている日付と同じなら無視するだけで良いみたいな処理なんだろう。同じ日付で数分ズレ程度でも3フレーム必要だから、誤差の範囲(数秒程度)を超えると多数決を取るのかな。

 最初、イヤホンを近づけてみたんだけど、全く受信しなかった。信号強度のアイコンが周期の長い(30秒程度の)フェージングみたいな変化の仕方だったけど、これはWAVの再生を止めても同じような傾向があったので、本物のJJYを受信していたんだと思う。逆に言えば、イヤホンからは本物のJJYより弱い強さでしか漏れないらしい。そもそもコイルが小さいから磁束が小さいのかな。スピーカーだとコイル径が大きいから磁束もそれなりに大きそう。イヤホンとスピーカーじゃ音量が全く違うから、電力(=磁力強度)にも大きな差があるだろうし。

 時刻信号は任意に設定できるので、1月7日8時40分頃のLS1,LS2を適当に設定したデータを作成。LS1=LS2=1でうるう秒(60秒)の挿入、LS1=1,LS2=0でうるう秒(59秒)の削除、となるが、前回の腕時計およびカシオの置き時計のどちらも、うるう秒の表示には非対応だった。安物の腕時計はともかく、家庭用とはいえカシオの置き時計でもうるう秒は非対応なんだな。うるう秒に対応した電波時計って結構レアな存在?

 腕時計はAGC除いて3分(3フレーム)で受信を完了する。カシオの時計はそれより大幅に長い時間が必要。感度が悪いのか、多数決でより多くのサンプルを集めているのか。コイルが大きい分、勾配の大きい電磁場だと感度が悪くなる、みたいな可能性はありそうだけど。


 今回使用したスピーカーはUSBで電源を取るタイプ。めちゃくちゃノイズが大きい。試しに電源をUSBハブからモバイルバッテリーに変えたら、ノイズがほとんど消えた。やっぱりUSBって電源ガタガタなんだろうな。


 電波時計の「うるう秒」対応について | CASIO

 うるう秒挿入以降、時計は1秒進むことになりますが、その後強制受信や自動受信に成功すれば正しい時刻に合わせることができます。

 GPSハイブリッド電波時計も同様に、強制受信や自動受信に成功すれば正しい時刻に合わせることができます。

 要するに自動的に調整はしてくれないらしい。JJYもGPSもうるう秒の予定は放送してるのに、使ってないんだな。

 最近のカシオのGPS電波時計については、毎年6月と12月にGPSのうるう秒挿入予定を受信することで、うるう秒を処理できるらしい。ただ、「うるう秒の情報を受信するには最大13分かかる」と書かれているのが不自然。時計がリセットされたあとにGPS時刻とUTCのオフセット(うるう秒の発生回数)を受信する必要はないんだろうか? うるう秒の挿入を見逃さなければその間は問題ないから、EEPROMに焼いておけばOK、みたいなことなんだろうか。うるう秒を1月と7月にいれるのは慣例的にそうしているというだけであって、地球の自転速度が極端に変化した場合は他の月にも挿入するだろうから、そういう場合はカシオのGPS電波時計は困りそう。まあ、あと10年の間に1年に3回とか4回とかうるう秒をいれるような事態も起きるまいし、実用上は問題ないだろうけど。


***


 GPSのアルマナックってどれくらいの精度があるんだろうか。200N 20.3.3.5.2.1によると通常900m、短期的に3.6km、長期的に300km、みたいに書いてあるけど、軌道要素が300kmずれるって相当な時間が必要なはずでは。long-termってどれくらいの時間を想定しているんだろうか。

 アルマナックの精度がaf0/af1含めてトータルで100m程度に収まっているのであれば、直接C/Aコードを捕捉できそうだけど、ちょっと精度が足りない? 無闇矢鱈に探索するよりはマシなのかもしれないけど。時間領域で探索するなら1msの中の数usをスキャンすればいいだろうから百倍くらい早くなりそう。周波数領域で探索するならコード位相は任意の位置を検出できるから、0.5us程度の精度がないと高速化には使えないはず。


 GPSの電離圏補正、太陽高度の季節変動(地球自転軸成分)ってどういう扱いになっているんだろうか。


 試しに電離圏補正の量を画像化




 6時間毎に、方位0度 仰角90度で各地点の遅延量をヒートマップで表示している。

 なーんか違和感あるんだよなぁ。

 そもそも電離圏モデルって有効期間どれくらいあるんだろう? 振幅(AMP)と周期(PER)は時間の3次関数でモデル化しているから、時間が離れれば2乗とか3乗の成分が強く効いてくる。一つの係数はあまり長時間使うことはできないのかも? というか、AMP/PERってなんで3次でモデル化してるんだろうか。電離層ってそんなに変な動き方をするのかな。

 この係数はQZSから受信したものだから、日本周辺以外はうまくモデル化できていないという可能性もある。


 GPSから受信した電離圏補正値

 QZSに比べて緯度方向で平均的な感じがする。ただし東経180度と西経180度が不連続なのは同様。計算方法ミスってるのかな。

 なお、GPSで18ページ(SF4 SvId56 電離圏補正値)狙いで受信したところ、QZSからはSF4 SvId51が受信された(GPSではSvId51はSF5の内容)。QZSはSF4/5で送る内容がGPSから変更されているけど、電離圏補正を出すタイミングも変わってるのか。QZSからは電離圏補正は1分秒周期で出されているから、GPSの12.5分周期とはズレるんだろうけど、地味に不便。



 GPSのフルフレームの区切りの一覧

 左側にフルフレームの開始時刻を、右側に各フルフレームでのページの内容を書いている。

 任意の内容(e.g. 電離圏補正)を受信したい場合は、現在の時刻以降に始まるフルフレームを探して、そこに目的のページの時間を加算し、それに余裕を持った時刻から記録を開始し、開始時刻から30秒+余裕を見て記録を停止する。時刻の加算がちょっと面倒。



 GPSの復調で時々全衛星を一気にロストすることがある。IQファイルの開始位置をずらせばその分ロスト位置もずれるから、デコーダ側の問題じゃなくてIQファイルの問題(途中で1マイクロ秒以上データがドロップしたとか)だと思うんだけど、とはいえrtl_tcpから送られてくるバイト列をファイルに書き出しているだけだし、rtl_tcp側もエラーログとかは出してないし、問題ないはずなんだけどなぁ。


 GPS系時刻とファイル系時刻の差を、開始時を原点としてグラフ化

 ノイズの多いグラフはDLLの相関値(コヒーレント長25ms)を、破線は時間差(ミリ秒)を示している。時間差が傾いているのはドップラ成分のはず。トラッキングのロストとか再捕捉の処理は作っていないので、30秒を1組としてDLLの同期やメッセージの復調を行っている。

 相関値が高く出ている部分は正しく復調できていると考えられる部分。200秒付近の2箇所や1200秒付近の2箇所、1800秒付近の相関値が落ち込んでいる部分が衛星をロストした部分。

 相関値が下がった部分で時間差が不連続になっている。やはりファイルが不連続になっているのが衛星ロストの原因っぽい。じゃあファイルが不連続になる原因は何だ、という話になるけど。


 SDR#からUSB接続でサンプリング

 こっちはバージョンが古くて2GiB未満しかサンプリングできないので2.4Mspsだと450秒(7.5分)程度しかサンプリングできないけど、不連続無く受信できているっぽい。あるいは確率の問題かもしれないけど。


 rtl_tcp経由で、1920kspsでサンプリング(以前は2.4Msps)

 とりあえず15分程度ではドロップはなさそう。2048kspsだと10分で1回ドロップしたっぽいので、ビットレートが高くなるとバッファの書き込みが追いつかなくなるのかな?


 なんとなく、rtl_tcp.exe(rtlsdrblog,v1.3.6)ないしそれに使っているライブラリのバグっぽい感じなのかな?

 ISDB-Tで遊んでいたときはIQファイルの不連続性は全く気にならなかったはずなんだが。Mode 3の1フレームが約1msとしても、フィードバックは1フレーム毎に1サンプル分(約0.5us)シークする程度の処理だったはずだから、10usとかズレたら吸収しきれないはずだし、おそらくIQサンプルのドロップは発生していなかったはず。 

 ISDB-Tはちょうど1年前(’24年2月)頃まで遊んでいたはずだから、その当時はrtlsdrblog版のrtl_sdr.exe系はv1.3.4が最新版。1.3.5でレジスタの設定を変更したらしいので、そのあたりでなにかやらかしているのかも。今週は時間切れなので、次はバージョンを戻して試してみよう。

 あるいは、ISDB-Tは約2.03Mspsなので、かろうじてバッファが間に合っていた、という可能性もあるが。


***


 C#関連の愚痴など。


 span.Fillで構造体の適当な値を指定したときに、その値がゼロの場合、Clearを推奨されるの、まあわからないでもないけど、とはいえ、わざわざ構造体で指定しているんだから、Clearに変えるとあとあと構造体の中身を変えたときに困りそうな気がする。あとから構造体の中身変えるなよ、という話ではあるんだけど。


 C#のインクリメントって読み出したり書き込んだりのタイミングってどうなってるんだろうか。f(a++);でfの中から呼ばれるイベントでaを書き換えたら、一応期待通りの挙動(インクリメントする前の値を書き換えて、書き換えたあとにインクリメント)をしているけど、こういう挙動って使っていいんだろうか。CとかC++だとこういう挙動って避けたほうがいいとされているはずだけど、C#ならあんまり気にせず、期待した通りに動いているならそのまま使っちゃっていいのかな。


 LINQでvar a=foo.Where(a=>a.Flag);if(a.Any()){ aを使う処理; }みたいに、Whereの結果が1個以上を保証したいときに、一旦変数を作ってAnyを呼ぶのが地味に面倒なの、どうにかならないものかな。

 一応、拡張メソッドでpublic static bool WhereAny<T>(this IEnumerable<T> a,Func<T,bool>b,out IEnumerable<T>c)=>(c=a.Where(b)).Any();みたいなのを作ると、if(foo.WhereAny(a=>a.Flag,out var a)){ aを使う処理; }みたいに書ける。varに突っ込む1行を減らせる程度でしかないから、1,2箇所で使う程度なら拡張メソッドを書く分面倒だが。


 レコードのプライマリコンストラクタをprivateとかprotectedにアクセス制限したい。プライマリコンストラクタを書かず、public Type Hoge{get;private init;}とかで定義して、Deconstructも定義すればほしい挙動は作れるけど、面倒くさい。プライマリコンストラクタが無いとDeconstructで出てくる要素が見えないから困る、みたいな話はありそうだけど。


 readonly record structのプロパティがpublic initなの、withで書き換えることができるのが便利そうだけど、書き換えられると困るような中身が入っていると不便な気がする。自分でpublic Hoge Fuga{get;private init;}とか書けばwithで書き換えることはできないけど、面倒。Deconstructも書かなくちゃいけなくなるし。


 派生クラスの機能を基底クラスからしか呼べないようにする、みたいなことってできないんだろうか? 基底クラスの機能を派生クラスからしか呼べないようにするにはprotectedをつければいいけど、その逆をやりたい。

 生データのパーサーを書くときに、基底クラスのTryParseを呼び出して、フォーマットに応じて派生クラスのParseを呼ぶが、外部からは派生クラスのParseを直接呼べないようにする、みたいな状況。派生クラスからはさらに派生クラスがあって、基底クラスは派生型の派生型は知らなくても良い、みたいな実装にしたい。こんな処理いくらでもあるだろうし、C#で対応してないってことは別のやり方があるんだろうけど。基底クラスが派生クラスをすべて把握してなきゃいけない、ってのは設計的に問題がありそうだし。


 Addの無いコレクション(StackとかQueueとか)をスプレッド演算子で初期化できないのが地味に不便。拡張メソッドでAddを追加してやればスプレッド演算子で初期化できるけど、今度は普通のコードからもAddが見えるようになる。PushとかEnqueueの代わりにAddを呼んで特に不便があるわけではないけど。AddにObsoleteをつけるとスプレッド演算子にも警告が出る。第2引数をtrueにするとコンパイルエラーになる。その機能を使わせたくないわけだから、スプレッド演算子経由でも警告やエラーになるのは理解できるが。


 Windowsの端末ってConsole.Write($"\e[38;2;{r};{g};{b}m");で文字色を24bitで設定できるんだな。38じゃなくて48を指定すれば背景色を設定できるし、\e[mで書式をリセットできる。C#13でエスケープシーケンスを\eで書けるようになったので色の指定とかがだいぶ楽になってる。

 グラデーションを表示してスクショしてカラーピッカーで取ったら1文字毎に1変化するから、ちゃんと24bitで表示されているっぽい。

 Formを作るまでもないからConsoleで作りたいけどちょっとしたプログレスバーを表示したり、サチりそうなときはオレンジで、サチったときは赤く表示したい、みたいなときに便利そう。そこまでやるならFormで作れよ、という気もしないでもないけど。


0 件のコメント:

コメントを投稿