首页 > 其他分享 >圆弧路径规划C重构

圆弧路径规划C重构

时间:2025-01-13 10:43:13浏览次数:1  
标签:重构 double travel 路径 arc ffi 圆弧 angular AXIS

参数

  • currentPos: 命名元组 Coord(x=-155.0, y=0.0, z=0.4, e=0.0)
  • targetPos: [0.0, -155.0, 0.3]
  • offset: [155.0, 0.0] 圆心坐标
  • clockwise: True 顺时针,Fasle 逆时针
  • mm_per_arc_segment: 默认值1.0,支持配置文件动态获取
  • 输入和输出,和python代码的实现保持一致。

C代码实现

  • 第一版v1.0
#include <stdio.h>
#include <math.h>
#include <stdlib.h>

#define X_AXIS 0
#define Y_AXIS 1
#define Z_AXIS 2

#define M_PI 3.14159265358979323846


// Function to plan the arc and return the generated coordinates
double** planArc(double currentPos[3], double targetPos[3], double offset[2], int clockwise, double mm_per_arc_segment) {
    // Radius vector from center to current location
    double r_P = -offset[0];
    double r_Q = -offset[1];

    // Determine angular travel
    double center_P = currentPos[X_AXIS] - r_P;
    double center_Q = currentPos[Y_AXIS] - r_Q;
    double rt_X = targetPos[X_AXIS] - center_P;
    double rt_Y = targetPos[Y_AXIS] - center_Q;
    double angular_travel = atan2(r_P * rt_Y - r_Q * rt_X, r_P * rt_X + r_Q * rt_Y);

    if (angular_travel < 0.0) {
        angular_travel += 2.0 * M_PI;
    }
    if (clockwise) {
        angular_travel -= 2.0 * M_PI;
    }

    if (angular_travel == 0.0 &&
        currentPos[X_AXIS] == targetPos[X_AXIS] &&
        currentPos[Y_AXIS] == targetPos[Y_AXIS]) {
        // Make a circle if the angular rotation is 0 and the target is the current position
        angular_travel = 2.0 * M_PI;
    }

    // Determine number of segments
    double linear_travel = targetPos[Z_AXIS] - currentPos[Z_AXIS];
    double radius = hypot(r_P, r_Q);
    double flat_mm = radius * angular_travel;
    double mm_of_travel = (linear_travel != 0.0) ? hypot(flat_mm, linear_travel) : fabs(flat_mm);

    int segments = (int)fmax(1.0, floor(mm_of_travel / mm_per_arc_segment));
    printf("==== Numbers: %d\n", segments);

    //*segment_count = segments;  // Store the number of segments in the output parameter

    // Allocate memory for coordinates
    double** coords = (double**)malloc((segments + 1) * sizeof(double*));
    for (int i = 0; i <= segments; i++) {
        coords[i] = (double*)malloc(3 * sizeof(double));
    }

    // Generate coordinates
    double theta_per_segment = angular_travel / segments;
    double linear_per_segment = linear_travel / segments;

    for (int i = 1; i < segments; i++) {
        double dist_Z = i * linear_per_segment;
        double cos_Ti = cos(i * theta_per_segment);
        double sin_Ti = sin(i * theta_per_segment);
        double temp_r_P = -offset[0] * cos_Ti + offset[1] * sin_Ti;
        double temp_r_Q = -offset[0] * sin_Ti - offset[1] * cos_Ti;

        coords[i][X_AXIS] = center_P + temp_r_P;
        coords[i][Y_AXIS] = center_Q + temp_r_Q;
        coords[i][Z_AXIS] = currentPos[Z_AXIS] + dist_Z;
    }

    // Add the target position as the last coordinate
    coords[segments][X_AXIS] = targetPos[X_AXIS];
    coords[segments][Y_AXIS] = targetPos[Y_AXIS];
    coords[segments][Z_AXIS] = targetPos[Z_AXIS];

    return coords;  // Return the array of coordinates
}

int main() {
    double currentPos[3] = {-155.0, 0.0, 0.4};
    double targetPos[3] = {0.0, -155.0, 0.3};
    double offset[2] = {155.0, 0.0};
    int clockwise = 0;
    double mm_per_arc_segment = 1.0;
    int segment_count = 243;  // 测试参数值

    // Plan the arc
    double** coords = planArc(currentPos, targetPos, offset, clockwise, mm_per_arc_segment);

    // Print the result
    for (int i = 1; i <= segment_count; i++) {
        printf("Segment %d: X = %.13f, Y = %.13f, Z = %.13f\n", i, coords[i][X_AXIS], coords[i][Y_AXIS], coords[i][Z_AXIS]);
    }

    // Free memory
    for (int i = 0; i <= segment_count; i++) {
        free(coords[i]);
    }
    free(coords);

    return 0;
}
  • 第二版v2.0
