Spaces:
Running
Running
Update simulation_modules.py
Browse files- simulation_modules.py +48 -55
simulation_modules.py
CHANGED
@@ -524,83 +524,76 @@ def world_to_pixel(world_points: np.ndarray, grid_size_pixels: tuple, grid_size_
|
|
524 |
return np.vstack((pixel_x, pixel_y)).T
|
525 |
|
526 |
# ===================================================================
|
527 |
-
# الخطوة 2: دالة render_bev (محدثة للمرحلة الثانية: الخرائط المستقبلية)
|
528 |
# ===================================================================
|
529 |
def render_bev(
|
530 |
active_tracks: List,
|
531 |
-
|
532 |
ego_pos_global: np.ndarray,
|
533 |
ego_theta_global: float,
|
534 |
pixels_per_meter: int = 20,
|
535 |
grid_size_meters: tuple = (20, 20),
|
536 |
-
future_time_steps: tuple = (1.0, 2.0)
|
537 |
) -> Dict[str, np.ndarray]:
|
538 |
-
|
539 |
-
[المرحلة الثانية]
|
540 |
-
تنشئ خريطة للحظة الحالية (t0) وخرائط تنبؤ مستقبلية (t1, t2).
|
541 |
-
"""
|
542 |
side_m, fwd_m = grid_size_meters
|
543 |
width_px, height_px = int(side_m * pixels_per_meter), int(fwd_m * pixels_per_meter)
|
544 |
|
545 |
-
# مصفوفة التحويل
|
546 |
R_world_to_ego = np.array([[math.cos(ego_theta_global), math.sin(ego_theta_global)],
|
547 |
[-math.sin(ego_theta_global), math.cos(ego_theta_global)]])
|
548 |
-
|
549 |
-
# إنشاء قواميس للخرائط الفارغة
|
550 |
bev_maps = {
|
551 |
't0': np.zeros((height_px, width_px, 3), dtype=np.uint8),
|
552 |
't1': np.zeros((height_px, width_px, 3), dtype=np.uint8),
|
553 |
't2': np.zeros((height_px, width_px, 3), dtype=np.uint8)
|
554 |
}
|
555 |
|
556 |
-
|
557 |
for track in active_tracks:
|
558 |
-
|
559 |
-
|
560 |
-
yaw_rad_global
|
561 |
-
|
562 |
-
extent
|
563 |
-
|
564 |
-
|
565 |
-
|
566 |
-
|
567 |
-
|
568 |
-
|
569 |
-
|
570 |
-
|
571 |
-
|
572 |
-
|
573 |
-
|
574 |
-
|
575 |
-
|
576 |
-
|
577 |
-
# --- د. التنبؤ بالمستقبل ورسمه ---
|
578 |
-
for i, t in enumerate(future_time_steps):
|
579 |
-
# حساب الإزاحة بناءً على السرعة والاتجاه والزمن
|
580 |
-
# (هذه العمليات تتم في الإطار المرجعي العالمي)
|
581 |
-
offset = np.array([math.cos(yaw_rad_global), math.sin(yaw_rad_global)]) * speed * t
|
582 |
-
future_pos_global = pos_global + offset
|
583 |
-
|
584 |
-
# تحويل الموقع المستقبلي إلى إحداثيات نسبية ثم إلى بكسلات
|
585 |
-
relative_pos_future = R_world_to_ego.dot(future_pos_global - ego_pos_global)
|
586 |
-
center_pixel_future = world_to_pixel(np.array([relative_pos_future]), (width_px, height_px), grid_size_meters)[0]
|
587 |
-
|
588 |
-
# رسم الصندوق المستقبلي (نفس الحجم والزاوية، ولكن بموقع ولون مختلفين)
|
589 |
-
key = f't{i+1}' # 't1', 't2', etc.
|
590 |
-
box_points_future = cv2.boxPoints(((float(center_pixel_future[0]), float(center_pixel_future[1])), box_size_px, angle_deg))
|
591 |
-
cv2.drawContours(bev_maps[key], [box_points_future.astype(np.int32)], 0, (255, 0, 128), 2) # بنفسجي
|
592 |
-
|
593 |
-
# --- 2. رسم مركبة الأنا (يجب رسمها على كل الخرائط) ---
|
594 |
-
ego_center_pixel = ((width_px / 2 ) + 20 , height_px - 10)
|
595 |
-
ego_size_px = (1.8 * pixels_per_meter, 2.0 * pixels_per_meter)
|
596 |
-
ego_box = cv2.boxPoints((ego_center_pixel, ego_size_px, -90))
|
597 |
for key in bev_maps:
|
598 |
-
cv2.drawContours(bev_maps[key],
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
599 |
|
600 |
-
|
601 |
-
|
602 |
-
|
603 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
604 |
|
605 |
return bev_maps
|
606 |
# =========================================================
|
|
|
524 |
return np.vstack((pixel_x, pixel_y)).T
|
525 |
|
526 |
# ===================================================================
|
|
|
527 |
# ===================================================================
|
528 |
def render_bev(
|
529 |
active_tracks: List,
|
530 |
+
waypoints_to_draw: np.ndarray,
|
531 |
ego_pos_global: np.ndarray,
|
532 |
ego_theta_global: float,
|
533 |
pixels_per_meter: int = 20,
|
534 |
grid_size_meters: tuple = (20, 20),
|
535 |
+
future_time_steps: tuple = (1.0, 2.0)
|
536 |
) -> Dict[str, np.ndarray]:
|
537 |
+
|
|
|
|
|
|
|
538 |
side_m, fwd_m = grid_size_meters
|
539 |
width_px, height_px = int(side_m * pixels_per_meter), int(fwd_m * pixels_per_meter)
|
540 |
|
541 |
+
# ... (كود مصفوفة التحويل وإنشاء الخرائط يبقى كما هو)
|
542 |
R_world_to_ego = np.array([[math.cos(ego_theta_global), math.sin(ego_theta_global)],
|
543 |
[-math.sin(ego_theta_global), math.cos(ego_theta_global)]])
|
|
|
|
|
544 |
bev_maps = {
|
545 |
't0': np.zeros((height_px, width_px, 3), dtype=np.uint8),
|
546 |
't1': np.zeros((height_px, width_px, 3), dtype=np.uint8),
|
547 |
't2': np.zeros((height_px, width_px, 3), dtype=np.uint8)
|
548 |
}
|
549 |
|
550 |
+
|
551 |
for track in active_tracks:
|
552 |
+
pos_global=track.last_pos;yaw_rad_global=getattr(track,'last_yaw',0);
|
553 |
+
speed=getattr(track,'speed',0);extent=getattr(track,'last_extent',(1.0,2.0));
|
554 |
+
relative_yaw_rad=yaw_rad_global-ego_theta_global;angle_deg=90-math.degrees(relative_yaw_rad);
|
555 |
+
width_px_obj=extent[1]*2*pixels_per_meter;
|
556 |
+
length_px_obj=extent[0]*2*pixels_per_meter;
|
557 |
+
box_size_px=(float(width_px_obj),float(length_px_obj));
|
558 |
+
relative_pos_t0=R_world_to_ego.dot(pos_global-ego_pos_global);
|
559 |
+
center_pixel_t0=world_to_pixel(np.array([relative_pos_t0]),(width_px,height_px),grid_size_meters)[0];
|
560 |
+
box_points_t0=cv2.boxPoints(((float(center_pixel_t0[0]),float(center_pixel_t0[1])-40),box_size_px,angle_deg));
|
561 |
+
cv2.drawContours(bev_maps['t0'],[box_points_t0.astype(np.int32)],0,(0,0,255),2);
|
562 |
+
for i,t in enumerate(future_time_steps):
|
563 |
+
offset=np.array([math.cos(yaw_rad_global),math.sin(yaw_rad_global)])*speed*t;
|
564 |
+
future_pos_global=pos_global+offset;
|
565 |
+
relative_pos_future=R_world_to_ego.dot(future_pos_global-ego_pos_global);
|
566 |
+
center_pixel_future=world_to_pixel(np.array([relative_pos_future]),(width_px,height_px-40),grid_size_meters)[0];key=f't{i+1}';box_points_future=cv2.boxPoints(((float(center_pixel_future[0]),float(center_pixel_future[1])),box_size_px,angle_deg));
|
567 |
+
cv2.drawContours(bev_maps[key],[box_points_future.astype(np.int32)],0,(255,0,128),2);
|
568 |
+
ego_center_pixel=((width_px/2)+20,height_px);
|
569 |
+
ego_size_px=(1.8*pixels_per_meter,3.8*pixels_per_meter);
|
570 |
+
ego_box=cv2.boxPoints((ego_center_pixel,ego_size_px,0));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
571 |
for key in bev_maps:
|
572 |
+
cv2.drawContours(bev_maps[key],[ego_box.astype(np.int32)],0,(0,255,255),-1);
|
573 |
+
|
574 |
+
# =========================================================================
|
575 |
+
# =========================================================================
|
576 |
+
if waypoints_to_draw is not None and waypoints_to_draw.size > 0:
|
577 |
+
waypoints_corrected = waypoints_to_draw.copy()
|
578 |
+
waypoints_corrected[:, 1] *= 1 # [Forward, Left] -> [Forward, -Left] which is [Forward, Right]
|
579 |
+
|
580 |
+
|
581 |
+
waypoints_pixels = world_to_pixel(
|
582 |
+
waypoints_corrected,
|
583 |
+
(width_px, height_px),
|
584 |
+
grid_size_meters
|
585 |
+
)
|
586 |
|
587 |
+
for point in waypoints_pixels:
|
588 |
+
center = (int(point[0])+20, int(point[1]))
|
589 |
+
cv2.circle(
|
590 |
+
bev_maps['t0'],
|
591 |
+
center,
|
592 |
+
radius=3,
|
593 |
+
color=(0, 255, 0),
|
594 |
+
thickness=-1,
|
595 |
+
lineType=cv2.LINE_AA
|
596 |
+
)
|
597 |
|
598 |
return bev_maps
|
599 |
# =========================================================
|