Skip to content
Open
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
5a8e0d9
first attempt to create state tag pins
Apr 13, 2026
cac77e5
After getting most things working except publishing pins
Apr 14, 2026
52572e5
corrections for straight heading
Apr 24, 2026
da9fa18
Merge branch 'master' into state-tags-arcs
Apr 26, 2026
12d2cc2
changes for abort
May 1, 2026
d4f3a18
Merge remote-tracking branch 'upstream/master'
May 1, 2026
00450b3
Merge branch 'master' into state-tags-arcs
May 1, 2026
1321309
add normalheading and an iscircle flag
May 2, 2026
7ae6979
update docs for normal heading and iscircle
May 2, 2026
8a869ec
M70 problems
May 2, 2026
2702760
state-tags: clean up M70 fix, iscircle null-deref, wrong flag-as-fiel…
grandixximo May 2, 2026
7c6f016
Merge pull request #10 from grandixximo/fix-state-tags-stack-overflow
rodw-au May 2, 2026
8413344
reset iscircle, remove output_buffer.9 intermediate file
May 2, 2026
245e91b
state-tags: replace M_PI_2 with M_PI/2 for RTAI build
grandixximo May 3, 2026
de27899
Merge pull request #11 from grandixximo/fix-rtai-mpi2
rodw-au May 3, 2026
7021690
edit .gitignore to exclude docs/man/man9/output_buffer.9
May 3, 2026
20992b0
1. Deleted nc_files folder which was added due to Issue #3924 that wa…
May 3, 2026
5b2d61f
Revert interp_convert to master branch version
May 3, 2026
5461c2d
Reformatted interp_conv.cc by reverting to master branch version,
May 3, 2026
bafea85
Restore -nc-files folder that I thought had been added by bug introdu…
May 4, 2026
b576a1f
housekeeping with gitignore
May 4, 2026
ecb5799
delete file not part of this PR. Resolved permanently in #4002
May 4, 2026
d61aea7
state_tag.h - Corrected error in comment that predated this commit
May 4, 2026
34af536
Merge remote-tracking branch 'upstream/master' into state-tags-arcs
May 4, 2026
37bd9ba
Merge remote-tracking branch 'upstream/master'
May 4, 2026
026421b
removed unused tag GM_FIELD_FLOAT_FEEDRATE
May 4, 2026
aa3f8e3
remove unused tag GM_FIELD_FLOAT_FEEDRATE
May 4, 2026
892b9a3
remove typo caused by editor
May 4, 2026
4fc14bc
force added missing 3D_Chips.pdf file
May 4, 2026
8560dac
Minor White space cleanup
May 5, 2026
81e061d
removed duplicate pin which broke runtests
May 5, 2026
d707137
Changes:
May 7, 2026
2d9030a
Correct tor runtests RTAI buildbot error
May 7, 2026
cbc2c6d
runtest for motion.heading - incomplete
May 8, 2026
9d7b041
update hal and ini to remove voluminous debug statements
May 8, 2026
b79afe5
restore interp/subdoutine-return test
May 8, 2026
90a6c94
changes to use sampler via python ui -interim
May 9, 2026
87a2fb2
update with tests mostly working. I have to correct for machine units…
May 10, 2026
28395da
not understading how to do the final test
May 10, 2026
697ac51
Runtests finally working!
May 11, 2026
44bf837
Final changes to test all scenarios for metric and imperial machines …
May 13, 2026
01dba4d
Merge remote-tracking branch 'upstream/master'
May 13, 2026
b700943
Merge branch 'master' into state-tags-arcs
May 13, 2026
b59c583
remove error in git merge
May 13, 2026
d0d7143
add back in test files
May 13, 2026
43c1a2a
Resolve clang error on github workflow
May 13, 2026
f030b39
Not using correct radius calculation AND not using G20 in Gcode
May 13, 2026
0b572ff
Revert interp_convert.cc to state at HEAD~2
May 13, 2026
043af1f
Implemented tests all in one folder
May 13, 2026
f9e9707
final changes after review
May 13, 2026
3e3ac4f
last minute fixes from review
May 13, 2026
39a2445
Adjust white space. Editor automatically adds a tab. Grr
May 13, 2026
1305055
whitespace take 2
May 13, 2026
82cc7f0
whitespace cleanup, some code cleanup
May 14, 2026
c608d9f
revised gcode file to not use machine units
May 14, 2026
b4e3848
white space cleanup
May 14, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions docs/src/man/man9/motion.9.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,49 @@ Note: feed-inhibit applies to G-code commands -- not jogs.
*motion.tp-reverse* OUT BIT::
Trajectory planning is reversed (reverse run)

