知識がなくても始められる、AIと共にある豊かな毎日。
AIコーディング

G-code を書き換えるプラグインを AI に書かせて検査する — 層ごとの一時停止・温度・ファンが狙った層に入るか

ゲンキ

30 層目で一時停止してナットを埋め込み、50 層目から少しノズル温度を上げ、70 層目から部品冷却ファンを強めたい。こうした「狙った層での変更」は、書き出した G-code を後から書き換えれば入れられる。問題は、その書き換えが本当に 30 層目・50 層目・70 層目に、一度だけ、他の行を壊さずに入っているかだ。

そこで、G-code 書き換えのコードを AI に書かせ、狙った層に正しく入るかを検査した。書かせたのは OrcaSlicer 2.5.0-alpha(2026-10-16 公開、pre-release)に入った、スライスの処理の中で G-code を後処理する Python プラグインの、書き換えの部分である。これを claude -p に書かせ、書き換えの関数だけを取り出して、手元の Bambu Studio CLI(2.8.4.57、2026-09-22 公開の Public Beta)と、比較用に OrcaSlicer 2.5 の CLI でスライスした G-code に当てた。プラグインを OrcaSlicer の中では動かしていない。

※本記事にはアフィリエイト広告(PR)が含まれます。

先に結果を書く。AI に渡す資料を増やすほど、G-code 書き換えは狙いに近づいた。資料を渡さないとプラグインの形にならず(API を確認できないとして単体スクリプトを返し)何も動かず、公式 wiki と公式サンプルを渡すと層の区切りの推測を外して無変化、実物の G-code の抜粋まで見せた条件だけ、見せた方の出力では一時停止・温度・ファンが全部入った。ところが同じプラグインを別のスライサーの出力に当てると、一時停止が 1 層ずれた。いずれも各条件 1 回の実行である。

忍者AdMax

G-code 書き換えを AI に任せる前に — 「最適化」と「検査」の違い

G-code 書き換えを AI に任せる前に — 「最適化」と「検査」の違い

LLM G-code最適化:大規模言語モデルが書く「人間より速い」ツールパス(2026-02-27 公開) では、スライサーが書き出した G-code を LLM で後処理し、トラベル経路の並べ替えやリトラクションの調整、Klipper のマクロへの変換で速くする話を扱った。あの記事の狙いは、G-code を賢く作り替えることにある。

本記事の狙いは逆に近い。作り替えるのではなく、人があらかじめ決めた変更——この層で止める、この層から温度を変える——が、狙った層に正しく入るかを確かめる。つまり G-code 書き換え自体は単純で、難しいのは「どこに入れるか」を出力の G-code から読み取る部分だ。

この違いは、層の区切りの書き方にそのまま出る。あの記事では、Klipper 連携の層の印として ;LAYER_CHANGE を挙げた。これは Slic3r 系の汎用の書き方で、OrcaSlicer も Bambu Lab 機以外を選ぶとこの形で書く。しかし Bambu Lab の機種では、OrcaSlicer も Bambu Studio も層の区切りを ; CHANGE_LAYER と書く。同じ「層の変わり目」でも文字列が違うので、;LAYER_CHANGE をそのまま一般化すると当たらない。後で見るとおり、AI はまさにここでつまずいた。

後処理プラグインが G-code を受け取る場所 — Slicing Pipeline の psGCodePostProcess

後処理プラグインが G-code を受け取る場所 — Slicing Pipeline の psGCodePostProcess

OrcaSlicer 2.5 のプラグインは、スライスの処理(Slicing Pipeline)の決まった段に割り込んで動く。段は全部で 13 個あり、G-code の後処理はそのうちの1つで、名前は Step.psGCodePostProcess だ。この段は、従来の後処理スクリプトの後に動く。

受け渡しは文字列ではない。G-code は作業用ファイルのパス(ctx.gcode_path)で渡され、プラグインはそのファイルをその場で書き換える。公式サンプルの説明にも、この段では ctx.print と ctx.object は None で、代わりに ctx.gcode_path が入ると書かれている。設定の場所は、プロセス設定の Others にある Slicing Pipeline Plugin(Advanced)である。

