按建议,继续下一步工作

结论:已将 LinuxCNC TP 源码纳入 wasm-port 的可复现 vendor 清单和 native probe 构建,新增真实 tpCreate/tpAddLine/tpRunCycle 线性运动验证,并通过 native probes 全量验证。
This commit is contained in:
2026-06-07 07:39:26 +08:00
parent 078f1f6f8e
commit e328394184
72 changed files with 27200 additions and 0 deletions

View File

@@ -0,0 +1,60 @@
#ifndef AXIS_H
#define AXIS_H
#include <rtapi_bool.h>
#include <hal.h>
#ifdef __cplusplus
extern "C" {
#endif
void axis_init_all(void);
void axis_initialize_external_offsets(void);
int axis_init_hal_io(int mot_comp_id);
void axis_handle_jogwheels(bool motion_teleop_flag, bool motion_enable_flag, bool homing_is_active);
bool axis_plan_external_offsets(double servo_period, bool motion_enable_flag, bool all_homed);
void axis_check_constraints(double pos[], int failing_axes[]);
void axis_jog_cont(int axis_num, double vel, long servo_period);
void axis_jog_incr(int axis_num, double offset, double vel, long servo_period);
void axis_jog_abs(int axis_num, double offset, double vel);
bool axis_jog_abort_all(bool immediate);
bool axis_jog_abort(int axis_num, bool immediate);
bool axis_jog_is_active(void);
void axis_output_to_hal(double *pcmd_p[]);
void axis_set_max_pos_limit(int axis_num, double maxLimit);
void axis_set_min_pos_limit(int axis_num, double minLimit);
void axis_set_vel_limit(int axis_num, double vel);
void axis_set_acc_limit(int axis_num, double acc);
void axis_set_jerk_limit(int axis_num, double jerk);
void axis_set_ext_offset_vel_limit(int axis_num, double ext_offset_vel);
void axis_set_ext_offset_acc_limit(int axis_num, double ext_offset_acc);
void axis_set_locking_joint(int axis_num, int joint);
double axis_get_min_pos_limit(int axis_num);
double axis_get_max_pos_limit(int axis_num);
double axis_get_vel_limit(int axis_num);
double axis_get_acc_limit(int axis_num);
int axis_get_locking_joint(int axis_num);
double axis_get_compound_velocity(void);
double axis_get_ext_offset_curr_pos(int axis_num);
double axis_get_teleop_vel_cmd(int axis_num);
void axis_sync_teleop_tp_to_carte_pos(int extfactor, double *pcmd_p[]);
void axis_sync_carte_pos_to_teleop_tp(int extfactor, double *pcmd_p[]);
void axis_apply_ext_offsets_to_carte_pos(int extfactor, double *pcmd_p[]);
int axis_update_coord_with_bound(double *pcmd_p[], double servo_period);
int axis_calc_motion(double servo_period);
#ifdef __cplusplus
}
#endif
#endif /* AXIS_H */

View File

