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

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

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

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

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

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


person Pepijn    schedule 16.04.2012    source источник
comment
Вы пытаетесь найти путь вдоль одномерной кривой в трехмерном пространстве или путь, покрывающий двумерную криволинейную поверхность в трехмерном пространстве?   -  person Beta    schedule 17.04.2012


Ответы (3)


Что ж, на ЧПУ обычно есть больше, чем просто 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 — центр дуги.

В случае вращения, не выровненного по оси, вы можете вместо этого использовать Rodrigues_rotation_formula.

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

person Spektre    schedule 12.02.2020
comment
Как вы можете себе представить, 7 лет — это много, поэтому я больше не внедряю драйвер ЧПУ, но это очень исчерпывающий ответ, так что спасибо! (хотя 7 лет назад я понятия не имел о матрицах вращения и тому подобных вещах) - person Pepijn; 13.02.2020

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

person Roland Smith    schedule 19.04.2012

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

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

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

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

person Jeff Epler    schedule 03.05.2014