Commit | Line | Data |
---|---|---|
1217e470 QH |
1 | #include "MorganSCARASolution.h" |
2 | #include <fastmath.h> | |
3 | #include "checksumm.h" | |
4 | #include "ConfigValue.h" | |
5 | #include "libs/Kernel.h" | |
6 | //#include "StreamOutputPool.h" | |
7 | //#include "Gcode.h" | |
8 | //#include "SerialMessage.h" | |
9 | //#include "Conveyor.h" | |
10 | //#include "Robot.h" | |
11 | //#include "StepperMotor.h" | |
12 | ||
13 | #include "libs/nuts_bolts.h" | |
14 | ||
15 | #include "libs/Config.h" | |
16 | ||
17 | #define arm1_length_checksum CHECKSUM("arm1_length") | |
18 | #define arm2_length_checksum CHECKSUM("arm2_length") | |
19 | #define morgan_offset_x_checksum CHECKSUM("morgan_offset_x") | |
20 | #define morgan_offset_y_checksum CHECKSUM("morgan_offset_y") | |
21 | #define axis_scaling_x_checksum CHECKSUM("axis_scaling_x") | |
22 | #define axis_scaling_y_checksum CHECKSUM("axis_scaling_y") | |
3e1f5b74 | 23 | #define morgan_homing_checksum CHECKSUM("morgan_homing") |
1217e470 QH |
24 | |
25 | #define SQ(x) powf(x, 2) | |
26 | #define ROUND(x, y) (roundf(x * 1e ## y) / 1e ## y) | |
27 | ||
28 | MorganSCARASolution::MorganSCARASolution(Config* config) | |
29 | { | |
30 | // arm1_length is the length of the inner main arm from hinge to hinge | |
31 | arm1_length = config->value(arm1_length_checksum)->by_default(150.0f)->as_number(); | |
32 | // arm2_length is the length of the inner main arm from hinge to hinge | |
33 | arm2_length = config->value(arm2_length_checksum)->by_default(150.0f)->as_number(); | |
34 | // morgan_offset_x is the x offset of bed zero position towards the SCARA tower center | |
35 | morgan_offset_x = config->value(morgan_offset_x_checksum)->by_default(100.0f)->as_number(); | |
36 | // morgan_offset_y is the y offset of bed zero position towards the SCARA tower center | |
37 | morgan_offset_y = config->value(morgan_offset_y_checksum)->by_default(-65.0f)->as_number(); | |
38 | ||
39 | init(); | |
40 | } | |
41 | ||
42 | void MorganSCARASolution::init() { | |
43 | ||
44 | } | |
45 | ||
46 | float MorganSCARASolution::to_degrees(float radians) { | |
47 | return radians*(180.0F/3.14159265359f); | |
48 | } | |
49 | ||
50 | void MorganSCARASolution::cartesian_to_actuator( float cartesian_mm[], float actuator_mm[] ) | |
51 | { | |
52 | ||
53 | float SCARA_pos[2], | |
54 | SCARA_C2, | |
55 | SCARA_S2, | |
56 | SCARA_K1, | |
57 | SCARA_K2, | |
58 | SCARA_theta, | |
59 | SCARA_psi; | |
60 | ||
61 | SCARA_pos[X_AXIS] = cartesian_mm[X_AXIS] - this->morgan_offset_x; //Translate cartesian to tower centric SCARA X Y | |
62 | SCARA_pos[Y_AXIS] = cartesian_mm[Y_AXIS] - this->morgan_offset_y; // morgan_offset not to be confused with home offset. Makes the SCARA math work. | |
63 | ||
64 | if (this->arm1_length == this->arm2_length) | |
65 | SCARA_C2 = (SQ(SCARA_pos[X_AXIS])+SQ(SCARA_pos[Y_AXIS])-2.0f*SQ(this->arm1_length)) / (2.0f * SQ(this->arm1_length)); | |
66 | else | |
900601b5 QH |
67 | SCARA_C2 = (SQ(SCARA_pos[X_AXIS])+SQ(SCARA_pos[Y_AXIS])-SQ(this->arm1_length)-SQ(this->arm2_length)) / (2.0f * SQ(this->arm1_length)); |
68 | ||
69 | // SCARA position is undefined if abs(SCARA_C2) >=1 | |
70 | // In reality abs(SCARA_C2) >0.95 is problematic. | |
71 | ||
72 | if (SCARA_C2 > 0.95f) | |
73 | SCARA_C2 = 0.95f; | |
74 | else if (SCARA_C2 < -0.95f) | |
75 | SCARA_C2 = -0.95f; | |
76 | ||
1217e470 QH |
77 | |
78 | SCARA_S2 = sqrtf(1.0f-SQ(SCARA_C2)); | |
79 | ||
80 | SCARA_K1 = this->arm1_length+this->arm2_length*SCARA_C2; | |
81 | SCARA_K2 = this->arm2_length*SCARA_S2; | |
82 | ||
83 | SCARA_theta = (atan2f(SCARA_pos[X_AXIS],SCARA_pos[Y_AXIS])-atan2f(SCARA_K1, SCARA_K2))*-1.0f; // Morgan Thomas turns Theta in oposite direction | |
84 | SCARA_psi = atan2f(SCARA_S2,SCARA_C2); | |
85 | ||
86 | ||
87 | actuator_mm[ALPHA_STEPPER] = to_degrees(SCARA_theta); // Multiply by 180/Pi - theta is support arm angle | |
88 | actuator_mm[BETA_STEPPER ] = to_degrees(SCARA_theta + SCARA_psi); // Morgan kinematics (dual arm) | |
89 | //actuator_mm[BETA_STEPPER ] = to_degrees(SCARA_psi); // real scara | |
90 | actuator_mm[GAMMA_STEPPER] = cartesian_mm[Z_AXIS]; // No inverse kinematics on Z - Position to add bed offset? | |
91 | ||
92 | } | |
93 | ||
94 | void MorganSCARASolution::actuator_to_cartesian( float actuator_mm[], float cartesian_mm[] ) { | |
95 | // Perform forward kinematics, and place results in cartesian_mm[] | |
96 | ||
97 | float y1, y2, | |
98 | actuator_rad[2]; | |
99 | ||
100 | actuator_rad[X_AXIS] = actuator_mm[X_AXIS]/(180.0F/3.14159265359f); | |
101 | actuator_rad[Y_AXIS] = actuator_mm[Y_AXIS]/(180.0F/3.14159265359f); | |
102 | ||
103 | y1 = sinf(actuator_rad[X_AXIS])*this->arm1_length; | |
104 | y2 = sinf(actuator_rad[Y_AXIS])*this->arm2_length + y1; | |
105 | ||
106 | cartesian_mm[X_AXIS] = cosf(actuator_rad[X_AXIS])*this->arm1_length + cosf(actuator_rad[Y_AXIS])*this->arm2_length + this->morgan_offset_x; | |
107 | cartesian_mm[Y_AXIS] = y2 + this->morgan_offset_y; | |
108 | cartesian_mm[Z_AXIS] = actuator_mm[Z_AXIS]; | |
109 | ||
110 | cartesian_mm[0] = ROUND(cartesian_mm[0], 4); | |
111 | cartesian_mm[1] = ROUND(cartesian_mm[1], 4); | |
112 | cartesian_mm[2] = ROUND(cartesian_mm[2], 4); | |
113 | } | |
114 | ||
115 | bool MorganSCARASolution::set_optional(const arm_options_t& options) { | |
116 | ||
117 | arm_options_t::const_iterator i; | |
118 | ||
119 | i= options.find('T'); // Theta arm1 length | |
120 | if(i != options.end()) { | |
121 | arm1_length= i->second; | |
122 | ||
123 | } | |
124 | i= options.find('P'); // Psi arm2 length | |
125 | if(i != options.end()) { | |
126 | arm2_length= i->second; | |
127 | } | |
128 | i= options.find('X'); // Home initial position X | |
129 | if(i != options.end()) { | |
130 | morgan_offset_x= i->second; | |
131 | } | |
132 | i= options.find('Y'); // Home initial position Y | |
133 | if(i != options.end()) { | |
134 | morgan_offset_y= i->second; | |
135 | } | |
136 | ||
137 | init(); | |
138 | return true; | |
139 | } | |
140 | ||
141 | bool MorganSCARASolution::get_optional(arm_options_t& options) { | |
142 | options['T']= this->arm1_length; | |
143 | options['P']= this->arm2_length; | |
144 | options['X']= this->morgan_offset_x; | |
145 | options['Y']= this->morgan_offset_y; | |
146 | return true; | |
147 | }; |