@@ -0,0 +1,355 @@
/*******************************************************************
* Description: mot_priv.h
* Macros and declarations local to the realtime sources.
*
* Author:
* License: GPL Version 2
* System: Linux
*
* Copyright (c) 2004 All rights reserved.
********************************************************************/
#ifndef MOT_PRIV_H
#define MOT_PRIV_H
/***********************************************************************
* TYPEDEFS, ENUMS, ETC. *
************************************************************************/
/* First we define structures for data shared with the HAL */
/* HAL visible data notations:
RPA: read only parameter
WPA: write only parameter
WRPA: read/write parameter
RPI: read only pin
WPI: write only pin
WRPI: read/write pin
*/
/* joint data */
#include <hal.h>
#include "../motion/motion.h"
typedef struct {
// creating a lot of pins for spindle control to be very flexible
// the user needs only a subset of these
// simplest way of spindle control (output start/stop)
hal_bit_t *spindle_on; /* spindle spin output */
// same thing for 2 directions
hal_bit_t *spindle_forward; /* spindle spin-forward output */
hal_bit_t *spindle_reverse; /* spindle spin-reverse output */
// simple velocity control (as long as the output is active the spindle
// should accelerate/decelerate
hal_bit_t *spindle_incr_speed; /* spindle spin-increase output */
hal_bit_t *spindle_decr_speed; /* spindle spin-decrease output */
// simple output for brake
hal_bit_t *spindle_brake; /* spindle brake output */
// output of a prescribed speed (to hook-up to a velocity controller)
hal_float_t *spindle_speed_out; /* spindle speed output */
hal_float_t *spindle_speed_out_rps; /* spindle speed output */
hal_float_t *spindle_speed_out_abs; /* spindle speed output absolute*/
hal_float_t *spindle_speed_out_rps_abs; /* spindle speed output absolute*/
hal_float_t *spindle_speed_cmd_rps; /* spindle speed command without SO applied */
hal_float_t *spindle_speed_in; /* spindle speed measured */
hal_bit_t *spindle_index_enable; /* spindle inde I/O pin */
hal_bit_t *spindle_inhibit;
hal_float_t *spindle_revs;
hal_bit_t *spindle_is_atspeed;
hal_bit_t *spindle_amp_fault;
// spindle orient
hal_float_t *spindle_orient_angle; /* out: desired spindle angle, degrees */
hal_s32_t *spindle_orient_mode; /* out: 0: least travel; 1: cw; 2: ccw */
hal_bit_t *spindle_orient; /* out: signal orient in progress */
hal_bit_t *spindle_locked; /* out: signal orient complete, spindle locked */
hal_bit_t *spindle_is_oriented; /* in: orientation completed */
hal_s32_t *spindle_orient_fault; /* in: error code of failed operation */
} spindle_hal_t;
typedef struct {
hal_float_t *coarse_pos_cmd;/* RPI: commanded position, w/o comp */
hal_float_t *joint_vel_cmd; /* RPI: commanded velocity, w/o comp */
hal_float_t *joint_acc_cmd; /* RPI: commanded acceleration, w/o comp */
hal_float_t *joint_jerk_cmd;/* RPI: commanded jerk, w/o comp */
hal_float_t *backlash_corr; /* RPI: correction for backlash */
hal_float_t *backlash_filt; /* RPI: filtered backlash correction */
hal_float_t *backlash_vel; /* RPI: backlash speed variable */
hal_float_t *motor_offset; /* RPI: motor offset, for checking homing stability */
hal_float_t *motor_pos_cmd; /* WPI: commanded position, with comp */
hal_float_t *motor_pos_fb; /* RPI: position feedback, with comp */
hal_float_t *joint_pos_cmd; /* WPI: commanded position w/o comp, not ofs */
hal_float_t *joint_pos_fb; /* RPI: position feedback, w/o comp */
hal_float_t *f_error; /* RPI: following error */
hal_float_t *f_error_lim; /* RPI: following error limit */
hal_float_t *free_pos_cmd; /* RPI: free traj planner pos cmd */
hal_float_t *free_vel_lim; /* RPI: free traj planner vel limit */
hal_bit_t *free_tp_enable; /* RPI: free traj planner is running */
hal_bit_t *kb_jjog_active; /* RPI: executing keyboard jog */
hal_bit_t *wheel_jjog_active;/* RPI: executing handwheel jog */
hal_bit_t *active; /* RPI: joint is active, whatever that means */
hal_bit_t *in_position; /* RPI: joint is in position */
hal_bit_t *error; /* RPI: joint has an error */
hal_bit_t *phl; /* RPI: joint is at positive hard limit */
hal_bit_t *nhl; /* RPI: joint is at negative hard limit */
hal_bit_t *f_errored; /* RPI: joint had too much following error */
hal_bit_t *faulted; /* RPI: joint amp faulted */
hal_bit_t *pos_lim_sw; /* RPI: positive limit switch input */
hal_bit_t *neg_lim_sw; /* RPI: negative limit switch input */
hal_bit_t *amp_fault; /* RPI: amp fault input */
hal_bit_t *amp_enable; /* WPI: amp enable output */
hal_bit_t *unlock; /* WPI: command that axis should unlock for rotation */
hal_bit_t *is_unlocked; /* RPI: axis is currently unlocked */
hal_s32_t *jjog_counts; /* WPI: jogwheel position input */
hal_bit_t *jjog_enable; /* RPI: enable jogwheel */
hal_float_t *jjog_scale; /* RPI: distance to jog on each count */
hal_float_t *jjog_accel_fraction; /* RPI: to limit wheel jog accel */
hal_bit_t *jjog_vel_mode; /* RPI: true for "velocity mode" jogwheel */
} joint_hal_t;
typedef struct {
hal_float_t *posthome_cmd; // IN pin extrajoint
} extrajoint_hal_t;
/* machine data */
typedef struct {
hal_bit_t *probe_input; /* RPI: probe switch input */
hal_bit_t *enable; /* RPI: motion inhibit input */
hal_float_t *adaptive_feed; /* RPI: adaptive feedrate, 0.0 to 1.0 */
hal_bit_t *feed_hold; /* RPI: set TRUE to stop motion maskable with g53 P1*/
hal_bit_t *feed_inhibit; /* RPI: set TRUE to stop motion (non maskable)*/
hal_bit_t *homing_inhibit; /* RPI: set TRUE to inhibit homing*/
hal_bit_t *jog_inhibit; /* RPI: set TRUE to inhibit jogging*/
hal_bit_t *jog_stop; /* RPI: set TRUE to stop jogging following accel values*/
hal_bit_t *jog_stop_immediate; /* RPI: set TRUE to stop jogging immediately*/
hal_bit_t *jog_is_active; /* RPI: TRUE if active jogging*/
hal_bit_t *tp_reverse; /* Set true if trajectory planner is running in reverse*/
hal_bit_t *motion_enabled; /* RPI: motion enable for all joints */
hal_bit_t *is_all_homed; /* RPI: TRUE if all active joints is homed */
hal_bit_t *in_position; /* RPI: all joints are in position */
hal_bit_t *coord_mode; /* RPA: TRUE if coord, FALSE if free */
hal_bit_t *teleop_mode; /* RPA: TRUE if teleop mode */
hal_bit_t *coord_error; /* RPA: TRUE if coord mode error */
hal_bit_t *on_soft_limit; /* RPA: TRUE if outside a limit */
hal_s32_t *program_line; /* RPA: program line causing current motion */
hal_s32_t *motion_type; /* RPA: type (feed/rapid) of currently commanded motion */
hal_float_t *current_vel; /* RPI: velocity magnitude in machine units */
hal_float_t *requested_vel; /* RPI: requested velocity magnitude in machine units */
hal_float_t *distance_to_go;/* RPI: distance to go in current move*/
hal_bit_t debug_bit_0; /* RPA: generic param, for debugging */
hal_bit_t debug_bit_1; /* RPA: generic param, for debugging */
hal_float_t debug_float_0; /* RPA: generic param, for debugging */
hal_float_t debug_float_1; /* RPA: generic param, for debugging */
hal_float_t debug_float_2; /* RPA: generic param, for debugging */
hal_float_t debug_float_3; /* RPA: generic param, for debugging */
hal_s32_t debug_s32_0; /* RPA: generic param, for debugging */
hal_s32_t debug_s32_1; /* RPA: generic param, for debugging */
hal_bit_t *synch_do[EMCMOT_MAX_DIO]; /* WPI array: output pins for motion synched IO */
hal_bit_t *synch_di[EMCMOT_MAX_DIO]; /* RPI array: input pins for motion synched IO */
hal_float_t *analog_input[EMCMOT_MAX_AIO]; /* RPI array: input pins for analog Inputs */
hal_float_t *analog_output[EMCMOT_MAX_AIO]; /* RPI array: output pins for analog Inputs */
hal_bit_t *misc_error[EMCMOT_MAX_MISC_ERROR]; /* RPI array: output pins for misc error Inputs */
// FIXME - debug only, remove later
hal_float_t traj_pos_out; /* RPA: traj internals, for debugging */
hal_float_t traj_vel_out; /* RPA: traj internals, for debugging */
hal_u32_t traj_active_tc; /* RPA: traj internals, for debugging */
hal_float_t tc_pos[4]; /* RPA: traj internals, for debugging */
hal_float_t tc_vel[4]; /* RPA: traj internals, for debugging */
hal_float_t tc_acc[4]; /* RPA: traj internals, for debugging */
// realtime overrun detection
hal_u32_t *last_period; /* pin: last period in clocks */
hal_float_t *last_period_ns; /* pin: last period in nanoseconds */
hal_float_t *tooloffset_x;
hal_float_t *tooloffset_y;
hal_float_t *tooloffset_z;
hal_float_t *tooloffset_a;
hal_float_t *tooloffset_b;
hal_float_t *tooloffset_c;
hal_float_t *tooloffset_u;
hal_float_t *tooloffset_v;
hal_float_t *tooloffset_w;
spindle_hal_t spindle[EMCMOT_MAX_SPINDLES]; /*spindle data */
joint_hal_t joint[EMCMOT_MAX_JOINTS]; /* data for each joint */
extrajoint_hal_t ejoint[EMCMOT_MAX_EXTRAJOINTS]; /* data for each extrajoint */
hal_bit_t *eoffset_active; /* ext offsets active */
hal_bit_t *eoffset_limited; /* ext offsets exceed limit */
hal_float_t *feed_upm; /* feed G-code units per minute*/
hal_float_t *feed_inches_per_minute; /* feed inches per minute*/
hal_float_t *feed_inches_per_second; /* feed inches per second*/
hal_float_t *feed_mm_per_minute; /* feed mm per minute*/
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_arc_center_z;
hal_float_t *interp_straight_heading;
hal_float_t *interp_normal_heading;
hal_bit_t *iscircle;
} emcmot_hal_data_t;
/***********************************************************************
* GLOBAL VARIABLE DECLARATIONS *
************************************************************************/
/* pointer to emcmot_hal_data_t struct in HAL shmem, with all HAL data */
extern emcmot_hal_data_t *emcmot_hal_data;
/* pointer to array of joint structs with all joint data */
/* the actual array may be in shared memory or in kernel space, as
determined by the init code in motion.c */
extern emcmot_joint_t joints[EMCMOT_MAX_JOINTS];
/* Variable defs */
extern KINEMATICS_FORWARD_FLAGS fflags;
extern KINEMATICS_INVERSE_FLAGS iflags;
/* these variable have the 1/servo cycle time */
/* Struct pointers */
extern struct emcmot_struct_t *emcmotStruct;
extern struct emcmot_command_t *emcmotCommand;
extern struct emcmot_status_t *emcmotStatus;
extern struct emcmot_config_t *emcmotConfig;
extern struct emcmot_internal_t *emcmotInternal;
extern struct emcmot_error_t *emcmotError;
/***********************************************************************
* PUBLIC FUNCTION PROTOTYPES *
************************************************************************/
/* function definitions */
extern void emcmotCommandHandler(void *arg, long period);
extern void emcmotController(void *arg, long period);
extern void emcmotSetCycleTime(unsigned long nsec);
/* these are related to synchronized I/O */
extern void emcmotDioWrite(int index, char value);
extern void emcmotAioWrite(int index, double value);
extern void emcmotSetRotaryUnlock(int axis, int unlock);
extern int emcmotGetRotaryIsUnlocked(int axis);
//
// Try to change the Motion mode to Teleop.
//
// This function can be called at any time. Returns without changing
// mode if Teleop is not currently allowed. This code doesn't actually
// make the transition, it just sets a flag requesting the transition.
// The real transition to Teleop mode is done in emcmotController().
//
void switch_to_teleop_mode(void);
/* recalculates jog limits */
extern void refresh_jog_limits(emcmot_joint_t *joint,int joint_num);
/* handles 'homed' flags, see command.c for details */
extern void clearHomes(int joint_num);
extern void emcmot_config_change(void);
extern void reportError(const char *fmt, ...) __attribute__((format(printf,1,2))); /* Use the rtapi_print call */
int joint_is_lockable(int joint_num);
#define ALL_JOINTS emcmotConfig->numJoints
// number of kinematics-only joints:
#define NO_OF_KINS_JOINTS (ALL_JOINTS - emcmotConfig->numExtraJoints)
#define IS_EXTRA_JOINT(jno) (jno >= NO_OF_KINS_JOINTS)
// 0-based Joint numbering:
// kinematic-only jno.s: [0 ... (NO_OF_KINS_JOINTS -1) ]
// extrajoint jno.s: [NO_OF_KINS_JOINTS ... (ALL_JOINTS -1) ]
/* rtapi_get_time() returns a nanosecond value. In time, we should use a u64
value for all calcs and only do the conversion to seconds when it is
really needed. */
#define etime() (((double) rtapi_get_time()) / 1.0e9)
/* macros for reading, writing bit flags */
/* motion flags */
#define GET_MOTION_ERROR_FLAG() (emcmotStatus->motionFlag & EMCMOT_MOTION_ERROR_BIT ? 1 : 0)
#define SET_MOTION_ERROR_FLAG(fl) if (fl) emcmotStatus->motionFlag |= EMCMOT_MOTION_ERROR_BIT; else emcmotStatus->motionFlag &= ~EMCMOT_MOTION_ERROR_BIT;
#define GET_MOTION_COORD_FLAG() (emcmotStatus->motionFlag & EMCMOT_MOTION_COORD_BIT ? 1 : 0)
#define SET_MOTION_COORD_FLAG(fl) if (fl) emcmotStatus->motionFlag |= EMCMOT_MOTION_COORD_BIT; else emcmotStatus->motionFlag &= ~EMCMOT_MOTION_COORD_BIT;
#define GET_MOTION_TELEOP_FLAG() (emcmotStatus->motionFlag & EMCMOT_MOTION_TELEOP_BIT ? 1 : 0)
#define SET_MOTION_TELEOP_FLAG(fl) if (fl) emcmotStatus->motionFlag |= EMCMOT_MOTION_TELEOP_BIT; else emcmotStatus->motionFlag &= ~EMCMOT_MOTION_TELEOP_BIT;
#define GET_MOTION_INPOS_FLAG() (emcmotStatus->motionFlag & EMCMOT_MOTION_INPOS_BIT ? 1 : 0)
#define SET_MOTION_INPOS_FLAG(fl) if (fl) emcmotStatus->motionFlag |= EMCMOT_MOTION_INPOS_BIT; else emcmotStatus->motionFlag &= ~EMCMOT_MOTION_INPOS_BIT;
#define GET_MOTION_ENABLE_FLAG() (emcmotStatus->motionFlag & EMCMOT_MOTION_ENABLE_BIT ? 1 : 0)
#define SET_MOTION_ENABLE_FLAG(fl) if (fl) emcmotStatus->motionFlag |= EMCMOT_MOTION_ENABLE_BIT; else emcmotStatus->motionFlag &= ~EMCMOT_MOTION_ENABLE_BIT;
#define GET_TRAJ_PLANNER_TYPE() (emcmotStatus->planner_type)
#define SET_TRAK_PLANNER_TYPE(tp) (emcmotStatus->planner_type = tp)
/* joint flags */
#define GET_JOINT_ENABLE_FLAG(joint) ((joint)->flag & EMCMOT_JOINT_ENABLE_BIT ? 1 : 0)
#define SET_JOINT_ENABLE_FLAG(joint,fl) if (fl) (joint)->flag |= EMCMOT_JOINT_ENABLE_BIT; else (joint)->flag &= ~EMCMOT_JOINT_ENABLE_BIT;
#define SET_JOINT_ACTIVE_FLAG(joint,fl) if (fl) (joint)->flag |= EMCMOT_JOINT_ACTIVE_BIT; else (joint)->flag &= ~EMCMOT_JOINT_ACTIVE_BIT;
#define SET_JOINT_INPOS_FLAG(joint,fl) if (fl) (joint)->flag |= EMCMOT_JOINT_INPOS_BIT; else (joint)->flag &= ~EMCMOT_JOINT_INPOS_BIT;
#define GET_JOINT_ERROR_FLAG(joint) ((joint)->flag & EMCMOT_JOINT_ERROR_BIT ? 1 : 0)
#define SET_JOINT_ERROR_FLAG(joint,fl) if (fl) (joint)->flag |= EMCMOT_JOINT_ERROR_BIT; else (joint)->flag &= ~EMCMOT_JOINT_ERROR_BIT;
#define GET_JOINT_PHL_FLAG(joint) ((joint)->flag & EMCMOT_JOINT_MAX_HARD_LIMIT_BIT ? 1 : 0)
#define SET_JOINT_PHL_FLAG(joint,fl) if (fl) (joint)->flag |= EMCMOT_JOINT_MAX_HARD_LIMIT_BIT; else (joint)->flag &= ~EMCMOT_JOINT_MAX_HARD_LIMIT_BIT;
#define GET_JOINT_NHL_FLAG(joint) ((joint)->flag & EMCMOT_JOINT_MIN_HARD_LIMIT_BIT ? 1 : 0)
#define SET_JOINT_NHL_FLAG(joint,fl) if (fl) (joint)->flag |= EMCMOT_JOINT_MIN_HARD_LIMIT_BIT; else (joint)->flag &= ~EMCMOT_JOINT_MIN_HARD_LIMIT_BIT;
#define GET_JOINT_FERROR_FLAG(joint) ((joint)->flag & EMCMOT_JOINT_FERROR_BIT ? 1 : 0)
#define SET_JOINT_FERROR_FLAG(joint,fl) if (fl) (joint)->flag |= EMCMOT_JOINT_FERROR_BIT; else (joint)->flag &= ~EMCMOT_JOINT_FERROR_BIT;
#define GET_JOINT_FAULT_FLAG(joint) ((joint)->flag & EMCMOT_JOINT_FAULT_BIT ? 1 : 0)
#define SET_JOINT_FAULT_FLAG(joint,fl) if (fl) (joint)->flag |= EMCMOT_JOINT_FAULT_BIT; else (joint)->flag &= ~EMCMOT_JOINT_FAULT_BIT;
#if defined(__KERNEL__)
#define HAVE_CPU_KHZ
#endif
#endif /* MOT_PRIV_H */

