40~60s完赛
This commit is contained in:
@@ -102,7 +102,7 @@ controller_server:
|
|||||||
GoalCritic:
|
GoalCritic:
|
||||||
enabled: true
|
enabled: true
|
||||||
cost_power: 1
|
cost_power: 1
|
||||||
cost_weight: 6.0
|
cost_weight: 5.0
|
||||||
threshold_to_consider: 1.4
|
threshold_to_consider: 1.4
|
||||||
GoalAngleCritic:
|
GoalAngleCritic:
|
||||||
enabled: true
|
enabled: true
|
||||||
@@ -126,7 +126,7 @@ controller_server:
|
|||||||
PathAlignCritic:
|
PathAlignCritic:
|
||||||
enabled: true
|
enabled: true
|
||||||
cost_power: 1
|
cost_power: 1
|
||||||
cost_weight: 8.0
|
cost_weight: 10.0
|
||||||
max_path_occupancy_ratio: 0.05
|
max_path_occupancy_ratio: 0.05
|
||||||
trajectory_point_step: 4
|
trajectory_point_step: 4
|
||||||
threshold_to_consider: 0.5
|
threshold_to_consider: 0.5
|
||||||
@@ -224,8 +224,8 @@ global_costmap:
|
|||||||
extra_inflation: 0.02
|
extra_inflation: 0.02
|
||||||
inflation_layer:
|
inflation_layer:
|
||||||
plugin: "nav2_costmap_2d::InflationLayer"
|
plugin: "nav2_costmap_2d::InflationLayer"
|
||||||
cost_scaling_factor: 2.0
|
cost_scaling_factor: 3.0
|
||||||
inflation_radius: 0.35
|
inflation_radius: 0.30
|
||||||
always_send_full_costmap: True
|
always_send_full_costmap: True
|
||||||
global_costmap_client:
|
global_costmap_client:
|
||||||
ros__parameters:
|
ros__parameters:
|
||||||
@@ -252,10 +252,10 @@ planner_server:
|
|||||||
analytic_expansion_ratio: 3.5
|
analytic_expansion_ratio: 3.5
|
||||||
analytic_expansion_max_length: 3.0
|
analytic_expansion_max_length: 3.0
|
||||||
minimum_turning_radius: 0.40
|
minimum_turning_radius: 0.40
|
||||||
reverse_penalty: 1.6
|
reverse_penalty: 2.0
|
||||||
change_penalty: 2.0
|
change_penalty: 1.0
|
||||||
non_straight_penalty: 1.2
|
non_straight_penalty: 1.2
|
||||||
cost_penalty: 4.0
|
cost_penalty: 3.0
|
||||||
retrospective_penalty: 0.015
|
retrospective_penalty: 0.015
|
||||||
# 5 m covers the rolling planning horizon without the startup and memory
|
# 5 m covers the rolling planning horizon without the startup and memory
|
||||||
# cost of the previous 20 m (401-cell) Hybrid-A* lookup table.
|
# cost of the previous 20 m (401-cell) Hybrid-A* lookup table.
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ racing_control:
|
|||||||
frame_id: odom
|
frame_id: odom
|
||||||
use_post_qr_pose: false
|
use_post_qr_pose: false
|
||||||
enable_vlm_image_relay: false
|
enable_vlm_image_relay: false
|
||||||
enable_dynamic_replanning: true
|
enable_dynamic_replanning: false
|
||||||
enable_recovery: true
|
enable_recovery: true
|
||||||
vlm_image_input_topic: /image
|
vlm_image_input_topic: /image
|
||||||
vlm_image_output_topic: /vlm_image
|
vlm_image_output_topic: /vlm_image
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
|
#include <cstddef>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -153,6 +154,38 @@ inline geometry_msgs::msg::PoseStamped poseFromXYYaw(
|
|||||||
return pose;
|
return pose;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline double poseDistance2d(
|
||||||
|
const geometry_msgs::msg::PoseStamped & a,
|
||||||
|
const geometry_msgs::msg::PoseStamped & b)
|
||||||
|
{
|
||||||
|
const auto dx = a.pose.position.x - b.pose.position.x;
|
||||||
|
const auto dy = a.pose.position.y - b.pose.position.y;
|
||||||
|
return std::hypot(dx, dy);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::size_t advanceReachedWaypointIndex(
|
||||||
|
const std::vector<geometry_msgs::msg::PoseStamped> & waypoints,
|
||||||
|
const geometry_msgs::msg::PoseStamped & current,
|
||||||
|
const std::size_t next_waypoint_index,
|
||||||
|
const double tolerance)
|
||||||
|
{
|
||||||
|
auto next = next_waypoint_index;
|
||||||
|
while (next < waypoints.size() && poseDistance2d(current, waypoints[next]) <= tolerance) {
|
||||||
|
++next;
|
||||||
|
}
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::vector<geometry_msgs::msg::PoseStamped> remainingWaypoints(
|
||||||
|
const std::vector<geometry_msgs::msg::PoseStamped> & waypoints,
|
||||||
|
const std::size_t next_waypoint_index)
|
||||||
|
{
|
||||||
|
if (next_waypoint_index >= waypoints.size()) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
return {waypoints.begin() + static_cast<std::ptrdiff_t>(next_waypoint_index), waypoints.end()};
|
||||||
|
}
|
||||||
|
|
||||||
inline std::vector<geometry_msgs::msg::PoseStamped> posesFromFlatDoubles(
|
inline std::vector<geometry_msgs::msg::PoseStamped> posesFromFlatDoubles(
|
||||||
const std::vector<double> & values, const std::string & frame_id)
|
const std::vector<double> & values, const std::string & frame_id)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -616,6 +616,7 @@ private:
|
|||||||
if (vlm_capture_mode_ == VlmCaptureMode::PassThrough) {
|
if (vlm_capture_mode_ == VlmCaptureMode::PassThrough) {
|
||||||
active_segment_ = RouteSegment::FullRoute;
|
active_segment_ = RouteSegment::FullRoute;
|
||||||
active_segment_waypoints_ = route.waypoints;
|
active_segment_waypoints_ = route.waypoints;
|
||||||
|
active_segment_next_waypoint_index_ = 0;
|
||||||
runRouteSegmentPlanning("full route with pass-through VLM capture");
|
runRouteSegmentPlanning("full route with pass-through VLM capture");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -624,6 +625,7 @@ private:
|
|||||||
active_segment_waypoints_.assign(
|
active_segment_waypoints_.assign(
|
||||||
route.waypoints.begin(),
|
route.waypoints.begin(),
|
||||||
route.waypoints.begin() + vlm_index + 1);
|
route.waypoints.begin() + vlm_index + 1);
|
||||||
|
active_segment_next_waypoint_index_ = 0;
|
||||||
runRouteSegmentPlanning("to VLM waypoint");
|
runRouteSegmentPlanning("to VLM waypoint");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -640,6 +642,7 @@ private:
|
|||||||
active_segment_waypoints_.assign(
|
active_segment_waypoints_.assign(
|
||||||
route.waypoints.begin() + vlm_index + 1,
|
route.waypoints.begin() + vlm_index + 1,
|
||||||
route.waypoints.end());
|
route.waypoints.end());
|
||||||
|
active_segment_next_waypoint_index_ = 0;
|
||||||
runRouteSegmentPlanning("after VLM waypoint");
|
runRouteSegmentPlanning("after VLM waypoint");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -809,6 +812,10 @@ private:
|
|||||||
if (!current) {
|
if (!current) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
updateActiveSegmentWaypointProgress(*current);
|
||||||
|
if (active_segment_next_waypoint_index_ >= active_segment_waypoints_.size()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
const auto distance_to_goal = distance2d(*current, active_segment_waypoints_.back());
|
const auto distance_to_goal = distance2d(*current, active_segment_waypoints_.back());
|
||||||
const auto elapsed = (now() - last_dynamic_replan_time_).seconds();
|
const auto elapsed = (now() - last_dynamic_replan_time_).seconds();
|
||||||
if (!shouldDynamicReplan(
|
if (!shouldDynamicReplan(
|
||||||
@@ -830,8 +837,15 @@ private:
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const auto replan_goals = remainingWaypoints(
|
||||||
|
active_segment_waypoints_, active_segment_next_waypoint_index_);
|
||||||
|
if (replan_goals.empty()) {
|
||||||
|
dynamic_replan_in_flight_ = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ComputePathThroughPoses::Goal goal;
|
ComputePathThroughPoses::Goal goal;
|
||||||
goal.goals = stampPoses({active_segment_waypoints_.back()});
|
goal.goals = stampPoses(replan_goals);
|
||||||
goal.planner_id = planner_id_;
|
goal.planner_id = planner_id_;
|
||||||
goal.use_start = false;
|
goal.use_start = false;
|
||||||
|
|
||||||
@@ -864,6 +878,22 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
compute_path_client_->async_send_goal(goal, options);
|
compute_path_client_->async_send_goal(goal, options);
|
||||||
|
RCLCPP_INFO(
|
||||||
|
get_logger(), "dynamic route replanning through %zu remaining waypoint(s), next index=%zu",
|
||||||
|
replan_goals.size(), active_segment_next_waypoint_index_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateActiveSegmentWaypointProgress(const geometry_msgs::msg::PoseStamped & current)
|
||||||
|
{
|
||||||
|
const auto previous_index = active_segment_next_waypoint_index_;
|
||||||
|
active_segment_next_waypoint_index_ = advanceReachedWaypointIndex(
|
||||||
|
active_segment_waypoints_, current, active_segment_next_waypoint_index_,
|
||||||
|
circle_goal_tolerance_);
|
||||||
|
if (active_segment_next_waypoint_index_ != previous_index) {
|
||||||
|
RCLCPP_INFO(
|
||||||
|
get_logger(), "route waypoint progress advanced: next index %zu -> %zu",
|
||||||
|
previous_index, active_segment_next_waypoint_index_);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void onDynamicReplanFailed(const std::string & reason)
|
void onDynamicReplanFailed(const std::string & reason)
|
||||||
@@ -1293,6 +1323,7 @@ private:
|
|||||||
VlmCaptureMode vlm_capture_mode_{VlmCaptureMode::Stop};
|
VlmCaptureMode vlm_capture_mode_{VlmCaptureMode::Stop};
|
||||||
RouteSegment active_segment_{RouteSegment::None};
|
RouteSegment active_segment_{RouteSegment::None};
|
||||||
std::vector<geometry_msgs::msg::PoseStamped> active_segment_waypoints_;
|
std::vector<geometry_msgs::msg::PoseStamped> active_segment_waypoints_;
|
||||||
|
std::size_t active_segment_next_waypoint_index_{0};
|
||||||
nav_msgs::msg::Path active_path_;
|
nav_msgs::msg::Path active_path_;
|
||||||
bool vlm_capture_triggered_{false};
|
bool vlm_capture_triggered_{false};
|
||||||
std::optional<geometry_msgs::msg::PoseStamped> recovery_start_pose_;
|
std::optional<geometry_msgs::msg::PoseStamped> recovery_start_pose_;
|
||||||
|
|||||||
@@ -132,6 +132,37 @@ TEST(RacingControlHelpers, DynamicReplanningStopsNearGoal)
|
|||||||
EXPECT_FALSE(racing_control::shouldDynamicReplan(false, false, 0.6, 0.5, 1.0, 1.0));
|
EXPECT_FALSE(racing_control::shouldDynamicReplan(false, false, 0.6, 0.5, 1.0, 1.0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(RacingControlHelpers, AdvancesNextWaypointOnlyAfterItIsReached)
|
||||||
|
{
|
||||||
|
const auto waypoints = racing_control::posesFromFlatDoubles(
|
||||||
|
{0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 2.0, 0.0, 0.0},
|
||||||
|
"map");
|
||||||
|
|
||||||
|
EXPECT_EQ(
|
||||||
|
racing_control::advanceReachedWaypointIndex(
|
||||||
|
waypoints, racing_control::poseFromXYYaw(0.65, 0.0, 0.0, "map"), 1, 0.30),
|
||||||
|
1U);
|
||||||
|
EXPECT_EQ(
|
||||||
|
racing_control::advanceReachedWaypointIndex(
|
||||||
|
waypoints, racing_control::poseFromXYYaw(1.05, 0.0, 0.0, "map"), 1, 0.30),
|
||||||
|
2U);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(RacingControlHelpers, DynamicReplanningKeepsRemainingUnreachedWaypoints)
|
||||||
|
{
|
||||||
|
const auto waypoints = racing_control::posesFromFlatDoubles(
|
||||||
|
{0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 2.0, 0.0, 0.0},
|
||||||
|
"map");
|
||||||
|
|
||||||
|
const auto remaining = racing_control::remainingWaypoints(waypoints, 1);
|
||||||
|
|
||||||
|
ASSERT_EQ(remaining.size(), 2U);
|
||||||
|
EXPECT_DOUBLE_EQ(remaining[0].pose.position.x, 1.0);
|
||||||
|
EXPECT_DOUBLE_EQ(remaining[1].pose.position.x, 2.0);
|
||||||
|
EXPECT_TRUE(racing_control::remainingWaypoints(waypoints, waypoints.size()).empty());
|
||||||
|
EXPECT_TRUE(racing_control::remainingWaypoints(waypoints, waypoints.size() + 1).empty());
|
||||||
|
}
|
||||||
|
|
||||||
TEST(RacingControlHelpers, RecoveryBackupStopsByDistanceOrTimeout)
|
TEST(RacingControlHelpers, RecoveryBackupStopsByDistanceOrTimeout)
|
||||||
{
|
{
|
||||||
EXPECT_TRUE(racing_control::recoveryBackupComplete(0.04, 0.04, 0.1, 0.2));
|
EXPECT_TRUE(racing_control::recoveryBackupComplete(0.04, 0.04, 0.1, 0.2));
|
||||||
|
|||||||
Reference in New Issue
Block a user