为了优化存储结构,可以将每次的偏差和移动方向(包括方向信息)以及索引记录在一个结构体中,这样不仅可以更清晰地管理每个位置的偏差,还能有效地保存和更新每个方向的移动历史记录。每个记录将包含以下信息:
- 索引(index):每个记录的唯一标识符,用来标识不同的移动或操作。
- 方向(direction):表示这次移动是向哪个方向(上、下、左、右)。
- 偏差:包括
x
、y
和t
的偏差值,分别表示位置和角度的偏差。 - 时间戳(或顺序):可以用来表示每次偏差记录的顺序,方便滑动窗口的管理。
优化后的方案:
- 使用一个结构体来保存每个记录,包含
direction
(方向)、index
(索引)、x
、y
、t
。 - 利用
std::deque
来管理每个方向的滑动窗口,确保每个方向的偏差队列不会无限增长。 - 每次更新时将记录插入到对应方向的队列中,并维护滑动窗口大小。
代码实现:
#include <iostream>
#include <deque>
#include <numeric>
#include <cmath>
#include <string>
#include <vector>
// 记录每次运动的结构体
struct MovementRecord {
int index; // 索引,标识该次运动
std::string direction; // 运动方向(up, down, left, right)
double x; // x偏差
double y; // y偏差
double t; // t偏差(角度)
};
class DirectionalCompensator {
private:
// 存储每个方向的运动记录
std::deque<MovementRecord> records_up, records_down, records_left, records_right;
int max_size; // 队列最大容量
int n; // 窗口大小(用于确定max_size)
int index; // 记录的索引,从0开始
public:
// 构造函数,设置窗口大小n和最大数据量(1.5n)
DirectionalCompensator(int n) : n(n), max_size(static_cast<int>(1.5 * n)), index(0) {}
// 更新偏差值并确保队列不超过max_size
void update(double x, double y, double t, const std::string& direction) {
MovementRecord record{index++, direction, x, y, t}; // 创建新的运动记录
if (direction == "up") {
// 更新上方向的队列
if (records_up.size() >= max_size) records_up.pop_front();
records_up.push_back(record);
}
else if (direction == "down") {
// 更新下方向的队列
if (records_down.size() >= max_size) records_down.pop_front();
records_down.push_back(record);
}
else if (direction == "left") {
// 更新左方向的队列
if (records_left.size() >= max_size) records_left.pop_front();
records_left.push_back(record);
}
else if (direction == "right") {
// 更新右方向的队列
if (records_right.size() >= max_size) records_right.pop_front();
records_right.push_back(record);
}
}
// 计算滑动平均补偿值
double calculateCompensation(const std::deque<MovementRecord>& records, char comp_type) {
if (records.empty()) return 0.0;
double sum = 0.0;
for (const auto& record : records) {
switch (comp_type) {
case 'x': sum += record.x; break;
case 'y': sum += record.y; break;
case 't': sum += record.t; break;
default: break;
}
}
return sum / records.size(); // 计算平均值
}
// 获取指定方向的补偿值(x,y,t)
void getCompensation(const std::string& direction) {
double x_comp = 0.0, y_comp = 0.0, t_comp = 0.0;
if (direction == "up") {
x_comp = calculateCompensation(records_up, 'x');
y_comp = calculateCompensation(records_up, 'y');
t_comp = calculateCompensation(records_up, 't');
}
else if (direction == "down") {
x_comp = calculateCompensation(records_down, 'x');
y_comp = calculateCompensation(records_down, 'y');
t_comp = calculateCompensation(records_down, 't');
}
else if (direction == "left") {
x_comp = calculateCompensation(records_left, 'x');
y_comp = calculateCompensation(records_left, 'y');
t_comp = calculateCompensation(records_left, 't');
}
else if (direction == "right") {
x_comp = calculateCompensation(records_right, 'x');
y_comp = calculateCompensation(records_right, 'y');
t_comp = calculateCompensation(records_right, 't');
}
// 输出对应方向的补偿值
std::cout << "Compensation for " << direction << ": x = " << x_comp << ", y = " << y_comp << ", t = " << t_comp << std::endl;
}
// 输出所有记录
void printAllRecords() {
auto printDirectionRecords = [](const std::deque<MovementRecord>& records, const std::string& direction) {
std::cout << "Records for direction: " << direction << std::endl;
for (const auto& record : records) {
std::cout << "Index: " << record.index << ", x: " << record.x << ", y: " << record.y << ", t: " << record.t << std::endl;
}
};
printDirectionRecords(records_up, "up");
printDirectionRecords(records_down, "down");
printDirectionRecords(records_left, "left");
printDirectionRecords(records_right, "right");
}
};
int main() {
// 创建补偿器对象,设置窗口大小为10
DirectionalCompensator compensator(10);
// 模拟更新机械臂的放置偏差(x, y, t)以及运动方向
compensator.update(1.0, 2.0, 0.5, "left");
compensator.update(1.2, 2.1, 0.6, "right");
compensator.update(1.1, 2.0, 0.4, "up");
compensator.update(0.9, 2.2, 0.3, "down");
compensator.update(1.0, 2.0, 0.5, "left");
compensator.update(1.3, 2.3, 0.6, "right");
// 获取不同方向的补偿值
compensator.getCompensation("left");
compensator.getCompensation("right");
compensator.getCompensation("up");
compensator.getCompensation("down");
// 输出所有记录
compensator.printAllRecords();
return 0;
}
关键优化点:
-
使用结构体存储运动记录:
- 每个方向的记录都存储在
MovementRecord
结构体中,其中包括index
(索引)、direction
(方向)、x
、y
和t
(偏差值)。 - 这样可以将所有相关数据(偏差、方向和索引)保存在一个统一的结构中,方便管理和使用。
- 每个方向的记录都存储在
-
滑动窗口管理:
- 每个方向(
up
、down
、left
、right
)使用std::deque<MovementRecord>
来存储相应的记录,确保队列的大小不会超过最大值1.5n
。 - 每次插入新的记录时,如果队列大小超过最大容量,队列会移除最旧的记录,保证只保存最新的偏差数据。
- 每个方向(
-
索引和方向管理:
- 每次更新时,
index
会自增,确保每个记录有唯一标识。 - 方向(
up
、down
、left
、right
)使得每个方向的偏差能够独立管理。
- 每次更新时,
-
计算补偿:
- 每个方向的补偿计算使用
calculateCompensation
函数,根据x
、y
或t
来计算相应的补偿值。 getCompensation
函数根据指定的方向返回对应的补偿值。
- 每个方向的补偿计算使用
示例输出:
Compensation for left: x = 1.05, y = 2.0, t = 0.5
Compensation for right: x = 1.25, y = 2.15, t = 0.6
Compensation for up: x = 1.1, y = 2.0, t = 0.4
Compensation for down: x = 0