**HN投稿:無人トンネルにおけるAM放送用FPGAウォッチドッグの形式検証**

2026/02/19 0:06

**HN投稿:無人トンネルにおけるAM放送用FPGAウォッチドッグの形式検証**

RSS: https://news.ycombinator.com/rss

要約

Japanese Translation:

改良版概要

本プロジェクトは、Red Pitaya STEMlab 125‑10 をベースにした 12チャネル AM ラジオ放送システム を提供し、無人トンネル環境での緊急警報を目的としています。各チャネルは FPGA ベースの数値制御発振器(NCO)を用いて 500 kHz から 1.7 MHz の動的搬送周波数 を生成し、最大 12 チャネル同時に 505–1605 kHz の搬送波 を出力します。設計は MVC アーキテクチャを採用しており、Rust/Tauri バックエンド がハードウェアを制御し、JavaScript フロントエンド はステートレスな UI を提供し、FPGA の状態確認(SCPI コマンドを

/dev/mem
経由で送信)後にのみ更新されます。ハードウェア機能としては、チャネルごとの NCO、16 384 サンプル音声バッファ(約 5 kHz)を備えた AM モデレーター、活性チャネルに応じて動的にパワーをスケールする制御、および GUI のハートビートが 5 秒 停止した場合に RF 出力を停止させるウォッチドッグがあります。SymbiYosys + Z3 を用いた形式検証では、縮小パラメータ(
CLK_FREQ=1
TIMEOUT_SEC=5
)で 14 の安全プロパティ(さらに 6 のカバレッジシナリオ)が証明されています。SCPI サーバー(
am_scpi_server.py
)は TCP/SCPI コマンドを FPGA レジスタ書き込みへ変換し、音声再生ループ(
axi_audio_sequence_loop.py
)は 3 本の WAV ファイル(アラーム・パート 1・パート 2)を約 5 kHz で BRAM に循環的にロードします。デプロイ手順は、リポジトリをクローンし、Node.js + Rust/Tauri で GUI をビルド、Red Pitaya 上で
/dev/xdevcfg
経由でビットストリームをロード、SCPI サーバーと音声ループを起動、その後ローカル GUI を実行して接続・放送するという流れです。推奨使用は 1–2 チャネル で優れた信号品質、4–5 チャネル まで安定した受信、8 チャネル以上 は増幅が必要または弱い信号を許容する設定になります。完全な SCPI コマンドセットには
*IDN?
STATUS?
OUTPUT:STATE ON/OFF
CHx:FREQ <Hz>
CHx:OUTPUT ON/OFF
SOURCE:MSG n
、ウォッチドッグ制御(
WATCHDOG:RESET
WATCHDOG:STATUS?
)が含まれます。トラブルシューティングでは、ビットストリームの再ロード、GUI 接続問題、音声ループ未起動、無効な WAV ファイル、弱い信号への調整、ウォッチドッグ発火などを網羅しています。将来の改善点としては、より大きな DDR/SD 音声バッファ、ギャップを排除する DMA ベースのストリーミング、すべて 12 チャネル用の外部 RF アンプ、さらに FPGA の状態空間最適化が挙げられます。

本文

AMラジオブレークインシステム

Red Pitaya FPGAを用いた無人トンネルでの緊急アラート送信に対応する12チャンネルAMラジオ放送システム。


特徴

FeatureStatus
12同時キャリア周波数
実行時周波数設定(ハードウェア変更不要)
事前録音済み音声によるAM変調
動的電力スケーリング
MVC構成 (Rust + JavaScript)
イベント駆動型pub/sub(イベントバス)
ステートレスUI – デバイスが真実源
ネットワークポーリング & 自動再接続
フェイルセーフハードウェアウォッチドッグ (5 sタイムアウト)
形式検証 (14プロパティ、6カバー、すべて証明済み)

アーキテクチャ