プラグインの形は公式サンプルの G-code Stamp が示している。要点だけ引くと、capability のクラスが execute(self, ctx) を持ち、後処理の段でなければ何もせず成功を返す。

class GCodeStamp(orca.slicing.SlicingPipelineCapabilityBase):
    def execute(self, ctx):
        if ctx.step != orca.slicing.Step.psGCodePostProcess:
            return orca.ExecutionResult.success()
        # ctx.gcode_path のファイルを開いて書き換える

出典は OrcaSlicer のサンプル sandboxes/orca_gcode_stamp_plugin_any.py(コミット 3880f2c、AGPL-3.0)で、全文は末尾の参照から確かめてほしい。登録は @orca.plugin を付けたクラスで orca.register_capability を呼ぶ。プラグインは .py 1本か .whl の形を取る。

注意が2つある。1つは、この仕組みが新しく、公式が API は変わりうると明記していること。もう1つは、CLI では後処理(スクリプトもプラグインも)が動かないことだ。OrcaSlicer も Bambu Studio も、CLI で後処理を呼ぶ行はソースでコメントアウトされ、エラーの一覧には「CLI では後処理に対応しない」という文言がある。だから本記事の検査は、画面でプラグインを動かすのではなく、書き換えの関数を取り出して G-code に当てる形を取った。

失敗したときの扱いも押さえておく。後処理のプラグインが例外を出すか、失敗を返すと、OrcaSlicer はそれを通常のスライスのエラーとして扱う。公式のリリースノートも、プラグインのエラーは OrcaSlicer を落とすのではなく、普通のスライスのエラーとして現れると書いている。つまり後処理が例外を出したり失敗を返したりすれば、黙って壊れた G-code が出てくるのではなく、スライスのエラーとして現れる。ただしこの仕組みが見るのは、例外・失敗・出力ファイルの欠落までで、「成功を返したが中身が狙いと違う(層がずれている)」ところまでは捕まえない。実際この実験でも、何も変えなかった wiki の条件も、1層ずれた実物入りの条件も、プラグインは成功を返している。だから、変更が狙いどおり入ったかどうかは、この安全側の挙動とは別に、解析器で数えるしかない。

実測の条件 — AI にプラグインを書かせ、OrcaSlicer の外で当てる

実測の条件 — AI にプラグインを書かせ、OrcaSlicer の外で当てる

検査の段取りはこうだ。まず claude -p(Claude Code の非対話実行。ツールや MCP、設定ファイルを読まない最小構成)に、後処理プラグインの psGCodePostProcess の部分を書かせる。AI に渡す資料を3通りに変えた。

  • 資料なし: 課題文だけを渡す
  • 公式 wiki と公式サンプル: OrcaSlicer のプラグインの wiki と、sandboxes/ の公式サンプルを渡す
  • +実物の G-code の抜粋: 上に加えて、実際にスライスした G-code の先頭と層の区切りの抜粋を渡す

書かせたプラグインから書き換えの関数を取り出し、OrcaSlicer の中ではなく手元で動かした。orca モジュールの代役を用意し、ctx.step を後処理の段に、ctx.gcode_path を G-code のコピーに、ctx.print と ctx.object を None に設定して(公式サンプルが後処理の段の仕様として書いているとおり)、execute を 1 回呼ぶ。AI が書いたコードは、ファイルの読み書き以外をしないことを先に読んで確かめてから当てた。

プラグインまるごとではなく書き換えの関数だけを取り出したのは、プラグインの読み込みや登録の部分まで動かすと、検査したい「G-code をどう書き換えるか」の挙動に、仕組みの再現度の粗さが混ざってしまうからだ。代役の orca モジュールは、ソースから作った正解表にある名前だけが解決し、存在しない名前を呼べばその場で失敗する。だから、資料なしの条件で AI が OrcaSlicer のプラグインの形を取らず単体スクリプトを返したときには、capability が登録されないことがそのまま表に出た。