#include <stdio.h>
#include <math.h>
#include <stdlib.h>

#include "compiler.h"

#define X_AXIS 0
#define Y_AXIS 1
#define Z_AXIS 2

#define M_PI 3.14159265358979323846


typedef struct {
    double** coords;
    int rows;
} arc_result;

// chailinnan add ...
// Function to plan the arc and return the generated coordinates
arc_result __visible
    planArc(double currentPos[3], double targetPos[3], double offset[2], int clockwise, double mm_per_arc_segment) {
    // Radius vector from center to current location
    double r_P = -offset[0];
    double r_Q = -offset[1];

    // Determine angular travel
    double center_P = currentPos[X_AXIS] - r_P;
    double center_Q = currentPos[Y_AXIS] - r_Q;
    double rt_X = targetPos[X_AXIS] - center_P;
    double rt_Y = targetPos[Y_AXIS] - center_Q;
    double angular_travel = atan2(r_P * rt_Y - r_Q * rt_X, r_P * rt_X + r_Q * rt_Y);

    if (angular_travel < 0.0) {
        angular_travel += 2.0 * M_PI;
    }
    if (clockwise) {
        angular_travel -= 2.0 * M_PI;
    }

    if (angular_travel == 0.0 &&
        currentPos[X_AXIS] == targetPos[X_AXIS] &&
        currentPos[Y_AXIS] == targetPos[Y_AXIS]) {
        // Make a circle if the angular rotation is 0 and the target is the current position
        angular_travel = 2.0 * M_PI;
    }

    // Determine number of segments
    double linear_travel = targetPos[Z_AXIS] - currentPos[Z_AXIS];
    double radius = hypot(r_P, r_Q);
    double flat_mm = radius * angular_travel;
    double mm_of_travel = (linear_travel != 0.0) ? hypot(flat_mm, linear_travel) : fabs(flat_mm);

    int segments = (int)fmax(1.0, floor(mm_of_travel / mm_per_arc_segment));
    // printf("==== Numbers: %d\n", segments);
    //*segment_count = segments;  // Store the number of segments in the output parameter

    arc_result result;
    result.rows = segments;

    // Allocate memory for coordinates
    result.coords = (double**)malloc((segments + 1) * sizeof(double*));
    for (int i = 0; i <= segments; i++) {
        result.coords[i] = (double*)malloc(3 * sizeof(double));
    }

    // Generate coordinates
    double theta_per_segment = angular_travel / segments;
    double linear_per_segment = linear_travel / segments;

    for (int i = 1; i < segments; i++) {
        double dist_Z = i * linear_per_segment;
        double cos_Ti = cos(i * theta_per_segment);
        double sin_Ti = sin(i * theta_per_segment);
        double temp_r_P = -offset[0] * cos_Ti + offset[1] * sin_Ti;
        double temp_r_Q = -offset[0] * sin_Ti - offset[1] * cos_Ti;

        result.coords[i][X_AXIS] = center_P + temp_r_P;
        result.coords[i][Y_AXIS] = center_Q + temp_r_Q;
        result.coords[i][Z_AXIS] = currentPos[Z_AXIS] + dist_Z;
    }

    // Add the target position as the last coordinate
    result.coords[segments][X_AXIS] = targetPos[X_AXIS];
    result.coords[segments][Y_AXIS] = targetPos[Y_AXIS];
    result.coords[segments][Z_AXIS] = targetPos[Z_AXIS];

    return result;
}



// free arc_result memory
void __visible free_arc_result(arc_result result) {
    for (int i = 0; i <= result.rows; i++) {
        free(result.coords[i]);
    }
    free(result.coords);
}
  • __visible 关键词,表示编译后对外部可见,支持外部调用

编译

  • **init.py **里面需要把添加的c代码模块,定义进去,然后进行编译
  • /home/pi/klippy-env/bin/python init.py
    • 对添加的c代码进行编译

python 调用

from cffi import FFI

ffi = FFI()
ffi.cdef("""
    double* planArc(...);  // C函数的声明
    void free(void*);  // C中释放内存的函数
""")

C = ffi.dlopen("your_c_library.so")

# 使用ffi.gc绑定返回的指针和C的free函数
coords = ffi.gc(C.planArc(...), C.free)

# 使用coords,Python会在coords不再被引用时自动调用C.free

  • python 调用示例,释放内存资源
ffi_main, ffi_lib = chelper.get_ffi()
coords = ffi_main.gc(ffi_lib.planArc(...),
                     ffi_lib.free)
  • 具体调用实现

测试

import chelper
from gcode import Coord