=== Interpreter Metadata Pins

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.

==== Interpreter Status Pins

* `motion.interp.line-number` (s32, out) +
The current G-code line number being executed.

* `motion.interp.motion-type` (s32, out) +
The type of motion currently in progress:
** 0: None
** 1: Rapid (G0)
** 2: Feed (G1)
** 3: Arc (G2, G3)
** 4: Tool Change/Other

* `motion.interp.feedrate` (float, out) +
The interpreted feedrate for the current segment in units per minute.

==== Interpreter Geometric Pins

* `motion.interp.heading` (float, out) +
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.

* `motion.interp.arc-radius` (float, out) +
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.

* `motion.interp.arc-center-x` (float, out) +
The absolute X-coordinate of the center point for the current arc.

* `motion.interp.arc-center-y` (float, out) +
The absolute Y-coordinate of the center point for the current arc.
Comment thread
rodw-au marked this conversation as resolved.
Outdated

* `motion.interp.normal-heading` (float, out) +
the heading from the current point back to the arc circlefor the current arc.

* `motion.interp.iscircle` (bit, out) +
True if the current arc is a full circle.
Comment thread
rodw-au marked this conversation as resolved.
Outdated

[NOTE]
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.

== AXIS PINS

(*L* is the axis letter, one of: *x y z a b c u v w*)
Expand Down
Binary file removed nc_files/3D_Chips.pdf
Binary file not shown.
9 changes: 9 additions & 0 deletions src/emc/motion/command.c
Original file line number Diff line number Diff line change
Expand Up @@ -530,6 +530,15 @@ void emcmotCommandHandler_locked(void *arg, long servo_period)
SET_JOINT_FAULT_FLAG(joint, 0);
}
emcmotStatus->paused = 0;
// Clear pins on abort so tests see a clean state
if (emcmot_hal_data) {
*(emcmot_hal_data->interp_arc_radius) = 0.0;
*(emcmot_hal_data->interp_arc_center_x) = 0.0;
*(emcmot_hal_data->interp_arc_center_y) = 0.0;
*(emcmot_hal_data->interp_straight_heading) = 0.0;
Comment thread
BsAtHome marked this conversation as resolved.
*(emcmot_hal_data->interp_normal_heading) = 0.0;
*(emcmot_hal_data->iscircle) = 0.0;
}
break;

case EMCMOT_JOG_ABORT:
Expand Down
96 changes: 92 additions & 4 deletions src/emc/motion/control.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,15 @@
#include <posemath.h>
#include <kinematics.h> //for kinematicsSwitchable()
#include <motion_types.h>

#include "../tp/tp.h"
#include "simple_tp.h"
#include "motion.h"
#include "mot_priv.h"
#include "config.h"
#include "homing.h"
#include "axis.h"
#include "state_tag.h"


// Mark strings for translation, but defer translation to userspace
#define _(s) (s)
Expand Down Expand Up @@ -1888,6 +1889,20 @@ static void output_to_hal(void)
*(emcmot_hal_data->coord_error) = GET_MOTION_ERROR_FLAG();
*(emcmot_hal_data->on_soft_limit) = emcmotStatus->on_soft_limit;

/* Update the HAL Output Pins from the active tag */
/* Geometric Metadata */
*(emcmot_hal_data->interp_arc_radius) = emcmotStatus->tag.fields_float[GM_FIELD_FLOAT_ARC_RADIUS];
*(emcmot_hal_data->interp_arc_center_x) = emcmotStatus->tag.fields_float[GM_FIELD_FLOAT_ARC_CENTER_X];
*(emcmot_hal_data->interp_arc_center_y) = emcmotStatus->tag.fields_float[GM_FIELD_FLOAT_ARC_CENTER_Y];
*(emcmot_hal_data->interp_straight_heading) = emcmotStatus->tag.fields_float[GM_FIELD_FLOAT_STRAIGHT_HEADING];

/* Performance Metadata */
*(emcmot_hal_data->interp_feedrate) = emcmotStatus->tag.fields_float[GM_FIELD_FLOAT_FEED];

