vdbsh

好的,我们可以简化数据存储逻辑,将所有数据仅存储在 workingData 中,而不单独为每个方向维护数据结构。具体做法如下:

  1. 数据统一存储:

    • 所有的补偿数据按机械臂编号存储在 workingData 中(一个二维 vector)。
  2. 按方向筛选:

    • 在计算补偿时,根据方向条件筛选出符合要求的数据(如果需要按方向补偿)。
    • 当按方向的数据不足时,直接使用全局数据(不考虑方向)。
  3. 清晰简化逻辑:

    • 只需要维护 workingData,减少复杂度。

修改后的代码

#include <iostream>
#include <vector>
#include <numeric>
#include <algorithm>

enum Dir {
    LEFT,
    RIGHT,
    UP,
    DOWN
};

struct Compen {
    long lPadIndex;           // 数据编号
    unsigned short usArmId;   // 机械臂编号
    Dir dir;                  // 数据方向
    double X, Y, T;           // 偏差值
    double dCompensation;     // 补偿值
};

class CompensationCalculator {
public:
    CompensationCalculator(int windowSize, bool useDirectionCompensation)
        : n(windowSize), useDirectionCompensation(useDirectionCompensation) {
        workingData.resize(2); // 初始化存储空间,支持两个机械臂
    }

    double calculateCompensation(unsigned short armId, Dir dir) {
        const auto& data = workingData[armId];

        // 按方向筛选数据
        std::vector<Compen> filteredData;
        if (useDirectionCompensation) {
            for (const auto& entry : data) {
                if (entry.dir == dir) {
                    filteredData.push_back(entry);
                }
            }
        }

        // 判断是否使用全局补偿
        if (filteredData.size() < n) {
            std::cout << "Not enough data for direction compensation, falling back to global compensation." << std::endl;
            filteredData = data; // 全局补偿使用所有数据
        }

        // 如果全局数据不足,返回补偿值 0
        if (filteredData.size() < n) {
            return 0.0;
        }

        // 取最近 n 条数据计算平均补偿值
        double sum = 0.0;
        for (int i = filteredData.size() - n; i < filteredData.size(); ++i) {
            sum += (filteredData[i].dCompensation +
                    filteredData[i].X +
                    filteredData[i].Y +
                    filteredData[i].T);
        }
        return sum / n;
    }

    void addData(unsigned short armId, const Compen& newEntry) {
        auto& data = workingData[armId];
        data.push_back(newEntry);
        // 如果数据超过 n 条,则移除最早的数据
        if (data.size() > n * 4) { // 假设每个方向最多存储 n 条
            data.erase(data.begin());
        }
    }

private:
    int n;                                     // 滑动窗口大小
    bool useDirectionCompensation;            // 是否按方向补偿
    std::vector<std::vector<Compen>> workingData; // 每个机械臂的数据存储
};

int main() {
    CompensationCalculator calculator(5, true); // 窗口大小为5,启用方向补偿

    // 添加示例数据
    calculator.addData(0, {1, 0, LEFT, 0.1, 0.2, 0.3, 0.4});
    calculator.addData(0, {2, 0, LEFT, 0.2, 0.3, 0.4, 0.5});
    calculator.addData(0, {3, 0, LEFT, 0.3, 0.4, 0.5, 0.6});
    calculator.addData(0, {4, 0, RIGHT, 0.4, 0.5, 0.6, 0.7});

    // 测试按方向补偿
    unsigned short armId = 0;
    Dir currentDir = LEFT;
    double newCompensation = calculator.calculateCompensation(armId, currentDir);

    std::cout << "New Compensation for Arm " << armId << " (Direction LEFT): " << newCompensation << std::endl;

    // 测试全局补偿(方向不足时触发)
    currentDir = UP; // 使用新方向,但没有数据
    newCompensation = calculator.calculateCompensation(armId, currentDir);

    std::cout << "New Compensation for Arm " << armId << " (Global Fallback): " << newCompensation << std::endl;

    return 0;
}

关键改动

  1. 数据存储:

    • 所有数据统一存储在 workingData 中,按机械臂编号分类。
    • 每个方向不再独立维护数据结构。
  2. 按方向筛选:

    • calculateCompensation 中,先筛选出符合方向的数据。
    • 如果筛选后数据不足 n 条,则回退到全局数据。
  3. 全局补偿逻辑:

    • 直接使用所有数据计算全局补偿。
    • 如果全局数据不足 n 条,直接返回 0.0
  4. 数据管理:

    • 每个机械臂最多保留 n * 4 条数据(假设每个方向最多存储 n 条数据)。
    • 超过限制时,移除最早的数据,保证数据队列长度受控。

输出示例

假设数据如下:

  • LEFT 方向数据:3 条
  • RIGHT 方向数据:1 条
  • UPDOWN 方向数据:0 条

程序输出:

Not enough data for direction compensation, falling back to global compensation.
New Compensation for Arm 0 (Direction LEFT): 0.55
Not enough data for direction compensation, falling back to global compensation.
New Compensation for Arm 0 (Global Fallback): 0.575