View File

@@ -0,0 +1,780 @@
/********************************************************************
* Description: motion.h
* Data structures used throughout emc2.
*
* Author:
* License: GPL Version 2
* System: Linux
*
* Copyright (c) 2004 All rights reserved
********************************************************************/
/* jmk says: This file is a mess! */
/*
Misc ramblings:
The terms axis and joint are used inconsistently throughout EMC.
For all new code, the usages are as follows:
axis - one of the nine degrees of freedom, x, y, z, a, b, c, u, v, w
these refer to axes in Cartesian space, which may or
may not match up with joints (see below). On Cartesian
machines they do match up, but for hexapods, robots, and
other non-Cartesian machines they don't.
joint - one of the physical degrees of freedom of the machine
these might be linear (leadscrews) or rotary (rotary
tables, robot arm joints). There can be any number of
joints. The kinematics code is responsible for translating
from axis space to joint space and back.
There are three main kinds of data needed by the motion controller
1) data shared with higher level stuff - commands, status, etc.
2) data that is local to the motion controller
3) data shared with lower level stuff - hal pins
In addition, some internal data (2) should be shared for trouble
shooting purposes, even though it is "internal" to the motion
controller. Depending on the type of data, it can either be
treated as type (1), and made available to the higher level
code, or it can be treated as type (3), and made available to
the hal, so that halscope can monitor it.
This file should ONLY contain structures and declarations for
type (1) items - those that are shared with higher level code.
Type (2) items should be declared in mot_priv.h, along
with type (3) items.
In the interest of retaining my sanity, I'm not gonna attempt
to move everything to its proper location yet....
However, all new items will be defined in the proper place,
and some existing items may be moved from one struct definition
to another.
*/
#ifndef MOTION_H
#define MOTION_H
#include <rtapi_stdint.h>
#include <stdarg.h>
#include <rtapi_bool.h>
#include <rtapi_limits.h>
#include <posemath.h> /* PmCartesian, PmPose, pmCartMag() */
#include <emcpos.h> /* EmcPose */
#include "../kinematics/cubic.h" /* CUBIC_STRUCT, CUBIC_COEFF */
#include <emcmotcfg.h> /* EMCMOT_MAX_JOINTS */
#include <kinematics.h>
#include "simple_tp.h"
#include "state_tag.h"
#include "../tp/tp_types.h"
// define a special value to denote an invalid motion ID
// NB: do not ever generate a motion id of MOTION_INVALID_ID
// this should be really be tested for in command.c
#define MOTION_INVALID_ID INT_MIN
#define MOTION_ID_VALID(x) ((x) != MOTION_INVALID_ID)
#include <rtapi.h> /* must precede rtapi_atomic.h in kernel mode */
#include <rtapi_atomic.h>
#ifdef __cplusplus
extern "C" {
#endif
/* This enum lists all the possible commands */
typedef enum {
EMCMOT_ABORT = 1, /* abort all motion */
EMCMOT_ENABLE, /* enable servos for active joints */
EMCMOT_DISABLE, /* disable servos for active joints */
EMCMOT_PAUSE, /* pause motion */
EMCMOT_REVERSE, /* run reverse motion */
EMCMOT_FORWARD, /* run reverse motion */
EMCMOT_RESUME, /* resume motion */
EMCMOT_STEP, /* resume motion until id encountered */
EMCMOT_FREE, /* set mode to free (joint) motion */
EMCMOT_COORD, /* set mode to coordinated motion */
EMCMOT_TELEOP, /* set mode to teleop */
EMCMOT_SPINDLE_SCALE, /* set scale factor for spindle speed */
EMCMOT_SS_ENABLE, /* enable/disable scaling the spindle speed */
EMCMOT_FEED_SCALE, /* set scale factor for feedrate */
EMCMOT_RAPID_SCALE, /* set scale factor for rapids */
EMCMOT_FS_ENABLE, /* enable/disable scaling feedrate */
EMCMOT_FH_ENABLE, /* enable/disable feed_hold */
EMCMOT_AF_ENABLE, /* enable/disable adaptive feedrate */
EMCMOT_OVERRIDE_LIMITS, /* temporarily ignore limits until jog done */
EMCMOT_SET_LINE, /* queue up a linear move */
EMCMOT_SET_CIRCLE, /* queue up a circular move */
EMCMOT_SET_TELEOP_VECTOR, /* Move at a given velocity but in
world cartesian coordinates, not
in joint space like EMCMOT_JOG_* */
EMCMOT_CLEAR_PROBE_FLAGS, /* clears probeTripped flag */
EMCMOT_PROBE, /* go to pos, stop if probe trips, record
trip pos */
EMCMOT_RIGID_TAP, /* go to pos, with sync to spindle speed,
then return to initial pos */
EMCMOT_SET_VEL, /* set the velocity for subsequent moves */
EMCMOT_SET_VEL_LIMIT, /* set the max vel for all moves (tooltip) */
EMCMOT_SET_ACC, /* set the max accel for moves (tooltip) */
EMCMOT_SET_JERK, /* set the max jerk for moves (tooltip) */
EMCMOT_SET_PLANNER_TYPE, /* set planner type (0=trapezoidal, 1=S-curve) */
EMCMOT_SET_TERM_COND, /* set termination condition (stop, blend) */
EMCMOT_SET_NUM_JOINTS, /* set the number of joints */
EMCMOT_SET_NUM_SPINDLES, /* set the number of spindles */
EMCMOT_SET_WORLD_HOME, /* set pose for world home */
EMCMOT_SET_DEBUG, /* sets the debug level */
EMCMOT_SET_DOUT, /* sets or unsets a DIO, this can be immediate or synched with motion */
EMCMOT_SET_AOUT, /* sets or unsets a AIO, this can be immediate or synched with motion */
EMCMOT_SET_SPINDLESYNC, /* synchronize motion to spindle encoder */
EMCMOT_SPINDLE_ON, /* start the spindle */
EMCMOT_SPINDLE_OFF, /* stop the spindle */
EMCMOT_SPINDLE_INCREASE, /* spindle faster */
EMCMOT_SPINDLE_DECREASE, /* spindle slower */
EMCMOT_SPINDLE_BRAKE_ENGAGE, /* engage the spindle brake */
EMCMOT_SPINDLE_BRAKE_RELEASE, /* release the spindle brake */
EMCMOT_SPINDLE_ORIENT, /* orient the spindle */
EMCMOT_SET_OFFSET, /* set tool offsets */
EMCMOT_SET_MAX_FEED_OVERRIDE,
EMCMOT_SETUP_ARC_BLENDS,
EMCMOT_SET_PROBE_ERR_INHIBIT,
EMCMOT_ENABLE_WATCHDOG, /* enable watchdog sound, parport */
EMCMOT_DISABLE_WATCHDOG, /* enable watchdog sound, parport */
EMCMOT_JOG_CONT, /* continuous jog */
EMCMOT_JOG_INCR, /* incremental jog */
EMCMOT_JOG_ABS, /* absolute jog */
EMCMOT_JOG_ABORT, /* abort one joint num or axis num */
EMCMOT_JOINT_ACTIVATE, /* make joint active */
EMCMOT_JOINT_DEACTIVATE, /* make joint inactive */
EMCMOT_JOINT_HOME, /* home a joint or all joints */
EMCMOT_JOINT_UNHOME, /* unhome a joint or all joints*/
EMCMOT_SET_JOINT_POSITION_LIMITS, /* set the joint position +/- limits */
EMCMOT_SET_JOINT_BACKLASH, /* set the joint backlash */
EMCMOT_SET_JOINT_MIN_FERROR, /* minimum following error, input units */
EMCMOT_SET_JOINT_MAX_FERROR, /* maximum following error, input units */
EMCMOT_SET_JOINT_VEL_LIMIT, /* set the max joint vel */
EMCMOT_SET_JOINT_ACC_LIMIT, /* set the max joint accel */
EMCMOT_SET_JOINT_HOMING_PARAMS, /* sets joint homing parameters */
EMCMOT_SET_JOINT_JERK_LIMIT, /* set the max joint jerk */
EMCMOT_UPDATE_JOINT_HOMING_PARAMS, /* updates some joint homing parameters */
EMCMOT_SET_JOINT_MOTOR_OFFSET, /* set the offset between joint and motor */
EMCMOT_SET_JOINT_COMP, /* set a compensation triplet for a joint (nominal, forw., rev.) */
EMCMOT_SET_AXIS_POSITION_LIMITS, /* set the axis position +/- limits */
EMCMOT_SET_AXIS_VEL_LIMIT, /* set the max axis vel */
EMCMOT_SET_AXIS_ACC_LIMIT, /* set the max axis acc */
EMCMOT_SET_AXIS_LOCKING_JOINT, /* set the axis locking joint */
EMCMOT_SET_AXIS_JERK_LIMIT, /* set the max axis jerk */
EMCMOT_SET_SPINDLE_PARAMS, /* One command to set all spindle params */
} cmd_code_t;
/* this enum lists the possible results of a command */
typedef enum {
EMCMOT_COMMAND_OK = 0, /* cmd honored */
EMCMOT_COMMAND_UNKNOWN_COMMAND, /* cmd not understood */
EMCMOT_COMMAND_INVALID_COMMAND, /* cmd can't be handled now */
EMCMOT_COMMAND_INVALID_PARAMS, /* bad cmd params */
EMCMOT_COMMAND_BAD_EXEC /* error trying to initiate */
} cmd_status_t;
/* termination conditions for queued motions */
#define EMCMOT_TERM_COND_STOP 1
#define EMCMOT_TERM_COND_BLEND 2
#define EMCMOT_TERM_COND_TANGENT 3
/*********************************
COMMAND STRUCTURE
*********************************/
/* This is the command structure. There is one of these in shared
memory, and all commands from higher level code come thru it.
*/
typedef struct emcmot_command_t {
cmd_code_t command; /* command code (enum) */
int commandNum; /* increment this for new command */
double motor_offset; /* offset from joint to motor position */
double maxLimit; /* pos value for position limit, output */
double minLimit; /* neg value for position limit, output */
double min_pos_speed; /* spindle minimum positive speed */
double max_neg_speed; /* spindle maximum negative speed */
EmcPose pos; /* line/circle endpt, or teleop vector */
PmCartesian center; /* center for circle */
PmCartesian normal; /* normal vec for circle */
int turn; /* turns for circle or joint number for a locking indexer*/
double vel; /* max velocity */
double ini_maxvel; /* max velocity allowed by machine
constraints (the INI file) */
int motion_type; /* this move is because of traverse, feed, arc, or toolchange */
double spindlesync; /* user units per spindle revolution, 0 = no sync */
double acc; /* max acceleration */
double jerk; /* jerk for traj */
double ini_maxjerk;
int planner_type; /* planner type: 0 = trapezoidal, 1 = S-curve */
double backlash; /* amount of backlash */
int id; /* id for motion */
int termCond; /* termination condition */
double tolerance; /* tolerance for path deviation in CONTINUOUS mode */
int joint; /* which joint index to use for below */
int axis; /* which axis index to use for below */
int spindle; /* which spindle to use */
double scale; /* velocity scale or spindle_speed scale arg */
double offset; /* input, output, or home offset arg */
double home; /* joint home position */
double home_final_vel; /* joint velocity for moving from OFFSET to HOME */
double search_vel; /* home search velocity */
double latch_vel; /* home latch velocity */
int flags; /* homing config flags, other boolean args */
int home_sequence; /* order in homing sequence */
int volatile_home; /* joint should get unhomed when we get unhome -2
(generated by task upon estop, etc) */
double minFerror; /* min following error */
double maxFerror; /* max following error */
int wdWait; /* cycle to wait before toggling wd */
int debug; /* debug level, from DEBUG in INI file */
unsigned char now, out, start, end; /* these are related to synched AOUT/DOUT. now=whether now or synched, out = which gets set, start=start value, end=end value */
unsigned char mode; /* used for turning overrides etc. on/off */
double comp_nominal, comp_forward, comp_reverse; /* compensation triplet, nominal, forward, reverse */
unsigned char probe_type; /* ~1 = error if probe operation is unsuccessful (ngc default)
|1 = suppress error, report in # instead
~2 = move until probe trips (ngc default)
|2 = move until probe clears */
int probe_jog_err_inhibit; // setting to inhibit probe tripped while jogging error.
int probe_home_err_inhibit; // setting to inhibit probe tripped while homeing error.
EmcPose tool_offset; /* TLO */
double orientation; /* angle for spindle orient */
int state; /*spindle state seems to just be 0 for off and 1 for on andypugh 2025-04-03*/
char direction; /* CANON_DIRECTION flag for spindle orient */
double timeout; /* of wait for spindle orient to complete */
unsigned char wait_for_spindle_at_speed; // EMCMOT_SPINDLE_ON now carries this, for next feed move
int arcBlendOptDepth;
int arcBlendEnable;
int arcBlendFallbackEnable;
int arcBlendGapCycles;
double arcBlendRampFreq;
double arcBlendTangentKinkRatio;
double maxFeedScale;
double ext_offset_vel; /* velocity for an external axis offset */
double ext_offset_acc; /* acceleration for an external axis offset */
struct state_tag_t tag;
} emcmot_command_t;
/*! \todo FIXME - these packed bits might be replaced with chars
memory is cheap, and being able to access them without those
damn macros would be nice
*/
/* motion flag type */
typedef unsigned short EMCMOT_MOTION_FLAG;
/*
motion status flag structure-- looks like:
MSB LSB
v---------------v------------------v
| | | | T | CE | C | IP | EN |
^---------------^------------------^
where:
EN is 1 if calculations are enabled, 0 if not
IP is 1 if all joints in position, 0 if not
C is 1 if coordinated mode, 0 if in free mode
CE is 1 if coordinated mode error, 0 if not
T is 1 if we are in teleop mode.
*/
/* bit masks */
#define EMCMOT_MOTION_ENABLE_BIT 0x0001
#define EMCMOT_MOTION_INPOS_BIT 0x0002
#define EMCMOT_MOTION_COORD_BIT 0x0004
#define EMCMOT_MOTION_ERROR_BIT 0x0008
#define EMCMOT_MOTION_TELEOP_BIT 0x0010
/* joint flag type */
typedef unsigned short EMCMOT_JOINT_FLAG;
/*
joint status flag structure-- looks like:
MSB LSB
----------v-----------------v--------------------v-------------------v
| AF | FE | AH | HD | H | HS | NHL | PHL | - | - | ER | IP | AC | EN |
----------^-----------------^--------------------^-------------------^
x = unused
where:
EN is 1 if joint amplifier is enabled, 0 if not
AC is 1 if joint is active for calculations, 0 if not
IP is 1 if joint is in position, 0 if not (free mode only)
ER is 1 if joint has an error, 0 if not
PHL is 1 if joint is on maximum hardware limit, 0 if not
NHL is 1 if joint is on minimum hardware limit, 0 if not
HS is 1 if joint home switch is tripped, 0 if not
H is 1 if joint is homing, 0 if not
HD is 1 if joint has been homed, 0 if not
AH is 1 if joint is at home position, 0 if not
FE is 1 if joint exceeded following error, 0 if not
AF is 1 if amplifier is faulted, 0 if not
Suggestion: Split this in to an Error and a Status flag register..
Then a simple test on each of the two flags can be performed
rather than testing each bit... Saving on a global per joint
fault and ready status flag.
*/
/* bit masks */
#define EMCMOT_JOINT_ENABLE_BIT 0x0001
#define EMCMOT_JOINT_ACTIVE_BIT 0x0002
#define EMCMOT_JOINT_INPOS_BIT 0x0004
#define EMCMOT_JOINT_ERROR_BIT 0x0008
#define EMCMOT_JOINT_MAX_HARD_LIMIT_BIT 0x0010
#define EMCMOT_JOINT_MIN_HARD_LIMIT_BIT 0x0020
#define EMCMOT_JOINT_FERROR_BIT 0x0040
#define EMCMOT_JOINT_FAULT_BIT 0x0080
/*! \todo FIXME - the terms "teleop", "coord", and "free" are poorly
documented. This is my feeble attempt to understand exactly
what they mean.
According to Fred, teleop is never used with machine tools,
although that may not be true for machines with non-trivial
kinematics.
"coord", or coordinated mode, means that all the joints are
synchronized, and move together as commanded by the higher
level code. It is the normal mode when machining. In
coordinated mode, commands are assumed to be in the cartesean
reference frame, and if the machine is non-cartesean, the
commands are translated by the kinematics to drive each
joint in joint space as needed.
"free" mode means commands are interpreted in joint space.
It is used for jogging individual joints, although
it does not preclude multiple joints moving at once (I think).
Homing is also done in free mode, in fact machines with
non-trivial kinematics must be homed before they can go
into either coord or teleop mode.
'teleop' is what you probably want if you are 'jogging'
a hexapod. The jog commands as implemented by the motion
controller are joint jogs, which work in free mode. But
if you want to jog a hexapod or similar machine along
one particular cartesean axis, you need to operate more
than one joint. That's what 'teleop' is for.
*/
/* compensation structures */
typedef struct {
double nominal; /* nominal (command) position */
float fwd_trim; /* correction for forward movement */
float rev_trim; /* correction for reverse movement */
float fwd_slope; /* slopes between here and next pt */
float rev_slope;
} emcmot_comp_entry_t;
#define EMCMOT_COMP_SIZE 256
typedef struct {
int entries; /* number of entries in the array */
emcmot_comp_entry_t *entry; /* current entry in array */
emcmot_comp_entry_t array[EMCMOT_COMP_SIZE+2];
/* +2 because array has -HUGE_VAL and +HUGE_VAL entries at the ends */
} emcmot_comp_t;
/* motion controller states */
typedef enum {
EMCMOT_MOTION_DISABLED = 0,
EMCMOT_MOTION_FREE,
EMCMOT_MOTION_TELEOP,
EMCMOT_MOTION_COORD
} motion_state_t;
typedef enum {
EMCMOT_ORIENT_NONE = 0,
EMCMOT_ORIENT_COMPLETE,
EMCMOT_ORIENT_IN_PROGRESS,
EMCMOT_ORIENT_FAULTED,
} orient_state_t;
/* flags for enabling spindle scaling, feed scaling,
adaptive feed, and feed hold */
#define SS_ENABLED 0x01
#define FS_ENABLED 0x02
#define AF_ENABLED 0x04
#define FH_ENABLED 0x08
/* This structure contains all of the data associated with
a single joint. Note that this structure does not need
to be in shared memory (but it can, if desired for debugging
reasons). The portions of this structure that are considered
"status" and need to be made available to user space are
copied to a much smaller struct called emcmot_joint_status_t
which is located in shared memory.
*/
typedef struct {
/* configuration info - changes rarely */
int type; /* 0 = linear, 1 = rotary */
double max_pos_limit; /* upper soft limit on joint pos */
double min_pos_limit; /* lower soft limit on joint pos */
double max_jog_limit; /* jog limits change when not homed */
double min_jog_limit;
double vel_limit; /* upper limit of joint speed */
double acc_limit; /* upper limit of joint accel */
double jerk_limit; /* upper limit of joint jerk */
double min_ferror; /* zero speed following error limit */
double max_ferror; /* max speed following error limit */
double backlash; /* amount of backlash */
emcmot_comp_t comp; /* leadscrew correction data */
/* status info - changes regularly */
/* many of these need to be made available to higher levels */
/* they can either be copied to the status struct, or an array of
joint structs can be made part of the status */
EMCMOT_JOINT_FLAG flag; /* see above for bit details */
double coarse_pos; /* trajectory point, before interp */
double pos_cmd; /* commanded joint position */
double vel_cmd; /* commanded joint velocity */
double acc_cmd; /* commanded joint acceleration */
double jerk_cmd; /* comanded joint jerk */
double backlash_corr; /* correction for backlash */
double backlash_filt; /* filtered backlash correction */
double backlash_vel; /* backlash velocity variable */
double motor_pos_cmd; /* commanded position, with comp */
double motor_pos_fb; /* position feedback, with comp */
double pos_fb; /* position feedback, comp removed */
double ferror; /* following error */
double ferror_limit; /* limit depends on speed */
double ferror_high_mark; /* max following error */
simple_tp_t free_tp; /* planner for free mode motion */
int kb_jjog_active; /* non-zero during a keyboard jog */
int wheel_jjog_active; /* non-zero during a wheel jog */
/* internal info - changes regularly, not usually accessed from user
space */
CUBIC_STRUCT cubic; /* cubic interpolator data */
int on_pos_limit; /* non-zero if on limit */
int on_neg_limit; /* non-zero if on limit */
double motor_offset; /* diff between internal and motor pos, used
to set position to zero during homing */
int old_jjog_counts; /* prior value, used for deltas */
double big_vel; /* used for "debouncing" velocity */
} emcmot_joint_t;
/* This structure contains only the "status" data associated with
a joint. "Status" data is that data that should be reported to
user space on a continuous basis. An array of these structs is
part of the main status structure, and is filled in with data
copied from the emcmot_joint_t structs every servo period.
For now this struct contains more data than it really needs, but
paring it down will take time (and probably needs to be done one
or two items at a time, with much testing). My main goal right
now is to get get the large joint struct out of status.
*/
typedef struct {
EMCMOT_JOINT_FLAG flag; /* see above for bit details */
bool homed;
bool homing;
double pos_cmd; /* commanded joint position */
double pos_fb; /* position feedback, comp removed */
double vel_cmd; /* current velocity */
double acc_cmd; /* current acceleration */
double ferror; /* following error */
double ferror_high_mark; /* max following error */
/*! \todo FIXME - the following are not really "status", but taskintf.cc expects
them to be in the status structure. I don't know how or if they are
used by the user space code. Ideally they will be removed from here,
but each one will need to be investigated individually.
*/
double backlash; /* amount of backlash */
double max_pos_limit; /* upper soft limit on joint pos */
double min_pos_limit; /* lower soft limit on joint pos */
double min_ferror; /* zero speed following error limit */
double max_ferror; /* max speed following error limit */
} emcmot_joint_status_t;
typedef struct {
double speed; // spindle speed in RPMs
double scale; // spindle override value
double net_scale; // scale or zero if inhibited
double css_factor;
double xoffset;
int state;
int direction; // 0 stopped, 1 forward, -1 reverse
int brake; // 0 released, 1 engaged
int locked; // spindle lock engaged after orient
int orient_fault; // fault code from motion.spindle-orient-fault
int orient_state; // orient_state_t
int spindle_index_enable; /* hooked to a canon encoder index-enable */
double spindleRevs; /* position of spindle in revolutions */
double spindleSpeedIn; /* velocity of spindle in revolutions per minute */
int at_speed;
int fault; /* amplifier fault */
double max_pos_speed; /* spindle speed limits */
double min_pos_speed; /* signed values, so max_neg = 0 */
double max_neg_speed; /* and min_neg = -1e99 indicates no limit */
double min_neg_speed;
double home_angle;
double home_search_vel;
int home_sequence;
double increment;
} spindle_status_t;
typedef struct {
double teleop_vel_cmd; /* commanded axis velocity */
double max_pos_limit; /* upper soft limit on axis pos */
double min_pos_limit; /* lower soft limit on axis pos */
} emcmot_axis_status_t;
/*********************************
STATUS STRUCTURE
*********************************/
/* This is the status structure. There is one of these in shared
memory, and it reports motion controller status to higher level
code in user space. For the most part, this structure contains
higher level variables - low level stuff is made visible to the
HAL and troubleshooting, etc, is done using the HAL oscilloscope.
*/
/*! \todo FIXME - this struct is broken into two parts... at the top are
structure members that I understand, and that are needed for emc2.
Other structure members follow. All the later ones need to be
evaluated - either they move up, or they go away.
*/
typedef struct emcmot_status_t {
unsigned char head; /* flag count for mutex detect */
/* these three are updated only when a new command is handled */
cmd_code_t commandEcho; /* echo of input command */
int commandNumEcho; /* echo of input command number */
cmd_status_t commandStatus; /* result of most recent command */
/* these are config info, updated when a command changes them */
double feed_scale; /* velocity scale factor for all motion but rapids */
double rapid_scale; /* velocity scale factor for rapids */
unsigned char enables_new; /* flags for FS, SS, etc */
/* the above set is the enables in effect for new moves */
/* the rest are updated every cycle */
double net_feed_scale; /* net scale factor for all motion */
unsigned char enables_queued; /* flags for FS, SS, etc */
/* the above set is the enables in effect for the
currently executing move */
motion_state_t motion_state; /* operating state: FREE, COORD, etc. */
EMCMOT_MOTION_FLAG motionFlag; /* see above for bit details */
EmcPose carte_pos_cmd; /* commanded Cartesian position */
int carte_pos_cmd_ok; /* non-zero if command is valid */
EmcPose carte_pos_fb; /* actual Cartesian position */
int carte_pos_fb_ok; /* non-zero if feedback is valid */
EmcPose world_home; /* cartesean coords of home position */
emcmot_joint_status_t joint_status[EMCMOT_MAX_JOINTS]; /* all joint status data */
emcmot_axis_status_t axis_status[EMCMOT_MAX_AXIS]; /* all axis status data */
int spindleSync; /* spindle used for synchronised moves. -1 = none */
spindle_status_t spindle_status[EMCMOT_MAX_SPINDLES]; /* all spindle data */
int on_soft_limit; /* non-zero if any joint is on soft limit */
int probeVal; /* debounced value of probe input */
int probeTripped; /* Has the probe signal changed since start
of probe command? */
int probing; /* Currently looking for a probe signal? */
unsigned char probe_type;
EmcPose probedPos; /* Axis positions stored as soon as possible
after last probeTripped */
int synch_di[EMCMOT_MAX_DIO]; /* inputs to the motion controller, queried by G-code */
int synch_do[EMCMOT_MAX_DIO]; /* outputs to the motion controller, queried by G-code */
double analog_input[EMCMOT_MAX_AIO]; /* inputs to the motion controller, queried by G-code */
double analog_output[EMCMOT_MAX_AIO]; /* outputs to the motion controller, queried by G-code */
int misc_error[EMCMOT_MAX_MISC_ERROR]; /* Random Error pins*/
struct state_tag_t tag; /* Current interp state corresponding
to motion line */
/*! \todo FIXME - all structure members beyond this point are in limbo */
/* dynamic status-- changes every cycle */
uint64_t heartbeat; /* Incremented every time the motion controller is done. */
int config_num; /* incremented whenever configuration
changed. */
int id; /* id for executing motion */
int depth; /* motion queue depth */
int activeDepth; /* depth of active blend elements */
int queueFull; /* Flag to indicate the tc queue is full */
int paused; /* Flag to signal motion paused */
int overrideLimitMask; /* non-zero means one or more limits ignored */
/* 1 << (joint-num*2) = ignore neg limit */
/* 2 << (joint-num*2) = ignore pos limit */
int reverse_run;
/* static status-- only changes upon input commands, e.g., config */
double vel; /* scalar max vel */
double acc; /* scalar max accel */
double jerk; /* jerk for traj */
int planner_type; /* planner type: 0 = trapezoidal, 1 = S-curve */
int motionType;
double distance_to_go; /* in this move */
EmcPose dtg;
double current_vel;
double requested_vel;
/* S-curve motion state - for accurate jerk output */
double current_acc; /* current path acceleration */
double current_jerk; /* current path jerk (accurate value from TP) */
double decel_dist; /* S-curve deceleration distance (dlen1) for debugging */
PmCartesian current_dir; /* current motion direction unit vector */
unsigned int tcqlen;
EmcPose tool_offset;
int atspeed_next_feed; /* at next feed move, wait for spindle to be at speed */
unsigned char tail; /* flag count for mutex detect */
int external_offsets_applied;
EmcPose eoffset_pose;
int numExtraJoints;
int stepping;
bool jogging_active;
} emcmot_status_t;
/*********************************
CONFIG STRUCTURE
*********************************/
/* This is the config structure. This is currently in shared memory,
but I have no idea why... there are commands to set most of the
items in this structure. It seems we should either put the struct
in private memory and manipulate it with commands, or we should
put it in shared memory and manipulate it directly - not both.
The structure contains static or rarely changed information that
describes the machine configuration.
later: I think I get it now - the struct is in shared memory so
user space can read the config at any time, but commands are used
to change the config so they only take effect when the realtime
code processes the command.
*/
/*! \todo FIXME - this struct is broken into two parts... at the top are
structure members that I understand, and that are needed for emc2.
Other structure members follow. All the later ones need to be
evaluated - either they move up, or they go away.
*/
typedef struct emcmot_config_t {
unsigned char head; /* flag count for mutex detect */
int config_num; /* Incremented everytime configuration
changed, should match status.config_num */
int numJoints; /* The number of total joints in the system (which
must be between 1 and EMCMOT_MAX_JOINTS,
inclusive). includes extra joints*/
int numExtraJoints; /* The number of extra joints in the system (which
must be between 1 and EMCMOT_MAX_EXTRAJOINTS,
inclusive). */
int numSpindles; /* The number of spindles, 1 to EMCMOT_MAX_SPINDLES */
KINEMATICS_TYPE kinType;
int numDIO; /* userdefined number of digital IO. default is 4. (EMCMOT_MAX_DIO=64),
but can be altered at motmod insmod time */
int numAIO; /* userdefined number of analog IO. default is 4. (EMCMOT_MAX_AIO=16),
but can be altered at motmod insmod time */
int numMiscError; /* userdefined number of Misc Errors. default is 0.
but can be altered at motmod insmod time */
/*! \todo FIXME - all structure members beyond this point are in limbo */
double trajCycleTime; /* the rate at which the trajectory loop
runs.... (maybe) */
double servoCycleTime; /* the rate of the servo loop - Not the same
as the traj time */
int interpolationRate; /* grep control.c for an explanation....
approx line 50 */
double limitVel; /* scalar upper limit on vel */
int debug; /* copy of DEBUG, from INI file */
unsigned char tail; /* flag count for mutex detect */
int arcBlendOptDepth;
int arcBlendEnable;
int arcBlendFallbackEnable;
int arcBlendGapCycles;
double arcBlendRampFreq;
double arcBlendTangentKinkRatio;
double maxFeedScale;
int inhibit_probe_jog_error;
int inhibit_probe_home_error;
} emcmot_config_t;
/* error structure - lockfree MPSC ring buffer. See emcmotutil.c. */
typedef struct emcmot_error_t {
char error[EMCMOT_ERROR_NUM][EMCMOT_ERROR_LEN];
rtapi_atomic_ullong write_reserve;
rtapi_atomic_ullong write_commit;
rtapi_atomic_ullong read_seq;
} emcmot_error_t;
typedef struct emcmot_internal_t {
unsigned char head; /* flag count for mutex detect */
unsigned char tail; /* flag count for mutex detect */
int split; /* number of split command reads */
int enabling; /* starts up disabled */
int coordinating; /* starts up in free mode */
int teleoperating; /* starts up in free mode */
int overriding; /* non-zero means we've initiated an joint
move while overriding limits */
TP_STRUCT coord_tp; /* coordinated mode planner */
int idForStep; /* status id while stepping */
} emcmot_internal_t;
/* error ring buffer access functions */
extern int emcmotErrorInit(emcmot_error_t * errlog);
extern int emcmotErrorPut(emcmot_error_t * errlog, const char *error);
extern int emcmotErrorPutfv(emcmot_error_t * errlog, const char *fmt, va_list ap);
extern int emcmotErrorPutf(emcmot_error_t * errlog, const char *fmt, ...);
extern int emcmotErrorGet(emcmot_error_t * errlog, char *error);
#define GET_JOINT_ACTIVE_FLAG(joint) ((joint)->flag & EMCMOT_JOINT_ACTIVE_BIT ? 1 : 0)
#define GET_JOINT_INPOS_FLAG(joint) ((joint)->flag & EMCMOT_JOINT_INPOS_BIT ? 1 : 0)
#ifdef __cplusplus
}
#endif
#endif /* MOTION_H */