試験用の G-code は、20×20×30 mm の箱(150 層・層高 0.2 mm)を、手元の Bambu Studio CLI(P1S、0.4 mm ノズル、Generic PLA、単色)でスライスしたものだ。比較のため、同じ箱を OrcaSlicer 2.5 の CLI でもスライスした。なお、設定値そのものを AI に確かめさせる実測は スライサー設定の取り違えを AI に見つけさせる — 素材・温度・プレートの組み合わせを公式プロファイルで試す(2026-10-14 公開) で扱った。本記事が確かめるのは値の正しさではなく、決めた変更が狙った層に入るかである。

指示した変更は3つで、実行前に固定した。30 層目で一時停止、50 層目から 230 ℃、70 層目から部品冷却ファンを 50 %。ファンの 50 % は、255 段階では 255×50÷100 で 127.5 にあたる。ファンの値は整数で書くので、解析器は 127 か 128 を正解とした(AI は実際には 128 と書いた)。判定は、AI とは別に書いた解析器で、元の G-code と書き換え後を突き合わせて数えた。見るのは、(1) 一時停止(M400 U1 などの停止系の命令)が、狙った層の始まり付近に 1 回だけ入ったか、(2) 温度が 50 層目から最後まで、押し出す各移動で狙いの値か、(3) ファンが 70 層目から最後まで狙いの値(127〜128)か、(4) 変更より前の層で温度とファンの値が元のままか、(5) 末尾のヒーターとファンを止めた最終状態が元と同じか、の5つである。行そのものの不変性ではなく、押し出し時の温度・ファンの値と最終状態で見ている。採点そのものが正しく働くことは、先に2つの対照で確かめた。公式サンプルの G-code Stamp はコメントを1行入れて成功し、実験者が書いた手本のプラグインは5項目すべてを満たした。

試験用の G-code は Bambu Lab P1S の設定でスライスした。一時停止の M400 U1 のような命令の書き方も、この機種のプロファイルに合わせている。

狙った層をどう数えるか — 1 始まりと 0 始まりが混ざる G-code

狙った層をどう数えるか — 1 始まりと 0 始まりが混ざる G-code

ずれの話をする前に、「N 層目」の数え方を決めておく。解析器は、G-code を上から読み、; CHANGE_LAYER が出るたびに層の番号を1つ進め、上から N 番目の ; CHANGE_LAYER から始まる層を N 層目とする(最初の層が 1 層目)。開始の G-code には温度やファンの命令が多数あるが、まだ最初の ; CHANGE_LAYER が来ていないので、どの層の値としても数えない。押し出しは、材料を押し出す向き(E が正)の移動とみなす。

やっかいなのは、同じ層の中に 1 から数える番号と 0 から数える番号が混ざることだ。Bambu Studio の出力では、各層の区切りの近くに、進捗を示す M73 L と「layer num/total_layer_count」のコメントが 1 始まりで書かれ、同じ層に M991 S0 P が 0 始まりで書かれる。最初の層を見ると、M73 L1、コメントの 1/150、M991 S0 P0 が同居している。総層数は本体の手前に ; total layer number: 150 と書かれる。

この混在は、AI が層番号を取り違える入口になる。たとえば M991 S0 P の P をそのまま層番号と読むと、1 つずれる。狙った層の先頭に変更を入れるには、; CHANGE_LAYER の行より後、その層の最初の押し出し(X か Y を伴い、材料を押し出す向きの動き)より前に入れる必要がある。層の区切りの直後にあるワイプ(戻す向きの動き)は押し出しではないので、ここに入れてはいけない。

結果 — 資料を渡すほど近づき、実物を見せた条件だけ入った

結果 — 資料を渡すほど近づき、実物を見せた条件だけ入った

結果を表にする。各条件 1 回の実行で、横は解析器の5項目のうち、一時停止・温度・ファンの3つと、変更前の層・末尾が元のままかを示す。

渡した資料G-code の出どころ実行の結果一時停止温度ファン変更前の層末尾
資料なしOrcaSlicer 2.5capability が登録されず不動×××一致一致
資料なしBambu Studio同上×××一致一致
wiki+サンプルOrcaSlicer 2.5層の区切りが見つからず無変化×××一致一致
wiki+サンプルBambu Studio同上×××一致一致
+実物の抜粋OrcaSlicer 2.5150 層を処理○○○一致一致
+実物の抜粋Bambu Studio150 層を処理×(31 層目)×(51 層目から)○一致一致

資料なしのとき、AI は「API の仕様を確認できない」と述べ、OrcaSlicer のプラグインの形を取らなかった。返したのは、G-code のパスを受け取って書き換える単体のスクリプト(main と引数で動く形)で、OrcaSlicer が読み込む capability を登録する部分が無い。OrcaSlicer の実際の仕組みは、capability のクラスを orca.register_capability で登録するものなので、登録が無ければ後処理は呼ばれない。結果として、どちらの G-code も元のままである。

公式 wiki とサンプルを渡したときは、プラグインの形は正しくなった。ところが層の区切りを ;LAYER_CHANGE(Slic3r 系の汎用の書き方)と推測したため、; CHANGE_LAYER と書かれた実物と一致せず、どちらの G-code でも何も変えられなかった。層の区切りのコメントの文言は、実物を見ないと当てられなかったことになる。

実物の G-code の抜粋まで見せた条件で、初めて変更が入った。ただし全部正しかったのは、AI に抜粋を見せたのと同じ OrcaSlicer 2.5 の出力に当てたときだけだ。一時停止は 30 層目の先頭に1回、温度は 50 層目から最後まで 230 ℃、ファンは 70 層目から最後まで狙いの値になり、変更前の層と末尾は元のままだった。

同じプラグインが Bambu Studio の出力では1層ずれた

同じプラグインが Bambu Studio の出力では1層ずれた

問題は、同じプラグインを Bambu Studio の出力に当てたときに起きた。一時停止は 30 層目ではなく 31 層目に入り、温度は 51 層目から変わった(50 層目は元のまま)。1 層ずつ後ろにずれたのである。

原因は層の数え方にあった。AI は、抜粋で見せた OrcaSlicer 2.5 の出力に合わせて層を数えていた。層の区切りの近くに出るコメントや目印の並びは、OrcaSlicer の出力と Bambu Studio の出力で少しずつ違う。見せた方の並びに合わせて数える作りだったため、目印の出方が違う Bambu Studio の出力では、境目の取り方が1つずれた。先に M991 の P が 0 始まりだと書いたが、こうした 1 始まりと 0 始まりの混在や、目印の有無が、ずれの温床になる。

一方でファンは、両方の出力で狙いどおりになった。理由は、AI が1行入れるだけでなく、70 層目から最後までのスライサー自身の部品冷却ファンの命令(M106)をすべて書き換えたからだ。ここには F1(入ったか)と F2(効き続けるか)の2段がある。今回の元の G-code は Generic PLA でスライスしたため、本体の 39 の層にスライサー自身の M106 があった。1行入れるだけだと、その後のスライサーの M106 で上書きされ、70 層目から変わり続けない。AI はこれを避けて、70 層目以降の M106 を全部書き換えた。Bambu Studio の出力では、新しく挿入した1行は(層のずれのため)71 層目に入っていたが、70 層目以降の既存の M106 を書き換えたので、70 層目から値は合った。結果としてファンは合格したが、これは「決まった1行を1か所に入れる」とは別の操作になっている。

この実行から読めるのは、プラグインの API を正しく使えても(構文や関数の照合を通っても)、出力される G-code の方言——層の目印と層の数え方——を見ないと、狙った層に正しく入らない、ということだ。しかも、見せた方言には合うが、別の方言に当てると1層ずれる。

