二足歩行ロボットを作る(7)
数字は落ちなかった、と書いた。測り直したら、数字も落ちていた
「Nでは書けない答えが返ってきた」と書いたあとで、測る道具に穴が2つ見つかりました
この記事に出てくる数値・結論は、すべてMuJoCo上のシミュレーションで測ったものです。実機による検証は経ていません。実際にロボットを組み立てて確かめた結果ではなく、計算機の中で起きたことである点をご承知おきください。
この連載は「専門家として正しさを保証する記事」ではなく、開発の実況記録です。うまくいかなかったことや、後から誤りだと分かったこともそのまま書いています。
この記事は9月半ばに書きました。公開の前に確かめ直したところ、本文の「推定器を入れて500Hzで回すと崩れる」という結果は、測る道具の穴だったと分かりました。道具を直して測り直すと、500Hzでも崩れません。
続けて、題の柱だった「実機相当」も測り直しました。押しの強さの探し方にも穴があり、それを直して測ると、数字も落ちていました。そこで題を書き換えています。書いたときの題は「数字は落ちなかった。落ちたのは「同じ結果が出ること」だった」です。
本文は書いたときのまま残し、その箇所に印を付けました。何が起きていたかは、最後の「あとで分かったこと」と「さらに分かったこと」に書き足しています。
6回ぶんの数字は、ある前提の上に乗っていた
ここまで6回かけて、押し出し限界、消費率、上限歩幅と、いろいろな数字を詰めてきました。前回の最後に書いたとおり、その数字は全部、ひとつの前提の上に乗っています。
立って押されても耐える力を測り、その場で足踏みするだけで余裕の何割を使うのかを測り、どこまで歩幅を伸ばせるかを測りました。どれも「この機体は歩けている」という前提から出てきた数字です。
この機体の制御は、シミュレータが持つ「正解の値」——骨盤がいまどこにあり、どんな速度で動いているか——を、誤差ゼロでそのまま読んでいます。実機に、それを教えてくれるセンサーはありません。
だから今回やることは決まっていました。正解を取り上げて、数字がいくつ落ちるかを測る。そのつもりでした。
数字は、ほとんど落ちませんでした。代わりに別のものが落ちました。「同じことをして、同じ結果になる」という性質のほうです。
そして「いくつ落ちるか」という問いには、数字で答えられませんでした。問いの立て方のほうが間違っていた、というのが今回の結末です。
※この「結果」は、あとで測る道具を直して測り直すと、成り立ちませんでした。数字も落ちていました(さらに分かったこと)。
「いくら損するか」を測るつもりで用意した実験が、「その聞き方だと答えは出ません」と返してきた回。実験が失敗したんじゃなくて、実験が答えを出したのだと思う。
この機体は「正解を教えてもらいながら」歩いていた
シミュレータの中では、骨盤の位置も速度も、計算した本人が知っています。誤差はゼロです。制御はその値を直接読んで、次の一歩をどこに出すかを決めていました。
実機にはそれがありません。実機で分かるのは、IMU(傾きを測るセンサー)が返す姿勢と、各関節が返す角度だけです。骨盤が床に対してどこにいるかは、そこから推定するしかありません。
推定は当たり続けません。足が少し滑れば、そのぶんだけ現在地の見積もりがずれます。そしてずれは、歩いている間ずっと積み上がります。誰も「いま本当はここです」と教えてくれないからです。
ずれた現在地のまま、次の一歩をどこに出すか決めます。出した足が思ったところに着かなければ、次の推定もまたずれます。この差を、今回はじめて測ります。
| 骨盤がどこにいるか | 誤差 | |
|---|---|---|
| シミュレータの正解値 | そのまま読める | ゼロ |
| 実機(推定器) | IMUと関節角から推し量る | 積み上がる |
測り方——1回だけ測らない
比べる相手を3つ作りました。
| 呼び名 | 骨盤の位置 | 制御の周期 |
|---|---|---|
| 正解値 | シミュレータの値をそのまま | 500Hz |
| 実機相当 | 推定器 | 250Hz |
| 推定器・高速 | 推定器 | 500Hz |
制御の周期が2つあるのは、実機のマイコンが500Hzで回れるとは限らないからです。1秒間に500回、全関節の指令を計算し直すのと、250回にするのとでは、要る計算力が倍違います。250Hzのほうが実機に近い想定です。
3つ目の「推定器・高速」は、実機にはない組み合わせです。推定器のせいなのか、周期のせいなのかを分けるために入れました。
それぞれについて、初期条件を7通り振って測りました。歩き出すときの骨盤の左右位置を、0mm、±0.5mm、±1mm、±2mmの7通りずらしています。
1回だけ測ると、たまたま出た数字を拾います。前回、0.25〜0.5Nの差に理屈まで付けて説明し、その差が測定のばらつきの幅と同じだったせいで撤回しました。だから今回は、先にばらつきの幅——以下「帯」と呼びます——を測ってから比べます。
平均は、ほとんど動かなかった
指標は「どれくらいの力で押されたら歩けなくなるか」の、4方向のうち最も弱い方向の値です。大きいほど強い。
| 構成 | 7条件で出た値 | 帯(ばらつきの幅) |
|---|---|---|
| 正解値・500Hz | 7回とも 5.50N | 0.00 |
| 実機相当・250Hz | 5.00〜5.75N ※あとで測り直し | 0.75 |
| 推定器・500Hz | 0.00〜4.50N ※あとで取り下げ | 4.50 |
正解値では、7回測って7回とも同じ 5.50N が出ます。帯はゼロです。
実機相当では出ません。同じ設定で走らせても、5.00Nのときと5.75Nのときがあります。
いちばん悪い条件を見ると 5.50N から 5.00N で、0.50N下がっています。ただし、これを「下がった」とは書けません。
実機相当の帯は0.75です。0.50の差は、その帯の内側に収まっています。
つまり「下がった」とも「同じだった」とも言えません。正しい言い方は「この細かさでは、見分けがつかない」です。
前回はここを踏み外しました。幅0.50Nのばらつきの中にある0.25〜0.5Nの差に、原因の説明まで付けて報告しています。今回は先に帯を測ってあります。
※測り直すと、同じ物差しでも帯は0.50になり、0.50の差は「帯の内側」ではなく「帯と同じ幅」になりました。物差しを直すと、差は帯より大きくなります(さらに分かったこと)。
対照を足さなければ、推定器のせいにしていた
ここで一度、手が止まりました。
「実機相当」は、正解値から2つのことを同時に変えています。推定器を入れたことと、制御の周期を半分にしたこと。2つ変えたものを比べて、結果を推定器のせいにはできません。
そこで「推定器なし・250Hz」という、どこにも実在しない構成をわざわざ作って測りました。制御周期だけを変えた場合を見るためです。
| 変えたもの | 帯への効き |
|---|---|
| 制御の周期を 500 → 250Hz | +0.25 |
| 推定器を入れる | +0.00 |
| もう1つ(次の章) | +0.50 |
| 実機相当(合計) | 0.75 |
※測り直すと、「もう1つ」は+0.50ではなく+0.25、合計は0.50でした。周期の+0.25と推定器の+0.00は同じです(さらに分かったこと)。
推定器を入れても、帯は動きませんでした。広げていたのは別のものでした。
この測定の刻みは0.25です。「0」と「0.25より小さい何か」は区別できません。
言えるのは「この細かさでは動かなかった」までです。同じ話を、上でもしました。
対照を1本足して、まだ足りなくて、2本目でようやく分かれた。最初の表のまま書いていたら、犯人を取り違えた記事になっていた。
実機では読めない値が、もう1箇所だけ残っていた
帯を広げていたものの正体を書く前に、その手前の話をします。
「実機相当」と名乗るなら、実機で読めない値を1つも使っていないはずです。そこで制御のコードを1行ずつ全部見ました。残っていたのは1件です。
横方向のバランスを取る処理が、接地している足の裏の「本当の傾き」を、シミュレータから直接読んでいました。しかも条件つきではなく、体重を横に移している間じゅう、毎回です。
見つけたので、まず、どれくらい得をしていたのかを測りました。
| ロール | ピッチ | |
|---|---|---|
| ほとんどの時間 | 0.002° | 0.000° |
| いちばん外したとき | 0.446° | 0.609° |
小さい。理由もはっきりしています。この値は姿勢だけで決まり、姿勢はIMUと関節角から作れるからです。骨盤の位置の誤差は、ここには入ってきません。
これは「数値の欠陥」ではなく「出どころの欠陥」です。
測らずに「小さいから無視できる」と書くことはしません。
順番が肝です。先に測って、小さいと分かって、それでも実機で読めない値だから塞いだ——この順です。測る前に「小さいだろう」で片付けたのではありません。
そして塞いだ結果が、さっきの表の空欄でした。
| この1箇所 | 7条件で出た値 | 帯 |
|---|---|---|
| 開けたまま(実機では読めない値を使う) | 5.00〜5.25N | 0.25 |
| 塞いだ(実機相当) | 5.00〜5.75N ※あとで測り直し | 0.75。3倍 |
水準はほとんど同じで、帯だけが3倍になりました。この回の結論と、まったく同じ形です。実機に近づけると、落ちるのは水準ではなく決定性のほうでした。
※測り直すと、塞いだ側の帯は0.50で、「3倍」は「2倍」でした。そして物差しを直すと、水準も落ちていました(さらに分かったこと)。
「速いほうが良い」が、成り立たなかった
500Hzで崩れたのは、機体ではなく測る道具のほうでした。書いたときのまま残しています。くわしくはあとで分かったこと。
制御を速く回せば良くなる、と思っていました。
| 制御の周期 | 起きたこと |
|---|---|
| 250Hz | 決定性を失う(帯 0.75) |
| 500Hz | 機体を失う(帯 4.50。7条件のうち複数が完全に崩れる) |
推定器を入れたまま500Hzで回すと、条件によっては0.00N——つまり押す前に自分から倒れます。
なぜそうなるかは、まだ測っていません。「速いほうが良い」が成り立たない、という事実だけが出ています。ここに理屈を付けるのは、前回やって撤回した失敗そのものなので、やめておきます。
で、結局いくら失ったのか
250Hzでは決定性を失うだけで、水準は帯の内側。500Hzでは機体を失う。
※この答えは、前半も後半も、あとで取り下げました。後半の「500Hzでは機体を失う」と、下の「その大きさが制御の周期しだいで激変する」は、測る道具の穴でした(あとで分かったこと)。前半の「水準は帯の内側」は、物差しを直すと成り立ちませんでした(さらに分かったこと)。
「正解値を取り上げるといくら失うか」への答えは、数字では書けませんでした。
書けるのは、失うのは水準ではなく「同じことをして同じ結果になる」という性質だということと、その大きさが制御の周期しだいで激変するということの2つです。
この実験は「いくら失うかをNで測る」つもりで組みました。測った結果、Nでは答えられないと返ってきました。実験が失敗したのではなく、実験が答えを出したのだと思っています。
最後に——自分で書いた見出しを、自分で検算していなかった
この記事を書くために、実験のときの記録を開き直しました。そこで見つけたことを書きます。
同じファイルの中で、上と下が食い違っていました。
| 場所 | 書いてあったこと |
|---|---|
| 上の見出し | 帯を広げたのは推定器 |
| 下の表の中 | 帯を広げたのはあの1箇所(2日前に測り直した結果) |
反映し忘れた、という話ではありませんでした。
2日前に測り直して、撤回して、その結果を下の段に書いています。
そのあと2日にわたって、同じファイルの「上の見出し」のほうを引用し続けていました。
上が見出しで、下が表の中だったからです。自分のファイルの、要約のほうだけを読んでいました。
この記事は最初から最後まで、「その値はどこから来たのか」を1つずつ確かめる回でした。骨盤の位置はどこから来たのか。足裏の傾きはどこから来たのか。
要約が手元にあると、元のデータを開かなくなります。
それが自分の書いた要約でも同じです。むしろ自分のものほど疑いません。
似たことは、形を変えて起きます。開いていないのに開いたつもりでいる。開いたのに見ていない。そして読んだのに、要約のほうだけ読んだ。いちばん見つけにくいのは最後です。ちゃんと開いているので。
実験の数字は7回測って確かめたのに、その数字をまとめた自分の1行は1回も検算してなかった。順番が逆だった。
あとで分かったこと——500Hzの崩れは、測る道具の穴だった(2026-10-07 追記)
この記事を出す前に、書いてから3週間のあいだに取り下げたものが無いかを確かめました。ありました。
シミュレータの中では、推定器(骨盤の位置を推し量る仕組み)を、時間に合わせて少しずつ進めていく必要があります。ところが同じ道具が、設定によって進め方を変えていました。250Hzの設定では、制御の合間にも推定器を自分で進めていました。500Hzの設定では、制御が値を読んだときにしか進めていませんでした。
推定器を毎ステップ進めるように道具を直して、同じ7条件を、本文と同じ物差し(同じ押しの強さの探し方)で測り直した結果がこれです。
| 推定器・500Hz | 7条件で出た値 | 帯 |
|---|---|---|
| 本文(道具の穴あり) | 0.00〜4.50N | 4.50 |
| 道具を直して測り直し | 5.25〜5.50N | 0.25 |
7条件とも崩れません。「500Hzでは機体を失う」も、「速いほうが良い、が成り立たない」も、機体の性質ではなく道具の性質でした。
正解値の「7回とも5.50N」は、測り直しても同じでした。
一方、この記事の題の柱だった実機相当(250Hz)の帯0.75は、この時点ではまだ測り直していませんでした。押しの強さの探し方にも別の穴が見つかっていたためです。翌日に測り直した結果を、次の章に書きます。
本文では、500Hzで崩れる理由について「まだ測っていません」と書いて、理屈を付けませんでした。理屈を付けていたら、その理屈ごと撤回するところでした。そしてこの回の最後の章と同じく、確かめるべきだったのは数字だけではなく、その数字を出した道具のほうでもありました。
「値はどこから来たのか」を確かめる回だったのに、いちばん大きな数字の出どころは、測る道具そのものだった。書いたときのままにして、印を付けて出します。
さらに分かったこと——物差しを直したら、数字も落ちていた(2026-10-08 追記)
前の章を書いた翌日、題の柱だった「実機相当(250Hz)」も測り直しました。推定器を毎ステップ進める形にしたうえで、同じ7条件を、2つの物差しで測っています。
1つ目は本文と同じ物差しです。押しを1Nずつ強めていき、倒れたらそこから0.25N刻みで詰める探し方です。この探し方は、1N・2N・3Nが通ると、その間の2.25Nや2.5Nを一度も試しません。途中の弱い押しで倒れるところがあっても、見落とします。
2つ目は、その穴を直した物差しです。0.25Nから0.25Nずつ上げていき、最初に倒れた力の手前を上限にします。
| 本文と同じ物差しで | 本文 | 測り直し |
|---|---|---|
| 正解値・500Hz | 5.50N(帯0.00) | 5.50N(帯0.00) |
| 推定器なし・250Hz | 5.25〜5.50N(帯0.25) | 5.25〜5.50N(帯0.25) |
| 推定器・250Hz(足裏は開けたまま) | 5.00〜5.25N(帯0.25) | 5.00〜5.25N(帯0.25) |
| 実機相当・250Hz | 5.00〜5.75N(帯0.75) | 5.00〜5.50N(帯0.50) |
同じ物差しでは、実機相当の帯は0.75から0.50に縮みました。内訳は、周期の+0.25と推定器の+0.00が同じで、足裏の傾きを塞いだぶんが+0.50から+0.25に。塞いだ前後で「3倍」と書いたところは「2倍」です。
いちばん悪い値は5.00Nのままで、正解値から−0.50N。帯が0.50になったので、この差は「帯の内側」ではなく「帯と同じ幅」です。「見分けがつかない」とは、言いにくくなりました。
| 直した物差しで | 7条件で出た値 | 帯 |
|---|---|---|
| 正解値・500Hz | 7回とも 5.50N | 0.00 |
| 実機相当・250Hz | 4.00〜5.25N | 1.25 |
物差しを直すと、実機相当のいちばん悪い値は4.00Nでした。正解値から−1.50Nで、帯の1.25より大きい。水準も落ちていました。帯の幅を超えたのは、刻み1つ(0.25N)ぶんです。
本文の結論「250Hzでは決定性を失うだけで、水準は帯の内側」は、同じ物差しでは際どく残り、直した物差しでは成り立ちません。
「同じ結果が出ること」が失われたのは変わりません。正解値の帯はゼロで、実機相当には帯があります。推定器の進め方を直すと、7条件の1つ1つの値は、前の記録とほぼ同じ範囲の中で入れ替わりました。失われたのは、それだけではありませんでした。数字もでした。
直した物差しで測ったのは、正解値と実機相当だけです。帯の内訳(周期・推定器・足裏の傾き)は、本文と同じ物差しでの数字です。
足裏の傾きの大きさ(0.002°・0.446°など)は測り直していません。
「差が帯より小さいときは何も言えない」と書いた回で、その帯を測った物差しのほうに穴があった。直したら、帯の幅を刻み1つぶん超えて落ちていた。
確かめていないこと
いつもどおり、今回分かっていないことを並べておきます。
| まだ分かっていないこと |
|---|
| 直した物差しで測ったのは、正解値と実機相当だけです。帯の内訳(周期・推定器・足裏の傾き)は、本文と同じ物差しでの数字です |
| 足裏の傾きの大きさ(0.002°・0.446°など)は測り直していません |
| 実機では測っていません。全部シミュレータの中の話です |
| この機体には、まだ上半身がありません。骨盤の箱で終わっています |
胴・腕・頭を載せれば、重心が上がるので数字は変わります。実機を組めば、さらに変わります。先に書いておきます。