/* Line and Motion Type (Casting to int for s32 HAL pins) */
*(emcmot_hal_data->interp_line_number) = (int)emcmotStatus->tag.fields[GM_FIELD_LINE_NUMBER];
*(emcmot_hal_data->interp_motion_type) = (int)emcmotStatus->tag.fields[GM_FIELD_MOTION_MODE];
*(emcmot_hal_data->iscircle) = (hal_bit_t)((emcmotStatus->tag.packed_flags & (1UL << GM_FLAG_IS_CIRCLE)) != 0);
switch (emcmotStatus->motionType) {
case EMC_MOTION_TYPE_FEED: //fall thru
case EMC_MOTION_TYPE_ARC:
Expand Down Expand Up @@ -2033,10 +2048,8 @@ static void output_to_hal(void)
/* point to joint struct */
joint = &joints[joint_num];
joint_data = &(emcmot_hal_data->joint[joint_num]);

/* apply backlash and motor offset to output */
joint->motor_pos_cmd =
joint->pos_cmd + joint->backlash_filt + joint->motor_offset;
Comment thread
BsAtHome marked this conversation as resolved.
joint->motor_pos_cmd = joint->pos_cmd + joint->backlash_filt + joint->motor_offset;
/* point to HAL data */
/* write to HAL pins */
*(joint_data->motor_offset) = joint->motor_offset;
Expand Down Expand Up @@ -2131,6 +2144,9 @@ static void update_status(void)
// and the state machine is still active. The homing status deassertion
// must be delayed until the state machine is done.
joint_status->homing = get_homing(joint_num);
/* check to see if we should pause in order to implement
single emcmotStatus->stepping */

}
joint_status->homed = get_homed(joint_num);
joint_status->pos_cmd = joint->pos_cmd;
Expand Down Expand Up @@ -2211,6 +2227,78 @@ static void update_status(void)
emcmotStatus->stepping = 0;
emcmotStatus->paused = 1;
}
// State Tags handling
// Get the current executing trajectory component (the "Source of Truth")
/* Update the HAL Output Pins from the active tag */
if (emcmot_hal_data) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are you testing for emcmot_hal_data to be non-null?

This same function derefences that exact same variable and does not check. So, the check is superfluous and creates a false sense of guard. The whole containing if() construct is redundant.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a mess of spaces and tabs, went with spaces on my stuff

// Line and Motion Type
if (emcmot_hal_data->interp_line_number) {
*(emcmot_hal_data->interp_line_number) = (int)emcmotStatus->tag.fields[GM_FIELD_LINE_NUMBER];
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two issues:

  1. This added code uses tab indenting, which looks fine here, but is not looking good elsewhere because this file is a mixed jumble of tabs and spaces. You should use 4 spaces per level of indent. This happens also in other files. You should review all your additions in all changed files to use the style of that particular file (yes, it is a messy business). If the file uses all tabs, you also use tabs. If the file uses spaces, you also use spaces.
  2. You have trailing whitespace on many lines you added here. Please clean that up too. You should check all your additions for trailing whitespace.

}

// Performance Metadata
if (emcmot_hal_data->interp_feedrate) {
*(emcmot_hal_data->interp_feedrate) = emcmotStatus->tag.fields_float[GM_FIELD_FLOAT_FEED];
}

// Geometric Metadata

