|
@@ -212,7 +212,7 @@ bool LidarScanController::processSegmentData(const LaserScanSharedPtr &msg,
|
|
|
auto sections = getSections(begin_index, end_index, msg, xy_list);
|
|
auto sections = getSections(begin_index, end_index, msg, xy_list);
|
|
|
if (sections.empty())
|
|
if (sections.empty())
|
|
|
{
|
|
{
|
|
|
- //RCLCPP_WARN(node_->get_logger(), "没有获取到分段");
|
|
|
|
|
|
|
+ // RCLCPP_WARN(node_->get_logger(), "没有获取到分段");
|
|
|
return false;
|
|
return false;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -389,7 +389,6 @@ void LidarScanController::procData(RechargeResult &result)
|
|
|
// RCLCPP_INFO(node_->get_logger(), "右直线角度: %.2f°", right_angle);
|
|
// RCLCPP_INFO(node_->get_logger(), "右直线角度: %.2f°", right_angle);
|
|
|
// RCLCPP_INFO(node_->get_logger(), "角平分线角度: %.2f°", bisector_angle);
|
|
// RCLCPP_INFO(node_->get_logger(), "角平分线角度: %.2f°", bisector_angle);
|
|
|
|
|
|
|
|
-
|
|
|
|
|
// 更新结果
|
|
// 更新结果
|
|
|
result.middle_line = StraightLine(k3, b3);
|
|
result.middle_line = StraightLine(k3, b3);
|
|
|
result.left_line = StraightLine(k1, b1);
|
|
result.left_line = StraightLine(k1, b1);
|
|
@@ -412,12 +411,12 @@ void LidarScanController::controlRechargeMotion(const RechargeResult &result)
|
|
|
// 清除控制命令,避免定时器发布旧命令
|
|
// 清除控制命令,避免定时器发布旧命令
|
|
|
// 修改:不再清除控制命令,而是继续旋转
|
|
// 修改:不再清除控制命令,而是继续旋转
|
|
|
// 只清除线性速度,保持角速度
|
|
// 只清除线性速度,保持角速度
|
|
|
- double angular_velocity = 0.15; // 与RotationManager中的角速度一致
|
|
|
|
|
-
|
|
|
|
|
- ctrl_twist_.linear.x = 0.0; // 线速度保持0
|
|
|
|
|
- ctrl_twist_.angular.z = angular_velocity; // 保持旋转速度
|
|
|
|
|
|
|
+ double angular_velocity = 0.15; // 与RotationManager中的角速度一致
|
|
|
|
|
+
|
|
|
|
|
+ ctrl_twist_.linear.x = 0.0; // 线速度保持0
|
|
|
|
|
+ ctrl_twist_.angular.z = angular_velocity; // 保持旋转速度
|
|
|
ctrl_twist_time_ = node_->now();
|
|
ctrl_twist_time_ = node_->now();
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 发布旋转命令
|
|
// 发布旋转命令
|
|
|
pub_ctrl_->publish(ctrl_twist_);
|
|
pub_ctrl_->publish(ctrl_twist_);
|
|
|
return;
|
|
return;
|
|
@@ -445,20 +444,131 @@ void LidarScanController::controlRechargeMotion(const RechargeResult &result)
|
|
|
// 计算偏航角误差
|
|
// 计算偏航角误差
|
|
|
double yaw_diff = atan(k);
|
|
double yaw_diff = atan(k);
|
|
|
RCLCPP_INFO(node_->get_logger(), "偏航角误差: %.4f rad (%.2f 度)",
|
|
RCLCPP_INFO(node_->get_logger(), "偏航角误差: %.4f rad (%.2f 度)",
|
|
|
- yaw_diff, yaw_diff * 180.0 / M_PI);
|
|
|
|
|
|
|
+ yaw_diff, yaw_diff * 180.0 / M_PI);
|
|
|
|
|
+
|
|
|
|
|
+ if (checkStationAlignment(dx, dy, yaw_diff))
|
|
|
|
|
+ {
|
|
|
|
|
+ // 停止行车中,准备向前移动,再校准回充
|
|
|
|
|
+ RCLCPP_WARN(node_->get_logger(), "===== 开始对准误差调整 =====");
|
|
|
|
|
+ RCLCPP_WARN(node_->get_logger(), "当前误差 - 夹角:%.2f°, dy:%.3fm",
|
|
|
|
|
+ yaw_diff * 180.0 / M_PI, dy);
|
|
|
|
|
+
|
|
|
|
|
+ // 1. 停止当前运动
|
|
|
|
|
+ ctrl_twist_.linear.x = 0.0;
|
|
|
|
|
+ ctrl_twist_.angular.z = 0.0;
|
|
|
|
|
+ ctrl_twist_time_ = node_->now();
|
|
|
|
|
+ pub_ctrl_->publish(ctrl_twist_);
|
|
|
|
|
+ rclcpp::sleep_for(std::chrono::milliseconds(300));
|
|
|
|
|
+
|
|
|
|
|
+ // 2. 根据误差类型进行旋转调整
|
|
|
|
|
+ double adjust_duration = 0.0;
|
|
|
|
|
+ double adjust_angular = 0.0;
|
|
|
|
|
+ std::string adjust_type;
|
|
|
|
|
+
|
|
|
|
|
+ const double ANGLE_8DEG = 5.0 * M_PI / 180.0; // 6度阈值
|
|
|
|
|
+ const double DY_THRESHOLD = 0.05; // 5cm阈值
|
|
|
|
|
+
|
|
|
|
|
+ // 优先调整角度
|
|
|
|
|
+ if (fabs(yaw_diff) > ANGLE_8DEG)
|
|
|
|
|
+ {
|
|
|
|
|
+ adjust_type = "角度调整";
|
|
|
|
|
+ // 根据夹角大小计算调整时间
|
|
|
|
|
+ adjust_duration = fabs(yaw_diff) / 0.35; // 角速度0.25 rad/s
|
|
|
|
|
+ adjust_angular = (yaw_diff > 0) ? -0.35 : 0.35;
|
|
|
|
|
+
|
|
|
|
|
+ RCLCPP_WARN(node_->get_logger(), "旋转 %.2f 秒", adjust_duration);
|
|
|
|
|
+ }
|
|
|
|
|
+ // 角度满足要求后调整dy
|
|
|
|
|
+ // else
|
|
|
|
|
+ // {
|
|
|
|
|
+ // adjust_type = "横向偏移调整";
|
|
|
|
|
+ // // dy为正(偏右) -> 向左转;dy为负(偏左) -> 向右转
|
|
|
|
|
+ // adjust_duration = fabs(dy) * 20.0; // 每5cm误差旋转1秒
|
|
|
|
|
+ // adjust_angular = (dy > 0) ? 0.10 : -0.10;
|
|
|
|
|
+
|
|
|
|
|
+ // RCLCPP_WARN(node_->get_logger(), "旋转 %.2f 秒",adjust_duration);
|
|
|
|
|
+ // }
|
|
|
|
|
+
|
|
|
|
|
+ // 3. 执行旋转调整
|
|
|
|
|
+ if (active_)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (adjust_duration > 0.1)
|
|
|
|
|
+ {
|
|
|
|
|
+ geometry_msgs::msg::Twist adjust_cmd;
|
|
|
|
|
+ adjust_cmd.linear.x = 0.0;
|
|
|
|
|
+ adjust_cmd.angular.z = adjust_angular;
|
|
|
|
|
+
|
|
|
|
|
+ // 按计算的时间连续旋转
|
|
|
|
|
+ rclcpp::Time adjust_start = node_->now();
|
|
|
|
|
+ int publish_count = 0;
|
|
|
|
|
+
|
|
|
|
|
+ while ((node_->now() - adjust_start).seconds() < adjust_duration)
|
|
|
|
|
+ {
|
|
|
|
|
+ pub_ctrl_->publish(adjust_cmd);
|
|
|
|
|
+ publish_count++;
|
|
|
|
|
+ rclcpp::sleep_for(std::chrono::milliseconds(50));
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
|
|
+ RCLCPP_WARN(node_->get_logger(), "%s完成: 发布%d次命令, 实际旋转%.2f秒",
|
|
|
|
|
+ adjust_type.c_str(), publish_count, adjust_duration);
|
|
|
|
|
+
|
|
|
|
|
+ // 4. 停止旋转
|
|
|
|
|
+ adjust_cmd.angular.z = 0.0;
|
|
|
|
|
+ pub_ctrl_->publish(adjust_cmd);
|
|
|
|
|
+ rclcpp::sleep_for(std::chrono::milliseconds(500));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 5. 向前走一小段距离(新增功能)
|
|
|
|
|
+ const double FORWARD_DISTANCE = 0.80; // 向前走150cm
|
|
|
|
|
+ const double FORWARD_SPEED = 0.08; // 前进速度 0.08 m/s
|
|
|
|
|
+
|
|
|
|
|
+ // 计算前进所需时间
|
|
|
|
|
+ double forward_duration = FORWARD_DISTANCE / FORWARD_SPEED;
|
|
|
|
|
+
|
|
|
|
|
+ RCLCPP_WARN(node_->get_logger(), "开始向前调整: 距离=%.2fm, 速度=%.2fm/s, 时间=%.2fs",
|
|
|
|
|
+ FORWARD_DISTANCE, FORWARD_SPEED, forward_duration);
|
|
|
|
|
+
|
|
|
|
|
+ // 发送前进命令
|
|
|
|
|
+ geometry_msgs::msg::Twist forward_cmd;
|
|
|
|
|
+ forward_cmd.linear.x = FORWARD_SPEED;
|
|
|
|
|
+ forward_cmd.angular.z = 0.0;
|
|
|
|
|
+
|
|
|
|
|
+ rclcpp::Time forward_start = node_->now();
|
|
|
|
|
+ int forward_count = 0;
|
|
|
|
|
+
|
|
|
|
|
+ while ((node_->now() - forward_start).seconds() < forward_duration)
|
|
|
|
|
+ {
|
|
|
|
|
+ pub_ctrl_->publish(forward_cmd);
|
|
|
|
|
+ forward_count++;
|
|
|
|
|
+ rclcpp::sleep_for(std::chrono::milliseconds(50));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 停止前进
|
|
|
|
|
+ forward_cmd.linear.x = 0.0;
|
|
|
|
|
+ pub_ctrl_->publish(forward_cmd);
|
|
|
|
|
+
|
|
|
|
|
+ RCLCPP_INFO(node_->get_logger(), "前进调整完成: 发布%d次命令, 实际前进%.2f秒",
|
|
|
|
|
+ forward_count, forward_duration);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 6. 重要:等待新一帧激光数据并更新result
|
|
|
|
|
+ // 等待激光数据更新(约100ms足够接收新数据)
|
|
|
|
|
+ rclcpp::sleep_for(std::chrono::milliseconds(450));
|
|
|
|
|
+
|
|
|
|
|
+ // 注意:这里无法直接更新result,但函数返回后,下一帧激光数据会触发新的processSegmentData
|
|
|
|
|
+ // 从而得到新的result,重新进入controlRechargeMotion
|
|
|
|
|
+
|
|
|
|
|
+ RCLCPP_WARN(node_->get_logger(), "===== 对准误差调整完成 =====");
|
|
|
|
|
+
|
|
|
|
|
+ // 7. 返回,等待下一帧激光数据重新计算
|
|
|
|
|
+ // 不继续执行后面的速度计算,避免使用旧数据
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
// 计算控制速度
|
|
// 计算控制速度
|
|
|
auto [linear_velocity, angular_velocity] = RechargeTool::computeDockingVelocity(dx - 0.3, dy, yaw_diff);
|
|
auto [linear_velocity, angular_velocity] = RechargeTool::computeDockingVelocity(dx - 0.3, dy, yaw_diff);
|
|
|
RCLCPP_DEBUG(node_->get_logger(), "基础控制速度 - 线速度: %.4f, 角速度: %.4f",
|
|
RCLCPP_DEBUG(node_->get_logger(), "基础控制速度 - 线速度: %.4f, 角速度: %.4f",
|
|
|
linear_velocity, angular_velocity);
|
|
linear_velocity, angular_velocity);
|
|
|
- RCLCPP_INFO(node_->get_logger(),"dx=%.4f,dy=%.4f",dx,dy);
|
|
|
|
|
- if(checkStationAlignment(dx,dy,yaw_diff))
|
|
|
|
|
- {
|
|
|
|
|
- //停止行车中,准备向前移动,再校准回充
|
|
|
|
|
- sleep(100);
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
|
|
+ RCLCPP_INFO(node_->get_logger(), "dx=%.4f,dy=%.4f", dx, dy);
|
|
|
// 限制角速度
|
|
// 限制角速度
|
|
|
if (angular_velocity > 0.0)
|
|
if (angular_velocity > 0.0)
|
|
|
{
|
|
{
|
|
@@ -537,11 +647,11 @@ void LidarScanController::controlRechargeMotion(const RechargeResult &result)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-bool LidarScanController::checkStationAlignment(double dx,double dy,double yaw_diff)
|
|
|
|
|
|
|
+bool LidarScanController::checkStationAlignment(double dx, double dy, double yaw_diff)
|
|
|
{
|
|
{
|
|
|
- bool isstop=false;
|
|
|
|
|
|
|
+ bool isstop = false;
|
|
|
const double ALIGNMENT_DISTANCE_THRESHOLD = 0.80; // 80cm
|
|
const double ALIGNMENT_DISTANCE_THRESHOLD = 0.80; // 80cm
|
|
|
- const double ALIGNMENT_ANGLE_THRESHOLD = 10.0 * M_PI / 180.0; // 5度
|
|
|
|
|
|
|
+ const double ALIGNMENT_ANGLE_THRESHOLD = 5.0 * M_PI / 180.0; // 5度
|
|
|
|
|
|
|
|
if (dx <= ALIGNMENT_DISTANCE_THRESHOLD)
|
|
if (dx <= ALIGNMENT_DISTANCE_THRESHOLD)
|
|
|
{
|
|
{
|
|
@@ -549,18 +659,18 @@ bool LidarScanController::checkStationAlignment(double dx,double dy,double yaw_d
|
|
|
dx, yaw_diff * 180.0 / M_PI);
|
|
dx, yaw_diff * 180.0 / M_PI);
|
|
|
|
|
|
|
|
// 判断是否对准(夹角小于10度)
|
|
// 判断是否对准(夹角小于10度)
|
|
|
- if (fabs(yaw_diff) <= ALIGNMENT_ANGLE_THRESHOLD&&fabs(dy)<1.088)
|
|
|
|
|
|
|
+ if (fabs(yaw_diff) <= ALIGNMENT_ANGLE_THRESHOLD)
|
|
|
{
|
|
{
|
|
|
RCLCPP_INFO(node_->get_logger(), "✓ 已对准基站,继续行驶 - 夹角: %.2f°,dx=%.2f,dy=%.2f",
|
|
RCLCPP_INFO(node_->get_logger(), "✓ 已对准基站,继续行驶 - 夹角: %.2f°,dx=%.2f,dy=%.2f",
|
|
|
- yaw_diff * 180.0 / M_PI,dx,dy);
|
|
|
|
|
|
|
+ yaw_diff * 180.0 / M_PI, dx, dy);
|
|
|
|
|
|
|
|
RCLCPP_DEBUG(node_->get_logger(), "对准行驶 - 线速度: %.4f", ctrl_twist_.linear.x);
|
|
RCLCPP_DEBUG(node_->get_logger(), "对准行驶 - 线速度: %.4f", ctrl_twist_.linear.x);
|
|
|
}
|
|
}
|
|
|
else
|
|
else
|
|
|
{
|
|
{
|
|
|
RCLCPP_WARN(node_->get_logger(), "✗ 未对准基站,停止行驶 - 夹角: %.2f° > 5°,dx=%.2f,dy=%.2f",
|
|
RCLCPP_WARN(node_->get_logger(), "✗ 未对准基站,停止行驶 - 夹角: %.2f° > 5°,dx=%.2f,dy=%.2f",
|
|
|
- yaw_diff * 180.0 / M_PI,dx,dy);
|
|
|
|
|
- isstop=true;
|
|
|
|
|
|
|
+ yaw_diff * 180.0 / M_PI, dx, dy);
|
|
|
|
|
+ isstop = true;
|
|
|
// RCLCPP_INFO(node_->get_logger(), "自动调整方向 - 旋转角速度: %.4f", adjust_angular);
|
|
// RCLCPP_INFO(node_->get_logger(), "自动调整方向 - 旋转角速度: %.4f", adjust_angular);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|