View File

@@ -0,0 +1,107 @@
/********************************************************************
* Description: simple_tp.h
* A simple, single axis trajectory planner
*
* Author:
* License: GPL Version 2
* System: Linux
*
* Copyright (c) 2004 All rights reserved
********************************************************************/
/* simple_tp.c and simple_tp.h define a simple, single axis trajectory
planner. It is based on the "free mode trajectory planner" that was
originally written as part of EMC2's control.c, but the code has
been pulled out of control.c and given a somewhat object oriented
API to allow it to be used for both teleop and free mode.
*/
#ifndef SIMPLE_TP_H
#define SIMPLE_TP_H
// stopping criterion:
#define TINY_DP(max_acc,period) (max_acc*period*period*0.001)
#ifdef __cplusplus
extern "C" {
#endif
typedef struct simple_tp_t {
double pos_cmd; /* position command */
double max_vel; /* velocity limit */
double max_acc; /* acceleration limit */
double max_jerk; /* jerk limit */
int enable; /* if zero, motion stops ASAP */
double curr_pos; /* current position */
double curr_vel; /* current velocity */
int active; /* non-zero if motion in progress */
double curr_acc; /* current acceleration */
double curr_jerk; /* current acceleration */
double last_move_length; /* current acceleration */
double last_pos_cmd;
int use_trapezoid;
double curr_max_vel;
int total_n;
int curr_n;
int n0;
int n1;
int n2;
int n3;
int n4;
int n5;
int n6;
int fix_verr;
double verr;
double vc;
double ve;
double vm;
double jm;
double j2;
double j4;
double v1;
double v2;
double v3;
double v5;
double v6;
double v7;
double a1;
double a2;
double a3;
double a5;
double a6;
double a7;
double prograss;
int status;
} simple_tp_t;
/* I could write a bunch of functions to read and write the first four
structure members, and to read the last three, but that seems silly.
*/
/* The update() function does all the work. If 'enable' is true, it
computes a new value of 'curr_pos', which moves toward 'pos_cmd'
while obeying the 'max_vel' and 'max_accel' limits. It also sets
'active' if movement is in progress, and clears it when motion
stops at the commanded position. The command or either of the
limits can be changed at any time. If 'enable' is false, it
ramps the velocity to zero, then clears 'active' and sets
'pos_cmd' to match 'curr_pos', to avoid motion the next time it
is enabled. 'period' is the period between calls, in seconds.
*/
extern void simple_tp_update(simple_tp_t *tp, double period);
extern void simple_tp_update_normal(simple_tp_t *tp, double period);
extern void simple_scurve_tp_update(simple_tp_t *tp, double period);
#ifdef __cplusplus
}
#endif
#endif /* SIMPLE_TP_H */