本文へ移動
サポートシェアリングソリューション
OKWAVE Plus

このQ&Aは役に立ちましたか?

ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:論理演算)

論理演算機能を使った判断文のコンパクト化方法

2023/09/07 03:30

このQ&Aのポイント
  • 論理演算機能を使用して判断文をコンパクトにする方法について教えてください。
  • 四角ポケットの角に逃がしを入れる際に、X・Y方向に逃がしを入れる場合について教えてください。
  • 判断文のコンパクト化において、ORの使用方法についてアドバイスをいただけますか?
※ 以下は、質問の原文です

論理演算

2012/02/22 12:31

四角ポケットの4つの角に対し、X・Y方向にそれぞれ半円形状の逃がしを入れる
マクロを作成しております。

論理演算機能を用い、判断文をコンパクトにしているのですが動きがスムーズではありません。
下記に例を載せてます。
プログラムを指令値毎に作成し長文にするか、多少ぎこちなさを我慢し短文にするか
どちらかになるのでしょうか?良い方法があればお願い致します。


*X方向を I(#4)、 Y方向を(#5)とし、右上の角から左回りに1・2・3・4 とします。
 つまり右上のX方向に逃がしを入れる場合はメインでI1.と指令します、
 ---------⊃
| |
| |
 ---------

*左上のX方向に逃がしを入れる場合はI2.、
⊂---------
| |
| |
 ---------

*全ての角(X方向)に入れる場合はI1234.、
⊂--------⊃
| |
| |
⊂--------⊃

*Y方向も追加し、すべての角2*4ヶ所=8に入れたい場合は、
 I1234.J1234.と指令します。
∩ ∩
   ⊂|--------|⊃
| |
| |
   ⊂|--------|⊃
∪ ∪


*四角ポケット、右上角の判断文を訳付きで、、、

IF[[#4EQ1.]OR[#4EQ12.]OR[#4EQ13.]OR[#4EQ14.]OR[#4EQ123.]OR[#4EQ124.]OR[#4EQ134.]OR[#4EQ1234.]]GOTO15211
もしI数値が1.または12.または13.または14.または123.または124.または134.または1234.と等しいならN15211へ行け
G1Y#18
直線切削 Y=コーナーR
IF[[#5EQ1.]OR[#5EQ12.]OR[#5EQ13.]OR[#5EQ14.]OR[#5EQ123.]OR[#5EQ124.]OR[#5EQ134.]OR[#5EQ1234.]]GOTO15212
もしJ数値が1.または12.または13.または14.または123.または124.または134.または1234.と等しいならN15212へ行け
G03X-#18Y#18R#18
左円弧 X=-コーナーR Y=コーナーR R=コーナーR
G01X-#18
直線切削 X-=コーナーR
GOTO15214
N15214へ行け

N15211
G1Y[#32+#11]
直線切削 Y=[工具補正量+仕上げ代]
X[#32+#11]
X=[工具補正量+仕上げ代]
G03Y[#18*2]R#18
左円弧Y=[コーナーR*2] R=コーナーR
G01X-[#32+#11]
直線切削 X=-[工具補正量+仕上げ代]
IF[[#5EQ1.]OR[#5EQ12.]OR[#5EQ13.]OR[#5EQ14.]OR[#5EQ123.]OR[#5EQ124.]OR[#5EQ134.]OR[#5EQ1234.]]GOTO15213
もしJ数値が1.または12.または13.または14.または123.または124.または134.または1234.と等しいならN15213へ行け
G01X-[#18*2]
直線切削 X-=[コーナーR*2]
GOTO15214
N15214へ行け

N15212
G01[Y#18+#32+#11]
直線切削 Y=[コーナーR+工具補正量+仕上げ代]
G03X-[#18*2]R#18
左円弧X-=[コーナーR*2] R=コーナーR
G01Y-[#32+#11]
直線切削 Y=-[工具補正量+仕上げ代]
X-[#32+#11]
X=-[工具補正量+仕上げ代]
GOTO15214
N15214へ行け

N15213
G1Y[#32+#11]
直線切削 Y=[工具補正量+仕上げ代]
G03X-[#18*2]R#18
左円弧X-=[コーナーR*2] R=コーナーR
G01Y-[#32+#11]
直線切削 Y=-[工具補正量+仕上げ代]
X-[#32+#11]
X=-[工具補正量+仕上げ代]

N15214
G01X-[#21-[#18*4]]
直線切削 X=-[X方向長さ-[コーナーR*4]]



単純にORの使い過ぎでしょうか。
宜しくお願いします。

質問者が選んだベストアンサー

ベストアンサー
2012/02/24 12:02
回答No.4

分かりやすさから1234は譲れないところなのでしょう。
それを判定しやすいビット列に変換するマクロを組めば良いと思います。
下記でどうでしょう。
とりあえず要点以外は定数にしたり、はしょったりしてあります。
#33がIJ指令をビット列に変換したものです。(#31#32は計算用一時変数)
bit0( 1)…右上X有無
bit1( 2)…左上X有無
bit2( 4)…左下X有無
bit3( 8)…右下X有無
bit4( 16)…右上Y有無
bit5( 32)…左上Y有無
bit6( 64)…左下Y有無
bit7(128)…右下Y有無
参考になれば幸いです。
----------
O0001
G65P0002I1234.J1234.
M30
O0002
#33=0
N10DO1
#31=#4-FIX[#4/10]*10-1
#32=1
WHILE[#31GT0]DO2
#32=#32*2
#31=#31-1
END2
#33=#33+#32
#4=FIX[#4/10]
IF[#4LE0]GOTO20
END1
N20DO1
#31=#5-FIX[#5/10]*10-1
#32=1
WHILE[#31GT0]DO2
#32=#32*2
#31=#31-1
END2
#33=#33+#32*16
#5=FIX[#5/10]
IF[#5LE0]GOTO100
END1
N100G0X0Y0
Z5.
G1Z-5.F100
X50.
Y50.
IF[[#33AND1]NE1]GOTO110(右上X)
G91X10.
X-10.
G90
N110IF[[#33AND16]NE16]GOTO120(右上X)
G91Y10.
Y-10.
G90
N120X-50.
IF[[#33AND2]NE2]GOTO130(左上X)
G91X-10.
X10.
G90
N130IF[[#33AND32]NE32]GOTO140(左上Y)
G91Y10.
Y-10.
G90
N140Y-50.
IF[[#33AND4]NE4]GOTO150(左下X)
G91X-10.
X10.
G90
N150IF[[#33AND64]NE64]GOTO160(左下Y)
G91Y-10.
Y10.
G90
N160X50.
IF[[#33AND8]NE8]GOTO170(右下X)
G91X10.
X-10.
G90
N170IF[[#33AND128]NE128]GOTO180(右下Y)
G91Y-10.
Y10.
G90
N180Y0
X0
G0Z100.
M99
----------

すみません、早速ですが訂正です。
----------
N10DO1
#31=#4-FIX[#4/10]*10-1
#32=1
WHILE[#31GT0]DO2
#32=#32*2
#31=#31-1
END2
#33=#33+#32
#4=FIX[#4/10]
IF[#4LE0]GOTO20
END1
N20DO1
#31=#5-FIX[#5/10]*10-1
#32=1
WHILE[#31GT0]DO2
#32=#32*2
#31=#31-1
END2
#33=#33+#32*16
#5=FIX[#5/10]
IF[#5LE0]GOTO100
END1
----------
下記のほうがGOTO不用でスタイリッシュです。
----------
WHILE[#4GT0]DO1
#31=#4-FIX[#4/10]*10-1
#32=1
WHILE[#31GT0]DO2
#32=#32*2
#31=#31-1
END2
#33=#33+#32
#4=FIX[#4/10]
END1
WHILE[#5GT0]DO1
#31=#5-FIX[#5/10]*10-1
#32=1
WHILE[#31GT0]DO2
#32=#32*2
#31=#31-1
END2
#33=#33+#32*16
#5=FIX[#5/10]
END1
----------

MODを使えば少し分かりやすく書けます。
----------
WHILE[#4GT0]DO1
#31=[#4MOD10]-1
#32=1
WHILE[#31GT0]DO2
#32=#32*2
#31=#31-1
END2
#33=#33+#32
#4=FIX[#4/10]
END1
WHILE[#5GT0]DO1
#31=[#5MOD*10]-1
#32=1
WHILE[#31GT0]DO2
#32=#32*2
#31=#31-1
END2
#33=#33+#32*16
#5=FIX[#5/10]
END1
----------
ですが、16i等ではMODは使えないと思います。

すみません、また訂正です。
----------
WHILE[#4GT0]DO1
#31=[#4MOD10]-1
#32=1
WHILE[#31GT0]DO2
#32=#32*2
#31=#31-1
END2
#33=#33+#32
#4=FIX[#4/10]
END1
WHILE[#5GT0]DO1
#31=[#5MOD*10]-1(<-)
#32=1
WHILE[#31GT0]DO2
#32=#32*2
#31=#31-1
END2
#33=#33+#32*16
#5=FIX[#5/10]
END1
----------
WHILE[#4GT0]DO1
#31=[#4MOD10]-1
#32=1
WHILE[#31GT0]DO2
#32=#32*2
#31=#31-1
END2
#33=#33+#32
#4=FIX[#4/10]
END1
WHILE[#5GT0]DO1
#31=[#5MOD10]-1(<-)
#32=1
WHILE[#31GT0]DO2
#32=#32*2
#31=#31-1
END2
#33=#33+#32*16
#5=FIX[#5/10]
END1
----------

これは、任意のビット位置の0/1を判定する定番の書き方で、
私も他人に教えてもらいました。

>仮にG65P0002I1.J1.だとすると#33=17になると思うのですが、
そのとおり、#33=(10進数)17=(2進数)00010001です。

>IF[[#33AND1]NE1]GOTO110(右上X)
(10進数)17=(2進数)00010001
(10進数) 1=(2進数)00000001
--------------------------
(AND) (2進数)00000001=(10進数)1←これを(10進数)1と比較(NE)。

>N110IF[[#33AND16]NE16]GOTO120(右上Y)←すみませんYでした
(10進数)17=(2進数)00010001
(10進数)16=(2進数)00010000
--------------------------
(AND) (2進数)00010000=(10進数)16←これを(10進数)16と比較(NE)。

128/64/32/16/8/4/2/1とすることで、
全てのビットを個別に判定できるわけです。

お礼

2012/02/24 14:58

ご丁寧に高度な解答有難うございます。
皆さんレベルが高いですね、、
頑張って解読します。

解りやすい解答有難うございます。
ANDは2進数判定するのですね。
10進数のみと思っていました。

さっそく試してみます。

質問者

補足

2012/02/29 13:41

>ですが、16i等ではMODは使えないと思います。

残念ながら16iもありますのでとりあえずMOD文ではなくて、
その前の追記文、FIXを用いた文例なのですが、、

仮にG65P0002I1.J1.だとすると#33=17になると思うのですが、

>IF[[#33AND1]NE1]GOTO110(右上X)
G91X10.
X-10.
G90
N110IF[[#33AND16]NE16]GOTO120(右上X)←Y?
G91Y10.
Y-10.
G90

この右上X・Yの判定文で#33=17との関連がよくわかりません。
(私の未熟さです。。)
よろしければ解説をお願いしたいのですが、、、

質問者

このQ&Aは役に立ちましたか?

この質問は投稿から一年以上経過しています。
解決しない場合、新しい質問の投稿をおすすめします。

質問する

その他の回答 (5件中 1~5件目)

2012/02/27 13:19
回答No.5

回答(4)さんの追記に反応して

MODが使える世代(31i等)なら、べき乗関数POWも使えるでしょうから
2のべき乗を計算をしている2重目のループが不要に出来ますね。

出来るだけ簡素に書くと

WHILE[#4GT0]DO1
#33=POW[2,[#4MOD10]-1]OR#33
#4=FIX[#4/10]
END1

WHILE[#5GT0]DO1
#33=POW[2,[#5MOD10]+3]OR#33
#5=FIX[#5/10]
END1

ただしこれじゃあまりにも不正値に対して弱いので
気休め程度のエラー処理を追加。

WHILE[#4GT0]DO1
#31=[#4MOD10]-1
IF[#31GT3]THEN#3000=1(I INCORRECT)
IF[#31GE0]THEN#33=POW[2,#31]OR#33
#4=FIX[#4/10]
END1

WHILE[#5GT0]DO1
#31=[#5MOD10]-1
IF[#31GT3]THEN#3000=1(J INCORRECT)
IF[#31GE0]THEN#33=POW[2,#31+4]OR#33
#5=FIX[#5/10]
END1

0は無視、5以上はエラー。

-------------
#33はフラグとして扱っているので
重複があるとビットシフトを起こす加算(+)を使うより
論理和(OR)を使った方が若干安全寄りな気がします。
おまじないみたいな物ですけど。

お礼

2012/03/16 09:15

遅くなってすいません。
かなりレベルが高いですね。
勉強になります、有難うございます。

質問者
2012/02/23 21:16
回答No.3

 回答(1)さんも言われているように、「逃し」の有無や方向を示す変数は“計算が容易”な形式を選んだ方が良いです。と言ってもそれを2進数の各ビットに割り当てて(10進数の)引数で渡すとなると、今度は人間様にとって対応が分りづらくなり使い難い。
その様な場合、引数としては人間に分かりやすい形式で表現し、マクロの先頭でそれを計算し易い形式に変換すると、人間もコンピュータもお互いハッピーに。

なのでまぁ1234でも良いんですが、もう少しだけ変換し易い書式にしても良いと思う。
2進数表記のまま10110100.などと渡してしまう方法もありますが、ここは

 ・X方向=1,Y方向=2として、右上から反時計回りに4桁で指示

という方法を提案。
例えば下記の様な形状の場合には 2011.(Y方向|無し|X方向|X方向) と表現します。

  __∩
 |  |
 |  |
⊂____⊃

で、これをどんな形式に変換するとマクロで処理しやすいのか、ですが

1つは回答(1)さんの言うように2進数に変換する方法。
2進数になってると、論理演算(ANDなど)でON・OFF判定が簡単に出来るから。

他にはたった4箇所だけなので、右上を#121、左上を#122...と言うように4つの変数に分けて保持する方法も考えられます。
この方法もカウンタ変数と合わせて#[121+#1]という風に扱えるので、WHILE文の中で使いやすい。
また2進数と違って状態を多数持てるので、逃し形状のバリエーションが増えた時などに対応し易いかも知れない。


-------------------------------

 次に加工動作のルーチンについて

コーナー形状が数パターンという事で、それをフラグに応じて条件分岐というのは間違いでは無いけど

> (実際はX,Y方向のどちらかの逃がしのみです。I,J同時に使用することはありません。)

この条件があるのであれば、基本的にポケット形状としては
「4つの直線と、4つの円弧」という構成は変化しない。
その上、円弧半径は全箇所共通、範囲も180度以下。
となると工具径補正を有効にすれば、必要なのは4つの円弧の始点・終点だけなので4x2x2=16個。
これくらいの量ならまとめて計算して#100番代などに順次放り込んでおき、最後にまとめて

G41G1D#7X_Y_F#9
G3X_Y_R_(接円アプローチ)
G1 (X#101) Y#102
G3 X#103 Y#104 R#33
G1 X#105 (Y#106)
G3 X#107 Y#108 R#33
G1 (X#109) Y#110
G3 X#111 Y#112 R#33
G1 X#113 (Y#114)
G3 X#115 Y#116 R#33
G1(X_)Y_
G3X_Y_R_(接円リトラクト)
G40G1X_Y_

などとしても良いんじゃないでしょうか。
これなら多少非力なNCでも経路途中でカクカクと止まることもないし、経路の先読みも確実に出来るのでオフセットベクトル計算も正しく行える筈。
括弧の所はポケットの向きが固定なら省略可。

一応工具径補正を使わなくても似たような事は可能ですが、もう少し(多分3倍くらい)計算が増えて面倒かと。

径補正を使う時の注意点はコーナーRと工具半径との関係ですが、それは冒頭で
  コーナーR>工具半径+仕上げ代
を満たしていなければ
  コーナーR=工具半径+仕上げ代、 および 逃しは全箇所無し
へとパラメータを変更してしまえば済む話。


この様にすると冒頭は計算が続くのでそこでのもたつきは発生し得るだろうけど、削ってる最中にカクつくよりは100倍マシ。
それに普通はZのアプローチ動作などが入るだろうから、その間に座標計算が終わってしまえば良いわけで...
どこに計算ルーチンを置くと演算ラグが気にならなくなるかは試行錯誤してみて下さい。

> 「4つの直線と、4つの円弧」という構成は変化しない。

よくよく考えたら仕上げ代がある場合には逃しの円弧の前後にG1なりG2なりを追加しないとまずそう。

となると結局

> 一応工具径補正を使わなくても似たような事は可能ですが、
> もう少し(多分3倍くらい)計算が増えて面倒かと。

と必要な計算量は同じになっちゃうかな?

と思ったけど、工具半径+仕上げ代をD99とかに入れておいて
G41D99にすれば最初の方法でも致命的な問題は無さそうな気がした。

次に円弧の始点・終点の座標の求め方ですが、例えば右上について見てみると

 角(右辺と上辺の交点)の座標を (X右,Y上)、
 コーナーの円弧半径を R とすると

・円弧の始点
  逃し形状 - X座標,Y座標
 (0)逃し無 - X右, Y上-R
 (1)X方向 - X右, Y上-2*R
 (2)Y方向 - X右, Y上

・円弧の終点
 (0)逃し無 - X右-R, Y上
 (1)X方向 - X右, Y上
 (2)Y方向 - X右-2*R, Y上

 ↑括弧内の数値はコーナー識別番号

他のコーナーも同様で、順序を抜きにすれば
ポケットの頂点座標にRの0,1,2倍を加減したものという関係。

...これ上手くすればIF文使わずに計算式だけで行けるんじゃ?

お礼

2012/02/24 14:56

有難うございます。
レベルが高すぎて現段階では呑み込めてません、、
じっくり理解していきます。

質問者
2012/02/22 22:14
回答No.2

式の評価に時間を食ってるんだと思います

逃がしありなしの サブプロを作っておく


N1000:1 逃がしありX
N1001:1 逃がしなしX

N1010:2 逃がしありX
N1011:2 逃がしなしX

N1020:3 逃がしありX
N1021:3 逃がしなしX

N1030:4 逃がしありX
N1031:4 逃がしなしX

N1100:1 逃がしありY
N1101:1 逃がしなしY









評価式で
X=12 Y=23 が成り立てば
ジャンプテーブルで

N1001 Xあり
N1100 Yなし

N1011 Xあり
N1110 Yなし

N1020 Xなし
N1121 Yあり

N1030 Xあり
N1131 Yなし


とする

ただしこの場合ジャンプテーブルが
長くなるが 4^4=256パターン

スムーズになるはず

補足

2012/02/23 18:29

サブを16パターン作るという事でしょうか?

IF文のORを一行に何度も使用しないで
何行かに分けるという事でしょうか?

質問者
2012/02/22 15:57
回答No.1

論理演算は十進数よりもビット単位でしょうが、、、

メンドクないヌスミ方法として、コーナのXY方向を一回で円弧で結んだ方が、除去量が少なく機能面でも見栄えでも優れます。

即ち、コーナの座標を通る円弧を描く。実際にはそれより幾分か0.1でも食い込み気味にする。


    *始点
|      
| * 円弧中心

 通過点*---------*-----
         終点
で判ると思います。
円弧の出っ張りは少ないので、半円丸ごとでは壁を破ってしまうな時でも、強度を心配せずに使えます。

これなら殆どの場合、4隅を一々指定せず全部やってしまってよいし、論理演算しての個々指定も4個で済みます。

人間には読みづらいがコンピュータはやはり二進数が扱いやすい。8ビットを各コーナに割当てる。

 二進数  十進数 加工部
00000001 = 1  1コーナのX
00000011 = 3  1 〃  XY
00001111 = 15  1,2 〃XY
00101111 = 47  1,2 〃XY +3のY

11111111 = 255  全て


プログラムの骨子だけ

   #1:引数

#2=1       ←初期設定

N1 IF[[#1 AND #2] EQ 0] GOTO 2 ←処理無いから次へ飛ぶ

  1コーナXの処理

N2 #2=#2*2      ←ビットをひとつ左へシフト
IF[[#1 AND #2] NE 0] GOTO 3

  1コーナYの処理

N3 #2=#2*2
IF[[#1 AND #2] NE 0] GOTO 4



この形状では工具径補正が非常に使いづらい。G4142は使わず、補正値を参照してその分軌跡をプログラムで変える方式にする。


なので、客先指定を変更するよう強力に働きかけるべきです。
スペアパーツ入れとか臍繰り用ポケットと言うなら別ですが、、、、

この形状は金型で多用します。設計初心者はマニュアル読まないとほぼ全てドカッとRを付けた絵を描く。
もし買い型でそれを発見したら、実力に?を付けます。

金型設計初心者はそうだが、一般機械屋は入れ子構造を使うのが少ないようで、ベテランでも多い。。。

>プログラムをコンパクトにしたくて

一方だけにして、他方はそれにミラーイメージを掛けるという手もあります。

×ミラーイメージ  →  座標回転 または 座標変換(+ミラーイメージ)

もうひとつのテクニック。
?カラ:#0?を使う。

#10=#0
#11=4.
G01 X#10 Y#11 → G01 Y4.

#0 はアドレスそのものを消し去ってしまうため、G90においてもXY両方向の動きが用意出来、変数で符号を変える操作をすると4隅ともに同じプログラムの繰返しで済ますことが出来るはずです。
マクロプログラムの極致!

IF[[#4EQ1.]OR[#4EQ12.]OR[#4EQ13.]OR[#4EQ14.]OR[#4EQ123.]OR[#4EQ124.]OR[#4EQ134.]OR[#4EQ1234.]]GOTO15211

この使い方マニュアルにありましたっけ? エラーになりません?
C言語などは出来るけどNCは?

EQ はIFまたはWHILE命令の中で使用する条件演算子。
OR は算術演算子。

算術演算子は複数使えるが、条件演算子は1個だけではないか?

補足

2012/02/22 16:25

>論理演算は十進数よりもビット単位でしょうが、、、

どういう意味でしょうか?(無知ですいません。)

>メンドクないヌスミ方法~

確かに簡単ですが、客先指定形状なので、、、すいません
(実際はX,Y方向のどちらかの逃がしのみです。I,J同時に使用することは
 ありません。ただプログラムをコンパクトにしたくて、、)

複数のアドバイス有難うございます。
2進数の考え方、いろいろ応用できそうです。

>ミラーイメージ
それもありですね。

>?カラ:#0?を使う。
すぐに構想できなさそうなのでじっくり考えてみます。

>この使い方マニュアルにありましたっけ? エラーになりません?
最近のFUNUCならできます。
約10年近く前の使用でもグレードによってはできました。

質問者

お礼をおくりました

さらに、この回答をベストアンサーに選びますか?

ベストアンサーを選ぶと質問が締切られます。
なおベストアンサーを選びなおすことはできません。