Рассчитайте n-мерный путь дуги

Я реализую драйвер для станка с ЧПУ, и у меня возникают проблемы с реализацией команд дуги G-кода.

Я нашел несколько реализаций алгоритма окружности средней точки, но на самом деле его нельзя использовать как есть.

Проблема с круговым алгоритмом средней точки, как я его обнаружил, заключается в том, что он 2D и рисует все октанты одновременно, в то время как мне нужны последовательные шаги по трехмерному пути, заданные начальной, конечной и центральной точками.

Я нашел хороший многомерный эквивалент алгоритма рисования линий Брезенхэма с использованием операций с плавающей запятой. Может быть, существует похожая вещь для рисования дуги?

Возможно, я смогу склонить этот алгоритм к своей воле, много размышляя и экспериментируя, но, поскольку рисование дуги не является нерешенной проблемой, и станки с ЧПУ уже изготавливались ранее, мне интересно, существует ли уже элегантное решение?

2 ответа

Мой пакет Python dxftools, используемый для обработки файлов DXF для не очень умного 2D-резака, имеет функцию разделения дуги на отрезки в 2D. Вы можете использовать этот код, а затем использовать трехмерные преобразования координат, чтобы произвольно поместить его в трехмерное пространство. Примеры преобразования координат можно найти в моем пакете py-stl.

Что ж, на ЧПУ обычно больше, чем просто 2D, так как есть также скорости, углы инструмента, более одного привода на ось, кинематика и т.д... Для этой цели я обычно использую параметрические кубики с параметромt=<0.0,1.0>. Поэтому я преобразовываю путь в набор кубических кривых, которые легко вычислить в любой размерности. После этого шага у вас появилось 3 обычных способа растеризации:

  1. постоянный dt шаг

    параметрические кубики обычно нелинейны, поэтому для перехода к другому пикселю (или чему-то еще) вам нужно увеличить параметр t с меньшим шагом, чем ваше разрешение, выглядит примерно так:

    dt < 1.0 / curve_length  
    

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

  2. искать дальше dt шаг

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

  3. преобразовать в строки

    вы можете разбить кубическую кривую на набор линий (количество зависит от размера кривой) и растрировать линии, как обычно, с помощью DDA или Bresenham. Это самый простой способ, но в результате получится не совсем кривая.

Кубики такие:

P(t) = a0 + a1*t + a2*t^2 + a3*t^3
t = <0.0,1.0>

где P(t) это позиция и a0,a1,a2,a3 - коэффициенты для m векторов, где каждая ось имеет собственный скалярный коэффициент.

См. Как я могу произвести многоточечную линейную интерполяцию? и подссылки о том, как их использовать / вычислять.

В любом случае, если вы настаиваете на интерполяции дуги, предполагая дугу окружности:

P(t) = ( Rotation_matrix(t) * (P0 - Pcenter) ) + Pcenter
t = <0.0,2*PI>

где Rotation_matrix вращает вашу точку вокруг (0,0,0,...,0) по t [rad] в направлении кривой и P0 это начальная точка и Pcenter находится в центре дуги.

В случае вращения без выравнивания оси вы можете вместо этого использовать https://en.wikipedia.org/wiki/Rodrigues%27_rotation_formula.

Однако использование однородных матриц преобразования - ваш лучший вариант в ND, вы просто увеличиваете размер матрицы:

В LinuxCNC генерация позиции отделена от генерации шага. В цикле генерации позиции система отслеживает расстояние, которое она уже прошла вдоль текущего примитива (линия или спираль), и использует простую формулу, чтобы получить местоположение, которое является расстоянием D вдоль этого примитива. (Как правило, это делается один раз в миллисекунду). Эта позиция может использоваться по-разному, в зависимости от того, есть ли у вас сервоприводы, аппаратная генерация или программная генерация.

В программной системе генерации шагов разность между старой заданной позицией и новой заданной позицией определяется вдоль каждой оси, и это используется для обновления скоростей генератора цифрового сигнала с использованием метода прямого цифрового синтеза (DDS). Затем с более высокой скоростью (обычно каждые 20-50 мкс) DDS определяет для каждой оси, следует ли генерировать шаг в это время.

Это другой дизайн, чем вы описываете, но он более гибкий. Например, отделяя генерацию позиции от генерации шага, вы можете пересмотреть алгоритм смешивания в своем коде генерации позиции без пересмотра генерации шага; и вы можете заменить генерацию программных шагов аппаратной генерацией или сервоуправлением алгоритмами, такими как PID.

В своем проекте вы можете аппроксимировать метод, который я описал выше, просто нарезая свою спиральную дугу на отрезки линии, как описано Роландом, и используя их в качестве входных данных в коде генерации вашего шага, который понимает только линии. В некотором смысле, это не слишком отличается от того, что делает LinuxCNC, за исключением того, что примитив кривой становится дискретизированным по расстоянию, а не по времени.

Другие вопросы по тегам