if (emcmot_hal_data->interp_arc_radius) {
*(emcmot_hal_data->interp_arc_radius) = emcmotStatus->tag.fields_float[GM_FIELD_FLOAT_ARC_RADIUS];
}
if (emcmot_hal_data->interp_arc_center_x) {
*(emcmot_hal_data->interp_arc_center_x) = emcmotStatus->tag.fields_float[GM_FIELD_FLOAT_ARC_CENTER_X];
}
if (emcmot_hal_data->interp_arc_center_y) {
*(emcmot_hal_data->interp_arc_center_y) = emcmotStatus->tag.fields_float[GM_FIELD_FLOAT_ARC_CENTER_Y];
}
// Get the current motion type from the tag (1=G1, 2=G2, 3=G3)
int motion_type = (int)emcmotStatus->tag.fields[GM_FIELD_MOTION_MODE];
if (motion_type == 10 || motion_type == 0) {
/* --- G1: STATIC HEADING --- */
// For linear moves, the heading doesn't change during the segment.
if (emcmot_hal_data->interp_straight_heading) {
*(emcmot_hal_data->interp_straight_heading) = emcmotStatus->tag.fields_float[GM_FIELD_FLOAT_STRAIGHT_HEADING];
}
}
else if (motion_type == 20 || motion_type == 30) {
/* --- G2/G3: DYNAMIC ARC HEADING --- */
double cx = emcmotStatus->tag.fields_float[GM_FIELD_FLOAT_ARC_CENTER_X];
double cy = emcmotStatus->tag.fields_float[GM_FIELD_FLOAT_ARC_CENTER_Y];
*(emcmot_hal_data->iscircle) = (hal_bit_t)((emcmotStatus->tag.packed_flags & (1UL << GM_FLAG_IS_CIRCLE)) != 0);
// Current RT feedback position
double dx = emcmotStatus->carte_pos_fb.tran.x - cx;
double dy = emcmotStatus->carte_pos_fb.tran.y - cy;
double angle_rad = atan2(dy, dx);
// Normal heading is tool-to-centre (opposite of radial)
double normal_heading_deg = (angle_rad * (180.0 / M_PI)) + 180.0;
while (normal_heading_deg < 0) normal_heading_deg += 360.0;
while (normal_heading_deg >= 360.0) normal_heading_deg -= 360.0;
*(emcmot_hal_data->interp_normal_heading) = normal_heading_deg;

double heading_deg;

// G3 (CCW): Heading is Radial Angle + 90 degrees
if (motion_type == 30) {
heading_deg = (angle_rad + (M_PI / 2.0)) * (180.0 / M_PI);
}
// G2 (CW): Heading is Radial Angle - 90 degrees
else {
heading_deg = (angle_rad - (M_PI / 2.0)) * (180.0 / M_PI);
}
// 0-360 Normalization
while (heading_deg < 0) heading_deg += 360.0;
while (heading_deg >= 360.0) heading_deg -= 360.0;

// Now assign the calculated value
if (emcmot_hal_data->interp_straight_heading)
*(emcmot_hal_data->interp_straight_heading) = heading_deg;
// Performance Metadata
if (emcmot_hal_data->interp_feedrate) {
*(emcmot_hal_data->interp_feedrate) = emcmotStatus->tag.fields_float[GM_FIELD_FLOAT_FEED];
}
}
}
#ifdef WATCH_FLAGS
/*! \todo FIXME - this is for debugging */
if ( old_motion_flag != emcmotStatus->motionFlag ) {
Expand Down
12 changes: 12 additions & 0 deletions src/emc/motion/mot_priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,18 @@ typedef struct {
hal_float_t *feed_mm_per_second; /* feed mm per second*/

hal_float_t *switchkins_type;
/* Interp State Pins */
hal_s32_t *interp_line_number;
hal_s32_t *interp_motion_type;
hal_float_t *interp_feedrate;

/* New Geometric Metadata Pins */
hal_float_t *interp_arc_radius;
hal_float_t *interp_arc_center_x;
hal_float_t *interp_arc_center_y;
hal_float_t *interp_straight_heading;
hal_float_t *interp_normal_heading;
hal_bit_t *iscircle;
} emcmot_hal_data_t;

/***********************************************************************
Expand Down
16 changes: 16 additions & 0 deletions src/emc/motion/motion.c
Original file line number Diff line number Diff line change
Expand Up @@ -551,6 +551,21 @@ static int init_hal_io(void)
CALL_CHECK(hal_pin_s32_newf(HAL_OUT, &(emcmot_hal_data->program_line), mot_comp_id, "motion.program-line"));
CALL_CHECK(hal_pin_bit_newf(HAL_OUT, &(emcmot_hal_data->jog_is_active), mot_comp_id, "motion.jog-is-active"));

/* Standard Interp State Pins */
CALL_CHECK(hal_pin_s32_newf(HAL_OUT, &(emcmot_hal_data->interp_line_number), mot_comp_id, "motion.interp.line-number"));
CALL_CHECK(hal_pin_s32_newf(HAL_OUT, &(emcmot_hal_data->interp_motion_type), mot_comp_id, "motion.interp.motion-type"));
CALL_CHECK(hal_pin_float_newf(HAL_OUT, &(emcmot_hal_data->interp_feedrate), mot_comp_id, "motion.interp.feedrate"));

/* New Geometric Metadata Pins */
CALL_CHECK(hal_pin_float_newf(HAL_OUT, &(emcmot_hal_data->interp_arc_radius), mot_comp_id, "motion.interp.arc-radius"));
CALL_CHECK(hal_pin_float_newf(HAL_OUT, &(emcmot_hal_data->interp_arc_center_x), mot_comp_id, "motion.interp.arc-center-x"));
CALL_CHECK(hal_pin_float_newf(HAL_OUT, &(emcmot_hal_data->interp_arc_center_y), mot_comp_id, "motion.interp.arc-center-y"));
CALL_CHECK(hal_pin_float_newf(HAL_OUT, &(emcmot_hal_data->interp_straight_heading), mot_comp_id, "motion.interp.heading"));
CALL_CHECK(hal_pin_float_newf(HAL_OUT, &(emcmot_hal_data->interp_normal_heading), mot_comp_id, "motion.interp.normal-heading"));
CALL_CHECK(hal_pin_bit_newf(HAL_OUT, &emcmot_hal_data->iscircle, mot_comp_id, "motion.interp.iscircle"));
//CALL_CHECK(hal_pin_bit_newf(HAL_OUT, &(emcmot_hal_data->jog_is_active), mot_comp_id, "motion.jog-is-active"));


/* export debug parameters */
/* these can be used to view any internal variable, simply change a line
in control.c:output_to_hal() and recompile */
Expand All @@ -563,6 +578,7 @@ static int init_hal_io(void)
CALL_CHECK(hal_param_s32_newf(HAL_RO, &(emcmot_hal_data->debug_s32_0), mot_comp_id, "motion.debug-s32-0"));
CALL_CHECK(hal_param_s32_newf(HAL_RO, &(emcmot_hal_data->debug_s32_1), mot_comp_id, "motion.debug-s32-1"));


Comment thread
BsAtHome marked this conversation as resolved.
Outdated
// FIXME - debug only, remove later
// export HAL parameters for some trajectory planner internal variables
// so they can be scoped
Expand Down
13 changes: 11 additions & 2 deletions src/emc/motion/state_tag.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ typedef enum {
GM_FLAG_IN_REMAP,
GM_FLAG_IN_SUB,
GM_FLAG_EXTERNAL_FILE,
GM_FLAG_IS_CIRCLE,
GM_FLAG_MAX_FLAGS
} StateFlag;

Expand All @@ -67,7 +68,7 @@ typedef enum {
* WARNING:
*
* 1) Since these are used as array indices, they have to start at 0,
* be monotonic, and the MAX_FIELDS enum MUST be last in the list.
* be monotonic, and the MAX_FIELDS GM_FIELD_FLOAT_MAX_FIELDS enum MUST be last in the list.
Comment thread
BsAtHome marked this conversation as resolved.
Outdated
*
* 2) If your application needs to pass state tags through NML, then
* you MUST update the corresponding cms->update function for state
Expand Down Expand Up @@ -98,6 +99,12 @@ typedef enum {
GM_FIELD_FLOAT_SPEED,
GM_FIELD_FLOAT_PATH_TOLERANCE,
GM_FIELD_FLOAT_NAIVE_CAM_TOLERANCE,
GM_FIELD_FLOAT_FEEDRATE,
Comment thread
BsAtHome marked this conversation as resolved.
Outdated
GM_FIELD_FLOAT_ARC_RADIUS,
GM_FIELD_FLOAT_ARC_CENTER_X,
GM_FIELD_FLOAT_ARC_CENTER_Y,
GM_FIELD_FLOAT_STRAIGHT_HEADING,
GM_FIELD_FLOAT_NORMAL_HEADING,
GM_FIELD_FLOAT_MAX_FIELDS
} StateFieldFloat;

Expand All @@ -118,7 +125,9 @@ struct state_tag_t {
float fields_float[GM_FIELD_FLOAT_MAX_FIELDS];

// Any G / M code states that doesn't pack nicely into a single bit
// These are an array mostly because it's easier to pass an
// These are an array mostly because In function ‘output_to_hal’,

//it's easier to pass an
// arbitrary-length array through NML than individual fields
Comment thread
BsAtHome marked this conversation as resolved.
Outdated
int fields[GM_FIELD_MAX_FIELDS];

Expand Down
Loading
Loading