1層のずれは小さく見えるが、検査なしでは気づきにくい。一時停止を入れたかった層と実際に入った層が1つ違っても、G-code を目で追うだけでは分からず、刷ってみて初めて「1層ずれた高さで止まった」と気づくことになる。だからこそ、変更が狙いの層に入ったかを、刷る前に別のコードで数えておく意味がある。今回の解析器は、一時停止・温度・ファンを層ごとに拾い、指示した 30・50・70 という番号と突き合わせるだけの単純なものだが、1層のずれはこれで拾えた。AI にコードを書かせるときは、書かせたコードと同じくらい、その出力を確かめる側の物差しを用意しておきたい。

入れた命令の意味 — M400 U1・M104・ファンの番号

入れた命令の意味 — M400 U1・M104・ファンの番号

入れた命令そのものの意味も、スライサーと機種で書き方が違う。ここでは根拠を Bambu Studio のソースとプロファイルに置き、一般的な意味は Marlin の公式文書を参照にとどめる。P1S のファームウェアは Bambu Lab 独自で、プロファイルの gcode_flavor が marlin なのは、スライサーの出力形式の設定にすぎない。

  • 一時停止: Bambu Studio の P1S のプロファイルが一時停止に使う G-code は M400 U1 だ。OrcaSlicer 同梱の Bambu Lab 機のプロファイルも同じ値を持つ。M0 や M600 が P1S で動くかは確かめていないので、不正解の判定は「Bambu Studio の書き方と違うかどうか」で行った
  • 温度: 待たずに目標を変える M104 S230 を正解にした。Marlin の文書では M109 は目標に達するまで待つ命令なので、待つ指示を含めるかは実行前に決めて別に数えた
  • ファン: Bambu Studio のソースでは、M106 のファン番号は P1 が部品冷却ファン、P2 が補助ファン、P3 がチャンバーファンだ。ただしスライサーが本体に書く部品冷却ファンは、P を付けない M106 S<値> の形で、止めるときも M106 S0 と書く。S の範囲は 0〜255(S255 で 100 %)だ。50 % は 255×50÷100 で 127.5 にあたるが、値は整数で書くので、解析器は 127 か 128 を正解とした(AI は 128 と書いた)。M106 P2 や M106 P3 は別のファンなので、ここに来たら不正解とした

M400 U1・M73 L・M991・M106 P1/P2/P3 は、いずれも Bambu の書き方で、Marlin の文書には無いか意味が違う。だから G-code 書き換えの検査では、「Marlin の一般論」ではなく「このスライサーがこの機種に書く形」を正解に据えた。

途中で止めてナットを埋め込むなら、M3 のねじとナットを一式そろえておくと、穴の寸法を決めやすい。

画面やスクリプトでも層に変更を入れられる

画面やスクリプトでも層に変更を入れられる

同じことは、スライサーの画面や後処理スクリプトでも入れられる。並べておく。

Bambu Studio と OrcaSlicer は、どちらもプレビューの層スライダーのつまみを右クリックすると、「Add Pause」や「Add Custom G-code」を選べる(ソースで確認した。画面は操作していない)。PrusaSlicer は公式の手順として、スライダーのオレンジのプラスのアイコンを右クリックして「Insert pause print (M601)」を選ぶ方法を案内している。この一時停止は、選んだ層を刷り始める前に入る。Bambu Studio 自身が層に入れる一時停止も、同じく「その層を刷り始める前」である。

書き出した G-code を外部のプログラムで書き換える後処理スクリプトもある。PrusaSlicer 2.x では「Print settings – Output options – Post-processing scripts」に、Bambu Studio と OrcaSlicer ではプロセス設定の Others に設定がある(PrusaSlicer 3.0 の alpha には、この後処理スクリプトはまだ入っていない)。これらは G-code のパスを引数に受け取り、その場で書き換える点で、今回のプラグインの後処理とよく似ている。特定の1社だけの機能ではない。

