TPL или Tool Path Language. Язык программирования для ЧПУ

Tool Path Language TPL

TPL или Tool Path Language — это язык программирования для создания траекторий станка для ЧПУ. Он основан на JavaScript и является мощной заменой почтенного, но во многом устаревшего языка GCode. Однако TPL может выводить GCode, поэтому он остается совместимым с существующим программным обеспечением для управления машинами, таким как LinuxCNC.

TPL является частью проекта и может использоваться вместе с симулятором ЧПУ CAMotics.

Загрузки

TPL является частью проекта CAMotics. См. загрузку с camotics.org для получения информации о загрузке и установке программного обеспечения.

Пример

Цель этого раздела — дать вам быстрое введение в TPL и некоторые его функции с помощью нескольких простых примеров.

Код TPL — это JavaScript с библиотекой встроенных функций, позволяющих генерировать траектории инструментов. Это выглядит так:

feed(400);     // Установите скорость подачи на 400 миллиметров в минуту.
tool(1);       // Выберите инструмент 1

rapid({z: 5}); // Переместитесь на безопасную высоту 5 мм.
rapid({x: 1, y: 1});  // Перейти в исходное положение
speed(2000);   // Вращение со скоростью 2000 об/мин по часовой стрелке.

cut({z: -3});  // Вырезать до глубины
cut({x: 11});  // Обрезать до второго угла
cut({y: 11});  // Обрезать до третьего угла
cut({x: 1});   // Обрезать до четвертого угла
cut({y: 1});   // Обрезать до начала

rapid({z: 5}); // Вернитесь в безопасное положение
speed(0);      // Остановить вращение
Симулятор CAMotics показывает результат
Симулятор CAMotics показывает результат

В предыдущем примере машина инициализируется, а затем вырезает квадрат. Обратите внимание, что вы всегда должны устанавливать скорость подачи на значение, отличное от нуля, перед выполнением резки. Также рекомендуется выбрать инструмент и установить скорость вращения шпинделя. Также обратите внимание, что TPL по умолчанию использует метрические единицы. Вы можете переключиться на имперские единицы, вызвав units(IMPERIAL).

Обратите внимание, что используемая выше нотация в квадратных скобках {}позволяет указать определенные аргументы и оставить для других значения по умолчанию. Все следующие вызовы функций эквивалентны:

rapid(5, 10, 15);
rapid({x: 5, y: 10, z: 15});
rapid({z: 15, x: 5, y: 10});

Код в квадратном примере может быть более читабельным, чем обычный GCode, но реальная мощь TPL заключается в его способности использовать более продвинутые языковые конструкции, такие как функции. Приведенный выше квадратный пример можно обернуть в такую ​​функцию:

function square(size, depth, safe) {
  cut({z: depth});  // Вырезать до глубины
  icut({x: size});  // Вырезать до глубины
  icut({y: size});  // Обрезать до третьего угла
  icut({x: -size}); // Вырезать до четвертого угла
  icut({y: -size}); // Обрезать до начала
  rapid({z: safe}); // Вернуться на безопасную позицию
}

feed(400);          // Установите скорость подачи 400 мм в минуту.
tool(1);            // Выбрать инструмент 1

rapid({z: 5});      // Переместить на безопасную высоту 5 мм.
rapid({x: 1, y: 1});  // Перейти в исходное положение
speed(2000);        // Вращение со скоростью 2000 об/мин по часовой стрелке.

square(10, -3, 5);

speed(0);           // Остановить вращение

Обратите внимание, что square()функция использует icut() инкрементную версию cut().

Учитывая square()функцию, теперь вы можете вырезать повторяющиеся квадраты следующим образом:

for (i = 1; i <= 10; i++) square(i * 5, -3, 5);
Вот результат выполнения squareфункции, как в цикле for выше
Вот результат выполнения
squareфункции, как в цикле for выше

Чтобы продолжить пример немного дальше и показать больше возможностей TPL, мы можем повторить и повернуть квадраты, чтобы создать интересный узор, используя следующую программу:

function square(size, depth, safe) {
   cut({z: depth});  // Вырезать до глубины
  icut({x: size});  // Вырезать до глубины
  icut({y: size});  // Обрезать до третьего угла
  icut({x: -size}); // Вырезать до четвертого угла
  icut({y: -size}); // Обрезать до начала
  rapid({z: safe}); // Вернуться на безопасную позицию
}

function squares(count, space, depth, safe) {
  for (var i = 1; i <= count; i++) {
    rapid({x: -space * i, y: -space * i});
    square(i * 2 * space, depth, safe);
  }
}

