Make feed override control the WASM trajectory
This commit is contained in:
@@ -253,7 +253,7 @@ if(EMSCRIPTEN)
|
||||
string(REPLACE "_sim_io_init" "_sim_io_size','_sim_io_init" _sim_module_link_flags "${_sim_module_link_flags}")
|
||||
string(REPLACE "_sim_io_set_estop','_sim_io_recover" "_sim_io_set_estop','_sim_io_set_power','_sim_io_recover" _sim_module_link_flags "${_sim_module_link_flags}")
|
||||
string(REPLACE "_sim_device_init" "_sim_device_io_size','_sim_device_init" _sim_module_link_flags "${_sim_module_link_flags}")
|
||||
string(REPLACE "_sim_motion_step','_sim_motion_read_state" "_sim_motion_step','_sim_motion_set_profile','_sim_motion_set_lookahead','_sim_motion_peek','_sim_motion_read_state" _sim_module_link_flags "${_sim_module_link_flags}")
|
||||
string(REPLACE "_sim_motion_step','_sim_motion_read_state" "_sim_motion_step','_sim_motion_set_profile','_sim_motion_set_lookahead','_sim_motion_set_feed_override','_sim_motion_peek','_sim_motion_read_state" _sim_module_link_flags "${_sim_module_link_flags}")
|
||||
string(REPLACE "_sim_motion_state_hash','_sim_motion_canonical" "_sim_motion_state_hash','_sim_motion_plan_hash','_sim_motion_canonical" _sim_module_link_flags "${_sim_module_link_flags}")
|
||||
set_target_properties(sim_core_module PROPERTIES LINK_FLAGS "${_sim_module_link_flags}")
|
||||
endif()
|
||||
|
||||
@@ -30,8 +30,11 @@ typedef struct sim_motion_command {
|
||||
sim_posemath_segment segment;
|
||||
uint32_t id;
|
||||
uint32_t tag;
|
||||
uint32_t flags;
|
||||
} sim_motion_command;
|
||||
|
||||
#define SIM_MOTION_COMMAND_FLAG_RAPID 1u
|
||||
|
||||
typedef struct sim_motion_state {
|
||||
sim_posemath_pose position;
|
||||
double velocity;
|
||||
@@ -65,6 +68,7 @@ int sim_motion_step(sim_motion_queue *queue);
|
||||
int sim_motion_set_profile(sim_motion_queue *queue, int profile);
|
||||
int sim_motion_set_lookahead(sim_motion_queue *queue, uint32_t depth);
|
||||
int sim_motion_set_dynamics(sim_motion_queue *queue, double acceleration_limit, double jerk_limit);
|
||||
int sim_motion_set_feed_override(sim_motion_queue *queue, double feed_override);
|
||||
int sim_motion_set_paused(sim_motion_queue *queue, uint32_t paused);
|
||||
int sim_motion_peek(const sim_motion_queue *queue, uint32_t offset, sim_motion_command *command);
|
||||
int sim_motion_read_state(const sim_motion_queue *queue, sim_motion_state *state);
|
||||
|
||||
@@ -70,6 +70,7 @@ enum sim_task_gate_command {
|
||||
SIM_TASK_GATE_SET_MODE = 13,
|
||||
SIM_TASK_GATE_PROGRAM_LOAD = 14,
|
||||
SIM_TASK_GATE_STEP = 15,
|
||||
SIM_TASK_GATE_OVERRIDE = 16,
|
||||
};
|
||||
|
||||
enum sim_task_gate_result {
|
||||
|
||||
@@ -12,6 +12,7 @@ typedef struct motion_meta {
|
||||
uint32_t lookahead;
|
||||
double acceleration_limit;
|
||||
double jerk_limit;
|
||||
double feed_override;
|
||||
double current_velocity;
|
||||
double current_acceleration;
|
||||
uint32_t paused;
|
||||
@@ -34,6 +35,7 @@ static motion_meta *meta_for(const sim_motion_queue *queue, int create) {
|
||||
free_slot->lookahead = 1;
|
||||
free_slot->acceleration_limit = 1e9;
|
||||
free_slot->jerk_limit = 1e12;
|
||||
free_slot->feed_override = 1.0;
|
||||
free_slot->paused = 0;
|
||||
return free_slot;
|
||||
}
|
||||
@@ -106,6 +108,7 @@ int sim_motion_reset(sim_motion_queue *queue) {
|
||||
meta->lookahead = 1;
|
||||
meta->acceleration_limit = 1e9;
|
||||
meta->jerk_limit = 1e12;
|
||||
meta->feed_override = 1.0;
|
||||
meta->current_velocity = 0.0;
|
||||
meta->current_acceleration = 0.0;
|
||||
meta->paused = 0;
|
||||
@@ -147,6 +150,13 @@ int sim_motion_set_dynamics(sim_motion_queue *queue, double acceleration_limit,
|
||||
return SIM_MOTION_OK;
|
||||
}
|
||||
|
||||
int sim_motion_set_feed_override(sim_motion_queue *queue, double feed_override) {
|
||||
motion_meta *meta = meta_for(queue, 1);
|
||||
if (meta == NULL || !isfinite(feed_override) || feed_override < 0.0 || feed_override > 2.0) return SIM_MOTION_ERR_RANGE;
|
||||
meta->feed_override = feed_override;
|
||||
return SIM_MOTION_OK;
|
||||
}
|
||||
|
||||
int sim_motion_set_paused(sim_motion_queue *queue, uint32_t paused) {
|
||||
motion_meta *meta = meta_for(queue, 1);
|
||||
if (meta == NULL || paused > 1u) return SIM_MOTION_ERR_ARGUMENT;
|
||||
@@ -174,11 +184,12 @@ static double planned_velocity(const sim_motion_queue *queue, uint32_t offset) {
|
||||
uint32_t index;
|
||||
if (queue == NULL || offset >= queue->count) return 0.0;
|
||||
index = (queue->head + offset) % SIM_MOTION_QUEUE_CAPACITY;
|
||||
velocity = queue->commands[index].segment.velocity;
|
||||
velocity = queue->commands[index].segment.velocity * (meta == NULL || (queue->commands[index].flags & SIM_MOTION_COMMAND_FLAG_RAPID) != 0u ? 1.0 : meta->feed_override);
|
||||
if (meta == NULL || meta->profile == SIM_MOTION_PROFILE_EXACT_STOP) return velocity;
|
||||
for (index = 1; index <= meta->lookahead && offset + index < queue->count; ++index) {
|
||||
uint32_t next = (queue->head + offset + index) % SIM_MOTION_QUEUE_CAPACITY;
|
||||
if (queue->commands[next].segment.velocity < velocity) velocity = queue->commands[next].segment.velocity;
|
||||
const double next_velocity = queue->commands[next].segment.velocity * ((queue->commands[next].flags & SIM_MOTION_COMMAND_FLAG_RAPID) != 0u ? 1.0 : meta->feed_override);
|
||||
if (next_velocity < velocity) velocity = next_velocity;
|
||||
}
|
||||
return velocity;
|
||||
}
|
||||
|
||||
@@ -224,6 +224,10 @@ int32_t sim_task_command_gate(const sim_task *task, uint32_t command,
|
||||
/* AXIS allows jog commands while idle in all three task modes; the
|
||||
manual tab changes mode before sending the command when required. */
|
||||
return machine_on && idle ? SIM_TASK_GATE_ALLOWED : io_estop ? SIM_TASK_GATE_ESTOP_ACTIVE : machine_on ? SIM_TASK_GATE_INTERP_ACTIVE : SIM_TASK_GATE_MACHINE_OFF;
|
||||
case SIM_TASK_GATE_OVERRIDE:
|
||||
/* Feed override is an online trajectory control. LinuxCNC accepts it
|
||||
while AUTO is running or paused, provided the machine is powered. */
|
||||
return io_estop ? SIM_TASK_GATE_ESTOP_ACTIVE : machine_on ? SIM_TASK_GATE_ALLOWED : SIM_TASK_GATE_MACHINE_OFF;
|
||||
case SIM_TASK_GATE_MDI:
|
||||
if (io_estop || !machine_on) return io_estop ? SIM_TASK_GATE_ESTOP_ACTIVE : SIM_TASK_GATE_MACHINE_OFF;
|
||||
if (!idle) return SIM_TASK_GATE_INTERP_ACTIVE;
|
||||
|
||||
@@ -44,6 +44,28 @@ int main(void) {
|
||||
assert(sim_motion_set_profile(&queue, SIM_MOTION_PROFILE_EXACT_STOP) == SIM_MOTION_OK);
|
||||
assert(sim_motion_set_lookahead(&queue, 0) == SIM_MOTION_ERR_RANGE);
|
||||
assert(sim_motion_set_dynamics(&queue, 0.0, 1.0) == SIM_MOTION_ERR_RANGE);
|
||||
{
|
||||
sim_motion_queue override_queue = {0};
|
||||
sim_motion_state override_state = {0};
|
||||
sim_motion_command override_command = {0};
|
||||
override_command.segment = line(0, 1);
|
||||
assert(sim_motion_init(&override_queue, 0.1, 10.0) == SIM_MOTION_OK);
|
||||
assert(sim_motion_set_feed_override(&override_queue, 0.5) == SIM_MOTION_OK);
|
||||
assert(sim_motion_set_feed_override(&override_queue, 0.5) == SIM_MOTION_OK);
|
||||
assert(sim_motion_set_feed_override(&override_queue, -0.1) == SIM_MOTION_ERR_RANGE);
|
||||
assert(sim_motion_set_feed_override(&override_queue, 2.1) == SIM_MOTION_ERR_RANGE);
|
||||
assert(sim_motion_enqueue(&override_queue, &override_command, 0) == SIM_MOTION_OK);
|
||||
assert(sim_motion_step(&override_queue) == SIM_MOTION_OK);
|
||||
assert(sim_motion_read_state(&override_queue, &override_state) == SIM_MOTION_OK);
|
||||
assert(override_state.position.tran.x > 0.049 && override_state.position.tran.x < 0.051);
|
||||
assert(override_state.velocity > 0.49 && override_state.velocity < 0.51);
|
||||
sim_motion_reset(&override_queue);
|
||||
override_command.flags = SIM_MOTION_COMMAND_FLAG_RAPID;
|
||||
assert(sim_motion_enqueue(&override_queue, &override_command, 0) == SIM_MOTION_OK);
|
||||
assert(sim_motion_step(&override_queue) == SIM_MOTION_OK);
|
||||
assert(sim_motion_read_state(&override_queue, &override_state) == SIM_MOTION_OK);
|
||||
assert(override_state.position.tran.x > 0.099 && override_state.position.tran.x < 0.101);
|
||||
}
|
||||
command.segment = line(9, 10);
|
||||
assert(sim_motion_enqueue(&queue, &command, 0) == SIM_MOTION_ERR_STATE);
|
||||
command.segment.motion_type = 99;
|
||||
|
||||
@@ -28,6 +28,9 @@ int main(void) {
|
||||
assert(sim_task_command_gate(&task, SIM_TASK_GATE_PAUSE, 0, 1, 0, 1, 0, 10) == SIM_TASK_GATE_PAUSE_STATE);
|
||||
assert(sim_task_set_mode(&task, SIM_TASK_MODE_AUTO) == SIM_TASK_OK);
|
||||
assert(sim_task_command_gate(&task, SIM_TASK_GATE_PAUSE, 0, 1, 0, 1, 0, 10) == SIM_TASK_GATE_ALLOWED);
|
||||
assert(sim_task_command_gate(&task, SIM_TASK_GATE_OVERRIDE, 0, 1, 0, 1, 0, 10) == SIM_TASK_GATE_ALLOWED);
|
||||
assert(sim_task_command_gate(&task, SIM_TASK_GATE_OVERRIDE, 0, 0, 0, 1, 0, 10) == SIM_TASK_GATE_MACHINE_OFF);
|
||||
assert(sim_task_command_gate(&task, SIM_TASK_GATE_OVERRIDE, 0, 1, 1, 1, 0, 10) == SIM_TASK_GATE_ESTOP_ACTIVE);
|
||||
assert(sim_task_command_gate(&task, SIM_TASK_GATE_POWER, 0, 1, 0, 1, 0, 10) == SIM_TASK_GATE_ALLOWED);
|
||||
assert(sim_task_command_gate(&task, SIM_TASK_GATE_SET_MODE, SIM_TASK_MODE_MANUAL, 1, 0, 1, 0, 10) == SIM_TASK_GATE_MODE_AUTO_ACTIVE);
|
||||
assert(sim_task_command_gate(&task, SIM_TASK_GATE_ESTOP, 1, 1, 0, 1, 0, 10) == SIM_TASK_GATE_ALLOWED);
|
||||
|
||||
Reference in New Issue
Block a user