5 Axis MCT Tool Positioning Plugin for Grasshopper
Vector to IJKABC is a dedicated laser scanner positioning tool developed for Hwacheon LP840 Laser Ablation Machining Center. This GH component will convert GH frame data into machine specific formatted data. LP840 has varient head/table configuration, which differ from one another not only in freedom of axis, but also in travel constraints. XYZ IJK ABC are as follow.
XYZ : target position coordinate
IJK : directional vector
ABC : rotation (deg) on each axis (YZ,XZ,XY plane respectively)
I used IJK to calculate rotation degree on A,B and C.
A = arctan(k/abs(j))-PI/2
B = (arctan(k/abs(j))-PI/2)*(i/abs(i))
if 0<i<1 and -1<j<1, C = (arctan(j/abs(i))-PI/2)*(i/(abs(i))
if -1<i<0 and -1<j<1, C = (arctan(j/abs(i))+PI/2)*(i/abs(i))-PI
For example, in 4 Axis with Head/Table setup, table rotates while laser head rotates around x or y axis only.
This component works as part of LP840 Smart Texture for Rhino Grasshopper plug-in.
private void RunScript(Point3d pt, Vector3d v, int Mode, ref object I, ref object J, ref object K, ref object A, ref object B, ref object C, ref object formatted)
{
AxisTransform at = new AxisTransform(v, (MachineType) Mode);
double i = Math.Round(at.I(), 4);
double j = Math.Round(at.J(), 4);
double k = Math.Round(at.K(), 4);
//rad to deg
double a = Math.Round(at.A() * 180 / Math.PI, 4);
double b = Math.Round(at.B() * 180 / Math.PI, 4);
double c = Math.Round(at.C() * 180 / Math.PI, 4);
//Formatter
switch ((MachineType) Mode){
case MachineType.qaxvt:
{
formatted = x + ” ” + y + ” ” + z + ” ” + i + ” ” + j + ” ” + k + ” ” + c + ” “;
break;
}
case MachineType.qaxht:
{
formatted = x + ” ” + y + ” ” + z + ” ” + i + ” ” + j + ” ” + k + ” ” + c + ” “;
break;
}
case MachineType.vaxht:
{
formatted = x + ” ” + y + ” ” + z + ” ” + i + ” ” + j + ” ” + k + ” ” + b + ” ” + c + ” “;
break;
}
case MachineType.vaxtt:
{
formatted = x + ” ” + y + ” ” + z + ” ” + i + ” ” + j + ” ” + k + ” ” + a + ” ” + c + ” “;
break;
}
}
}
public enum MachineType {qaxvt, qaxht,vaxtt,vaxht};
//transform class
class AxisTransform{
//properties
private Vector3d norm;
private double i;
private double j;
private double k;
private double a;
private double b;
private double c;
//set ABC rotation value by MachineType
public AxisTransform(Vector3d n, MachineType tp){
norm = n;
i = norm.X;
j = norm.Y;
k = norm.Z;
switch(tp){
case MachineType.qaxvt:
{
c = qvtc();
break;
}
case MachineType.qaxht:
{
c = qhtc();
break;
}
case MachineType.vaxht:
{
b = vhtb();
c = vhtc();
break;
}
case MachineType.vaxtt:
{
a = vtta();
c = vttc();
break;
}
}
}
//get value methods
public double I(){
return i;
}
public double J(){
return j;
}
public double K(){
return k;
}
public double A(){
return a;
}
public double B(){
return b;
}
public double C(){
return c;
}
//calculate ABC rotation degree
// 5 axis Head Table B
private double vhtb(){
double bx;
if(i == 0 && j == 0){
bx = 0;
}
else{
bx = -(System.Math.Atan(k / System.Math.Pow(Math.Pow(i, 2) + Math.Pow(j, 2), 0.5)) – System.Math.PI / 2);
}
return bx;
}
//5 axis Head Table C
private double vhtc(){
double cx;
if(i > 0){
cx = (Math.Atan(j / Math.Abs(i)) – (Math.PI / 2)) * (i / Math.Abs(i)) + (Math.PI / 2);
}
else if(i < 0){
cx = (Math.Atan(j / Math.Abs(i)) + (Math.PI / 2)) * (i / Math.Abs(i)) – (Math.PI / 2);
}
else{
cx = -Math.PI / 2;
}
return cx;
}
//5 axis Table Table A
private double vtta(){
double ax;
if(i == 0 && j == 0){
ax = 0;
}
else{
ax = System.Math.Atan(k / System.Math.Pow(Math.Pow(i, 2) + Math.Pow(j, 2), 0.5)) – System.Math.PI / 2;
}
return ax;
}
//5 axis Table Table C
private double vttc(){
double cx;
if(i > 0){
cx = (Math.Atan(j / Math.Abs(i)) – (Math.PI / 2)) * (i / Math.Abs(i));
}
else if(i < 0){
cx = (Math.Atan((j / Math.Abs(i)) + Math.PI / 2)) * (i / Math.Abs(i)) – Math.PI / 2;
}
else{
cx = 0;
}
return cx;
}
//4 axis Heac Table C
private double qhtc(){
double cx;
if(k == 1){
cx = 0;
}
else if(k == -1){
cx = -Math.PI;
}
else if(j == 1){
cx = -Math.PI / 2;
}
else if(j == -1){
cx = -3 * Math.PI / 2;
}
else if(j > 0){
cx = (Math.Atan((k / Math.Abs(j)) – Math.PI / 2)) * (j / Math.Abs(j));
}
else{
cx = (Math.Atan((k / Math.Abs(j)) – Math.PI / 2)) * (j / Math.Abs(j)) – Math.PI;
}
return cx;
}
//4 axis Table only C
private double qvtc(){
double cx;
if(j == 1){
cx = 0;
}
else if(j == -1){
cx = -Math.PI;
}
else if(i == 1){
cx = -Math.PI / 2;
}
else if(i == -1){
cx = -3 * Math.PI / 2;
}
else if(i > 0){
cx = (Math.Atan((j / Math.Abs(i)) – Math.PI / 2)) * (i / Math.Abs(i));
}
else{
cx = (Math.Atan((j / Math.Abs(i)) + Math.PI / 2)) * (i / Math.Abs(i)) – Math.PI;
}
return cx;
}
}