では、わざわざプラグインに書き換えを任せる意味はどこにあるか。画面の右クリックは手作業で、同じ変更を毎回入れ直すことになる。後処理スクリプトやプラグインなら、変更の規則をコードに書いておける。コードである以上、AI に書かせられる。ただし、今回見たとおり、出力の方言を見ずに書かせると狙った層に入らない。

一時停止で埋め込む部品の定番は、ナットのほかに小さな磁石だ。蓋や合わせ面を磁石で留める形は、層を指定した一時停止と相性がよい。

この検査で言えないこと

この検査で言えないこと

結果を読むときの限界を、まとめて書いておく。

  • 各条件 1 回の実行である。資料の渡し方3通り×2つのスライサーの出力で、各 1 回ずつ動かしただけだ。正答率として一般化できる数ではない
  • プラグインを OrcaSlicer の中で動かしていない。書き換えの関数を取り出し、CLI で出した G-code に当てた範囲の検査である。画面でプラグインとして読み込ませたときの挙動は見ていない
  • プレビューに後処理の結果が出るかは確かめていない。資料どうしで記述が食い違うため、本記事では触れない
  • 実機で止まるか・温度が変わるかは見ていない。判定は「Bambu Studio の書き方に合っているか」までで、当サイトは実機を使わない
  • M400 U1 とファンの番号の根拠は、Bambu Studio のソースとプロファイルだ。Bambu Lab がファームウェアの側で説明した公式文書は確かめていない
  • ファンが狙いどおりになったのは、スライサー自身の M106 も書き換えた結果だ。1行入れるだけの操作ではない。元の G-code に後続の M106 が無ければ、1行で足りた可能性がある
  • 元の G-code は Generic PLA・単色・まっすぐな箱だ。色替えや、順番に刷る設定、花瓶モードでは、層の区切りと層番号の対応が単純でなくなる

それでも、資料を増やすほど G-code 書き換えが狙いに近づくこと、そして実物の方言を見せても別のスライサーの出力では1層ずれたことは、この実行から読み取れる。

まとめ

まとめ
  • OrcaSlicer 2.5 の後処理プラグインは、G-code を作業用ファイルのパスで受け取り、その場で書き換える。本記事はこの書き換えの部分を claude -p に書かせ、関数を取り出して、Bambu Studio と OrcaSlicer の CLI で出した G-code に当てた(OrcaSlicer の中では動かしていない)
  • 資料なしではプラグインの形にならず(単体スクリプトを返して)不動、wiki とサンプルでは層の区切りを ;LAYER_CHANGE と推測して無変化、実物の抜粋を見せた条件だけ、見せた OrcaSlicer の出力で一時停止・温度・ファンが全部入った
  • 同じプラグインを Bambu Studio の出力に当てると、一時停止が 31 層目、温度が 51 層目からと、1 層ずれた。層の目印と数え方が出力で違うためだ
  • 命令の正解は「このスライサーがこの機種に書く形」に据えた。一時停止は M400 U1、温度は M104 S230、ファンは P を付けない M106(50 % は 127.5 にあたり、整数で 127〜128 を正解とした)

G-code 書き換えを AI に任せるなら、プラグインの API を正しく書けるかだけでなく、当てる相手の G-code の方言を資料に含めること。そして各層に1行入れて終わりではなく、スライサー自身が後から書き直す命令(ファンなど)との兼ね合いまで、別の解析器で数えて確かめることだ。方言が変われば、同じコードでも1層ずれる。

参照

ブラウザだけでできる本格的なAI画像生成【ConoHa AI Canvas】
ABOUT ME
swiftwand
swiftwand
AIを使って、毎日の生活をもっと快適にするアイデアや将来像を発信しています。 初心者にもわかりやすく、すぐに取り入れられる実践的な情報をお届けします。 Sharing ideas and visions for a better daily life with AI. Practical tips that anyone can start using right away.
記事URLをコピーしました