在嵌入式开发、机器人控制等资源受限场景中,浮点运算因复杂度高、硬件开销大,往往会被定点运算替代。本文将针对一段机器人控制中常用的“浮点型数据转定点数据”C++代码,进行逐行拆解,从原理到实战帮你彻底搞懂每一步的作用,适合嵌入式、机器人领域开发者入门学习。

先上核心代码(源自机器人位置/速度/扭矩控制模块):


// 位置、速度和扭矩采用线性映射的关系将浮点型数据转换成有符号的定点数据
static auto float_to_uint = [](float x, float xmin, float xmax, uint8_t bits) -> uint16_t {
    float span = xmax - xmin;
    float data_norm = (x - xmin) / span;
    uint16_t data_uint = data_norm * ((1 << bits) - 1);
    return data_uint;
};

一、核心概念铺垫

在解析代码前,先明确两个关键概念,避免理解障碍:

  • 浮点数(float):我们常用的数值类型,用“符号位+指数位+尾数位”表示(类似科学计数法),能灵活表示极大/极小的数,但运算复杂、占用硬件资源多(比如CPU算力、内存)。

  • 定点数:提前约定小数点位置的整数(比如“整数占10位、小数占6位”),用普通整数存储和运算。虽然表示范围和精度有限,但运算速度快、硬件开销低,特别适合机器人电机控制、嵌入式传感器数据处理等实时性要求高的场景。

本文代码的核心作用:将范围不固定的浮点型物理量(位置、速度、扭矩),通过线性映射转换成固定位数的无符号整数(定点数),供底层硬件(如电机驱动器)直接使用。

二、逐行代码深度解析

第1行:注释说明


// 位置、速度和扭矩采用线性映射的关系将浮点型数据转换成有符号的定点数据

作用:明确代码的应用场景核心功能

  • 应用场景:机器人的位置、速度、扭矩等物理量控制;

  • 核心逻辑:通过“线性映射”完成转换;

  • 注意:此处存在注释笔误——代码返回值是uint16_t(无符号整数),实际转换的是“无符号定点数”,若需转换为有符号定点数,需额外处理符号位(后文补充)。

  • x - xmin:将原始数据的取值起点从xmin平移到0(如x=-1.57xmin=-3.14,则x-xmin=1.57);

  • 除以span:将平移后的数据缩放到0~1区间(如1.57/6.28=0.25)。

  • 已知条件:扭矩范围xmin=-10N·mxmax=10N·m,定点数位数bits=16,当前扭矩x=5N·m

  • 步骤1:计算跨度span = 10 - (-10) = 20

  • 步骤2:归一化data_norm = (5 - (-10))/20 = 15/20 = 0.75

  • 步骤3:转定点数data_uint = 0.75 * 65535 = 49151

  • 结果:硬件收到49151后,可通过反向计算还原出5N·m的扭矩值,实现高效控制。

四、注意事项与扩展补充

1. 注释笔误修正(有符号定点数转换)

原代码注释写“转换成有符号的定点数据”,但实际返回无符号整数。若需转换为有符号定点数(如int16_t),需添加符号位处理,修正代码如下:


// 修正:转换为有符号定点数(int16_t)
static auto float_to_int = [](float x, float xmin, float xmax, uint8_t bits) -> int16_t {
    float span = xmax - xmin;
    float data_norm = (x - xmin) / span;
    // 映射到 -2^(bits-1) ~ 2^(bits-1)-1(有符号整数范围)
    int16_t data_int = data_norm * ((1 << (bits-1)) - 1) - (1 << (bits-1));
    return data_int;
};

2. 反向转换(定点数还原浮点数)

底层硬件处理完定点数后,需还原为浮点数供上层逻辑使用,反向转换代码如下:


// 无符号定点数还原为浮点数
static auto uint_to_float = [](uint16_t data_uint, float xmin, float xmax, uint8_t bits) -> float {
    float span = xmax - xmin;
    float data_norm = (float)data_uint / ((1 << bits) - 1);
    float x = data_norm * span + xmin;
    return x;
};

3. 应用场景限制

该代码适用于“物理量范围固定”的场景(如机器人关节限位、电机扭矩上限已知),若物理量超出xmin~xmax范围,会导致转换结果溢出,需在实际使用中添加范围判断(如裁剪超出部分)。

五、总结

本文解析的浮点转定点数代码,核心逻辑是“线性映射+归一化+整数映射”,通过3步完成转换:① 计算物理量范围跨度;② 浮点数归一化到0~1;③ 映射到固定位数的整数。这种转换能大幅降低硬件运算开销,是机器人控制、嵌入式开发中“高效数据处理”的常用技巧。

如果觉得本文对你有帮助,欢迎点赞、收藏,评论区留言讨论你在定点数应用中遇到的问题~

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