feed(400);          // Установите скорость подачи 400 мм в минуту.
tool(1);            // Выбрать инструмент 1
rapid({z: 5});      // Переместить на безопасную высоту 5 мм.
rapid({x: 1, y: 1}); // Перейти в исходное положение
speed(2000);        // Вращение со скоростью 2000 об/мин по часовой стрелке

for (var i = 0; i < 4; i++) {
  squares(10, 5, -3, 5);
  rotate(Math.PI / 8); // Повернуть по часовой стрелке на 15 градусов

}

speed(0);           // Остановить вращение
Симулятор показывает конечный результат
Симулятор показывает конечный результат

Использование TPL

После загрузки и установки последней версии CAMotics вы можете написать программу TPL или попробовать один из примеров. Программы TPL обычно имеют расширение файла .tpl. Вы можете выполнить программу TPL следующим образом:

tplang input.tpl

Это выведет полученный GCode на экран. Вы также можете сохранить вывод в файл следующим образом:

tplang input.tpl > output.gc

Затем вы можете просмотреть результаты в симуляторе CAMotics следующим образом:

camotics output.gc

Вам также, вероятно, придется настроить таблицу инструментов и определить заготовку (материал, который разрезается), чтобы получить правильную симуляцию. См. camotics для получения дополнительной информации об использовании симулятора.

API

Интерфейс прикладного программирования TPL позволяет вам легко дублировать любую программу GCode в гораздо более читабельном виде, но вы также имеете всю мощь языка JavaScript, так что возможно гораздо больше. На самом деле вам даже не нужно программное обеспечение CAM, вы можете моделировать формы, которые хотите вырезать, прямо в TPL.

Движение инструмента

rapid(x, y, z, a, b, c, u, v, w, incremental=false)

Выполните линейное движение со скоростью быстрой подачи из текущей позиции в новую позицию, определенную предоставленными аргументами осей.

rapid(0, 0, 0);          // Rapid to x=0, y=0, z=0
rapid(10, 10);           // Rapid to x=10, y=10, z remains 0
rapid({z: 10, y: 10});   // Rapid to y=10, z=10, x remains 10

irapid(x, y, z, a, b, c, u, v, w, incremental=true)

Аналогично, rapid()но incremental по умолчанию имеет значение true.

cut(x, y, z, a, b, c, u, v, w, incremental=false)

То же, что и rapid()за исключением перемещений с текущей скоростью подачи, заданной вызовом feed().

icut(x, y, z, a, b, c, u, v, w, incremental=true)

Аналогично, cut()но incremental по умолчанию имеет значение true.

arc(x, y, z, angle, plane)

x и укажите смещение y от z текущего положения до дальнего центра винтового перемещения в выбранной плоскости. Если z значение равно нулю, то перемещение представляет собой простую дугу в выбранной плоскости, в противном случае это винтовое перемещение с осью длины, равной абсолютному значению z, либо выше, либо ниже выбранной плоскости через текущую контрольную точку в зависимости от знака.

angle это вращение дуги в радианах. Положительное значение указывает на вращение по часовой стрелке, отрицательное — на вращение против часовой стрелки.

plane указывает, к какой плоскости винтовая ось перпендикулярна. Допустимые значения: XY(по умолчанию) XZ или YZ.

probe(x, y, z, a, b, c, u, v, w, port=0, active=true, error=true)

Сделайте линейное перемещение в указанном направлении, пока состояние не изменится на целевое состояние. Если active true, движение зонда остановится при контакте. В противном случае он остановится при потере контакта.

probe()вернет координаты положения на момент изменения состояния зонда. Если запрограммированная точка была достигнута до изменения состояния, вместо этого будет возвращена запрограммированная точка.

probe(z = -10);  // Probe towards z=-10
probe(z = 10, active = false);  // Probe away from current z

Это ошибка, если:

  • Текущая точка совпадает с запрограммированной точкой.
  • Текущая скорость подачи равна нулю.
  • Зонд уже находится в целевом состоянии.

dwell(seconds)

seconds укажите время в секундах, в течение которого все оси останутся неподвижными. Можно использовать доли секунды.

dwell(0.5);  // Dwell for half a second.

Состояние машины

feed(rate, mode = FEED_UNITS_PER_MIN)

rate указывает единицы в минуту в декартовой системе XYZ для всех последующих небыстрых перемещений до изменения скорости подачи.

mode может быть одним из следующих:

  • FEED_UNITS_PER_MIN— Скорость подачи указана в единицах в минуту. Единицами измерения могут быть дюймы, миллиметры или градусы в зависимости от текущей единицы длины и от того, какие оси перемещаются.
  • FEED_INVERSE_TIME— Указывает, что ходы должны быть выполнены за одну деленную на rate минуты. Например, если rate 2.0, ходы должны быть выполнены за полминуты.
  • FEED_UNITS_PER_REV— Означает, что контролируемая точка должна перемещаться на определенное количество единиц за один оборот.

Обратите внимание, что эти имена чувствительны к регистру.

Если аргументы не указаны, возвращает текущую скорость подачи и режим.

feed(4);           // Move at 4 units per minute
rate = feed()[0];  // Get the current feed rate

speed(rate, surface, max)

rate указывает число оборотов шпинделя в минуту.

Если rate положительно, шпиндель будет вращаться по часовой стрелке. Если отрицательный в направлении против часовой стрелки.

Нулевой rate выключает шпиндель.

Если surface указано, то выбирается постоянная скорость поверхности в surface, футах в минуту, если выбраны единицы измерения IMPERIAL, или в метрах в минуту, если выбраны единицы измерения METRIC. Если max также указано, это указывает на максимальное число оборотов шпинделя.

Если аргументы не указаны, возвращает текущую скорость шпинделя, скорость резания и максимальное число оборотов в минуту.

speed(1000);    // Spin clockwise at 1K RPM.
speed(-20000);  // Spin counterclockwise at 20K RPM.

tool(number)

Сделать инструмент number текущим инструментом.

tool(1);  // Select tool 1

Если аргументы не указаны, возвращается информация о выбранном в данный момент инструменте. Например:

{
   number: 1,
   shape: CONICAL,        // A tool type constant
   angle: Math.PI * 0.5,  // In radians, 90°
   length: 10,            // In current units
   diameter: 3.175,       // In current units
   snub_diameter: 1       // If shape == SNUBNOSE
}

Например, чтобы получить текущий радиус инструмента:

var tool_radius = tool().diameter / 2;

Константы типа инструмента следующие:

  • CYLINDRICAL
  • CONICAL
  • BALLNOSE
  • SPHEROID
  • SNUBNOSE

units(type)

type может быть либо METRIC миллиметры в качестве единицы измерения, либо IMPERIAL дюймы.

Если аргументы не указаны type, возвращается текущий.

units(METRIC);  // Select millimeters

pause(optional=false)

Приостановите программу, пока пользователь не возобновит работу. Если optional верно, то пауза только в том случае, если переключатель остановки активирован.

pause(true);

workpiece()

Получите смещение и размеры заготовки текущей симуляции.

workpiece() = {
  dims: {x: 100, y: 100, z: 10},
  offset: {x: -50, y: -50, z: -10}
}

Матрица

pushMatrix(matrix)

popMatrix(matrix)

loadIdentity(matrix)

scale(x=1, y=1, z=1, matrix)

translate(x=0, y=0, z=0, matrix)

rotate(angle, x=0, y=0, z=1, matrix)

Математика

JavaScript имеет встроенные математические функции и константы, которые являются членами встроенного объекта Math. Объект Math определен в спецификации EMCAScript, раздел 15.8, или, возможно, в более удобочитаемом формате в W3 Schools, справочник по объекту Math.

var negOne = Math.cos(Math.PI);

Отладка

print(...)

Преобразуйте все аргументы в строки и выведите их в выходной поток.

Обратите внимание, что print() запись выполняется в тот же поток вывода, что и функции gcode, поэтому, если вы не хотите мешать выводу gcode, вы должны заключить текст в круглые скобки () , чтобы он рассматривался как комментарий gcode.

print() не добавляет автоматически конец строки и не интерпретирует строки форматирования.

print("Hello World!\n");
print("(A gcode comment)\n");

comment(...)

Преобразуйте все аргументы в строки и выведите комментарий GCode.

comment("A gcode comment");

message(...)

Преобразуйте все аргументы в строки и выведите сообщение GCode.

В некоторых контекстах пользователю отображаются сообщения GCode.

message("Hello World");

console.log(...)

Распечатайте в журнал информационный поток.

console.debug(...)

Распечатайте, чтобы записать поток отладки.

console.warn(...)

Печать для записи потока предупреждений.

console.error(...)

Печать для регистрации потока ошибок.

Модуль

Загрузить модули кода.

require(path)

Загрузите указанный модуль. Модули ищутся в каталогах, указанных в TPL_PATH переменной окружения. Модуль TPL может быть либо файлом, заканчивающимся на .tpl , .js или .json , либо каталогом, содержащим файл package.json.

