お疲れ様です。最近3DプリンタへハマっているDX事業本部開発基盤グループの@k.bigwheelこと西田和史です。
問題解決とは
みなさん、問題を解決しているでしょうか? 問題とは、アプリケーションで発生したバグであったり、ウェブサーバーの期待より低いパフォーマンスであったり、はたまた売上が低いといったもっと上層のビジネス課題といったものから、毎月買った卵が余ってしまうといったことまで、困ったことなら何でもです。僕らエンジニアの仕事上での活動は言ってしまえばすべて問題を解決するために行っていると言えるでしょう。
エンジニアであれば、自分のよく知っている技術や自分が構築したインフラの問題などは簡単に解決してしまう場合が多いと思います。一方で、自分がよく知らない分野で発生した問題や、簡単に調べても原因がつかめない厄介な問題などは解決にとても苦労します。こういった簡単でない問題をきちんと解決できるかはエンジニアでも重視される能力の一つで、解決できるメンバーはどんどん能力や任される仕事の範囲が増えていきますし、逆にこれが解決できない人はそれが成長の壁になります。
今回はこの問題解決を行うための考え方のフレームワークを1つ紹介したいと思います。
理屈だけだとなかなか具体イメージが湧きづらいので、ちょうど最近問題があったうちの3Dプリンタを例にして話しましょう。
引用元の本
問題を解決するための体系立った分析法というのはコンサルティング分野で特に発達しているそうで様々な書籍がありますが今回は主に以下の書籍から特に引用します。この記事で紹介するのはそれらの極一部ですので興味が湧いた人はぜひ自分で読んでみてください。Speee社内であればSpeee Libraryにもあります。
基本3ステップ
問題解決本で一番最初に出てくる話であり、同時に最も重要なのがこの基本3ステップです。脱How思考、5whysなどはこれと同じことを言っています。
言っていることはとても単純で、
- 問題の特定(WHERE)
- 原因の深堀り(WHY)
- 打ち手の考案(HOW)
の順番で解決しましょう、というそれだけです。 その理由も単純で、
- 打ち手(HOW)から考えるとそれが効果があるのかどうかが博打になる
- → 効果的な打ち手(HOW)を選ぶためにまず根本原因を見つけましょう
- 根本原因を見つけるためには発生している現象から根本的な原因を見つける必要がある
- → 発生している問題から根本的な原因を深堀り(WHY)ましょう
- ある領域の中、どこで問題が発生しているかがわからないと原因が深堀りできない
- → データから問題の発生箇所を限定しましょう
という感じです。
早速実践例を見てみましょう。
例: 3Dプリンタの涙滴問題
つい先日買った3Dプリンタでいろいろとテスト印刷をしていたのですが、あるときから急に正常に印刷できなくなりました。 印刷物の立体から涙のように一部が垂れてしまうのです。
これによって形状が乱れるだけではなく、その周囲のフィラメントの層が薄くなってしまい造形物の強度も落ちてしまっていました。 3Dプリンタの精度を徐々に上げていきたいと思っていたのですがこれでは精度以前の問題です。
WHERE
特にソフトウェアエンジニアリングの分野でWHEREとWHYを調査するとき、重要なのが以下の2点です。
- その問題へぶつかったのが世界で自分が初めてか
- その問題の正しい呼称
その問題へぶつかったのが世界で自分が初めてか
その問題に遭遇したのが世界で自分が初めてではない場合、GitHub Issueやredditなどのフォーラムに同様の問題報告がある可能性が高いです。報告がある場合調査の非常に助けになりますが、この際その人の推測(WHY)は一旦おいておきどのようなことを行った人がその問題にあたったのか、あくまでWHEREの視点で参考にしましょう。
その問題の正しい呼称
もし過去に多くの人が遭遇している問題の場合、問題の名前に特有の呼称がある場合があります。googleを始めとした検索エンジンが調査の基礎となっているソフトウェアエンジニアリングではこの特有の呼称を見つけられるかどうかというのは調査の効率へ大きく影響します。
今回の場合、この問題に遭遇したのが自分が最初とは到底思えずウェブ上に同様の事例と解決策があることはほぼ確実でした。
そこでredditの3Dプリンタコミュニティや3DプリンタのナレッジサイトであるAll3DPなどを調べ周りこの現象の名前を探します。 3Dプリンタ自体にあまり詳しくないこともあり4, 5時間もかかりましたが1、およそこの現象がover extrusion(過剰押し出し)やblobと呼ばれている現象に近いことを突き止めました。
これでおよその問題領域がわかったので次はなぜそれが発生したかです。
WHY
3Dプリンタ関連の様々な知見が載っているAll3DPでは過剰押し出しが発生しているときの対策がまとめられています。それが以下です。
- 押出量を減らす
- 印刷温度を下げる
- フィラメントの直径を修正する
では、実際にこれらの対策を一つ一つ実行して問題が解決するかをチェックしてみます。
1. 押出量を減らす
スライサーの設定を変更して印刷してみた結果が以下です。
結論から言うと改善しませんでした。もっともひどいものと比べると頻度は下がっているものの、最初の印刷では一切blobが発生しなかったことを考えれば満足のいく結果ではありません。特に押出量を減らしていってもblobの量が減る傾向がなかったためこれが原因ではなさそうでした。
2. 印刷温度を下げる
温度とblobの発生に相関があるかをチェックするために印刷したのが次の温度タワーと呼ばれるものです。
これは各段ごとにextruderの温度が10度ずつ変更されています。これにより特定の段でblobが発生せず逆によく発生する段がある、ということがわかれば温度が原因だと判断できます。 しかし、これについても格段でまんべんなく2,3箇所のblobが発生しており温度との相関がないことがわかりました。
3. フィラメントの直径を修正する
これはフィラメント直径が間違っている場合に正しい値へ修正するというものです。 購入時のサイトやフィラメントが入っていた箱から指定している直径が設定と一致していることを確認した後、念の為購入したフィラメントをデジタルノギスで異なる箇所を3度図りましたが5%前後の誤差はあるものの十分許容範囲内でした。
4. 速度を下げる
印刷の速度を上げると問題につながるというのは一般的によく言われていることでしたので一旦速度を半分に下げて印刷してみました。
しかし、これでもblobは以前発生し続けていました。
このあともblobが発生する原因について数時間調査を続けましたが、めぼしい情報はありませんでした。
基本に立ち返る(観察)
こうなると、もはやよく観察するしかありません。blobが発生する瞬間になにか他と違いがないか、印刷中の1時間観察し続けることにしました。
そうして見ていると、印刷中気になる挙動があることに気づきました。 不定期の間隔で印刷が3~10秒ほど停止するのです。 最初はその挙動は正常な動作なのだと思っていましたが、blobが発生するタイミングと停止するタイミングが同一であるような気がしてきました。 僕が購入したものと同型のプリンタの動作動画をネット上で調べましたが、特にこのような停止が発生している様子はありません。
実は最初の印刷の直後から3DプリンタへOctoPrintと呼ばれる外部制御モジュールを追加してそこから印刷していたのですが、そのモジュールとのやり取りの中で本来プリンタが ok
を返すべきタイミングで k
だけが返ってきてOctoPrint側が実行成功だと認識できないという現象が確認されていました。この k
が返ってきてOctoPrint側が成功を認識できないタイミングと3Dプリンタが停止しているタイミングを比較すると、完全に一致しています。
そこでOctoPrint経由での印刷に問題があると仮定し、一度OctoPrintを外して3Dプリンタ単体で印刷した結果が以下です。
画像の通り、blob一つない結果が得られました。
HOW
これで原因の範囲はかなり絞り込めました。 あとはどう解決するかです。
まず、明らかに自明な解決方法はOctoPrintの使用をやめて直接印刷することです。 しかし、3Dプリンタ単体での印刷の場合いちいちSDカードへ書き込み抜き差しを繰り返す必要があります。一方OctoPrintを使用するとwifiでモデルを転送できるだけではなく印刷の開始終了の制御や現在どこまで印刷が進んでいるかを表示したり、カメラでtimelapse映像を取ることすら出来ます。とても便利なのでできる限りOctoPrintは使いたいです。
そこで、OctoPrint利用の中のどこが問題なのか、もう少しWHEREを続けてみることにしました。
WHEREを続ける
OctoPrintで印刷した場合にblobが出来てしまう原因を数時間調査すると以下のように様々な原因候補が出てきました。
- 通信のノイズ(ケーブルの問題)
- OctoPrintモジュールの供給電力の低さ
- 通信速度の問題
- ファームウェアのバグ(バッファオーバーフロー)
①のノイズの可能性は考えてみるとすぐに棄却できました。まず使用しているUSBケーブルがアンカーの高品質なものであること、もしノイズで問題が発生するとしたら通信内容はもっと不規則なエラーがありそうですが実際には ok
→ k
になるというとても規則的なものだったためです。 ②は電源モジュールが純正のしっかりしたものであること、OctoPrintモジュールへSSHで入って電圧をチェックしたものの問題なかったため可能性は低いと判断しました。③についても通信量はとても限定的でUSBで接続している3DプリンタとOctoPrintモジュールの間を逼迫するようなものとはとても思えませんでした2。
最後に残った④ですがこれが最も有力です。というのはこの3Dプリンタとよく似たモデルでほぼ同じような現象が報告されたのですが、そこでの結論がバッファの問題だったためです。断言できないのは僕が使用している3Dプリンタ(Aquila)のファームウェア・ドライバが公開されていないためバグの場所を特定できないためです。
これで最初に見つかった原因のOctoPrintを更に深ぼっての根本原因まで突き止められました。
HOW
真因が特定できたのであとはどう直すかです。 個人的な経験則としては、真因が特定できている場合エンジニアリングの領域でHOWに困ることはそんなにありません。バグが特定できれば直しますし、物理的な故障箇所があれば置き換える、そんな感じです。
今回の場合は以下の4つの選択肢がありました。
- OctoPrintをやめて3Dプリンタ単体で印刷する
- バグのある3Dプリンタファームウェア・ドライバを修正
- バグのある3Dプリンタファームウェア・ドライバをOSSの代替(Marlin)に置き換える
- OctoPrint側で
k
をok
に置換する
①は利便性のために一旦除外、②はコードが2021/09/20現在非公開なため実現不可能でした。③がもっともよい方法でAquilaはカスタムファームウェアが使えるという事前情報もあったためこれにしようと思ったのですが、都合の悪いことに僕が購入したバージョンがたまたまカスタムファームウェアが使えないチップを使用しておりこの方法は少なくとも2021/09/20段階では実行不可能でした。
となると残る選択肢は④です。 OctoPrintには非常に柔軟なプラグイン機構があり、しかも先述の類似ケースで問題に対処するためのコードがすでに存在しました。
それをベースに k
を ok
に修正するコードを書き、プラグインとしてインストールしてから実際に印刷してみた結果が次です。
完璧です、これでOctoPrint経由でも完全な印刷結果を得ることが出来ました!
まとめ
今回、問題解決のフレームワークを使って3Dプリンタで発生した問題に対処する例を説明しました。 実際には問題対処中にいちいちこの手順を思い浮かべてやっているわけではなく、もはや染み付いた習慣で無意識に実行しているのですが改めて言語化すると上記のような考えで問題を解決しています。 また、今回はキリがないために省きましたが実際にはMECE(ぬけもれダブリがないか)や因果関係の構造化、対処不能な事柄は無視するなど多数の注意点やテクニックがあります。興味が出てきた人はぜひ問題解決 ― あらゆる課題を突破する ビジネスパーソン必須の仕事術 | 高田貴久, 岩澤智之 | ビジネス教育 | Kindleストア | Amazonを読んでみてください。
今回、この問題解決にかかった期間は約20日間、印刷結果待ちの時間を除いた調査・検討の時間は少なく見積もっても40時間以上をかけました。 それだけ膨大な時間がかかるなんて、本当にこの問題解決フレームワークは効果的なのかと思われる人もいるかもしれませんが、当てずっぽうでやるよりもずっと早かったと確信できます。今回のように計画的に調査・実験し仮説を立てずにやった場合2倍3倍かかってもおかしくないでしょう。そして、なによりこういったフレームワークを使わない場合の典型的な結末は「原因がわからなかった」「途中で問題解決を諦めてしまった」です。当てずっぽうの場合建設的な進捗が出ずほとんどの人間が途中で諦めてしまうんですね。 つまり、問題解決のフレームワークは難しい問題を確実に一歩々々解決へ導く方法としてとても優秀なわけです。
エンジニアとして数年働くともはや同僚や先輩の誰も解決できないような問題に突き当たるときがあると思います。 そんなとき、このフレームワークを思い出して体系立てて解決に向かってはいかがでしょうか。