44from sensor_msgs .msg import PointCloud2
55from typing import Dict
66from ..component import Component
7- from ...state import ObjectPose , ObjectFrameEnum , Obstacle , ObstacleMaterialEnum , ObstacleStateEnum
7+ from ...state import ObjectPose , ObjectFrameEnum , Obstacle , ObstacleMaterialEnum , ObstacleState
88from ..interface .gem import GEMInterface
99from .utils .constants import *
10+ from .utils .math_utils import *
1011from .utils .detection_utils import *
1112from .utils .parking_utils import *
1213from .utils .visualization_utils import *
@@ -23,10 +24,11 @@ def __init__(
2324 # Init Variables
2425 self .vehicle_interface = vehicle_interface
2526 self .cone_pts_3D = []
26- self .ordered_cone_ground_centers_2D = []
27- self .goal_parking_spot = None
28- self .parking_obstacles_pose = []
29- self .parking_obstacles_dim = []
27+ self .grouped_ordered_ground_centers_2D = []
28+ self .parking_goal = None
29+ self .best_parking_spot = None
30+ self .parking_obstacles_poses = []
31+ self .parking_obstacles_dims = []
3032 self .ground_threshold = GROUND_THRESHOLD
3133 self .visualization = visualize_3d
3234
@@ -47,7 +49,8 @@ def __init__(
4749 self .pub_lidar_top_vehicle_pc2 = rospy .Publisher ("lidar_top_vehicle/point_cloud" , PointCloud2 , queue_size = 10 )
4850 self .pub_vehicle_marker = rospy .Publisher ("vehicle/marker" , MarkerArray , queue_size = 10 )
4951 self .pub_cones_centers_pc2 = rospy .Publisher ("cones_detection/centers/point_cloud" , PointCloud2 , queue_size = 10 )
50- self .pub_parking_spot_marker = rospy .Publisher ("parking_spot_detection/marker" , MarkerArray , queue_size = 10 )
52+ self .pub_parking_spot_marker = rospy .Publisher ("parking_spot_detection/spot/marker" , MarkerArray , queue_size = 10 )
53+ self .pub_parking_goal_marker = rospy .Publisher ("parking_spot_detection/goal/marker" , MarkerArray , queue_size = 10 )
5154 self .pub_polygon_marker = rospy .Publisher ("polygon_detection/marker" , MarkerArray , queue_size = 10 )
5255 self .pub_obstacles_marker = rospy .Publisher ("obstacle_detection/marker" , MarkerArray , queue_size = 10 )
5356
@@ -59,10 +62,11 @@ def callback(self, top_lidar_msg):
5962 if self .visualization :
6063 self .visualize (
6164 self .cone_pts_3D ,
62- self .ordered_cone_ground_centers_2D ,
63- self .goal_parking_spot ,
64- self .parking_obstacles_pose ,
65- self .parking_obstacles_dim ,
65+ self .grouped_ordered_ground_centers_2D ,
66+ self .parking_goal ,
67+ self .best_parking_spot ,
68+ self .parking_obstacles_poses ,
69+ self .parking_obstacles_dims ,
6670 lidar_ouster_frame
6771 )
6872
@@ -81,10 +85,11 @@ def state_outputs(self) -> list:
8185
8286 def visualize (self ,
8387 cone_pts_3D ,
84- ordered_cone_ground_centers_2D ,
85- goal_parking_spot ,
86- parking_obstacles_pose ,
87- parking_obstacles_dim ,
88+ grouped_ordered_ground_centers_2D ,
89+ parking_goal ,
90+ best_parking_spot ,
91+ parking_obstacles_poses ,
92+ parking_obstacles_dims ,
8893 lidar_ouster_frame ):
8994 # Transform top lidar pointclouds to vehicle frame for visualization
9095 latest_lidar_vehicle = transform_points (lidar_ouster_frame , self .T_l2v )
@@ -104,69 +109,119 @@ def visualize(self,
104109 self .pub_polygon_marker .publish (ros_delete_polygon_marker )
105110 ros_delete_parking_spot_markers = delete_markers ("parking_spot" , MAX_PARKING_SPOT_MARKERS )
106111 self .pub_parking_spot_marker .publish (ros_delete_parking_spot_markers )
112+ ros_delete_parking_goal_markers = delete_markers ("parking_goal" , MAX_PARKING_GOAL_MARKERS )
113+ self .pub_parking_goal_marker .publish (ros_delete_parking_goal_markers )
107114 ros_delete_obstacles_markers = delete_markers ("obstacles" , MAX_OBSTACLE_MARKERS )
108115 self .pub_obstacles_marker .publish (ros_delete_obstacles_markers )
109116
110117 # Draw polygon first
111- if len (ordered_cone_ground_centers_2D ) > 0 :
112- ros_polygon_marker = create_polygon_marker ( ordered_cone_ground_centers_2D , ref_frame = VEHICLE_FRAME )
113- self .pub_polygon_marker .publish (ros_polygon_marker )
118+ if len (grouped_ordered_ground_centers_2D ) > 0 :
119+ ros_polygon_markers = create_polygon_markers ( grouped_ordered_ground_centers_2D , ref_frame = VEHICLE_FRAME )
120+ self .pub_polygon_marker .publish (ros_polygon_markers )
114121
115122 # Create parking spot marker
116- if goal_parking_spot :
117- ros_parking_spot_marker = create_parking_spot_marker (goal_parking_spot , ref_frame = VEHICLE_FRAME )
123+ if best_parking_spot :
124+ ros_parking_spot_marker = create_parking_spot_marker (best_parking_spot , ref_frame = "vehicle" )
118125 self .pub_parking_spot_marker .publish (ros_parking_spot_marker )
119126
127+ # Create parking goal marker
128+ if parking_goal :
129+ ros_parking_goal_marker = create_parking_goal_marker (x = parking_goal [0 ],
130+ y = parking_goal [1 ],
131+ ref_frame = "vehicle" )
132+ self .pub_parking_goal_marker .publish (ros_parking_goal_marker )
133+
120134 # Create parking obstacles marker
121- if parking_obstacles_pose and parking_obstacles_dim :
122- ros_obstacles_marker = create_markers (parking_obstacles_pose ,
123- parking_obstacles_dim ,
135+ if parking_obstacles_poses and parking_obstacles_dims :
136+ ros_obstacles_marker = create_markers (parking_obstacles_poses ,
137+ parking_obstacles_dims ,
124138 OBSTACLE_MARKER_COLOR ,
125139 "obstacles" , VEHICLE_FRAME )
126140 self .pub_obstacles_marker .publish (ros_obstacles_marker )
127141
128142 # Draw 3D cone centers
143+ cone_ground_centers = []
129144 if len (cone_pts_3D ) > 0 :
130145 cone_ground_centers = np .array (cone_pts_3D )
131146 cone_ground_centers [:, 2 ] = 0.0
132147 cone_ground_centers = [tuple (point ) for point in cone_ground_centers ]
133- ros_cones_centers_pc2 = create_point_cloud (cone_ground_centers , color = CONE_CENTER_PC_COLOR )
134- self .pub_cones_centers_pc2 .publish (ros_cones_centers_pc2 )
148+ ros_cones_centers_pc2 = create_point_cloud (cone_ground_centers , color = CONE_CENTER_PC_COLOR )
149+ self .pub_cones_centers_pc2 .publish (ros_cones_centers_pc2 )
135150
136151
137- def update (self , cone_obstacles : Dict [str , Obstacle ]):
152+ def update (self , cone_obstacles : Dict [str , ObstacleState ]):
138153 # Initial variables
139- goal_parking_spot = None
140- parking_obstacles_pose = []
141- parking_obstacles_dim = []
142- ordered_cone_ground_centers_2D = []
154+ parking_goals = []
155+ best_parking_spots = []
156+ parking_obstacles_poses = []
157+ parking_obstacles_dims = []
158+ grouped_ordered_ground_centers_2D = []
143159
144160 # Populate cone points
145161 cone_pts_3D = []
146162 for cone in cone_obstacles .values ():
147163 cone_pt_3D = (cone .pose .x , cone .pose .y , 0.0 )
148164 cone_pts_3D .append (cone_pt_3D )
149165
150- # Detect parking spot
166+ # Detect single/multi parking spot
151167 if len (cone_pts_3D ) == NUM_CONES_PER_PARKING_SPOT :
152- goal_parking_spot , parking_obstacles_pose , parking_obstacles_dim , ordered_cone_ground_centers_2D = detect_parking_spot (cone_pts_3D )
168+ # Find goal parking pose of that spot, obstacles and centers that forms the polygon
169+ parking_goal , best_parking_spot , parking_obstacles_pose , parking_obstacles_dim , ordered_ground_centers_2D = detect_parking_spot (cone_pts_3D )
170+ # add them to the list
171+ parking_goals .append (parking_goal )
172+ best_parking_spots .append (best_parking_spot )
173+ grouped_ordered_ground_centers_2D .append (ordered_ground_centers_2D )
174+ parking_obstacles_poses = parking_obstacles_pose
175+ parking_obstacles_dims = parking_obstacles_dim
176+ elif is_valid_multiple_of_k (len (cone_pts_3D ), NUM_CONES_PER_PARKING_SPOT ):
177+ grouped_cone_pts_3D = group_points_by_multiple_of_k (cone_pts_3D , NUM_CONES_PER_PARKING_SPOT )
178+ for gc in grouped_cone_pts_3D :
179+ # Find goal parking pose of that spot, obstacles and centers that forms the polygon
180+ parking_goal , best_parking_spot , parking_obstacles_pose , parking_obstacles_dim , ordered_ground_centers_2D = detect_parking_spot (gc )
181+ # add them to the list
182+ parking_goals .append (parking_goal )
183+ best_parking_spots .append (best_parking_spot )
184+ grouped_ordered_ground_centers_2D .append (ordered_ground_centers_2D )
185+ parking_obstacles_poses += parking_obstacles_pose
186+ parking_obstacles_dims += parking_obstacles_dim
187+
188+ # Return if no goal parking spot is found
189+ if len (parking_goals ) < 1 :
190+ self .parking_goal = None
191+ self .best_parking_spot = None
192+ self .cone_pts_3D = []
193+ self .grouped_ordered_ground_centers_2D = []
194+ self .parking_obstacles_poses = []
195+ self .parking_obstacles_dims = []
196+ return None
153197
154198 # Update local variables for visualization
155199 self .cone_pts_3D = cone_pts_3D
156- self .ordered_cone_ground_centers_2D = ordered_cone_ground_centers_2D
157- self .goal_parking_spot = goal_parking_spot
158- self .parking_obstacles_pose = parking_obstacles_pose
159- self .parking_obstacles_dim = parking_obstacles_dim
160-
161- # Return if no goal parking spot is found
162- if not goal_parking_spot :
200+ self .grouped_ordered_ground_centers_2D = grouped_ordered_ground_centers_2D
201+ self .parking_obstacles_poses = parking_obstacles_poses
202+ self .parking_obstacles_dims = parking_obstacles_dims
203+
204+ # Filter out None spots
205+ parking_goals = [x for x in parking_goals if x is not None ]
206+ best_parking_spots = [x for x in best_parking_spots if x is not None ]
207+
208+ # Now select the closest parking goal, return if none is found
209+ if len (parking_goals ) > 1 :
210+ self .parking_goal = closest_point_to_origin (parking_goals )
211+ self .best_parking_spot = closest_point_to_origin (best_parking_spot )
212+ elif len (parking_goals ) == 1 :
213+ self .parking_goal = parking_goals [0 ]
214+ self .best_parking_spot = best_parking_spots [0 ]
215+ else :
216+ self .parking_goal = None
217+ self .best_parking_spot = None
163218 return None
164219
165220 # Constructing parking obstacles
166221 current_time = self .vehicle_interface .time ()
167- obstacle_id = 0
222+ obstacle_id = PARKING_OBSTACLE_START_ID
168223 parking_obstacles = {}
169- for o_pose , o_dim in zip (parking_obstacles_pose , parking_obstacles_dim ):
224+ for o_pose , o_dim in zip (self . parking_obstacles_poses , self . parking_obstacles_dims ):
170225 x , y , z , yaw = o_pose
171226 obstacle_pose = ObjectPose (
172227 t = current_time ,
@@ -183,13 +238,13 @@ def update(self, cone_obstacles: Dict[str, Obstacle]):
183238 dimensions = o_dim ,
184239 outline = None ,
185240 material = ObstacleMaterialEnum .BARRIER ,
186- collidable = True , state = ObstacleStateEnum . STANDING
241+ collidable = True
187242 )
188- parking_obstacles [f"parking_obstacle_ { obstacle_id } " ] = new_obstacle
243+ parking_obstacles [obstacle_id ] = new_obstacle
189244 obstacle_id += 1
190245
191246 # Constructing goal pose
192- x , y , yaw = goal_parking_spot
247+ x , y , yaw = self . parking_goal
193248 goal_pose = ObjectPose (
194249 t = current_time ,
195250 x = x ,
0 commit comments