Файлы.tpl или.js загружаются как код, тогда как файлы.json загружаются как данные. Модули кода должны присваивать значения словарю module.exports(как вариант exports), чтобы они были доступны. Например:

// A TPL module
module.exports = {
  data: [1, 2, 3],
 
  hello: function () {print("Hello World!\n");}
}

Если бы приведенный выше код находился в файле с именем hello.tpl, для доступа к нему можно было бы использовать следующее:

var m = require('hello.tpl');
 
m.hello();
 
for (var i = 0; i < m.data.length; i++)
  print(m.data[i], '\n');

Файлы package.json обрабатываются особым образом. Содержимое интерпретируется как словарь данных JSON, а атрибут main считывается, чтобы получить относительный путь точки входа для модуля. Затем указанный файл загружается как модуль кода или данных, как указано выше.

При загрузке модуля определяются следующие переменные:

module.nameИмя модуля.
module.idТо же, что и module.name.
module.filenameПолный путь к модулю.
module.exportsСловарь экспорта. Используется для экспорта общедоступных данных и функций. Может быть присвоено новое значение.
exportsТо же, что и module.exports, но переназначение не действует.
idТо же, что и module.name.

Если какие-либо модули имеют циклические вызовы require() , значения модуля могут быть недоступны во время загрузки модуля. Например:

а.tpl:

var b = require('b.tpl');
print(b.data, '\n');
module.exports = {data: 'A'}

b.tpl:

var a = require('a.tpl');
print(a.data, '\n');
module.exports = {data: 'B'}

main.tpl:

var a = require('a.tpl');
var b = require('b.tpl');
print(a.data, '\n');
print(b.data, '\n');

Запуск main.tpl приведет к следующему выводу:

undefined
B
A
B

Первая ссылка на a.data не определена, поскольку модуль A еще не полностью загружен при доступе к модулю B. Однако все данные были загружены к моменту обращения к ним main.tpl.

2D-полигоны

Некоторые базовые CAM-операции с 2D-полигонами.

offset(polys, delta, join, limit=1000, autoFix=true, scale=1000000)

polysСписок полигонов. См. формат ниже.
deltaДельта смещения. Положительный для начала. Отрицательный для вставки.
joinТип соединения. JOIN_SQUAREJOIN_ROUNDJOIN_MITER
limitПо умолчанию 1000 . Ограничение для JOIN_MITER.
autoFixПо умолчанию true. При необходимости автоматически исправлять ориентацию полигона и удалять повторяющиеся вершины.
scaleПо умолчанию 10 000 000. Масштабируйте точки многоугольника, чтобы повысить точность.

Используйте библиотеку Clipper для вычисления смещения полигонов.

Аргумент polysпредставляет собой массив из одного или нескольких полигонов и форматируется либо как массив массивов словарей:

[
  [{x: 0, y: 0}, {x: 1, y: 0},..., {x: 0, y: 0}],
...
]

или массив массивов:

[
  [[0, 0], [1, 0],..., [0, 0]],
...
]

Обратите внимание, что результаты dxf.open()не могут использоваться напрямую, offset()но другие функции в модуле dxf могут преобразовывать необработанные данные DXF в полигоны.

DXF

Поддержка формата файлов DXF.

Constants

POINT
LINE
ARC
POLYLINE
SPLINE

open(path)

Прочитайте файл DXF и верните данные JSON в виде словаря слоев. Каждый слой представляет собой список любых из следующих сущностей:

POINT

{
  type: dxf.POINT,
  x: 0,
  y: 0,
  z: 0
}

LINE

{
  type: dxf.LINE,
  start: {x: 0, y: 0, z: 0},
  end: {x: 1, y: 1, z: 1}
}

ARC

{
  type: dxf.ARC,
  center: {x: 0, y: 0, z: 0},
  radius: 1,
  startAngle: 0,
  endAngle: 2 * Math.PI,
  clockwise: true
}

POLYLINE

{
  type: dxf.POLYLINE,
  vertices: [
    {type: dxf.POINT, x: 0, y: 0, z: 0},
  ...
  ]
}

SPLINE

{
  type: dxf.SPLINE,
  degree: 3,
  ctrlPts: [
    {type: dxf.POINT, x: 0, y: 0, z: 0},
  ...
  ],
  knots: [0,...]
}

Пример

var dxf = require('dxf');
var layers = dxf.open('test.dxf');
 
 

Читайте также:

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *