Simplify yaw calculation, fine-tune goal cost

This commit is contained in:
TJU-Lu
2025-10-25 16:53:11 +08:00
parent 27acd66598
commit 1925c16b7a
4 changed files with 53 additions and 98 deletions

View File

@@ -300,9 +300,17 @@ void NetworkControl::imu_callback(const sensor_msgs::Imu &imu)
Eigen::Vector3d acc(imu.linear_acceleration.x, Eigen::Vector3d acc(imu.linear_acceleration.x,
imu.linear_acceleration.y, imu.linear_acceleration.y,
imu.linear_acceleration.z); imu.linear_acceleration.z);
if (is_simulation_)
{
cur_acc_ = acc;
}
else
{
Eigen::Vector3d acc_world = cur_att_ * acc; Eigen::Vector3d acc_world = cur_att_ * acc;
acc_world(2) -= 9.8; acc_world(2) -= 9.8;
cur_acc_ = acc_world; cur_acc_ = acc_world;
}
// so3_controller_.setAcc(acc_world); // so3_controller_.setAcc(acc_world);
} }

View File

@@ -18,7 +18,7 @@ class GuidanceLoss(nn.Module):
Returns: Returns:
guidance_loss: (batch_size) → guidance loss guidance_loss: (batch_size) → guidance loss
GuidanceLoss: distance_loss (better near the goal) or similarity_loss (better during flight) or terminal_aware_similarity_loss (balanced) GuidanceLoss: distance_loss (for straighter flight) or similarity_loss (for faster flight in large scenario)
""" """
cur_pos = Df[:, :, 0] cur_pos = Df[:, :, 0]
end_pos = Dp[:, :, 0] end_pos = Dp[:, :, 0]
@@ -26,10 +26,8 @@ class GuidanceLoss(nn.Module):
traj_dir = end_pos - cur_pos # [B, 3] traj_dir = end_pos - cur_pos # [B, 3]
goal_dir = goal - cur_pos # [B, 3] goal_dir = goal - cur_pos # [B, 3]
# NOTE: trajectory with distance_loss is straighter and reaches the goal more accurately,
# while our pre-trained model choose terminal_aware_similarity_loss only for higher speed in large-scale scenario.
guidance_loss = self.distance_loss(traj_dir, goal_dir) guidance_loss = self.distance_loss(traj_dir, goal_dir)
# guidance_loss = self.terminal_aware_similarity_loss(traj_dir, goal_dir) # guidance_loss = self.similarity_loss(traj_dir, goal_dir)
return guidance_loss return guidance_loss
def distance_loss(self, traj_dir, goal_dir): def distance_loss(self, traj_dir, goal_dir):
@@ -39,7 +37,7 @@ class GuidanceLoss(nn.Module):
L1Loss: L1 distance (same scale as the similarity loss) to the normalized goal (for numerical stability). L1Loss: L1 distance (same scale as the similarity loss) to the normalized goal (for numerical stability).
closer to the goal is preferred. closer to the goal is preferred.
Better near the goal, but slightly inferior to the similarity cost in general situations. Straighter flight, but slightly inferior to the similarity cost in flight speed.
""" """
l1_distance = F.smooth_l1_loss(traj_dir, goal_dir, reduction='none') # shape: (B, 3) l1_distance = F.smooth_l1_loss(traj_dir, goal_dir, reduction='none') # shape: (B, 3)
l1_distance = l1_distance.sum(dim=1) # (B) l1_distance = l1_distance.sum(dim=1) # (B)
@@ -52,34 +50,22 @@ class GuidanceLoss(nn.Module):
SimilarityLoss: Projection length of the trajectory onto the goal direction: SimilarityLoss: Projection length of the trajectory onto the goal direction:
higher cosine similarity and longer trajectory are preferred. higher cosine similarity and longer trajectory are preferred.
Performs better in general by allowing longer lateral avoidance without slowing down, but less precise near the goal. Faster flight in large-scale scenario by allowing longer lateral avoidance without slowing down, but less precise near the goal.
""" """
goal_length = goal_dir.norm(dim=1) goal_dir_norm = goal_dir / (goal_dir.norm(dim=1, keepdim=True) + 1e-8) # [B, 3]
goal_dir_norm = goal_dir / (goal_length.unsqueeze(1) + 1e-8) # [B, 3] # projection length of trajectory on goal direction
similarity = th.sum(traj_dir * goal_dir_norm, dim=1) # [B] traj_along = (traj_dir * goal_dir_norm).sum(dim=1) # [B]
goal_length = goal_dir.norm(dim=1) # [B]
similarity_loss = th.abs(goal_length - similarity) # length difference along goal direction (cosine similarity)
return similarity_loss parallel_diff = (goal_length - traj_along).abs() # [B]
def terminal_aware_similarity_loss(self, traj_dir, goal_dir): # length perpendicular to goal direction
""" traj_perp = traj_dir - traj_along.unsqueeze(1) * goal_dir_norm # [B, 3]
Returns: perp_diff = traj_perp.norm(dim=1) # [B]
similarity: (batch_size) → guidance loss
# distance weighting (reduce perpendicular constraint, allow lateral exploration)
SimilarityLoss: Projection length of the trajectory onto the goal direction: perp_weight = 0.5 # the given weight is trained with perp_weight = 0, for higher speed in large-scale scenario
higher cosine similarity and longer trajectory are preferred. similarity_loss = parallel_diff + perp_weight * perp_diff
Reduce perpendicular deviation when approaching the goal, and apply dynamic weighting to ensure loss continuity.
"""
goal_length = goal_dir.norm(dim=1)
goal_dir_norm = goal_dir / (goal_length.unsqueeze(1) + 1e-8) # [B, 3]
similarity = th.sum(traj_dir * goal_dir_norm, dim=1) # [B]
traj_dir_proj = similarity.unsqueeze(1) * goal_dir_norm # [B, 3]
perp_component = (traj_dir - traj_dir_proj).norm(dim=1) # [B]
perp_weight = ((self.goal_length - goal_length) / self.goal_length).clamp(min=0.0, max=0.6) # [B]
perp_weight[perp_weight < 1e-4] = 0.0 # eliminate tiny numerical errors for stability
similarity_loss = (1 - perp_weight) * th.abs(goal_length - similarity) + perp_weight * perp_component
return similarity_loss return similarity_loss

