好的,我们可以简化数据存储逻辑,将所有数据仅存储在 workingData
中,而不单独为每个方向维护数据结构。具体做法如下:
-
数据统一存储:
- 所有的补偿数据按机械臂编号存储在
workingData
中(一个二维vector
)。
- 所有的补偿数据按机械臂编号存储在
-
按方向筛选:
- 在计算补偿时,根据方向条件筛选出符合要求的数据(如果需要按方向补偿)。
- 当按方向的数据不足时,直接使用全局数据(不考虑方向)。
-
清晰简化逻辑:
- 只需要维护
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;
}
关键改动
-
数据存储:
- 所有数据统一存储在
workingData
中,按机械臂编号分类。 - 每个方向不再独立维护数据结构。
- 所有数据统一存储在
-
按方向筛选:
- 在
calculateCompensation
中,先筛选出符合方向的数据。 - 如果筛选后数据不足
n
条,则回退到全局数据。
- 在
-
全局补偿逻辑:
- 直接使用所有数据计算全局补偿。
- 如果全局数据不足
n
条,直接返回0.0
。
-
数据管理:
- 每个机械臂最多保留
n * 4
条数据(假设每个方向最多存储n
条数据)。 - 超过限制时,移除最早的数据,保证数据队列长度受控。
- 每个机械臂最多保留
输出示例
假设数据如下:
LEFT
方向数据:3 条RIGHT
方向数据:1 条UP
和DOWN
方向数据: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
优化点
-
简化存储:
- 数据仅存储在
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) {
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;
}