ポストプロセッサが最初の初期化に使用する、変数やテーブルをグローバルセクションと呼ぶようです。
これには、ポストカーネルからの情報であるカーネル設定変数、ポスト処理のダイアログに表示されるプロパティテーブル、NCデータの出力形式を制御するフォーマット定義、さらに、全ての関数がアクセスできるグローバル変数などが定義されています。
今回の記事を書くにあたっては、標準でインストールされている「fanuc.cps」を参考にしていますが、このファイルでは慣習的にグローバルセクションは分かりやすいように、ポストファイルの上部に配置されています。
カーネル設定(Kernel Settings)
参考の「fanuc.cps」では、上部36行までに、変数宣言(「var」が付かない)がない変数として定義されています。
これは、ポストエンジンとのやりとりに使われます。
ファイルの上部に配置され「var」がないので、特殊な変数である事はわかりますが、注意が必要です。
前回も話題にしましたが、JavaScript言語は変数宣言に「var」がなくても使用できてしまいます。
したがって、この付近へ新規に「var」なし変数への代入定義をしても、 エラーを出してくれません。
安易に宣言なしの、変数を使ってしまうと、カーネル変数なのか、個人的な変数なので分からなくなってしまうので、必ず新しい変数を定義する時には、宣言付きで定義し、カーネル変数の後部エリアで宣言する事をお勧めします。
では、Fusion360 CAM でポスト処理を実行し、ポストファイルとして「fanuc.cps」に設定してみます。
プロパティのテーブルに接頭(ビルトイン)が付いたプロパティが見つかります。
これは、「fanuc.cps」ファイルで「var」のない変数と見比べると、カーネル設定変数の一部なのが分かります。
この値自体は、ダイアログで編集する事も可能ですが、「fanuc.cps」の変数を直接編集する事で、デフォルト値にする事ができます。
この他にも、いくつか、ダイアログに表示される変数があります。
description = “FANUC”;
「ポスト処理」ダイアログでポストファイルを選択する、ボックスに表示されるタイトルの左側の文字になります。その後「/」の後に、実際のポストファイル名が表示されます
extension = “nc”;
この値が、作成されるNCデータの拡張子になります。
programNameIsInteger = true;
この値が、「true」の場合、「ポスト処理ダイアログ」の「プログラム名と番号」の項目に、数字しか使用できません。
「false」にする事で英文字なども使用できるようになります。
setCodePage(“ascii”);
NCデータを出力する時のエンコードを指定するようです。
ポストエラーログなどが文字化けたりした場合に「utf-8」に変更すると漢字が正常になったりします
「ansi」「utf-8」などがあるようです。
allowedCircularPlanes = undefined;
これは重要な変数です。見つけるまでに、結構時間がかかりました。
この1行がないと、 全ての出力が直線補間で処理されるようです。
通常、円弧の場合「onCircle( )」関数が実行されますが
この変数がないと、この関数に飛んでいきません。
ようするに、全て直線補間で処理されます。
これは結構、悩みました。
これらの変数も編集可能です。
試しに、拡張子など変更してみると、ポスト処理の再起動で反映されます。
プロパティ(Property Table)
ポストダイアログの「プロパティテーブル」には、(ビルトイン)以外の変数もリストされています。
ここを定義しているのが、properties = { }; とpropertyDefinitions = { }; の配列です。
JavaScript言語では、{ } で囲った配列は、通常の配列の拡張版で、「連想配列」と呼ばれています。
連想配列は、「:」を区切りに、「キーワード:値」 の形式で定義します。
使用時は「変数名」.「キーワード」の形式で参照する事ができます。
「propertyDefinitions」の配列は、さらに複雑ですね
連想配列の要素に、さらに連想配列が定義されています。
ただこれも、 「.」でつないで行く事で参照できます。
たとえば、
writeln ( propertyDefinitions.writeMachine.title );
のように、使用する事ができます。
properties = { }
properties変数は、ポスト処理ダイアログを開くと、「プロパティ」の項目にそのタイトルと値が表示されるのが分かります
したがって、ポストファイルの「properties」の内容を変更したり、追加・削除する事で、項目やデフォルト値を変更する事ができます。
使用しない項目は削除したほうが、すっきりしますね。
削除の場合は、いきなり削除せず「//」でコメントにしておいた方が安全です。
// writeMachine: true, // write machine
propertyDefinitions = { }
この変数は、プロパティテーブルへの表示を制御できます。
「title:」の値が表示されるタイトルとなり、「description:」でその項目の説明を定義できます。
説明は、プロパティテーブルの項目の上にマウスカーソルも持っていくと表示されます。
さらに、「group:」で、プロパティテーブルへの表示順序を制御できます。
「0」[1]・・と若い数字の「group」が上部に表示されるので、よく使用する変数は「0」「1」にしておくと、プロパティ設定が分かりやすくなります。
実は、この「propertyDefinitions」変数は、無くても動作するようです。
この変数全体をコメントアウトして実験してみましたら、説明分がでないだけで普通にポスト処理できました。
ただ、「Training Guide」マニュアルには、全てのエントリに一致するエントリが必要だとの記述がありますし、これがないと「tool tip text」が関連付けられないとあるので、よく理解できていませんが、 「properties」と「propertyDefinitions」の項目は合わせておいたほうが無難なようです。
冷却コード変数(coolants)
propertiesまでが、カーネル変数ですが、この定義から、下がっていくと「coolants」変数が定義されています。
こんな上部にクーラント定義が出てくるとはちょっと意外でしたが、 機械の依存コードで違いが多いのも、クーラントコードです。
同じメーカーの機械でも違う場合がありますから、そんな配慮でしょうか?
読んで字のごとく、機械の「クーラント(冷却)コード」指令の定義です。
まず、「var singleLineCoolant = false」とありますから、おそらく、クーラント指令で、単体か複数指令かの判定をする変数だと思われます。
たとえば、外部エアー指令の場合「M07」だけではなく、「M140 M07」と複数のMコード指令が必要な機械などへの対応だと思います。
複数定義の場合には、
on: [8, 88], off: [9, 89]
のように、連想配列のキー名の値として、さらに配列で指令するみたいです
結構複雑ですね。
ここまで、複雑にしなくても、いいように思いますが、ポスト作者の思想(性格)でしょうか?
ところで、参考にしている「fanuc.cps」を見てみると
{id: COOLANT_FLOOD, on: 8}, のように、「on」や「off」要素があるものと
{id: COOLANT_MIST}, のように「id」要素しかないケースがあります。
実は、工具設定で「ミスト」を指定して、このポストファイルで処理させると、エラーになってしまいます。
・ ・ # エラー: Unsupported 'mist' coolant. Error in operation: '2D 輪郭1' Failed while processing onSection() for record 475. # ・ ・
Fusion360 CAM の工具のクーラント設定の値をポスト処理する時には、この変数を参照しているのが分かります。
したがって、使用する機械のクーラントコードに合わせるには、この変数を編集すればいいと言うことになります。
使用機械の設備にない仕様には、意識して設定なしにしておく事で、 間違って指定した場合は、エラーが教えてくれる!がいい場合には、このように値を入れない事で実現できます。
ポストでエラーが出ると、戸惑ってしまうので、仕様にない設定でも、 とりあえず「M08」にしておこう!の場合は、on: 8の設定で実現できます。
ちなにに、実際のMコードへの変換は、2465行付近のsetCoolant(coolant) やgetCoolantCodes(coolant) 関数で行っています。
本当面倒な事しているように思います、もっと単純なプログラムにする事もできると思いますが、汎用性を意識するとこうなるのかもしれません。
フォーマット定義(Format Definitions)
次に、Format関連の定義が出てきました。
これは、主にNCプログラムの、ワード(G01とかM03とか)を出力するのに
使われています。
さらに、モーダル状態なども、定義しているようです。
ざっと眺めると、4個の組込関数があります。
createFormat()
createVariable()
createReferenceVariable()
createModal()
createFormat( )
NCコードの出力フォーマットを定義しています。
連想配列を引数でうけとり、出力方法を制御しています。
var gFormat = createFormat({prefix:"G", width:2, zeropad:true, decimals:1}); writeln(gFormat.format(1)); writeln(gFormat.format(53.1));
たとえばこの例では、まずは「G」を出力、文字列の幅2、幅が少ない場合には「0」を追加、小数点以下1桁。
の意味になり、このプログラムでは、「G01」「G53.1」が出力されます。
三項演算子
フォーマット定義からは、ちょっと脱線しますが、フォーマット定義を眺めていると、
(unit == MM ? 3 : 4)
このような構文が多数でてきますので、説明しておきます。
これは、「三項演算子」と呼ばれている、「演算子」の一つです。
C言語など他の言語にも同じような構文があります。
「if」文と同じように、条件判断をするときに使用します。
一行で表現できるので、単純な条件の場合には便利ですが、複雑になってくると暗号のようになって、理解しづらいプログラムになってしまいます。
複雑な場合には「if」文のほうが読みやすくなります。
この演算の意味は、
「 ? 」の前の式を評価し、結果が「真」であれば、「 : 」前の値を返し、「偽」であれば「 : 」の後ろの値を返します。
var a = (unit == MM ? 3 : 4);
この定義では、
「unit が MM であれば、a=3、そうでなければ、a=4」
となります。
if 文で書くと、こうなります。
var a; if(unit == MM){ a = 3; }else{ a = 4; }
ちなみに、「unit」や「MM」の変数はなんでしょうか?
「fanuc.cps」には、この変数の定義がみつかりません。
おそらく、ポストカーネル側で定義されている変数だと思います。
使用中デザインの単位ですね。
MMがミリ単位。INがインチ単位です。
この変数はどのように定義されているのでしょうか?
不明な変数を確認したい場合は、onOpen( )の最初にwriteln( )で出力させる方法が簡単です。
onOpen( )は、ポスト処理の最初に呼ばれるので、その先頭に書き込む事で、データの先頭に書きだされます。
function onOpen() { writeln(unit); writeln(IN); writeln(MM); ・ ・
このように、「writeln( )」で出力されてみると、どのように定義されているのか、わかります。
上の例では、
1 0 1 % O1001 (TEST01) ・ ・
このようになりました。
私の環境では、「unit = 1」なのがわかります。
その後の結果から、「IN = 0」「MM = 1」なので、「unit == MM」なのがわかります、
これを理解の上、下記のコードを分析してみましょう。
var xyzFormat = createFormat({decimals:(unit == MM ? 3 : 4), forceDecimal:true});
まず「decimais:」で小数点以下の桁数を定義しています。
その値は、「三項演算子」で条件判断されます。
具体的には、unit がミリであれば、「3」、インチであれば「4」になります。
「forceDecimal:」は整数の場合、小数点を出すか出さないかです。
この例では「true」なので、小数点を出力します。
このように、単純な条件判断の場合には、三項演算子は便利です。
createVariable()
定義済みのフォーマットを用いて、新しい出力を定義します
次のコードを見てみましょう
var xyzFormat = createFormat({decimals:(unit == MM ? 3 : 4), forceDecimal:true}); var xOutput = createVariable({prefix:"X"}, xyzFormat); var yOutput = createVariable({prefix:"Y"}, xyzFormat);
まず、「xyzFormat」で、ミリ単位であれば、3桁の小数点出力を定義してます。
その後、「createVariacle( )」で、接頭に「X」を付加するように再定義しています。
これも、onOpen( )へのwriteln( )で確認してみましょう。
function onOpen() { var x = 12.345678; writeln(xOutput.format(x)); ・ ・
ポスト処理させてみます。
X12.346
%
O1001 (TEST01)
・
・
きちんと、四捨五入までされて、下3桁の小数点で出力されました。
createReferenceVariable()
このオブジェクトは、最初の引数と次の引数が同一である場合に出力を省略させる場合に使用します。
主に円弧補間の「I J K」指令で、「0」の場合には出力させたくない場合に用いるようです。
「fanuc.cps」では、このように定義されています。
var xyzFormat = createFormat({decimals:(unit == MM ? 3 : 4), forceDecimal:true}); var iOutput = createReferenceVariable({prefix:"I"}, xyzFormat);
createVariable()と同じに見えますが、createVariable()は、引数が一つなのに対して、createReferenceVariable()は、2個の引数をとります。
今回も、onOpen( )で確認してみましょう。
function onOpen() { var x = 12.3; writeln(iOutput.format(x,0)); x = 0.000; writeln(iOutput.format(x,0)); ・ ・
ポスト処理させてみます。
I12.3 % O1001 (TEST01) ・ ・
このように、最初の引数の変数が、第2引数の「0」以外の時は、データが出力されますが、「0」の時には、改行だけとなりました。
createModal()
Gコードのモーダルコードの出力に使用します
モーダルコードが分からない方は、こちらで説明しています。
モーダルなコードは、同じグループのコードが指定されるまで、そのコードが引き継がれ省略可能なコードです。
関数の第一引数に「force:true」を指定すれば。モーダル状態であっても
出力します。
デフォルトは「false」なので、省略すると「false」になります。
次のコードで試してみましょう。
var gFormat = createFormat({prefix:"G", width:2, zeropad:true, decimals:1}); var gModal = createModal({},gFormat); var gModalForce = createModal({force:true}, gFormat);
gModal はモーダルな場合省略されますが、gModalForce は省略されません。
では、onOpen( )にコードを書き込んでみましょう。
省略状況を確認するために、グローバルで「gModal」と「gModalForce」を定義しています。
var gModal = createModal({},gFormat); var gModalForce = createModal({force:true}, gFormat); function onOpen() { writeln(gModal.format(0)); writeln(gModal.format(0)); writeln(gModalForce.format(0)); ・ ・
ポスト処理すると、このようになりました。
G00 G00 % O1001 (TEST01) ・ ・
一行目は「G00」が出力されていますが、二行目はモーダルなので省略されています。
三行目もモーダルですが、「force:true」の影響で出力されています。
では、モーダルでない場合もテストしてみましょう。
var gModal = createModal({},gFormat); var gModalForce = createModal({force:true}, gFormat); function onOpen() { writeln(gModal.format(1)); writeln(gModal.format(0)); ・ ・
G01 G00 % O1001 (TEST01) ・ ・
期待通り、「G01」の後、モーダルコードの値が変わったので「G00」が出力されました。
実は、Gコードなどを出力させるには、このようなフォーマット関数を使用しなくても、 「writeln(“G01”)」のように直接文字列を書けば、出力させる事は可能です。
ただその場合、現在のモーダル状態を記憶しません、「”G01″」はただの文字列と認識するだけです。
試してみましょう。
function onOpen() { writeln(gModal.format(1)); writeln("G00"); writeln(gModal.format(1)); ・ ・
本来であれば、「G01」の後「G00」が指令されているので、次に「G01」が来る場合 モーダルでないので「G01」が出力されなくてはいけません。
ところが、
G01 G00 % O1001 (TEST01) ・ ・
「G00」指令でフォーマット関数を使用しなかったため、モーダル情報では「G01」だと思っているので、三行目は「G01」が省略されてしまいました。
これ・・ Gコード的には結構怖いですよね~
切削モードのはずが、早送りになってしまっています。
このように、Gコードを直接文字列で出力させる事は簡単ですが、なるべく(特にモーダルコードは)フォーマット定義で出力させるようにしましょう!
まとめ
主に上部で定義してあるグローバルセクションの説明をしました。
フォーマット定義は単純に文字列を出力させるだけでなく、NCデータの状態や桁数、四捨五入も行う重要な定義です。
Gコード出力にはなるべくこの関数を使います。
さらにこの下段には、各関数から参照できるグローバル変が「var」で宣言されています。
ここでのグローバル変数は、自分で定義する関数からも参照できますし、自分で宣言したグローバル変数に既存の関数からもアクセスさせることもできます。
例えば、
「var G01Code_ = 0;」などとグローバルエリアで宣言しておき、この変数で「直線補間:G01」の出現個数を集計したいとします。
ポストは直線補間が現れると、「onLinear( )」関数が自動的に呼ばれますから
この関数の内部に、「G01Code_++;」を書いておくと、呼ばれるごとに、カウントアップされます。
ポスト処理最後には、「onClose( )」がよばれるので、ここに、この変数を表示させる事で目的の「直線補間の出現個数」を表示させる事ができます。
このように、グローバル変数をうまく使うと、ポスト処理の情報を取り込む事ができます。
次には、関数の定義が続いていますね。
ここからようやく、思い通りのデータを出力できるようになります。
Fusion360 ポスト記事
- 概要編
- 構成編
- 変数
- グローバルセクション
- 関数
- NCプログラム仕様検討
- onOpen( )
- onSection( ) No1
- onSection( ) No2
- onSectionEnd( ) & onClose( )
コメント
こんにちは。
>ちなみに、「unit」や「MM」の変数はなんでしょうか?
“unit” であれば、ドキュメントのこちらに記載があります。
(同一ページ内にMMも有ります)
https://cam.autodesk.com/posts/reference/classPostProcessor.html#aa63cd118027e6af31ecb0a9a45085e43
“Public Attributes” となっている為、属性のようです。
詳しく調べていないのですが、例えば “onOpen” 内のみ利用出来るもの等が
恐らくあるはずで、この辺りを調べるのが非常に難しいです・・・。
又、いざ “unit” ドキュメントをみても、何処の項目から引っ張り込んできて
いるものかがわからないので、かずばんさんが行っているような方法しか
わからないですね。
元々Autodesk社のHSM向けのドキュメントだったことが、わかりにくさの
原因かも知れませんが・・・。
kantokuさん、情報ありがとうございます
リンクしていただいたドキュメントはいつも参考にしているのですが、
Public Attributes の項目は気が付きませんでした。
なるほど、ここで、ポスト側で定義済みの変数名がわかるみたいですね。
「X」「Y」「Z」など、だれでも使いたくなりそうな変数名もありますね~
できれば、このような変数は、「__X」のように、特殊さがわかる名前にしてほしいです
知らなくて使っちゃったらどうなるでしょう?
ちょっと実験。
onOpen()の前にクローバルで定義してみました
var X = 123.5;
unit = 123.5;
function onOpen() {
writeln(unit);
writeln(X);
やはりエラーになりましたが、「unit」と「X」では変数の扱いが違うようです。
一つずつテストしてみると、「unit」の場合では、エラー以前に、
ポストダイアログで、プロパティ表になにも表示されない状態です
それでも無理やり実行すると、下記のエラーになりました
###############################################################################
Error: Error: Invalid output unit.
Error at line: 1
Stack dump:
(“Invalid output unit.”)@:0
@C:\Users\user\Desktop\post2\fanuc.cps:261
Failed while processing global script.
###############################################################################
「X」だけ再定義してみると、普通にポスト処理までは、行きますが
結局下記のエラーになりました。
別の関数で使用しているようです。
###############################################################################
Error: Bad axis specified for writeRetract().
Error at line: 2655
Failed while processing onSectionEnd() for record 519.
###############################################################################
「unit」は、内部的には、「const」レベルで定義されているのだと予想します。
やはり「Public Attributes」変数は、一応気にしておいたほうがよさそうです。
さらに自分用の命名ルールを決めておいたほうがいいかもしれません
例えば私の場合は、「kHensu」のように、先頭に半角小文字で「k」を付加して
その後一文字だけ半角大文字にしようかな。
ここまで柔軟な処理が出来るのであれば、何かNCファイル以外にも
利用出来そうな気がしているのですが・・・アイデアが思い付かないんです。
個人的には社内の3D測定器のプログラムを作れたら良いのになぁ
とは思っているのですが、腰が重くて始められていません。
最初にポスト触ったのは、レダースと言う海外の機械用のデータを吐き出したいと思った時でした。
この機械、動きのメジャーな部分は、ファナックGコードに近いですが、ちょっと違いもあります。
ただ、メインプロなどそれ以外の部分は全く違っていて、ポストの言語のようなプログラミング言語です。
なので、おそらく、Fusion360以外のCAMでは、ベンダーさんに作ってもらうようになると思います。
Fusion360の柔軟さで、どうにか対応できています。
他には、加工手順書の出力や、シミュレーションでTRYCUTを利用していますが
それの工具情報ファイルなどの出力をさせています。
タッチプローブ測定は、最近Fusion360のバージョンアップで使いやすくなったみたいですね
うちの若いのが、その機能を使いポストを作成してレダース用の測定プログラムの出力を企んでいます。
ただ、国産機の測定プログラムコードは、O9000番台のメーカーマクロが多いので
結構制限があるかもしれませんね。