View File

@@ -58,72 +58,33 @@ class Polys5Solver:
self.A[3][:, np.newaxis] * t ** 3 + self.A[4][:, np.newaxis] * t ** 4 + self.A[5][:, np.newaxis] * t ** 5) self.A[3][:, np.newaxis] * t ** 3 + self.A[4][:, np.newaxis] * t ** 4 + self.A[5][:, np.newaxis] * t ** 5)
return result.flatten() return result.flatten()
def wrap_to_pi(angle):
"""将角度限制在 [-pi, pi]"""
return (angle + np.pi) % (2 * np.pi) - np.pi
def calculate_yaw(vel_dir, goal_dir, last_yaw, dt, max_yaw_rate=0.3): def calculate_yaw(vel_dir, goal_dir, last_yaw, dt, max_yaw_rate=0.5):
YAW_DOT_MAX_PER_SEC = max_yaw_rate * np.pi # Normalize velocity and goal directions
# Direction of velocity
vel_dir = vel_dir / (np.linalg.norm(vel_dir) + 1e-5) vel_dir = vel_dir / (np.linalg.norm(vel_dir) + 1e-5)
# Direction of goal
goal_dist = np.linalg.norm(goal_dir) goal_dist = np.linalg.norm(goal_dir)
goal_dir = goal_dir / (goal_dist + 1e-5) # Prevent division by zero goal_dir = goal_dir / (goal_dist + 1e-5)
# Dynamically adjust weights between goal and velocity directions in yaw planning # Goal yaw and weighting
goal_yaw = np.arctan2(goal_dir[1], goal_dir[0]) goal_yaw = np.arctan2(goal_dir[1], goal_dir[0])
delta_yaw = goal_yaw - last_yaw delta_yaw = wrap_to_pi(goal_yaw - last_yaw)
delta_yaw = (delta_yaw + np.pi) % (2 * np.pi) - np.pi # wrap to [-π, π] weight = 6 * abs(delta_yaw) / np.pi # weight ∈ [0,6]; equal weight at 30°, goal weight increases as delta_yaw grows
weight = 6 * abs(delta_yaw) / np.pi # weight ∈ 6 * [0, 1] equal weight at 30°, goal weight increases as angle grows
# Desired direction # Desired direction and yaw
dir_des = vel_dir + weight * goal_dir dir_des = vel_dir + weight * goal_dir
yaw_desired = np.arctan2(dir_des[1], dir_des[0]) if goal_dist > 0.5 else last_yaw
# Temporary yaw calculation # Yaw difference and limit
yaw_temp = np.arctan2(dir_des[1], dir_des[0]) if goal_dist > 0.2 else last_yaw yaw_diff = wrap_to_pi(yaw_desired - last_yaw)
max_yaw_change = YAW_DOT_MAX_PER_SEC * dt max_yaw_change = max_yaw_rate * np.pi * dt
yaw_change = np.clip(yaw_diff, -max_yaw_change, max_yaw_change)
# Logic for yaw adjustment # Updated yaw and yaw rate
if yaw_temp - last_yaw > np.pi: yaw = wrap_to_pi(last_yaw + yaw_change)
if yaw_temp - last_yaw - 2 * np.pi < -max_yaw_change: yawdot = yaw_change / dt
yaw = last_yaw - max_yaw_change
if yaw < -np.pi:
yaw += 2 * np.pi
yawdot = -YAW_DOT_MAX_PER_SEC
else:
yaw = yaw_temp
if yaw - last_yaw > np.pi:
yawdot = -YAW_DOT_MAX_PER_SEC
else:
yawdot = (yaw_temp - last_yaw) / dt
elif yaw_temp - last_yaw < -np.pi:
if yaw_temp - last_yaw + 2 * np.pi > max_yaw_change:
yaw = last_yaw + max_yaw_change
if yaw > np.pi:
yaw -= 2 * np.pi
yawdot = YAW_DOT_MAX_PER_SEC
else:
yaw = yaw_temp
if yaw - last_yaw < -np.pi:
yawdot = YAW_DOT_MAX_PER_SEC
else:
yawdot = (yaw_temp - last_yaw) / dt
else:
if yaw_temp - last_yaw < -max_yaw_change:
yaw = last_yaw - max_yaw_change
if yaw < -np.pi:
yaw += 2 * np.pi
yawdot = -YAW_DOT_MAX_PER_SEC
elif yaw_temp - last_yaw > max_yaw_change:
yaw = last_yaw + max_yaw_change
if yaw > np.pi:
yaw -= 2 * np.pi
yawdot = YAW_DOT_MAX_PER_SEC
else:
yaw = yaw_temp
if yaw - last_yaw > np.pi:
yawdot = -YAW_DOT_MAX_PER_SEC
elif yaw - last_yaw < -np.pi:
yawdot = YAW_DOT_MAX_PER_SEC
else:
yawdot = (yaw_temp - last_yaw) / dt
return yaw, yawdot return yaw, yawdot