def test_v2():
    currentPos = Coord(x=-155.0, y=0.0, z=0.4, e=0.0)

    ffi_main, ffi_lib = chelper.get_ffi()
    arc_result = ffi_main.gc(ffi_lib.planArc(currentPos, [0.0, -155.0, 0.3], [155.0, 0.0],
                                             False, 1.0),
                             ffi_lib.free_arc_result)

    print(arc_result.coords)
    print(arc_result.rows)

    rows = arc_result.rows
    coords = arc_result.coords

    coords_list = [coords[i] for i in range(1, rows + 1)]

    numeric_values = [[ptr[0], ptr[1], ptr[2]] for ptr in coords_list]  # 读取每个指针指向的 double 值
    print(numeric_values)
    print(len(numeric_values))

标签:重构,double,travel,路径,arc,ffi,圆弧,angular,AXIS
From: https://www.cnblogs.com/logicalsky/p/18662194

相关文章

  • 你可能不知道的 @ 在路径使用指南
    ......
  • 奇安信代码扫描——路径遍历问题
    奇安信代码扫描——路径遍历问题解决路径遍历(PathTraversal)漏洞是一种常见的Web安全问题,它允许攻击者通过操纵文件路径访问不受限制的文件或目录。奇安信代码扫描工具检测到路径遍历问题,意味着你的应用程序中可能存在这种安全风险。要理解这个问题及其检测原理,我们需要深......
  • 代码随想录:路径总和
    代码随想录:路径总和思路很简单,但是一个传参很巧妙,每次递归减去当前节点的值,就只用一个传参/***Definitionforabinarytreenode.*structTreeNode{*intval;*TreeNode*left;*TreeNode*right;*TreeNode():val(0),left(nullptr),righ......
  • Windows 安装软件常用更改路径
     环境变量:#标题键值 #javaJAVA_HOMEE:\Programs\Java\jdk-20 #javaPath %JAVA_HOME%\bin (AI认为只有一个JAVA版本时可以直接写 E:\Programs\Java\jdk-20\bin而不需创建JAVA_HOME环境变量,写JAVA_HOME只是为了方便开发时用命令行切换Java版本) #vs......
  • 探讨人工智能机器人学之路径规划与导航:A*算法、Dijkstra算法等路径规划方法
    引言在人工智能(AI)和机器人学中,路径规划与导航是一个至关重要的课题。机器人在复杂的环境中,必须能够根据环境信息和目标要求,自动计算一条从起始位置到目标位置的最优或可行的路径。路径规划不仅仅是关于如何找到目标位置,还涉及如何在多变、动态的环境中避免障碍、实现效率和安......
  • LeetCode:112.路径总和
    LeetCode:112.路径总和解题思路在深度优先遍历的过程中,记录当前路径的节点值的和。在叶子节点处,判断当前路径的节点值的和是否等于目标值。解题步骤深度优先遍历二叉树,在叶子节点处,判断当前路径的节点值的和是否等于目标值,是就返回true。遍历结束,如果没有匹配,就返回false。varh......
  • 为什么设置MSVC cl.exe到PATH路径,依然无法正常编译?为什么MSVC toolchain有多个cl.exe
    为什么设置MSVCcl.exe到PATH路径,依然无法正常编译?MSVC可以正常编译C/C++代码的前提,还包括INCLUDE/LIB路径等都正确配置,而这无法仅仅通过MSVCcl.exe的PATH路径来完成。VS提供了一个官方的配置MSVC环境的方式,可以通过开始菜单的"DeveloperCommandPromptforVS2019......
  • 计算机视觉实战项目(图像分类+目标检测+目标跟踪+姿态识别+车道线识别+车牌识别+无人
    往期热门项目回顾:链接失效时请主页搜索关键词!!!!文章目录**往期热门项目回顾:**车辆跟踪及测距yolov5deepsort行人/车辆(检测+计数+跟踪+测距+测速)目标跟踪车道线识别语义分割姿态识别图像分类交通标志识别表情识别、人脸识别疲劳检测车牌识别代码图像去雾去雨+......
  • FTP上传目录路径解析及HTTP错误404解决办法
    问题描述:用户尝试通过FTP上传文件到指定目录(如www),但在浏览器访问时遇到了HTTP404错误。用户想知道正确的上传路径以及如何解决此问题。解决方案:您好,针对您遇到的FTP上传目录路径及HTTP404错误的问题,以下是详细的解决方案:FTP上传路径说明:网页端访问FTP空间:您可以通过FTP......
  • 请问yarn是怎么解决依赖重复很多次,嵌套路径过长的问题的?
    Yarn通过多种方式解决依赖重复和嵌套路径过长的问题,从而提高前端开发的效率和可靠性。以下是一些关键方法和策略:依赖扁平化:Yarn采用依赖扁平化的安装模式,这意味着它会尝试将依赖项尽可能地放在项目的顶层,而不是嵌套在深层子目录中。这种做法减少了依赖树的深度,简化了文件结构,并......