3. 圆弧插补

任务目标

给定圆弧的起点、终点和圆心坐标,以及顺/逆时针方向标志,实现圆弧插补:将圆弧离散为一系列插补点,供后续运动控制使用。本案例聚焦于二维平面圆弧,输出各插补点坐标及对应的弓高误差。

核心算法

采用时间分割法(插补周期固定),按以下步骤实现:

  1. 由起点、终点、圆心计算半径、起始角、终止角及圆弧方向;
  2. 根据插补周期和进给速度计算每周期角步距;
  3. 从起始角开始,按方向逐步累加角度,计算插补点坐标;
  4. 最后一点强制等于终点,避免累积误差。

关键完整代码

import math

def arc_interpolate(start, end, center, clockwise, feed_rate=100.0, cycle_time=0.001):
    """
    圆弧插补(二维平面)
    :param start: (x, y) 起点
    :param end: (x, y) 终点
    :param center: (cx, cy) 圆心
    :param clockwise: True=顺时针, False=逆时针
    :param feed_rate: 进给速度 mm/s
    :param cycle_time: 插补周期 s
    :return: 插补点列表 [(x, y), ...],含起点和终点
    """
    sx, sy = start
    ex, ey = end
    cx, cy = center

    # 1. 半径与角度
    r = math.hypot(sx - cx, sy - cy)
    start_angle = math.atan2(sy - cy, sx - cx)
    end_angle = math.atan2(ey - cy, ex - cx)

    # 2. 计算总角位移(考虑方向)
    if clockwise:
        # 顺时针:角度递减
        delta_angle = start_angle - end_angle
        if delta_angle < 0:
            delta_angle += 2 * math.pi
    else:
        # 逆时针:角度递增
        delta_angle = end_angle - start_angle
        if delta_angle < 0:
            delta_angle += 2 * math.pi

    # 3. 角步距
    arc_length = r * delta_angle
    num_steps = max(1, int(arc_length / (feed_rate * cycle_time)))
    angle_step = delta_angle / num_steps

    # 4. 生成插补点
    points = []
    for i in range(num_steps + 1):
        angle = start_angle + angle_step * i if not clockwise else start_angle - angle_step * i
        x = cx + r * math.cos(angle)
        y = cy + r * math.sin(angle)
        points.append((round(x, 6), round(y, 6)))

    # 5. 强制终点精确
    points[-1] = (round(ex, 6), round(ey, 6))
    return points

# 最小验证示例
if __name__ == "__main__":
    # 逆时针半圆:起点(0,0),终点(2,0),圆心(1,0)
    pts_ccw = arc_interpolate((0, 0), (2, 0), (1, 0), clockwise=False)
    print("逆时针半圆点数:", len(pts_ccw))
    print("首点:", pts_ccw[0], "末点:", pts_ccw[-1])

    # 顺时针四分之一圆:起点(1,0),终点(0,1),圆心(0,0)
    pts_cw = arc_interpolate((1, 0), (0, 1), (0, 0), clockwise=True)
    print("顺时针1/4圆点数:", len(pts_cw))
    print("首点:", pts_cw[0], "末点:", pts_cw[-1])

    # 验证所有点均在圆上(半径误差)
    r_test = math.hypot(1, 0)  # 半径=1
    max_err = max(abs(math.hypot(x, y) - r_test) for x, y in pts_cw)
    print("顺时针圆弧最大半径误差:", max_err)

运行与验证

运行方式:直接执行 python arc_interpolate.py(需Python 3.6+,无第三方依赖)。

通过条件:

  • 逆时针半圆首点为(0,0)、末点为(2,0),点数大于10;
  • 顺时针1/4圆首点为(1,0)、末点为(0,1);
  • 所有插补点到圆心的距离与半径之差小于1e-5(即代码输出的最大半径误差极小);
  • 相邻点间距近似等于 feed_rate × cycle_time = 0.1mm(可自行抽查)。

关键说明

  • 角度计算使用 atan2,自动处理象限;方向通过角度增减方向区分,无需额外分支判断跨象限问题。
  • 当起点与终点重合时,delta_angle 为0,函数返回单点(起点),实际应用中应预先判断整圆情况。
  • 插补周期与进给速度的乘积决定步长,步长过大时弓高误差增大,可据此调整参数。
X Y 圆心(1,0) 起点(0,0) 终点(2,0) 逆时针 圆心(0,0) 起点(1,0) 终点(0,1) 顺时针

上图示意两种方向的圆弧插补几何关系:逆时针半圆从起点经上方弧线到达终点,顺时针1/4圆从起点经右侧弧线到达终点。实际插补点沿弧线均匀分布,步长由进给速度与插补周期决定。