Skip to main content

ロケット「アリアンV」の大失敗と数値フォーマット

Ariane V heavy-lift rocket - Image credit: ESA-CNES-ARIANESPACE

1996年、初打ち上げ時に離陸後数秒で自己破壊した、まだプロトタイプ寄りのアリアン5ロケット
画像提供: ESA-CNES-ARIANESPACE

組み込みコンピュータは、単純あるいは複雑な数学的関数を含むアルゴリズムで処理するセンサーデータを用いて、「リアルタイム」で制御を行います。機械が数字を処理する方法は、ミッション運営を成功に導くためにきわめて重要ですが、過去の苦い経験からわかるように、アルゴリズムにこだわりすぎた反面、数値の形で表されているような、面倒な要素をおろそかにすることに対し、慣れが生まれてしまうことがあります。

手を抜いたばかりに…

…3.5億米ドル相当のアリアン5型ロケットと、4つのクラスター衛星が、打ち上げから37秒後に失われたのは、1996年6月4日のことでした。全てが順調に進んでいるかのように思えましたが、はっきりとした理由もなく、ロケットは本来の経路から大きく逸れ始めます。明らかな制御不能状態を検知するとすぐに、自動自己破壊システムが作動しました。Ariane 501(アリアン5型ロケット1号機の通称)は、ESAの新たな重量級ロケットの飛行性能を証明することを目的とし、地球の磁気圏を調査するために設計された4機の衛星を載せていました。失敗の原因は、些細なソフトウェアのバグで、その冗長システムをうまく通り抜け、慣性基準装置をクラッシュさせたというものでした。最終的な結果は、元をたどってみると、人災にはよくあるような複数のエラーの連鎖により引き起こされていました。アリアン4のソフトウェアモジュールの再利用から始まっていて、このモジュールは、アリアン5の誘導システムと互換性がなかったことが判明しました。詳細についてはreport of the enquiry board (調査委員会による報告)を読んでいただくとして、以下に、何が起きたのか要約し、紹介します。

連鎖1: 古いコードの再利用

アリアン4から移植された慣性基準装置 (IRS) 用のソフトウェアが、加速度計 / ジャイロスコープを使用して角度と速度を計算し、その結果が64ビット浮動小数点形式で保存されました。ここまでは何も問題はありません。実際に、実証済みのソフトウェアモジュールを再利用することは、高信頼性・ハイリスク応用の世界では奨励されています。ですが、エンジンをジンバルに入れることで操縦を制御するオンボードコンピュータ (OBC) は、このモーション情報を、16ビット整数の形で受信することを想定していました。その当時の非技術系のマスコミはこの形式の違いに飛びつき、怠慢な技術者がこれに気づかず愚かなミスを犯したのだと強くほのめかしました。このようにミスは起こりましたが、それほどあからさまなミスではありませんでした。

連鎖2:憶測を立てる

ソフトウェア技術者は、形式の相違を見逃したわけではありませんでした。さらに、これに対処するために、IRSソフトウェアに変換ルーチンを加えました。ただ、最初の実質的なエラーは憶測によるものだったのです。アリアン4の実際の性能データに基づいて、彼らは新しいロケットもほとんど同等の角度値 / 速度値 / 加速度値になるだろうと仮定しました。ここで参考にしたアリアン4の実際のフライトデータは、数字が16ビット整数形式の±32767の範囲を超えることがなかったことを示していました。彼らが知らなかった(おそらく誰も知らなかった)ことは、アリアン5の飛行中の速度 (基準装置が3次元の基準座標系で動作するため複数) が、その数字を超えるだろうということです。数値のオーバーフローが起こらないだろうと確信していた設計者らは、フォーマットコンバータの前に簡単なLimiter(リミッター)と呼ばれるコードを組み込むことを怠りましたが、もしも組み込んでいれば、オーバーフローを検出し、結果を最大有効値に「クランプ」していたことでしょう。性能は落ちますが、大事故発生の可能性は大幅に減らすことができたはずです。

連鎖3:通信断絶

