Fusion360 ポストファイルの構成は、グローバルセクションやグローバル変数定義の後は、関数の集まりになっています。
関数とはなんでしょう?
関数とは?
決まった処理をさせるプログラミング指令のかたまりですが、場合によっては引数から情報を受け取り、結果を返したりします。
NC言語で例えると、サブプログラムやマクロ呼び出しのような機能です。
関数は、言語に標準で付属している定義もありますし、自分で作成する事もできます。
JavaScript の関数
JavaScriptの関数の情報は、文献やネット上に多数情報がありますから、詳細はそちらを参照してください。
ただし、紹介されている関数が、ポストプロセッサですべて利用できるとは限りません。
関数の定義方法も何種類かあるみたいですが、Fusion360ポストでは、ほとんど「宣言方式」が使われているようです。
基本的な関数宣言は
function 名前 ( 引数、・・) {
// 処理、プログラム
return 結果;
}
こんなイメージです。
「fanction」が関数である事のキーワードで、その後に、適当な「名前」を書きます。
その後の ( ) 内に、関数へ渡す引数を , で区切り記述します。
引数がない場合でも、 ( ) は必要です。
次の { } の間に、関数にやらせたい処理をプログラムします。
もし、関数からの結果を渡したい場合には、「return」コマンドにつづけて、結果の値を書きます。
名前は使えない記号とか、ある程度の命名規則もあるようですが、半角英数字であればそれほど気にしなくてもいいと思います。
ただし、 その関数の処理内容をある程度イメージできる名前がいいと思います。
日本語も使えそうですが、使わないほうが無難ですね。
また、 大文字小文字は識別するので、注意が必要です。
関数の使い方は、こんな感じです
2個の引数を受け取り、大きい方を返す関数です
// 引数、aとb で大きい方を返す関数 function returnMax(a,b) { return (a>=b?a:b); } function onOpen() { var x1=10.23; var x2=11.56; var Max = returnMax(x1,x2); writeln(Max); //11.56が出力される。
このように、関数は引数を与えて呼び出すだけで決められた処理をしたり結果をもらうことができます。
関数がうまく使えるようになると、プログラムも見やすくなります。
Fusion360 ポストの関数
Fusion360のポストも、基本的にはJavaScript言語を使用しているので、定義の方法は同じです。
ただし、JavaScriptに標準で組み込まれている関数と、Fusion360特有の関数。ポストファイル作者個人が作成した関数、などがあります。
区別する意味でも、個人的に作成した関数は、命名ルールを決めておくと分かりやすくなります。
Fusion360の関数の詳細は、こちらの「Autodesk CAM Post Processor Documentation」に情報があります。
また、ポストファイル内に定義されている関数は、前回紹介した下記ページで紹介している「VSCode」エディタなら一覧で見る事ができます。
「VSCode」の、「エクスプローラー」機能の「FUNCTION LIST」に関数のリストが表示され、マウスクリックで瞬時にその関数にジャンプしてくれます。
特にこだわりのエディタがない場合には、VSCode がお勧めです。
Entry Functions
カーネルとポストプロセッサ間のやりとりをする関数をエントリ関数と呼んでいるようです。
この関数は、 接頭に半角小文字の「on」が付いている名前で、他の関数と区別されています。
したがって、自分で作成する関数の名前には、先頭に「on」は付けないほうがいいですね。
「VSCode」のエクスプローラで確認すると、かなり沢山のエントリ関数があるのがわかります。
ポストプロセッサファイルを編集するには、このエントリ関数を編集する事になります。
この関数は、Fusion360がポスト処理する際に、自動的に呼び出されます。
全てを編集する必要はありませんが、ある程度は各関数の役目を理解しておいたほうが、作業しやすくなると思います。
詳細は、「Autodesk CAM Post Processor Documentation」に記載されています。
Public Member Functions
ポストファイル内で、明示的に定義されている関数以外に、ポストプロセッサ内部で定義されている関数もあります。
「パブリックメンバー関数」と呼ばれるようですが、前回記事にした「format」などもこのメンバーです。
こちらも「Post Processor DocumentationのClassList」に情報があります。
ながめていると、使えそうなクラスもみつかります
たとえば、「FileSystem」には、ファイルのコピーや削除などの関数も用意されています。
NCデータを出力するだけでなく、加工工程や工具リスト、NCコードをDXF化したDXFファイルなど、NCデータとは別のファイルを出力させる事も可能です。
Fuison360のポストプロセッサは、単にNCデータ出力だけでなく、CAMからの情報をいろいろな形式で出力する事ができる非常に高機能なポストプロセッサです。
定義済み関数を調べてみる
参考の「fanuc.cps」に定義されている、関数を調べてみましょう。
前述の「VSCode・Function List」で確認すると、「on」で始まるエントリ関数以外にも、かなりの関数が定義されているのがわかります。
では、上部で定義されていて、その名前からNCデータを出力しそうな重要で使用頻度が高そうな「writeBlock() 」関数を分析してみましょう。
writeBlock()
この関数はNCデータを出力しそうだ?
と言う事が関数名でだいたいわかりますね。
おそらく、引数に与えられたNCワードを書きだす関数でしょう。
NC言語のブロックとは、一行に複数の指令コードが集まったコードですから、複数のNCワードを引数にとりなんらかの処理後、一行に書きだす関数と予想できます。
では、関数の中身を眺めてみましょう
function writeBlock() { var text = formatWords(arguments); if (!text) { return; } if (properties.showSequenceNumbers) { if (optionalSection) { if (text) { writeWords("/", "N" + sequenceNumber, text); } } else { writeWords2("N" + sequenceNumber, arguments); } sequenceNumber += properties.sequenceNumberIncrement; } else { if (optionalSection) { writeWords2("/", arguments); } else { writeWords(arguments); } } }
ポスト編集の学習するには、なかなかいい例題です。
結構、盛沢山です。
関数宣言
function writeBlock() で宣言されています。
「writeBlock」という「名前」の「関数」の定義の始まりです。
引数
あれ?不思議です。
この関数は、受け取った引数を細工して、一行に書きだす関数だと推測しているのですが、引数がありません。
どうやって、引数を受け取るのでしょうか?
argumentsオブジェクト
JavaScript には、こんな機能があるんですね。
C言語のコマンドライン引数「 *argv[ ] 」に似ていますかね。
関数が呼び出された時の引数が、自動的に argumentオブジェクトの配列内に格納されるみたいです。
この機能を利用して、text 変数に引数を取り込んでいます。
var text = formatWords(arguments);
ここでまた、formatWords( ) 関数が出てきました。
これは、パブリックメンバー関数です。
引数に与えられた、複数のワードをセパレータで区切り、一つの文字列にして最後に改行文字を追加する関数です。
また疑問が・・・セパレータとは?
実はこれは、「properties」にヒントがありました。
デフォルトでは「separateWordsWithSpace: true」と定義されています。
「true」であれば、デフォルトで「 」(スペース)になるようです。
したがって「arguments」で指定されたワードとワードは、「スペース」で区切られます。
実験してみます。
function onOpen() { writeln(formatWords("test1","test2","test3")); ・ ・
ポスト処理してみます
test1 test2 test3 % O1001 (TEST01) ・ ・
予想通り、3つの文字列が、「 」(スペース)で区切られました。
このセパレータは「setWordSeparator( )」のパブリックメンバー関数で再設定可能です。
function onOpen() { setWordSeparator("/"); writeWords("test1", "test2", "test3"); ・ ・
test1/test2/test3 % O1001 (TEST01)
今度は、” / ”が区切り文字になりました。
真偽(論理)値
次に、「if」文(条件分岐)がでてきました。
if (!text) { return; }
if文の ( ) は、論理的に「真(true)」であれば次の { } 内を実行し、「偽(false)」で { } の後に「else」があれば、その内部を実行します。
「else」がなければなにも実行せずに次に移ります。
論理判断は、例えば、「X == 0」とか「X > 10」など数値の比較はわかりやすいですが、
! text
はわかりづらいですね。
「!」は、条件判断の否定の意味です。条件が「真」であれば逆の「偽」になります。
また、条件判断は、 「何もない」場合には「偽」となります。
したがって、「 ! text 」の論理判断は、変数「text」になにも定義されていなければ「偽」と判断され、「!」により、逆の「真」の判断で次の定義が実行されます。
この例では「return」とあるので、そのままこの関数は終了となります。
まとめると
変数「text」に何も定義されていなければ、そのまま終了!
の意味となります。
グローバル変数で条件分岐
次も、「if」文です。
今回はちょっと複雑で、「if」文のなかに、「if」文が入っています。
さらに、「if」での判断が「偽」だった場合に実行させる「else」文も使われています。
条件判断の因子として、「properties.showSequenceNumbers」や「optionalSection」の変数が使われています。
前者は、プロパティテーブルで「showSequenceNumbers: true」と定義されていて、NC言語のシーケンス番号の出力の有無です。
この場合は、「true」なので、出力する仕様となります。
後者は、グローバル変数で「var optionalSection = false;」と定義されています
NC言語では、オプショナルスキップ「/」の出力の有無となります。
この部分のプログラムを要約すると
propertiesテーブルの showSequenceNumbers が 真で、さらにoptionalSection が真であれば、あれば、データに「/」と「Nシーケンス番号」を付加します。
optionalSection が偽であれば、「Nシーケンス番号」のみを付加します。
showSequenceNumbers が偽であれば、
optionalSectionの内容により「/」を付けるか付けないか、となります。
writeWords() と writeWords2()
データを書きだすのに、writeWords() と writeWords2()を使用していますね。
調べるとこの関数は、「パブリックメンバー関数」でした。
ドキュメントを読んでもよく理解できていませんが、writeWords2()は、引数が2個以上の時のみ書きだすような関数かと思っています。
「シーケンス番号」や「/」のみの出力を制限するのが目的でしょうか?
よくわかっていません。
さらに、writeBlock()をよく読んでみると、writeWords()で書きだすワードには、「text」の場合と「arguments」の場合があります。
これもよく理解できていません。
せっかく、変数「text」を準備したのだから、全て「text」でも結果は変わらないように思うのですが、よく理解できません。
もしわかる方いらっしゃったら教えてください。
加算代入演算子(+=)と インクリメント演算子(++)
カスタムマクロなどにはない、演算子を使っていたので説明しておきます。
「sequenceNumber += properties.sequenceNumberIncrement」
ちょっと見慣れない方もいらっしゃるかもしれません。
これは、加算代入演算子と呼ばれていて、「X += 10.5」は
X = X+ 10.5
と同等です。
さらに、「-=」、「*=」、「/=」などもあります。
現在の値に相対的な演算をさせたい時に便利な記述です。
ちなみに、インクリメント演算子(++)というのもあります。
これは、現在の値を「1」増やす(カウントアップ)演算子です。
「--」はデクリメント演算子でカウントダウンとなります。
さらに、この演算子は、変数への前置と後置の方法があります。
var A = 1; var B = 1; ++A; B++;
この場合は、AもBも結果的は同じで、「2」になります。
では、次の例ではどうでしょう。
var a = 1; var b = 1; writeWords(++a); writeWords(b++); writeWords("a=",a); writeWords("b=",b);
onOpen( )に追加してポストを通すとこうなりました。
2 1 a= 2 b= 2 % O1001 (TEST01) ・
まず、変数「a」「b」は「1」に定義しています。
writeWords(++a) は 加算された後に関数に渡される意味となり「2」が出力されてます。
次のwriteWords(b++)では、 関数に渡された後に加算される意味で「1」が出力されます。
その後、もう一度「a =」「b =」を付加して、現状の状態を書きだしてます
結果は、「a=2」「b=2」どちらも加算された後なので「2」です
「前置」と「後置」は次に処理が移ると、その変数の内容は同じですが、同じ行では相手への影響の与え方が違います。
「++a(前置)」は、インクリメントされた後の値を相手に渡します。
「b++(後置)」は、現在に値を相手に渡した後、インクリメントされます。
ちょっと、ややこしい仕様ですが、覚えておくと意外と便利です。
まとめ
本記事では関数の説明をしました。
ポストの編集では、自作の関数は必須ではありませんが、他人が作成した関数を分析し調べる事が理解を早める一番の近道だと思います。
最初は真似しながら、自分の関数を定義していくと、理解も深まりコードもわかりやすくなります。
writeBlock() だけでも、かなりのボリュームでした。
少しでもプログラミングの経験がある方は、だいたいの感覚でも、ポスト編集はできてしまいますが、言語の理解を深める事で簡潔でトラブルが少ないポストファイルとなります。
また、ポスト編集だけでなく、編集したコードがすぐに結果に反映するので、ゲーム感覚でプログラミングが体験でき、プログラミング言語の学習として利用してもいいと思います。
ポスト記事
- 概要編
- 構成編
- 変数
- グローバルセクション
- 関数
- NCプログラム仕様検討
- onOpen( )
- onSection( ) No1
- onSection( ) No2
- onSectionEnd( ) & onClose( )
コメント