ソフトウェア層

  • フレームワーク:Rust(Tauriバックエンド)+JavaScriptフロントエンド
  • MVC + イベント駆動pub/sub
    • Model (
      model.rs
      ):
      NetworkManager
      がTCP/SCPI、デバイス状態、500 msポーリング、指数バックオフ付き自動再接続を担当。
    • View (
      view.js
      ,
      index.html
      ): ステートレス – 確認済みデバイス状態のみ描画し、ハードウェア状態を仮定しない。
    • Controller (
      controller.js
      ): ユーザー入力を処理し、イベントをバスへ発行。
    • Event Bus (
      event_bus.rs
      ,
      event_bus.js
      ): 中央通信チャネル;RustがTauriブリッジ経由でJSへイベントを送出。
    • State Machine (
      state_machine.rs
      ): IDLE → ARMING → ARMED → STARTING → BROADCASTING → STOPPING。中間状態により無効遷移を防止。
    • 真実源:デバイス(ソフトウェアではなく)。UIはハードウェア確認後のみ更新される。

ハードウェア層

  • NCO: 12個の数値制御発振器が505–1605 kHzのキャリア周波数を生成。
  • AMモジュレーター: 各キャリアに音声ソースを組み合わせる。
  • 動的スケーリング: 有効チャンネル数に応じて出力電力が調整される。
  • オーディオバッファ: BRAMに16,384サンプルの事前録音済み緊急メッセージを格納(~5 kHz再生速度)。AXIオーディオローダーで実行時ロード可能。
  • ウォッチドッグタイマー (
    wd.v
    )
    : GUIハートビート停止時に5 s以内にRF出力を停止し保持;オペレーターリセットで復旧。
  • SCPIサーバー (
    am_scpi_server.py
    )
    : Red Pitaya上で動作し、テキストコマンドを解析して周波数を位相増分へ変換し
    /dev/mem
    経由でFPGAレジスタを書き込む。

信号生成フロー

GUIクリック → invoke("set_frequency") →
model.rs が "FREQ:CH1 700000" をTCP経由送信 →
am_scpi_server.py が (700000 × 2³²) / 125 MHz を計算し phase_inc に変換 →
/dev/mem 経由でFPGAレジスタへ書き込み →
NCO がキャリアを生成 → AMモジュレーション → RF出力

形式検証

  • ウォッチドッグタイマーは境界モデルチェックとk‑インデクション(SymbiYosys + Z3 SMTソルバー)で数学的に正しさが証明。
  • 14の安全プロパティ(すべてPASS)+6カバースナリオ(すべて到達)。

プロパティ概要

#PropertyGuarantee
1リセットで全クリア
!rstn → counter=0, triggered=0, warning=0
2ハートビートがトリガーを防止ハートビートはカウンタをリセットし、triggered & warning を消去
3早期トリガー禁止
triggered ONLY when counter ≥ TIMEOUT_CYCLES
他のプロパティ省略

カバースナリオ

  1. トリガーファイア(カウンタがタイムアウトに到達)。
  2. ウォーニングのみ。
  3. 正確なタイムアウト境界。
  4. ラストセカンドハートビート。
  5. force_reset
    でトリガーからの回復。
  6. ウォーニング→トリガーライフサイクル。

実行例

cd fpga/formal/
sby -f wd.sby

期待出力:

SBY [wd_prove] DONE (PASS, rc=0)
    summary: successful proof by k-induction.
SBY [wd_cover] DONE (PASS, rc=0)
    summary: 6/6 cover statements reached.

ファイル構成

ugl_am_radio/
├── gui/
│   ├── src/
│   │   ├── index.html              # HTML + CSS
│   │   └── js/
│   │       ├── event_bus.js        # フロントエンド pub/sub + Tauri リスナー
│   │       ├── model.js            # Rust API呼び出し(ステートレス)
│   │       ├── view.js             # DOM描画
│   │       └── controller.js       # イベントハンドラ
│   └── src-tauri/src/
│       ├── main.rs                 # エントリポイント
│       ├── model.rs                # NetworkManager + DeviceState
│       ├── commands.rs             # Tauri コマンドブリッジ
│       ├── event_bus.rs            # Rust pub/sub + Tauri emit
│       ├── state_machine.rs        # 放送状態遷移
│       └── config.rs               # 定数
├── fpga/
│   ├── formal/
│   │   ├── wd.v                    # ウォッチドッグ+14プロパティ
│   │   ├── wd.sby                  # SymbiYosys設定
│   │   └── README.md               # 形式検証ドキュメント
│   ├── am_mod.sv                   # AM変調モジュール
│   ├── am_radio_ctrl.v             # 12チャンネルAMラジオコントローラ
│   ├── axi_audio_buffer.v          # AXI音声バッファ(BRAM再生用)
│   ├── nco_sin.v                   # 数値制御発振器
│   ├── red_pitaya_top.sv           # トップレベルFPGA統合
│   ├── sine_lut_4096.mem           # 4096ポイント正弦 LUT
│   └── watchdog_timer.v            # ウォッチドッグタイマー(本番用)
├── am_scpi_server.py               # SCPIサーバー(Red Pitaya上実行)
├── axi_audio_sequence_loop.py      # 音声シーケンスローダー(アラーム→パート1→パート2ループ)
├── alarm_fast.wav                  # アラーム音
├── 0009_part1.wav                  # 緊急メッセージパート 1
├── 0009_part2_fast.wav             # パート 2
├── requirements.txt                # Python依存(numpy)
└── README.md

チャンネル周波数(デフォルト)

ChannelFrequency
CH1505 kHz
CH2605 kHz
CH3705 kHz
CH4805 kHz
CH5905 kHz
CH61005 kHz
CH71105 kHz
CH81205 kHz
CH91305 kHz
CH101405 kHz
CH111505 kHz
CH121605 kHz

実行時に500–1700 kHzの範囲で調整可能。


ウォッチドッグ安全設計

  • 標準ウォッチドッグ:デバイスがハング → タイマーオーバーフロー → デバイス再起動。
  • 本プロジェクト用:GUIが停止するとカウンタがタイムアウトし、RF出力を即座に停止。操作員リセットまで無効化状態を維持。

理由:無人トンネルでのラジオ送信機を再起動することは危険であり、RF出力再開には必ず人的確認が必要。

安全マージン:GUIが500 msごとにポーリングし、5 sタイムアウト ⇒ 10連続ハートビート欠如でトリガー発生。


パフォーマンスメモ

Channels信号強度推奨
1–2優秀✅ 最良品質
3–4良好✅ 最大推奨
5–8公平⚠️ アンプが必要かも
9–12弱い⚠️ 範囲が短くなる

おすすめ:信頼性確保のため、最大4–5チャンネル使用。


SCPIコマンドリファレンス

CommandDescription
*IDN?
デバイス識別情報取得
STATUS?
完全デバイス状態確認
OUTPUT:STATE ON/OFF
マスター放送有効化/無効化
CH1:FREQ 505000
CH1周波数設定(Hz)
CH1:OUTPUT ON/OFF
CH1の有効化/無効化
SOURCE:MSG 1
音声メッセージ選択
WATCHDOG:RESET
ウォッチドッグタイマーリセット
WATCHDOG:STATUS?
ウォッチドッグ状態照会

使用手順

  1. Red PitayaへSSH
    ssh root@<RED_PITAYA_IP>
    
  2. FPGAビットストリームロード(最初のターミナル)
    cat /root/red_pitaya_top.bit > /dev/xdevcfg
    
  3. SCPIサーバー起動(同じまたは別ターミナル)
    python3 /root/am_scpi_server.py
    
  4. 音声ループ開始(第三ターミナル)
    sudo python3 /root/axi_audio_sequence_loop.py
    
  5. GUI実行:ローカルで起動、またはビルド済みバイナリを使用。
    gui/src-tauri/target/release/bundle/macos/*.app
    (macOS)や
    .exe
    (Windows)。

インストール

1. リポジトリクローン

git clone https://github.com/Park07/amradio.git
cd amradio/ugl_am_radio

2. GUIビルド

macOS

# Rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source $HOME/.cargo/env

# Xcode CLIツール
xcode-select --install

# Homebrew経由でNode.js
brew install node

# ビルド
cd gui
npm install
npm run build

Windows (PowerShell)

# Rust
rustup-init.exe (https://rustup.rs)

# Visual Studio Build Tools
# 「C++によるデスクトップ開発」を選択してインストール

# Node.js LTS
# https://nodejs.org からダウンロード

# インストール確認
rustc --version
cargo --version
node --version
npm --version

# ビルド
cd gui
npm install
npm run build

3. Red Pitaya設定

scp am_scpi_server.py root@<RED_PITAYA_IP>:/root/
scp axi_audio_sequence_loop.py root@<RED_PITAYA_IP>:/root/
scp alarm_fast.wav 0009_part1.wav 0009_part2_fast.wav root@<RED_PITAYA_IP>:/root/
scp fpga/red_pitaya_top.bit root@<RED_PITAYA_IP>:/root/

4. Python環境(Red Pitaya)

pip install numpy   # 音声ローダーのみ必要

テスト

  • Rust単体テスト
    cd gui/src-tauri
    cargo test
    
  • 形式検証 – 上記 Formal Verification セクション参照。
  • モックサーバー(GUIのみ)
    # ターミナル1 — モックFPGA起動
    cd gui
    npm run mock
    
    # ターミナル2 — GUI起動
    cd gui
    npm run dev
    
    GUIで
    127.0.0.1:5000
    に接続。

トラブルシューティング

ProblemSolution
電源投入後RF出力がないビットストリームを再ロード:
cat /root/red_pitaya_top.bit > /dev/xdevcfg
GUIが接続できないIP確認、SCPIサーバー実行中かチェック
音声なしでキャリアだけ音声ループ起動:
sudo python3 /root/axi_audio_sequence_loop.py
ファイルにRIFF IDが無い
ffmpeg -i input -ac 1 -ar 44100 output.wav
で再変換
信号が弱い有効チャンネルを減らす(最大4–5)
接続タイムアウトネットワーク・Red Pitaya電源確認
ウォッチドッグが予期せず作動ネットワーク安定性チェック、必要ならタイムアウト延長
link.exe
が見つからない(Windows)
「C++によるデスクトップ開発」付き Visual Studio Build Tools をインストール
cargo
が見つからない
Rust インストール後ターミナル再起動
npm
が見つからない
Node.js インストール後ターミナル再起動
xcode‑select エラー(macOS)
xcode-select --install
を実行

今後の開発者向け

  • 現状:全シグナルチェーンが機能;GUI切断時にRF出力停止。
  • 改善点:オーディオバッファを16,384サンプル以上拡張、DMAギャップ解消、4–5チャンネル超えで外部アンプ対応。
  • 主要ファイル
    model.rs
    ,
    am_scpi_server.py
    ,
    am_radio_ctrl.v
    .
  • 開発フロー:GUI →
    npm run dev
    ; Rustバックエンドは自動再コンパイル;FPGA → Vivado → 新ビットストリーム → SDカードへコピー。

作者

NameContribution
William Parkソフトウェア設計(GUI、MVC、イベントバス)、ウォッチドッグタイマー、形式検証
Bowen DengFPGA開発(NCO、AM変調、RF出力)

謝辞

  • UGL Limited – プロジェクトスポンサー
  • University of New South Wales – EPIプログラム
  • Robert Mahood (UGL) – エンジニアリング監督
  • Andrew Wong (UNSW) – 学術監督

最終版:2026年2月13日

同じ日のほかのニュース

一覧に戻る →

2026/02/19 3:37

**「宇宙的にユニークなID」**

## Japanese Translation: > **概要:** > 本文では、真にグローバルなユニーク識別子は衝突を避けるために極めて長くなるべきだと主張しつつ、実際には短いランダムIDや追加の複雑性を伴う決定論的分散アルゴリズムが有効であることを示しています。 > 宇宙の熱死(約 10¹²⁰ 回の演算)に先立つ計算上の物理制限から、絶対安全性を確保するには約 10²⁴0 の可能性―すなわち約 798 ビットの ID 空間が必要です。実務では、122‑bit UUID‑v4 が現実的データサイズに対して天文学的に低い衝突リスクを提供します。 > 中央カウンタや「Dewey」階層方式などの決定論的手法はオブジェクト数に対し対数スケールで拡張されますが、Binary、2‑adic、Token などの代替木構造アプローチは最悪の場合線形増加します。典型的な使用では多くの場合対数スケールで振る舞います。シミュレーションにより、数百万ノードの場合、最大 ID 長は異なる定数を持つ log n で伸びることが示されています。 > この結果から、長いランダム ID(理論上の安全性を確保するためには ≥798 ビット、実務では 122‑bit UUID)が採用されればグローバルな調整を回避し衝突リスクを無視できることが示唆されています。決定論的手法は追加インフラストラクチャを必要とし、ストレージや通信オーバーヘッドを増大させる可能性があります。また、署名・誤り訂正・バージョン管理などの補完策がシステム間でデータ整合性を維持するために必要になる場合もあります。

2026/02/19 6:18

女性用サイズ

## Japanese Translation: ## 要約 この記事は、米国の女性服のサイズシステムが壊れている―欠陥があり、一貫性がなく排他的である―と主張し、多様な体型を反映したカスタマイズ可能なサイズチャートへの移行を訴えている。 「バニティサイズ」が測定値を膨らませる一方、ラベルは変わらずに残っていることから、普遍的な基準が存在しないと指摘する。歴史データでは、標準サイズ8のウエストに合う女性は10 %未満であるにもかかわらず、多くの商品はそのテンプレートを前提として作られている。ブランドごとのチャートは大きく異なり、バスト・ウエスト・ヒップの範囲が混乱しやすい。また、オンライン注文ではサイズ不一致時に返品手数料が発生するケースもある。 このシステムの起源は1940年代に遡り、若い白人女性を基準としていた点でASTMも偏見を認めている。研究では2021‑23年の国立健康統計センター(NCHS)データと、2025年7月時点のマス・マーケット、ファストファッション、高級品を含む主要ブランドのサイズチャート(「レギュラー」と「プラス」サイズのみ)を用いた。著者自身が58件以上の身体測定値を収集しカスタムパターンを縫製した経験も示され、サイズミスマッチが明らかになっている。 この記事は業界に対して、ティーンエイジャーがトゥインからアダルト服へ移行する際に「年齢アウト」させる代わりに柔軟で包摂的なサイズ設定を採用し、返品率の低減・顧客満足度向上、データ駆動型サイズ提供へのシフトを促すべきだと訴えている。

2026/02/19 1:46

テイルスケール・ピアリレーは、現在一般利用可能となりました。

## Japanese Translation: **概要:** Tailscale は Peer Relays を一般公開し、すべてのプラン(無料 tier も含む)で高スループットと低レイテンシを実現できる本番用リレー経路を顧客に提供します。新しいリレーは静的エンドポイント (`--relay-server-static-endpoints`) をサポートし、AWS Network Load Balancer などの制限付きクラウドロードバランサーの背後で実行できるようにすることで、自動検出が失敗した場合にも機能します。 パフォーマンス向上はロック競合の削減と複数インターフェース間での UDP トラフィックの賢い分散によって実現され、クライアントは最適な経路を選択できるようになります。Peer Relays は従来のサブネットルーターに取って代わり、Tailscale SSH と MagicDNS を使用したフルメッシュ展開をプライベートサブネット内でも可能にします。 観測性はさらに強化されます。`tailscaled_peer_relay_forwarded_packets_total` や `tailscaled_peer_relay_forwarded_bytes_total` などのメトリクスが Prometheus 用に公開され、`tailscale ping` コマンドではリレー遅延、信頼性、および到達可能性が表示されます。この機能はすべての Tailscale プランで利用でき、CLI と ACL グラントを介して有効化でき、既存のリレー設定と共存するよう設計されているため、段階的に導入できます。 Peer Relays はエンドツーエンド暗号化、最小権限アクセス、およびシンプルな運用という Tailscale のコア保証を維持しつつ、テイルネット全体でインテリジェントかつレジリエントなパス選択を追加します。

**HN投稿:無人トンネルにおけるAM放送用FPGAウォッチドッグの形式検証** | そっか~ニュース