📄 command.c
字号:
/********************************************************************* Description: command.c* emcmotCommandhandler() takes commands passed from user space and* performs various functions based on the value in emcmotCommand->command.* For the full list, see the EMCMOT_COMMAND enum in motion.h** pc says:** Most of the configs would be better off being passed via an ioctl* implimentation leaving pure realtime data to be handled by* emcmotCommmandHandler() - This would provide a small performance* increase on slower systems.** jmk says:** Using commands to set config parameters is "undesireable", because* of the large amount of code needed for each parameter. Today you* need to do the following to add a single new parameter called foo:** 1) Add a member 'foo' to the config or joint structure in motion.h* 2) Add a command 'EMCMOT_SET_FOO" to the cmd_code_t enum in motion.h* 3) Add a field to the command_t struct for the value used by* the set command (if there isn't already one that can be used.)* 4) Add a case to the giant switch statement in command.c to* handle the 'EMCMOT_SET_FOO' command.* 5) Write a function emcSetFoo() in taskintf.cc to issue the command.* 6) Add a prototype for emcSetFoo() to emc.hh* 7) Add code to iniaxis.cc (or one of the other inixxx.cc files) to* get the value from the ini file and call emcSetFoo(). (Note* that each parameter has about 16 lines of code, but the code* is identical except for variable/parameter names.)* 8) Add more code to iniaxis.cc to write the new value back out* to the ini file.* After all that, you have the abililty to get a number from the* ini file to a structure in shared memory where the motion controller* can actually use it. However, if you want to manipulate that number* using NML, you have to do more:* 9) Add a #define EMC_SET_FOO_TYPE to emc.hh* 10) Add a class definition for EMC_SET_FOO to emc.hh* 11) Add a case to a giant switch statement in emctaskmain.cc to* call emcSetFoo() when the NML command is received. (Actually* there are about 6 switch statements that need at least a* case label added.* 12) Add cases to two giant switch statements in emc.cc, associated* with looking up and formating the command.*** Derived from a work by Fred Proctor & Will Shackleford** Author:* License: GPL Version 2* System: Linux** Copyright (c) 2004 All rights reserved.** Last change:* $Revision: 1.53.2.1 $* $Author: jmkasunich $* $Date: 2006/05/18 17:41:09 $*********************************************************************/#include <linux/types.h>#include <float.h>#include "posemath.h"#include "rtapi.h"#include "hal.h"#include "motion.h"#include "emcmotglb.h"#include "mot_priv.h"/* debugging functions */extern void print_pose ( EmcPose *pos );extern void check_stuff(char *msg);/* value for world home position */EmcPose worldHome = { {0.0, 0.0, 0.0}, 0.0, 0.0, 0.0};/* kinematics flags */KINEMATICS_FORWARD_FLAGS fflags = 0;KINEMATICS_INVERSE_FLAGS iflags = 0;/* loops through the active joints and checks if any are not homed */int checkAllHomed(void) { int joint_num; emcmot_joint_t *joint; /* bail out if the allHomed flag is already set */ if (0 != emcmotDebug) { if (emcmotDebug->allHomed) return 1; } for (joint_num = 0; joint_num < EMCMOT_MAX_AXIS; joint_num++) { /* point to joint data */ joint = &joints[joint_num]; if (!GET_JOINT_ACTIVE_FLAG(joint)) { /* if joint is not active, don't even look at its limits */ continue; } if (!GET_JOINT_HOMED_FLAG(joint)) { /* if any of the joints is not homed return false */ return 0; } } /* set the global flag that all axes are homed */ if (0 != emcmotDebug) { emcmotDebug->allHomed = 1; } /* return true if all are actives are homed*/ return 1;}/* checkLimits() returns 1 if none of the soft or hard limits are set, 0 if any are set. Called on a linear and circular move. */static int checkLimits(void){ int joint_num; emcmot_joint_t *joint; for (joint_num = 0; joint_num < EMCMOT_MAX_AXIS; joint_num++) { /* point to joint data */ joint = &joints[joint_num]; if (!GET_JOINT_ACTIVE_FLAG(joint)) { /* if joint is not active, don't even look at its limits */ continue; } if (GET_JOINT_PSL_FLAG(joint) || GET_JOINT_NSL_FLAG(joint) || GET_JOINT_PHL_FLAG(joint) || GET_JOINT_NHL_FLAG(joint)) { return 0; } } return 1;}/* check the value of the axis and velocity against current position, returning 1 (okay) if the request is to jog off the limit, 0 (bad) if the request is to jog further past a limit. Software limits are ignored if the joint hasn't been homed */static int checkJog(int joint_num, double vel){ emcmot_joint_t *joint; /* point to joint data */ joint = &joints[joint_num]; if (emcmotStatus->overrideLimits) { return 1; /* okay to jog when limits overridden */ } if (joint_num < 0 || joint_num >= EMCMOT_MAX_AXIS) { reportError("Can't jog out of range axis %d.", joint_num); return 0; } if (vel > 0.0 && GET_JOINT_PSL_FLAG(joint)) { reportError("Can't jog axis %d further past max soft limit.", joint_num); return 0; } if (vel > 0.0 && GET_JOINT_PHL_FLAG(joint)) { reportError("Can't jog axis %d further past max hard limit.", joint_num); return 0; } if (vel < 0.0 && GET_JOINT_NSL_FLAG(joint)) { reportError("Can't jog axis %d further past min soft limit.", joint_num); return 0; } if (vel < 0.0 && GET_JOINT_NHL_FLAG(joint)) { reportError("Can't jog axis %d further past min hard limit.", joint_num); return 0; } /* okay to jog */ return 1;}/* Jogs are not allowed to go all the way to the soft limits, to prevent soft limit errors. The margin a small fraction of the total axis range. This is an attempt to make it independent of units and machine size. When the joint is not homed, the limits are set to the current position +/- the full range of the axis.*/static void refresh_jog_limits(emcmot_joint_t *joint){ double range, margin; range = joint->max_pos_limit - joint->min_pos_limit; if (GET_JOINT_HOMED_FLAG(joint)) { /* if homed, set jog limits just inside soft limits */ margin = range * 0.001; joint->max_jog_limit = joint->max_pos_limit - margin; joint->min_jog_limit = joint->min_pos_limit + margin; } else { /* not homed, set limits based on current position */ joint->max_jog_limit = joint->pos_fb + range; joint->min_jog_limit = joint->pos_fb - range; }}/* inRange() returns non-zero if the position lies within the joint limits, or 0 if not */static int inRange(EmcPose pos){ double joint_pos[EMCMOT_MAX_AXIS]; int joint_num; emcmot_joint_t *joint; /* fill in all joints with 0 */ for (joint_num = 0; joint_num < EMCMOT_MAX_AXIS; joint_num++) { joint_pos[joint_num] = 0.0; } /* now fill in with real values, for joints that are used */ kinematicsInverse(&pos, joint_pos, &iflags, &fflags); for (joint_num = 0; joint_num < EMCMOT_MAX_AXIS; joint_num++) { /* point to joint data */ joint = &joints[joint_num]; if (!GET_JOINT_ACTIVE_FLAG(joint)) { /* if joint is not active, don't even look at its limits */ continue; } if ((joint_pos[joint_num] > joint->max_pos_limit) || (joint_pos[joint_num] < joint->min_pos_limit)) { return 0; /* can't move further past limit */ } } /* okay to move */ return 1;}/* clearHomes() will clear the homed flags for joints that have moved since homing, outside coordinated control, for machines with no forward kinematics. This is used in conjunction with the rehomeAll flag, which is set for any coordinated move that in general will result in all joints moving. The flag is consulted whenever a joint is jogged in joint mode, so that either its flag can be cleared if no other joints have moved, or all have to be cleared. */static void clearHomes(int joint_num){ int n; emcmot_joint_t *joint; if (kinType == KINEMATICS_INVERSE_ONLY) { if (rehomeAll) { for (n = 0; n < EMCMOT_MAX_AXIS; n++) { /* point at joint data */ joint = &(joints[n]); /* clear flag */ SET_JOINT_HOMED_FLAG(joint, 0); } } else { /* point at joint data */ joint = &joints[joint_num]; /* clear flag */ SET_JOINT_HOMED_FLAG(joint, 0); } } if (0 != emcmotDebug) { emcmotDebug->allHomed = 0; }}/*! \function emcmotDioWrite() sets or clears a HAL DIO pin, pins get exported at runtime index is valid from 0 to EMCMOT_MAX_DIO, defined in emcmotcfg.h */void emcmotDioWrite(int index, char value){ if ((index >= EMCMOT_MAX_DIO) || (index < 0)) { rtapi_print_msg(RTAPI_MSG_ERR, "ERROR: index out of range, %d not in [0..%d] (increase EMCMOT_MAX_DIO)\n",index,EMCMOT_MAX_DIO); } else { if (value != 0) { *(emcmot_hal_data->synch_do[index])=1; } else { *(emcmot_hal_data->synch_do[index])=0; } }}/*! \function emcmotAioWrite() sets or clears a HAL AIO pin, pins get exported at runtime \todo Implement function, it doesn't do anything right now RS274NGC doesn't support it now, only defined/used in emccanon.cc */void emcmotAioWrite(int index, double value){ rtapi_print_msg(RTAPI_MSG_ERR, "emcmotAioWrite called, yet not implemented\n");}/* emcmotCommandHandler() is called each main cycle to read the shared memory buffer */void emcmotCommandHandler(void *arg, long period){ int joint_num; emcmot_joint_t *joint; check_stuff ( "before command_handler()" ); /* check for split read */ if (emcmotCommand->head != emcmotCommand->tail) { emcmotDebug->split++; return; /* not really an error */ } if (emcmotCommand->commandNum != emcmotStatus->commandNumEcho) { /* increment head count-- we'll be modifying emcmotStatus */ emcmotStatus->head++; emcmotDebug->head++; /* got a new command-- echo command and number... */ emcmotStatus->commandEcho = emcmotCommand->command; emcmotStatus->commandNumEcho = emcmotCommand->commandNum; /* clear status value by default */ emcmotStatus->commandStatus = EMCMOT_COMMAND_OK; /* ...and process command */ /* Many commands uses "command->axis" to indicate which joint they wish to operate on. This code eliminates the need to copy command->axis to "joint_num", limit check it, and then set "joint" to point to the joint data. All the individual commands need to do is verify that "joint" is non-zero. */ joint_num = emcmotCommand->axis; if (joint_num >= 0 && joint_num < EMCMOT_MAX_AXIS) { /* valid joint, point to it's data */ joint = &joints[joint_num]; } else { /* bad joint number */ joint = 0; }/* printing of commands for troubleshooting */ rtapi_print_msg(RTAPI_MSG_DBG, "%d: CMD %d, code %3d ", emcmotStatus->heartbeat, emcmotCommand->commandNum, emcmotCommand->command); switch (emcmotCommand->command) { case EMCMOT_ABORT: /* abort motion */ /* can happen at any time */ /* this command attempts to stop all machine motion. it looks at the current mode and acts accordingly, if in teleop mode, it sets the desired velocities to zero, if in coordinated mode, it calls the traj planner abort function (don't know what that does yet), and if in free mode, it disables the free mode traj planners which stops axis motion */ rtapi_print_msg(RTAPI_MSG_DBG, "ABORT"); rtapi_print_msg(RTAPI_MSG_DBG, " %d", emcmotCommand->axis); /* check for coord or free space motion active */ if (GET_MOTION_TELEOP_FLAG()) { emcmotDebug->teleop_data.desiredVel.tran.x = 0.0; emcmotDebug->teleop_data.desiredVel.tran.y = 0.0; emcmotDebug->teleop_data.desiredVel.tran.z = 0.0; emcmotDebug->teleop_data.desiredVel.a = 0.0; emcmotDebug->teleop_data.desiredVel.b = 0.0; emcmotDebug->teleop_data.desiredVel.c = 0.0; } else if (GET_MOTION_COORD_FLAG()) { tpAbort(&emcmotDebug->queue); SET_MOTION_ERROR_FLAG(0); } else { for (joint_num = 0; joint_num < EMCMOT_MAX_AXIS; joint_num++) { /* point to joint struct */ joint = &joints[joint_num]; /* tell joint planner to stop */ joint->free_tp_enable = 0; /* stop homing if in progress */ if ( joint->home_state != HOME_IDLE ) { joint->home_state = HOME_ABORT; } } } /* clear axis errors (regardless of mode */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -