ToolInformationFlow - rmu75/linuxcnc-wiki GitHub Wiki


date: '2011-08-17T13:33:04' title: ToolInformationFlow

The flow of tool information in EMC2

I'm trying to summarize a high-level view of tool information flow in EMC2. Please correct/extend as needed. 'GUI' is synonymous with Axis for now.

Location of tool information:

Tool Information is held in the following locations:

  • in the iocontrol process
  • in the interpreter _setup.tool_table array and some other C++ member variables. Interpreter instances with per-process copies of this table appear in:
    • milltask process interpreter instance
    • the GUI process interpreter instance
  • in the GUI Python address space tool information is held as a set of Pyrhon variables.
  • in the external tool table file

This table is shared by means of the emcStatus structure, which conceptually is shared memory for the purpose of this discussion (it is implemented with periodic synchronous message passing with pretty much the same effect).

Tool-related fields in the emcStatus structure:

*io.toolInSpindle - tool number of the current tool. 0 means 'no tool loaded' *io.tool.toolTable - array as managed by iocontrol *io.tool.pocketPrepped - the pocket number of a prepared tool. -1 if none prepared.

iocontrol is the authoritative source for tool information and reads/writes the external tool table file. It works directly from/to the emcStatus.tool.toolTable array.

Change of tool information in emcStatus

Change of tool-related fields is initiated by NML messages generated by the milltask interpreter instance, queued to the task executor, and from there directed towards iocontrol. iocontrol acts on these messages and changes some fields in the emcStatus structure, which is again shared by the other components.

The NML messages manipulating tool information are:

  • EMC_TOOL_SET_OFFSET which contrary to the name not just sets an offset but the whole tool entry,
  • EMC_TOOL_LOAD (changes io.toolInSpindle and io.tool.pocketPrepped)
  • EMC_TOOL_LOAD_TOOL_TABLE (after external tool table change)
  • EMC_TOOL_SET_NUMBER (changes tool.toolInSpindle)

When a UI needs to execute a code, for instance G10 L1 (set tool table), this command is sent from the UI, to task, as an EMC_TASK_PLAN_EXECUTE message. The task executor passes this message to the milltask interpreter instance for execution. As a result, an EMC_TOOL_SET_OFFSET message is queued to task, which in turn sends it to iocontrol, which acts upon it, updates tool.toolTable in emcStatus, and writes the tool table to the filesystem. Other components like the UI pull the updated emcStatus structure and now have updated information.

Flow of tool information from iocontrol to other locations:

Conceptually emcStatus is managed by the task executor, and the other components pull a copy when needed, or "push" in the case of iocontrol.

On a lower level, an interpreter instance uses the GET_EXTERNAL_TOOL_TABLE() canon call to obtain a single tool table entry, which is currently indexed by pocket.

Depending on the environment the canon layer may access tool information as follows:

  • in milltask, GET_EXTERNAL_TOOL_TABLE() directly accesses milltask's copy of the emcStatus structure.

  • in axis, the emcStatus structure is accessed in the Python context by means calls to emc.stat.poll(). This results in the self.tool_array being set (lib/python/rs274/interpret.py). If the interpreter needs to access a tool table entry, it calls upon GET_EXTERNAL_TOOL_TABLE() C function which resides within the gcode Python module. This results in a callback from C, into Python, to retrieve a tool entry through the Python get_tool method, and from there into _setup.tool_table .

Tool change & information flow:

"tool change" from an interpreter perspective happens at different points in time: in the GUI during preview generation, and in milltask during execution.

During "parse_file", the GUI retrieves the current tooltable lib/python/rs274/interpret.py, Class StatMixin method init()) and holds it as a member variable of type list of tools.

During preview, the GUI accesses a tool entry by means of the 'get_tool' method and 'changes tools' by means of the change_tool method (lib/python/rs274/interpret.py Class StatMixin). The result of this method is only significant for the UI, and causes no external changes. Also, the fact that a tool change must be waited for is ignored with the UI (like probe, or wait for HAL pin) since it's a simulated process which should run as fast as possible.

For the milltask interpreter instance, which runs in execution-time context, a change operation is a 'queue buster': task stops readahead until the change is complete and emcStatus is updated by iocontrol, reflecting updated toolInSpindle and toolTable configuration. Then the task executor calls the interpreter.synch() method, which directs the interpreter its internal view with the external world model. Among others, that causes calls to GET_EXTERNAL_TOOL_TABLE() to re-read tool_table from milltask's emcStatus structure entry-by-entry.

iocontrol modifies several fields in emcStatus - it changes toolInSpindle, and swaps the current and prepared pocket, effectively swapping two entries in the toolTable array. This is managed by iocontrol, depending on the changer type (random or nonrandom).

In the GUI, the same process is mirrored during preview generation (StatMixin.change_tool).

open questions

  • reading axis.py + friends, I understand that the current tool table is pulled from emcStatus once when a new file interpretation starts: when open_file_guts() is invoked and a new AxisCanon instance created, which inherits from StatMixin, whose init() method assigns the 'tools' array from emcStatus (s.tool_table). From then on, modifications to the tools array are local and a consequence of executing a 'toolchange" during preview generation. Correct?
  • axis.py calls emc.stat.poll and hence an updated tooltable from emcStatus on every LivePlotter.update() call, which seems to be called from the idle loop. Correct?
  • if so, it it is unclear why at initialisation time, and and parsing of a gcode file with open_file_guts() the whole tool table is re-copied from stat.tool_table into self.tools. Is this because an execution-time toolchange by iocontrol swaps table entries, which could happen at the wrong time for axis, which it why it works on its own copy to start with?
⚠️ **GitHub.com Fallback** ⚠️