打ち上げから最初の30秒間ほどは、数値のオーバーフローは発生しませんでした。しかし、変換コードが問題を報告する時点まで水平速度が増加した際、IRSが勝手にシャットダウンし、OBCに診断メッセージを送信しました。この段階で、コンピュータがエラーメッセージを正確に解釈し、冗長バックアップユニットに切り替えるか、少なくとも一部のデフォルトデータにフォールバックできていたら、まだ回復することは可能でしたが、どちらも行われませんでした。

連鎖4:冗長性の低いハードウェア

IRSハードウェアは複製され、ロケットへと搭載されました。残念ながら、ソフトウェアも同様です。そのため、第1ユニット同様、第2ユニットのシャットダウンも引き起こされました。それに応じてOBCは、様々な不思議な理由から、エラーメッセージを有効なデータとして解釈してしまいます。結果、ロケットは 90°逸れて水平方向に向かいました。OBCは存在していない状況を正そうという試みからエンジンをいきなり「オポジットロック」に入れるという賭けに出ましたが、OBCの誤解を考えると、こういった結果は不可避でしょう。

正しいフォーマットの選択

アリアン4に向けてIRSソフトウェアを書いたエンジニアらは、おそらくどの程度の精密さが角度計算や速度計算に必要なのかを分かっておらず、そのため安全策を取ってIEEE-754-1985 64ビット倍精度算術規格を採用することにしたのでしょう。これは、数字を小数点以下15桁以上の精度で扱うものですが、明らかにこれはやりすぎで、加速度計 / ジャイロスコープセンサ―がそこまでの精度で出力されていたかどうかは疑問が残ります。OBCの設計者は、実際のアリアン4からのテレメトリーデータの利点から、16ビット整数で十分に事足りるだろうと考えていたため、明らかに、OBCは64ビット浮動小数点数を受信すると想定していませんでした。より高速なアリアン5に32ビット整数を使用していたら、おそらく事故は回避できていたことでしょう。では、アリアン501に使用された特有のフォーマットをみてみましょう。

固定小数点数

最初期のマイクロプロセッサ、Intel 4004と4040は4ビット算術で作動しました。この後の8080 / 8085の登場が8ビット時代の幕開けのきっかけとなります。これは、1970年代後半に、ナショナルセミコンダクター社が16ビットPACE機を、Intel社が8086を発表するまで続きました。最近、市場は32ビットデバイスに支配されており、通常、ARM Cortexコアを搭載しています。また、ほぼすべてのPCが今では64ビットシリコンをマルチプロセッサコアで使用しています。膨大な数字を、細かな精度で扱う必要のないアプリケーションが多く存在するため、これらの開発すべてで未だに8 / 16ビット技術を採用し続けています。アリアンのOBCは、速度データを、Fig.1aにあるような16ビット整数の形式と考えています。整数には小数点部分がなく、固定小数点クラスの数字の特殊ケースなだけで、ここでは「バイナリポイント」が最下位ビットの右側あります。バイナリや、2進数にとって、このバイナリポイントは、小数点、または、10進数における小数点であり、整数部分と小数(1未満)部分の間の境界を示します。Fig.1aからわかるように、16ビット整数のみの数字は、0から65536までの範囲を符号無しの10進で表すことができ、符号付きの -32768から+32767までを、2の補数変換を用いて表すことが可能です。

Fig 1 - Fixed-Point Binary Numbers

時には、小数点形式で数字を表す必要がありますが、それでも単純な2の補数の符号付き算術を扱える能力を維持する必要があります。ここで、固定小数点により、これが容易に行えるようになります。Fig.1bをご覧ください。バイナリポイントを数字に沿って必要な範囲や、分解能になるまで移動させるだけです。広い範囲だと低い分解能になり、範囲が狭いとより細かな分解能になるというように、2つは常に両立できない関係性を持ちます。整数形式のFig.1aの例は極端なケースで、最大限に広げた範囲を分解能1で実現しています。 ここでは魔法のような手法は登場しません。バイナリポイントを左に移動させることで、ただ単にビット値(1、2、4、8など)を上げ、そのたびにより高い値(128、64など) を無くしているだけです。バイナリポイントは右端から始まるため、1回の左移動によって、表現できる最大値が半分になりますが、分解能を1ビットから ½ビットに増やすことが可能です。さらに移動させると、再び範囲は半分になりますが、分解法は倍の¼ビットになる、といったように、分解能を上げていくことが可能ですが、実際のところは、処理できる最大範囲は、以下のように、割り当てられたビット数によって制限されます。

  • 8ビットの数: (最大範囲)= 0~255または-128~+127符号付き
  • 16ビットの数: (最大範囲)= 0~65,535または-32,768~+32,767符号付き
  • 32ビットの数: (最大範囲)= 0~4,294,967,295または-2,147,483,648~+2,147,483,647符号付き

特定のアプリケーションに対してデバイスを選択している場合、速度と数値分解能の面での複雑な演算要件を満たす能力は、非常に重要な検討事項になります。それは、入出力に対する正確な仕様を持ち、一方を他方に変えるために処理がいくら必要かを知ることを意味します。例えば、

  • 7ビットASCII文字を入力し、プリンターに出力する前に書式設定を行うテキスト処理システムでは、Microchip PIC16のような8ビットマイクロコントローラ以上のものが必要になる可能性は低いです。
  • 高速サンプリングされたアナログデータの、本格的なデジタル信号処理が必要なアプリケーションでは、アルゴリズムにより少なくとも16ビット、 推奨としては32ビットが必要です。16ビットMicrochip dsPIC33のような専用マイクロコントローラはDSP作業に最適化されており、16 x 16から40ビットの積和演算を単一クロックサイクルで実行できます。

スケーリング

固定小数点数で計算を実行する際、特に乗算の場合は、すぐにオーバーフローが起こることがあります。ほとんどのプロセッサは、特殊なフラグビットがステータスレジスタにあるためオーバーフローを検出できますが、そのレスポンスとしては、エラーメッセージを伴った、所定のシャットダウンに限られるかもしれません。私たちはそれがどうアリアン501内で動作したのかを知っています。可能なソリューションとしては、数字を「スケーリング」し、それらを範囲内に収めておくことが考えられます。次の例では、2つの8ビット符号なし整数をそれぞれ2倍にスケーリングし、乗算した結果が16ビット範囲内にしっかりと収まる様子を示します。

スケーリング前 (括弧内10進相当):

FFh x FFh (255 x 255) = FE01h (65,025)
FFFFhの最大許容値 (65,535) に近く、後に続く操作はオーバーフローを招く可能性があります。そのため、それぞれの入力数を2で割ってから掛けてみます。

スケーリング後:

7Fh x 7Fh (127 x 127) = 3F01h (16,129)
結果は実際には4でスケーリングされているので、今度は2を掛ける必要があります。

3F01h x 2 = 7E02h (32,258)
乗算の最終スケーリング結果が出ました。しかし、確認として、スケーリングされた結果にもう一度2を掛けることで元の値に復元できるのでしょうか?

7E02h x 2 = FC04h (64,516)
おっと。何かがうまくいっていません。ですが、ここで理由を見つけ出すのは難しくはありません。入力数を2で割った際、整数の結果を生成していませんでした。255 / 2 = 127.5です。この0.5が無くなったことが、大きな違いをもたらしてしまいました。幸いなことに、これを解決するような、より良い方法があります。

バイナリポイント(BP)を移動:

まず、2進表記法に移ります。これは、BPを動かしたときに何が起こるかを確認するのが容易なためです。

1111 1111. x 1111 1111. = 1111 1110 0000 0001.(255 x 255 = 65,025)
BPに注目します。

ここで、2で割ってスケーリング(1ビット右にシフト)する代わりに、BPを1ビットに移動します。

1111 111.1 (127.5) 最下位ビット の値は2-1または ½ になります。

1111 111.1 x 1111 111.1 = 1111 1110 0000 00.01 (127.5 x 127.5 = 16,256.25)

乗算関数に変更はなく、同様の1と0のシーケンスを生成しますが、 ここで、BPを2段階左に移動してみます。前と同じく、スケールファクターを維持するためには、結果を2で掛ける必要があります。これはBPを1ビット右に移動するだけです。もう一度右に移動させると、開始値の65,025に戻ります。

1111 1110 0000 00.01 x 2 = 1111 1110 0000 000.1 (32,512.5)
正解!

1111 1110 0000 000.1 x 2 = 1111 1110 0000 0001.(65,025)
そして、確認もできました。

仕組みを理解するのは簡単です。16ビットの結果のFE01hはどの段階でも変わりませんが、BPだけが移動して、毎回値が変わります。ビットが「無くなる」ことはないので、100%正確な状態のままです。固定小数点形式では、範囲と精度のトレードオフに苦しみます。非常に大きな数字や、非常に小さな数字ではワード長が実用的なものではなくなるでしょう。

長年、 デジタル・シグナル・プロセッサ (DSP) には、ハードウェアでQ フォーマット固定小数点数を分数で処理するものがありますが、 より新しいデバイスでは、オンチップハードウェアを搭載するようになり、浮動小数点のような、非常に大きな(または非常に小さな)高精度数で作動するという利点があります。

浮動小数点数

浮動小数点数は単に1と0を書式化して集めたものではなく、パラメーターのセットで数式によって操作されるものです。これにより、非常に大きな高精度数を、比較的小さな物理ビットの数でエンコードすることが可能になります。浮動小数点数の基本式は、

S M x Beとなり、ここでMは仮数(英語でMantissa またはSignificand)で、 符号なしの整数です。B は基数(英語で BaseまたはRadix)で、通常2または10です。eは指数で、符号付きの整数です。

Sは符号ビットで、別に評価されます。

Mは1.x のフォームに正規化された数の数値です。

Bは指数の基数です。バイナリで作業している場合、B = 2で、10進形式で作業している場合は B = 10です。

eは符号付き整数で数の大きさを設定します。大きな数が正、小さな数が負です。

16ビット浮動小数点数の基本的なストレージフォーマットを、 Fig.2. に示します。IEEE-754標準が作成されるまで、原則に基づいた形式が各種誕生していましたが、どれもお互いに互換性がありませんでした。

Fig 2 - Floating-Point Binary Numbers

いつ浮動小数点を選択すべきか

浮動小数点ハードウェアを備えた32ビットマイクロプロセッサーが出る前は、大きくて複雑なデータセットを操作するのに、数値の、広いダイナミックレンジが必要なアプリケーションは、DEC PDP- やVAX-11のようなミニコンピュータか、メインフレームで実行していました。マイクロプロセッサはソフトウェア実装に依存しなくてはならず、しばしばCのような高水準コンパイラが含まれています。これがプログラム内でのライブラリの肥大化を招き、実行速度が非常に遅くなります。最近では、32ビットARM Cortex-M4 core microに、IEEE-754 単精度浮動小数点数 (FPU) が合うように拡張命令セット付きで含まれています。新しいBBC micro:bitコンピュータボード (201-2414) でさえ、これが付いています!固定小数点算術の日々はもう終わったと結論づけたい気持ちが非常に強くなりますが、大きな数字の処理を高速で行わないような、一般目的の応用には、あまり利点はないでしょう。問題は、浮動小数点がrounding errors(丸め誤差)のおかげで多くの数に対して近似しか生成しないことです。GPIOポートに送るために算術結果が正確な整数である必要がある場合は、固定小数点数 / 整数のほうがコーディングの手間が少なくて済むかもしれません。

最後に

アリアン501の大失敗に対する追記:
欠陥のあったコードモジュールは、ロケットが発射台を離れた時点から、全く目的を果たしませんでした。モジュールの唯一の機能は、打ち上げ前にシステムを連携することで、切られるべきでした。皮肉にも、カウントダウン中の短い待機時間に備えて、システムを再開しやすくするために、意図的に実行状態で保たれました。そうする代わりに…

特に何もすることがなかったら、ぜひ私のTwitterの投稿をフォローしてください。最新のエレクトロニクスや、関連技術についての興味深い記事を共有し、ロボットや宇宙探索、その他の問題についての記事を見つけてはリツイートしています。

Engineer, PhD, lecturer, freelance technical writer, blogger & tweeter interested in robots, AI, planetary explorers and all things electronic. STEM ambassador. Designed, built and programmed my first microcomputer in 1976. Still learning, still building, still coding today.
DesignSpark Electrical Logolinkedin