View File

@@ -7,7 +7,7 @@ Panels:
- /Map1/Autocompute Value Bounds1 - /Map1/Autocompute Value Bounds1
- /Trajectory1 - /Trajectory1
Splitter Ratio: 0.6625221967697144 Splitter Ratio: 0.6625221967697144
Tree Height: 387 Tree Height: 653
- Class: rviz/Selection - Class: rviz/Selection
Name: Selection Name: Selection
- Class: rviz/Tool Properties - Class: rviz/Tool Properties
@@ -215,7 +215,7 @@ Visualization Manager:
Views: Views:
Current: Current:
Class: rviz/Orbit Class: rviz/Orbit
Distance: 49.83913803100586 Distance: 134.25611877441406
Enable Stereo Rendering: Enable Stereo Rendering:
Stereo Eye Separation: 0.05999999865889549 Stereo Eye Separation: 0.05999999865889549
Stereo Focal Distance: 1 Stereo Focal Distance: 1
@@ -240,10 +240,10 @@ Window Geometry:
collapsed: false collapsed: false
Displays: Displays:
collapsed: false collapsed: false
Height: 1016 Height: 1495
Hide Left Dock: false Hide Left Dock: false
Hide Right Dock: true Hide Right Dock: true
QMainWindow State: 000000ff00000000fd0000000400000000000002700000033afc0200000009fb0000001200530065006c0065006300740069006f006e00000001e10000009b0000005c00fffffffb0000001e0054006f006f006c002000500072006f007000650072007400690065007302000001ed000001df00000185000000b0fb000000120056006900650077007300200054006f006f02000001df000002110000018500000122fb000000200054006f006f006c002000500072006f0070006500720074006900650073003203000002880000011d000002210000017afb000000100044006900730070006c006100790073010000003d000001c0000000c900fffffffb0000002000730065006c0065006300740069006f006e00200062007500660066006500720200000138000000aa0000023a00000294fb00000014005700690064006500530074006500720065006f02000000e6000000d2000003ee0000030bfb0000000c004b0069006e0065006300740200000186000001060000030c00000261fb0000000a004400650070007400680100000203000001740000001600ffffff00000001000001b90000035afc0200000003fb0000001e0054006f006f006c002000500072006f00700065007200740069006500730100000041000000780000000000000000fb0000000a00560069006500770073000000003d0000035a000000a400fffffffb0000001200530065006c0065006300740069006f006e010000025a000000b200000000000000000000000200000490000000a9fc0100000001fb0000000a00560069006500770073030000004e00000080000002e10000019700000003000007380000005efc0100000002fb0000000800540069006d0065010000000000000738000003bc00fffffffb0000000800540069006d00650100000000000004500000000000000000000004c20000033a00000004000000040000000800000008fc0000000100000002000000010000000a0054006f006f006c00730100000000ffffffff0000000000000000 QMainWindow State: 000000ff00000000fd0000000400000000000002700000051dfc0200000009fb0000001200530065006c0065006300740069006f006e00000001e10000009b0000005c00fffffffb0000001e0054006f006f006c002000500072006f007000650072007400690065007302000001ed000001df00000185000000b0fb000000120056006900650077007300200054006f006f02000001df000002110000018500000122fb000000200054006f006f006c002000500072006f0070006500720074006900650073003203000002880000011d000002210000017afb000000100044006900730070006c006100790073010000003b000002c8000000c700fffffffb0000002000730065006c0065006300740069006f006e00200062007500660066006500720200000138000000aa0000023a00000294fb00000014005700690064006500530074006500720065006f02000000e6000000d2000003ee0000030bfb0000000c004b0069006e0065006300740200000186000001060000030c00000261fb0000000a0044006500700074006801000003090000024f0000001600ffffff00000001000001b90000035afc0200000003fb0000001e0054006f006f006c002000500072006f00700065007200740069006500730100000041000000780000000000000000fb0000000a00560069006500770073000000003d0000035a000000a000fffffffb0000001200530065006c0065006300740069006f006e010000025a000000b200000000000000000000000200000490000000a9fc0100000001fb0000000a00560069006500770073030000004e00000080000002e10000019700000003000009f40000005efc0100000002fb0000000800540069006d00650100000000000009f40000030700fffffffb0000000800540069006d006501000000000000045000000000000000000000077e0000051d00000004000000040000000800000008fc0000000100000002000000010000000a0054006f006f006c00730100000000ffffffff0000000000000000
Selection: Selection:
collapsed: false collapsed: false
Time: Time:
@@ -252,6 +252,6 @@ Window Geometry:
collapsed: false collapsed: false
Views: Views:
collapsed: true collapsed: true
Width: 1848 Width: 2548
X: 72 X: 1920
Y: 27 Y: 378