Skip to content

Commit ded5c73

Browse files
authored
Merge pull request #3995 from rodw-au/state-tags-arcs
Add headings and other geometric pins in motion using State_tags
2 parents 8579ea3 + 292bff4 commit ded5c73

20 files changed

Lines changed: 900 additions & 4 deletions

docs/src/man/man9/motion.9.adoc

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,52 @@ Note: feed-inhibit applies to G-code commands -- not jogs.
263263
*motion.tp-reverse* OUT BIT::
264264
Trajectory planning is reversed (reverse run)
265265

266+
=== Interpreter Metadata Pins
267+
268+
These pins provide geometric intent and interpreter state for the segment of motion currently being executed. Unlike standard position feedback, these values are synchronized with the trajectory planner's execution point.
269+
270+
==== Interpreter Status Pins
271+
272+
* `motion.interp.line-number` (s32, out) +
273+
The current G-code line number being executed.
274+
275+
* `motion.interp.motion-type` (s32, out) +
276+
The type of motion currently in progress:
277+
** 0: None
278+
** 1: Rapid (G0)
279+
** 2: Feed (G1)
280+
** 3: Arc (G2, G3)
281+
** 4: Tool Change/Other
282+
283+
* `motion.interp.feedrate` (float, out) +
284+
The interpreted feedrate for the current segment in units per minute.
285+
286+
==== Interpreter Geometric Pins
287+
288+
* `motion.interp.heading` (float, out) +
289+
The XY plane heading of the current linear move in degrees. Measured counter-clockwise from the +X axis (0 to 360). This could be used to control a tangential knife.
290+
291+
* `motion.interp.arc-radius` (float, out) +
292+
The radius of the current circular move. This value is 0.0 during linear moves. This could be used to modify plasma cutting parameters based on the arc radius and when hole cutting.
293+
294+
* `motion.interp.arc-center-x` (float, out) +
295+
The absolute X-coordinate of the center point for the current arc. 0 if in YZ plane
296+
297+
* `motion.interp.arc-center-y` (float, out) +
298+
The absolute Y-coordinate of the center point for the current arc. 0 if in XZ plane
299+
300+
* `motion.interp.arc-center-z` (float, out) +
301+
The absolute Y-coordinate of the center point for the current arc if in XZ or YZ plane.
302+
303+
* `motion.interp.normal-heading` (float, out) +
304+
the heading from the current point back to the arc centre for the current arc.
305+
306+
* `motion.interp.iscircle` (bit, out) +
307+
True if the current arc is a full circle and not a helix.
308+
309+
[NOTE]
310+
These pins represent the *commanded geometric intent* from the interpreter and are updated in real-time as each motion segment is consumed by the trajectory planner.
311+
266312
== AXIS PINS
267313

268314
(*L* is the axis letter, one of: *x y z a b c u v w*)

src/emc/motion/command.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -530,6 +530,16 @@ void emcmotCommandHandler_locked(void *arg, long servo_period)
530530
SET_JOINT_FAULT_FLAG(joint, 0);
531531
}
532532
emcmotStatus->paused = 0;
533+
// Clear pins on abort so tests see a clean state
534+
if (emcmot_hal_data) {
535+
*(emcmot_hal_data->interp_arc_radius) = 0.0;
536+
*(emcmot_hal_data->interp_arc_center_x) = 0.0;
537+
*(emcmot_hal_data->interp_arc_center_y) = 0.0;
538+
*(emcmot_hal_data->interp_arc_center_z) = 0.0;
539+
*(emcmot_hal_data->interp_straight_heading) = 0.0;
540+
*(emcmot_hal_data->interp_normal_heading) = 0.0;
541+
*(emcmot_hal_data->iscircle) = 0.0;
542+
}
533543
break;
534544

535545
case EMCMOT_JOG_ABORT:

src/emc/motion/control.c

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include "config.h"
3535
#include "homing.h"
3636
#include "axis.h"
37+
#include "state_tag.h"
3738