优化点

  1. 简化存储:

    • 数据仅存储在 workingData 中,按机械臂编号分类。
    • 不再维护按方向的数据队列,逻辑更加清晰。
  2. 统一逻辑:

    • 通过筛选实现按方向补偿,无需额外的数据结构。
    • 方向数据不足时自动回退到全局补偿。
  3. 高效扩展:

    • 支持多方向和多机械臂,易于调整窗口大小。
#include <iostream>
#include <vector>
#include <numeric>
#include <algorithm>

enum Dir {
    LEFT,
    RIGHT,
    UP,
    DOWN
};

struct Compen {
    long lPadIndex;           // 数据编号,唯一标识
    unsigned short usArmId;   // 机械臂编号
    Dir dir;                  // 数据方向
    double X, Y, T;           // 偏差值
    double dCompensation;     // 补偿值
};

class CompensationCalculator {
public:
    CompensationCalculator(int windowSize, bool useDirectionCompensation)
        : n(windowSize), useDirectionCompensation(useDirectionCompensation) {
        workingData.resize(2); // 初始化存储空间,支持两个机械臂
    }

    double calculateCompensation(unsigned short armId, Dir dir) {
        auto& data = workingData[armId];

        // 按方向筛选数据
        std::vector<Compen> filteredData;
        if (useDirectionCompensation) {
            for (const auto& entry : data) {
                if (entry.dir == dir) {
                    filteredData.push_back(entry);
                }
            }
        }

        // 判断是否使用全局补偿
        if (filteredData.size() < n) {
            std::cout << "Not enough data for direction compensation, falling back to global compensation." << std::endl;
            filteredData = data; // 全局补偿使用所有数据
        }

        // 如果全局数据不足,返回补偿值 0
        if (filteredData.size() < n) {
            return 0.0;
        }

        // 按 lPadIndex 排序,确保取到最新的数据
        std::sort(filteredData.begin(), filteredData.end(), [](const Compen& a, const Compen& b) {
            return a.lPadIndex < b.lPadIndex;  // 按 lPadIndex 排序
        });

        // 取最近 n 条数据计算平均补偿值
        double sum = 0.0;
        int count = std::min(n, static_cast<int>(filteredData.size()));
        for (int i = filteredData.size() - count; i < filteredData.size(); ++i) {
            sum += (filteredData[i].dCompensation +
                    filteredData[i].X +
                    filteredData[i].Y +
                    filteredData[i].T);
        }
        return sum / count;
    }

    void addData(unsigned short armId, const Compen& newEntry) {
        auto& data = workingData[armId];
        
        // 查找是否已存在相同 lPadIndex 的条目
        auto it = std::find_if(data.begin(), data.end(), [&newEntry](const Compen& entry) {
            return entry.lPadIndex == newEntry.lPadIndex;
        });

        // 如果找到相同的 lPadIndex,则修改数据
        if (it != data.end()) {
            *it = newEntry;
            std::cout << "Updated data for lPadIndex: " << newEntry.lPadIndex << std::endl;
        } else {
            // 否则,添加新数据
            data.push_back(newEntry);
            std::cout << "Added new data for lPadIndex: " << newEntry.lPadIndex << std::endl;
        }

        // 如果数据超过 n 条,则移除最早的数据
        if (data.size() > n * 4) { // 假设每个方向最多存储 n 条数据
            data.erase(data.begin());
        }
    }

private:
    int n;                                     // 滑动窗口大小
    bool useDirectionCompensation;            // 是否按方向补偿
    std::vector<std::vector<Compen>> workingData; // 每个机械臂的数据存储
};

int main() {
    CompensationCalculator calculator(5, true); // 窗口大小为5,启用方向补偿

    // 添加示例数据
    calculator.addData(0, {1, 0, LEFT, 0.1, 0.2, 0.3, 0.4});
    calculator.addData(0, {2, 0, LEFT, 0.2, 0.3, 0.4, 0.5});
    calculator.addData(0, {3, 0, LEFT, 0.3, 0.4, 0.5, 0.6});
    calculator.addData(0, {4, 0, RIGHT, 0.4, 0.5, 0.6, 0.7});

    // 测试按方向补偿
    unsigned short armId = 0;
    Dir currentDir = LEFT;
    double newCompensation = calculator.calculateCompensation(armId, currentDir);

    std::cout << "New Compensation for Arm " << armId << " (Direction LEFT): " << newCompensation << std::endl;

    // 修改已有的 lPadIndex 为 2 的数据
    calculator.addData(0, {2, 0, LEFT, 0.25, 0.35, 0.45, 0.55});  // 更新 lPadIndex 为 2 的数据

    // 再次计算补偿
    newCompensation = calculator.calculateCompensation(armId, currentDir);
    std::cout << "New Compensation after Update for Arm " << armId << " (Direction LEFT): " << newCompensation << std::endl;

    // 测试全局补偿(方向不足时触发)
    currentDir = UP; // 使用新方向,但没有数据
    newCompensation = calculator.calculateCompensation(armId, currentDir);

    std::cout << "New Compensation for Arm " << armId << " (Global Fallback): " << newCompensation << std::endl;

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值