@@ -58,8 +58,8 @@ def _calc_dynamic_window(self, x):
5858 Vd = [
5959 x [3 ] - self .max_accel * self .dt ,
6060 x [3 ] + self .max_accel * self .dt ,
61- x [ 4 ] - self .max_delta_yaw_rate * self .dt ,
62- x [ 4 ] + self .max_delta_yaw_rate * self .dt
61+ - self .max_delta_yaw_rate * self .dt ,
62+ self .max_delta_yaw_rate * self .dt
6363 ]
6464
6565 # Final dynamic window (intersection of constraints)
@@ -93,6 +93,8 @@ def _calc_control_and_trajectory(self, x, dw, goal, obstacles):
9393
9494 valid_trajectories = 0
9595
96+ # print(f"[DEBUG] 현재: x={x[0]:.2f}, y={x[1]:.2f}, yaw={x[2]:.2f}") # debug
97+
9698 # Sample velocities in dynamic window
9799 for v in np .arange (dw [0 ], dw [1 ], self .v_resolution ):
98100
@@ -103,12 +105,16 @@ def _calc_control_and_trajectory(self, x, dw, goal, obstacles):
103105
104106 for omega in omegas :
105107
108+ # print("=====") #debug
109+
106110 # Predict trajectory
107111 trajectory = self ._predict_trajectory (x_init , v , omega )
108112
109113 # Calculate costs
110114 obstacle_cost = self ._calc_obstacle_cost (trajectory , obstacles )
111-
115+ if obstacle_cost == 0.0 :
116+ continue
117+
112118 speed_cost = self ._calc_speed_cost (trajectory )
113119 goal_cost = self ._calc_goal_cost (trajectory , goal )
114120 curvature_cost = self ._calc_curvature_cost (trajectory , goal )
@@ -120,17 +126,23 @@ def _calc_control_and_trajectory(self, x, dw, goal, obstacles):
120126 self .obstacle_cost_gain * obstacle_cost +
121127 self .curvature_cost_gain * curvature_cost
122128 )
123- if obstacle_cost == 0.0 :
124- continue
129+
125130 # Skip collision trajectories
126131 valid_trajectories += 1
127-
132+
133+
134+ # print(f"omega: {omega:.4f}, total_cost: {total_cost:.4f}") #debug
135+ # print(f"trajectory: {trajectory[-1, 0]}, {trajectory[-1, 1]}, {trajectory[-1, 2]}") #debug
136+ #print(f"costs: speed: {speed_cost:.4f}, goal: {goal_cost:.4f}, obstacle: {obstacle_cost:.4f}, curvature: {curvature_cost:.4f}") #debug
137+
128138 # Update best trajectory
129139 if total_cost > max_cost :
130140 max_cost = total_cost
131141 self .best_u = [v , omega ]
132142 best_trajectory = trajectory
133-
143+
144+ # print(f"best u: {self.best_u[0]}, {self.best_u[1]} = max_cost: {max_cost:.4f}") #debug
145+ # print("--------------------------------------------") #debug
134146 return self .best_u , best_trajectory
135147
136148 def _predict_trajectory (self , x_init , v , omega ):
@@ -152,29 +164,50 @@ def _predict_trajectory(self, x_init, v, omega):
152164
153165 return trajectory
154166
167+
155168 def _calc_speed_cost (self , trajectory ):
156169 """Speed cost - encourages higher speeds (normalized)"""
157170 if len (trajectory ) == 0 :
158171 return 0.0
159172 # Normalize speed cost (higher speed = higher cost value for maximization)
160173 return trajectory [- 1 , 3 ] / self .max_speed
161174
162- def _calc_goal_cost (self , trajectory , goal ):
163- """Goal cost - encourages moving toward goal"""
175+ def _calc_goal_cost (self , trajectory , goal , alpha = 0.3 , beta = 0.7 ):
176+ """
177+ 혼합 goal cost 계산 함수 (높을수록 좋은 값)
178+ - alpha: 방향 cost 가중치
179+ - beta: 거리 cost 가중치
180+ """
164181 if len (trajectory ) == 0 :
165- return 1.0
166-
167- # Distance to goal from final trajectory point
168- dx = goal [0 ] - trajectory [- 1 , 0 ]
169- dy = goal [1 ] - trajectory [- 1 , 1 ]
170-
171- # Heading error - angle between robot heading and direction to goal
182+ return 1.0 # 최악의 경우
183+
184+ x , y , theta = trajectory [- 1 , 0 ], trajectory [- 1 , 1 ], trajectory [- 1 , 2 ]
185+
186+ dx = goal [0 ] - x
187+ dy = goal [1 ] - y
188+ distance = np .hypot (dx , dy )
189+ #print(f"[DEBUG] Goal position: {goal}, Robot position: ({x:.2f}, {y:.2f}), Distance: {distance:.2f}") # debug
190+
191+ # 거리 기반 cost (가까울수록 높음)
192+ distance_cost = 1.0 / (distance + 1e-6 )
193+
194+ # 각도 차이 계산 함수
195+ def angle_diff (a , b ):
196+ diff = (a - b + np .pi ) % (2 * np .pi ) - np .pi
197+ return diff
198+
199+ # 방향 기반 cost
172200 goal_angle = np .arctan2 (dy , dx )
173- heading_error = goal_angle - trajectory [- 1 , 2 ]
174- heading_error = np .abs (heading_error ) % (2 * np .pi )
175- heading_cost = np .pi - heading_error
176- # Combined cost: distance + heading (both should be minimized, so we use 1/cost format)
177- return heading_cost / np .pi
201+ heading_error = abs (angle_diff (goal_angle , theta ))
202+ heading_cost = (np .pi - heading_error ) / np .pi # 1에 가까울수록 방향이 정확함
203+
204+ # print(f"[DEBUG] Goal cost - Heading: {heading_cost:.4f}, Distance: {distance_cost:.4f}") # debug
205+
206+ # 혼합 cost
207+ total_cost = alpha * heading_cost + beta * distance_cost
208+ return total_cost
209+
210+
178211
179212 # def _calc_obstacle_cost(self, trajectory, obstacles):
180213 # """Obstacle cost - avoids obstacles (optimized for ROSbot2)"""
@@ -229,8 +262,13 @@ def _calc_obstacle_cost(self, trajectory, obstacles):
229262 if len (distances ) > 0 :
230263 min_dist = np .min (distances )
231264 if min_dist <= safety_radius :
265+ #print(f"[WARNING] 장애물이 매우 가까움! 거리: {min_dist:.2f} m (safety_radius={safety_radius:.2f})")
232266 return 0.0
233267
268+ elif min_dist <= safety_radius + 0.2 :
269+ #print(f"[INFO] 장애물 접근 감지: 거리 {min_dist:.2f} m")
270+ return max (min_dist / (safety_radius + 0.2 ), 0.01 )
271+
234272 elif min_dist < min_distance :
235273 min_distance = min_dist
236274
0 commit comments