3839
// Mark strings for translation, but defer translation to userspace
3940
#define _(s) (s)
@@ -1888,6 +1889,13 @@ static void output_to_hal(void)
18881889
*(emcmot_hal_data->coord_error) = GET_MOTION_ERROR_FLAG();
18891890
*(emcmot_hal_data->on_soft_limit) = emcmotStatus->on_soft_limit;
18901891

1892+
/* Performance Metadata */
1893+
*(emcmot_hal_data->interp_feedrate) = emcmotStatus->tag.fields_float[GM_FIELD_FLOAT_FEED];
1894+
1895+
/* Line and Motion Type (Casting to int for s32 HAL pins) */
1896+
*(emcmot_hal_data->interp_line_number) = (int)emcmotStatus->tag.fields[GM_FIELD_LINE_NUMBER];
1897+
*(emcmot_hal_data->interp_motion_type) = (int)emcmotStatus->tag.fields[GM_FIELD_MOTION_MODE];
1898+
*(emcmot_hal_data->iscircle) = (hal_bit_t)((emcmotStatus->tag.packed_flags & (1UL << GM_FLAG_IS_CIRCLE)) != 0);
18911899
switch (emcmotStatus->motionType) {
18921900
case EMC_MOTION_TYPE_FEED: //fall thru
18931901
case EMC_MOTION_TYPE_ARC:
@@ -2211,6 +2219,74 @@ static void update_status(void)
22112219
emcmotStatus->stepping = 0;
22122220
emcmotStatus->paused = 1;
22132221
}
2222+
// State Tags handling
2223+
// Get the current executing trajectory component (the "Source of Truth")
2224+
/* Update the HAL Output Pins from the active tag */
2225+
// Line and Motion Type
2226+
*(emcmot_hal_data->interp_line_number) = (int)emcmotStatus->tag.fields[GM_FIELD_LINE_NUMBER];
2227+
2228+
// Performance Metadata
2229+
*(emcmot_hal_data->interp_feedrate) = emcmotStatus->tag.fields_float[GM_FIELD_FLOAT_FEED];
2230+
2231+
// Geometric Metadata
2232+
*(emcmot_hal_data->interp_arc_radius) = emcmotStatus->tag.fields_float[GM_FIELD_FLOAT_ARC_RADIUS];
2233+
*(emcmot_hal_data->interp_arc_center_x) = emcmotStatus->tag.fields_float[GM_FIELD_FLOAT_ARC_CENTER_X];
2234+
*(emcmot_hal_data->interp_arc_center_y) = emcmotStatus->tag.fields_float[GM_FIELD_FLOAT_ARC_CENTER_Y];
2235+
*(emcmot_hal_data->interp_arc_center_z) = emcmotStatus->tag.fields_float[GM_FIELD_FLOAT_ARC_CENTER_Z];
2236+
2237+
// Get the current motion type from the tag (1=G1, 2=G2, 3=G3)
2238+
int motion_type = (int)emcmotStatus->tag.fields[GM_FIELD_MOTION_MODE];
2239+
if (motion_type == 10 || motion_type == 0) {
2240+
/* --- G1/G0 STATIC HEADING --- */
2241+
// For linear moves, the heading doesn't change during the segment.
2242+
*(emcmot_hal_data->interp_straight_heading) = emcmotStatus->tag.fields_float[GM_FIELD_FLOAT_STRAIGHT_HEADING];
2243+
}
2244+
else if (motion_type == 20 || motion_type == 30) {
2245+
/* --- G2/G3: DYNAMIC ARC HEADING --- */
2246+
2247+
// 1. Get Static Center from Tag
2248+
double cx = emcmotStatus->tag.fields_float[GM_FIELD_FLOAT_ARC_CENTER_X];
2249+
double cy = emcmotStatus->tag.fields_float[GM_FIELD_FLOAT_ARC_CENTER_Y];
2250+
double cz = emcmotStatus->tag.fields_float[GM_FIELD_FLOAT_ARC_CENTER_Z];
2251+
2252+
// 2. Get Real-Time Feedback Deltas
2253+
double dx = emcmotStatus->carte_pos_fb.tran.x - cx;
2254+
double dy = emcmotStatus->carte_pos_fb.tran.y - cy;
2255+
double dz = emcmotStatus->carte_pos_fb.tran.z - cz;
2256+
2257+
// 3. Determine Plane and Radial Angle
2258+
int plane = emcmotStatus->tag.fields[GM_FIELD_PLANE];
2259+
double angle_rad = 0.0; // Initialize to prevent "uninitialized" error
2260+
2261+
if (plane == 170) { // XY: X is Horizontal, Y is Verradiustical
2262+
angle_rad = atan2(dy, dx);
2263+
}
2264+
else if (plane == 180) { // XZ: Z is Horizontal, X is Vertical
2265+
angle_rad = atan2(dx, dz);
2266+
}
2267+
else if (plane == 190) { // YZ: Y is Horizontal, Z is Vertical
2268+
angle_rad = atan2(dz, dy);
2269+
}
2270+
// Optional: add an else here for a default plane if 170/180/190 aren't found
2271+
2272+
// 4. Calculate Normal Heading (Tool-to-Center)
2273+
double normal_deg = (angle_rad * (180.0 / M_PI)) + 180.0;
2274+
while (normal_deg < 0) normal_deg += 360.0;
2275+
while (normal_deg >= 360.0) normal_deg -= 360.0;
2276+
*(emcmot_hal_data->interp_normal_heading) = normal_deg;
2277+
2278+
// 5. Calculate Tangent Heading (Direction of Travel)
2279+
double tangent_rad = (motion_type == 30) ? (angle_rad + (M_PI / 2.0)) : (angle_rad - (M_PI / 2.0));
2280+
double heading_deg = tangent_rad * (180.0 / M_PI);
2281+
2282+
// 6. Final Normalization and Assignment
2283+
while (heading_deg < 0) heading_deg += 360.0;
2284+
while (heading_deg >= 360.0) heading_deg -= 360.0;
2285+
2286+
if (emcmot_hal_data->interp_straight_heading) {
2287+
*(emcmot_hal_data->interp_straight_heading) = heading_deg;
2288+
}
2289+
}
22142290
#ifdef WATCH_FLAGS
22152291
/*! \todo FIXME - this is for debugging */
22162292
if ( old_motion_flag != emcmotStatus->motionFlag ) {

src/emc/motion/mot_priv.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,19 @@ typedef struct {
199199
hal_float_t *feed_mm_per_second; /* feed mm per second*/
200200

201201
hal_float_t *switchkins_type;
202+
/* Interp State Pins */
203+
hal_s32_t *interp_line_number;
204+
hal_s32_t *interp_motion_type;
205+
hal_float_t *interp_feedrate;
206+
207+
/* New Geometric Metadata Pins */
208+
hal_float_t *interp_arc_radius;
209+
hal_float_t *interp_arc_center_x;
210+
hal_float_t *interp_arc_center_y;
211+
hal_float_t *interp_arc_center_z;
212+
hal_float_t *interp_straight_heading;
213+
hal_float_t *interp_normal_heading;
214+
hal_bit_t *iscircle;
202215
} emcmot_hal_data_t;
203216

204217
/***********************************************************************

src/emc/motion/motion.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -551,6 +551,20 @@ static int init_hal_io(void)
551551
CALL_CHECK(hal_pin_s32_newf(HAL_OUT, &(emcmot_hal_data->program_line), mot_comp_id, "motion.program-line"));
552552
CALL_CHECK(hal_pin_bit_newf(HAL_OUT, &(emcmot_hal_data->jog_is_active), mot_comp_id, "motion.jog-is-active"));
553553

554+
/* Standard Interp State Pins */
555+
CALL_CHECK(hal_pin_s32_newf(HAL_OUT, &(emcmot_hal_data->interp_line_number), mot_comp_id, "motion.interp.line-number"));
556+
CALL_CHECK(hal_pin_s32_newf(HAL_OUT, &(emcmot_hal_data->interp_motion_type), mot_comp_id, "motion.interp.motion-type"));
557+
CALL_CHECK(hal_pin_float_newf(HAL_OUT, &(emcmot_hal_data->interp_feedrate), mot_comp_id, "motion.interp.feedrate"));
558+
559+
/* New Geometric Metadata Pins */
560+
CALL_CHECK(hal_pin_float_newf(HAL_OUT, &(emcmot_hal_data->interp_arc_radius), mot_comp_id, "motion.interp.arc-radius"));
561+
CALL_CHECK(hal_pin_float_newf(HAL_OUT, &(emcmot_hal_data->interp_arc_center_x), mot_comp_id, "motion.interp.arc-center-x"));
562+
CALL_CHECK(hal_pin_float_newf(HAL_OUT, &(emcmot_hal_data->interp_arc_center_y), mot_comp_id, "motion.interp.arc-center-y"));
563+
CALL_CHECK(hal_pin_float_newf(HAL_OUT, &(emcmot_hal_data->interp_arc_center_z), mot_comp_id, "motion.interp.arc-center-z"));
564+
CALL_CHECK(hal_pin_float_newf(HAL_OUT, &(emcmot_hal_data->interp_straight_heading), mot_comp_id, "motion.interp.heading"));
565+
CALL_CHECK(hal_pin_float_newf(HAL_OUT, &(emcmot_hal_data->interp_normal_heading), mot_comp_id, "motion.interp.normal-heading"));
566+
CALL_CHECK(hal_pin_bit_newf(HAL_OUT, &emcmot_hal_data->iscircle, mot_comp_id, "motion.interp.iscircle"));
567+
554568
/* export debug parameters */
555569
/* these can be used to view any internal variable, simply change a line
556570
in control.c:output_to_hal() and recompile */

src/emc/motion/state_tag.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ typedef enum {
5757
GM_FLAG_IN_REMAP,
5858
GM_FLAG_IN_SUB,
5959
GM_FLAG_EXTERNAL_FILE,
60+
GM_FLAG_IS_CIRCLE,
6061
GM_FLAG_MAX_FLAGS
6162
} StateFlag;
6263

@@ -67,7 +68,7 @@ typedef enum {
6768
* WARNING:
6869
*
6970
* 1) Since these are used as array indices, they have to start at 0,
70-
* be monotonic, and the MAX_FIELDS enum MUST be last in the list.
71+
* be monotonic, and the GM_FIELD_MAX_FIELDS enum MUST be last in the list.
7172
*
7273
* 2) If your application needs to pass state tags through NML, then
7374
* you MUST update the corresponding cms->update function for state
@@ -98,6 +99,12 @@ typedef enum {
9899
GM_FIELD_FLOAT_SPEED,
99100
GM_FIELD_FLOAT_PATH_TOLERANCE,
100101
GM_FIELD_FLOAT_NAIVE_CAM_TOLERANCE,
102+
GM_FIELD_FLOAT_ARC_RADIUS,
103+
GM_FIELD_FLOAT_ARC_CENTER_X,
104+
GM_FIELD_FLOAT_ARC_CENTER_Y,
105+
GM_FIELD_FLOAT_ARC_CENTER_Z,
106+
GM_FIELD_FLOAT_STRAIGHT_HEADING,
107+
GM_FIELD_FLOAT_NORMAL_HEADING,
101108
GM_FIELD_FLOAT_MAX_FIELDS
102109
} StateFieldFloat;
103110

0 commit comments

Comments
 (0)