Skip to content

Commit 6fb2fc9

Browse files
author
Aadarsh
committed
working
1 parent 3a1919a commit 6fb2fc9

11 files changed

Lines changed: 226 additions & 62 deletions

File tree

GEMstack/knowledge/defaults/computation_graph.yaml

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ components:
2222
inputs: [vehicle, roadgraph]
2323
outputs: vehicle_lane
2424
- parking_detection:
25-
inputs: agents
25+
inputs: obstacles
2626
outputs: [goal, obstacles]
2727
- sign_detection:
2828
inputs: [vehicle, roadgraph]
@@ -49,13 +49,10 @@ components:
4949
- driving_logic:
5050
inputs:
5151
outputs: intent
52-
- parking_component: # one way
52+
- _mission_planner: # one way
5353
inputs: all
5454
outputs: mission_plan
55-
- summon_component: # one way
56-
inputs: all
57-
outputs: route
58-
- route_planning_component: # one way
55+
- _route_planner: # one way
5956
inputs: all
6057
outputs: route
6158
- motion_planning:
@@ -66,4 +63,4 @@ components:
6663
outputs:
6764
- signaling:
6865
inputs: [intent]
69-
outputs:
66+
outputs:

GEMstack/onboard/perception/cone_detection.py

Lines changed: 66 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from ...state import AllState, VehicleState, ObjectPose, ObjectFrameEnum, AgentState, AgentEnum, AgentActivityEnum
1+
from ...state import AllState, VehicleState, ObjectPose, ObjectFrameEnum, AgentState, AgentEnum, AgentActivityEnum, ObstacleState, Obstacle, ObstacleStateEnum, ObstacleMaterialEnum
22
from ..interface.gem import GEMInterface
33
from ..component import Component
44
from ultralytics import YOLO
@@ -707,9 +707,12 @@ def update(self, vehicle: VehicleState) -> Dict[str, AgentState]:
707707

708708
class FakConeDetector(Component):
709709
def __init__(self, vehicle_interface: GEMInterface):
710+
"""
711+
Initializes the FakeConeDetector with two parking spots:
712+
- One standard 2x2 rectangular spot
713+
- One wider mouth for easier entry
714+
"""
710715
self.vehicle_interface = vehicle_interface
711-
self.times = [(5.0, 20.0), (30.0, 35.0)]
712-
self.t_start = None
713716

714717
def rate(self):
715718
return 4.0
@@ -718,27 +721,71 @@ def state_inputs(self):
718721
return ['vehicle']
719722

720723
def state_outputs(self):
721-
return ['agents']
724+
return ['obstacles']
722725

723-
def update(self, vehicle: VehicleState) -> Dict[str, AgentState]:
724-
if self.t_start is None:
725-
self.t_start = self.vehicle_interface.time()
726-
t = self.vehicle_interface.time() - self.t_start
726+
def update(self, vehicle: VehicleState) -> Dict[str, ObstacleState]:
727+
"""
728+
Called every simulation step, updates the timestamp and publishes the obstacle states.
729+
"""
730+
731+
current_time = self.vehicle_interface.time()
732+
733+
# === Standard Parking Spot ===
734+
# cones_standard = {
735+
# 'cone0': (5.0, 5.0, 0.5, 0.5), # Front Left
736+
# 'cone1': (5.0, 7.0, 0.5, 0.5), # Back Left
737+
# 'cone2': (7.0, 5.0, 0.5, 0.5), # Front Right
738+
# 'cone3': (7.0, 7.0, 0.5, 0.5) # Back Right
739+
# }
740+
741+
# === Wider Mouth Parking Spot ===
742+
cones_wide = {
743+
'cone4': (6.0, 9.0, 0.5, 0.5), # Front Left (wide)
744+
'cone5': (10.0, 9.0, 0.5, 0.5), # Back Left
745+
'cone6': (3.0, 4.0, 0.5, 0.5), # Front Right (wide)
746+
'cone7': (7.0, 4.0, 0.5, 0.5) # Back Right
747+
}
748+
749+
# Populate the obstacle states
727750
res = {}
728-
for time_range in self.times:
729-
if t >= time_range[0] and t <= time_range[1]:
730-
res['cone0'] = box_to_fake_agent((0, 0, 0, 0))
731-
rospy.loginfo("Detected a Cone (simulated)")
732-
return res
751+
for name, box in {**cones_wide}.items():
752+
res[name] = box_to_fake_obstacle(box, current_time)
753+
754+
# Update timestamp
755+
for obstacle in res.values():
756+
obstacle.pose.t = current_time
733757

758+
rospy.loginfo(f"[FakeConeDetector] Simulated Two Parking Spots Detected")
759+
return res
734760

735-
def box_to_fake_agent(box):
761+
def box_to_fake_obstacle(box, current_time):
762+
"""
763+
Helper function to create a fake obstacle (cone) from bounding box coordinates.
764+
"""
736765
x, y, w, h = box
737-
pose = ObjectPose(t=0, x=x + w / 2, y=y + h / 2, z=0, yaw=0, pitch=0, roll=0, frame=ObjectFrameEnum.CURRENT)
738-
dims = (w, h, 0)
739-
return AgentState(pose=pose, dimensions=dims, outline=None,
740-
type=AgentEnum.CONE, activity=AgentActivityEnum.MOVING,
741-
velocity=(0, 0, 0), yaw_rate=0)
766+
pose = ObjectPose(
767+
t=current_time,
768+
x=x,
769+
y=y,
770+
z=0.0,
771+
yaw=0.0,
772+
pitch=0.0,
773+
roll=0.0,
774+
frame=ObjectFrameEnum.START
775+
)
776+
777+
dims = (w, h, 1.0)
778+
779+
new_obstacle = Obstacle(
780+
pose=pose,
781+
dimensions=dims,
782+
outline=None,
783+
material=ObstacleMaterialEnum.TRAFFIC_CONE,
784+
collidable=True
785+
)
786+
print("Obstacles made")
787+
return new_obstacle
788+
742789

743790

744791
if __name__ == '__main__':
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
from ...state import VehicleState, ObjectPose, ObjectFrameEnum, ObstacleState, ObstacleMaterialEnum, ObstacleStateEnum
2+
from ..interface.gem import GEMInterface
3+
from ..component import Component
4+
from typing import Dict
5+
import yaml
6+
import rospy
7+
import time
8+
from ...utils import settings
9+
10+
11+
OBSTACLE_TYPE_TO_ENUM = {
12+
'cone': ObstacleMaterialEnum.TRAFFIC_CONE,
13+
}
14+
15+
OBSTACLE_DIMENSIONS = {
16+
'cone': (0.5, 0.5, 1.0),
17+
}
18+
19+
20+
class FakeObstacleDetector(Component):
21+
def __init__(self, vehicle_interface: GEMInterface):
22+
"""
23+
Args:
24+
vehicle_interface: GEMInterface instance
25+
"""
26+
self.vehicle_interface = vehicle_interface
27+
28+
# Load path from the settings, with a default if not present
29+
self.scene_path = settings.get("run.drive.perception.obstacle_detection.largs.scene_path", None)
30+
31+
if not self.scene_path:
32+
raise ValueError("Scene path not specified in the YAML configuration under `largs.scene_path`")
33+
34+
self.t_start = None
35+
self.obstacles = self.load_obstacles(self.scene_path)
36+
37+
def load_obstacles(self, scene_path: str) -> Dict[str, ObstacleState]:
38+
"""
39+
Loads obstacles from a YAML scene file and initializes them as ObstacleState objects.
40+
"""
41+
print(f"[FakeObstacleDetector] Loading obstacles from: {scene_path}")
42+
43+
with open(scene_path, 'r') as file:
44+
data = yaml.safe_load(file)
45+
46+
obstacles = {}
47+
for name, attributes in data['obstacles'].items():
48+
pose = ObjectPose(
49+
frame=ObjectFrameEnum.ABSOLUTE_CARTESIAN,
50+
t=0.0, # Time is dynamically assigned during simulation
51+
x=attributes['position'][0],
52+
y=attributes['position'][1],
53+
yaw=attributes.get('yaw', 0)
54+
)
55+
56+
# Add velocity if it exists, else default to (0, 0, 0)
57+
58+
obstacle_state = ObstacleState(
59+
type=OBSTACLE_TYPE_TO_ENUM[attributes['type']],
60+
activity=ObstacleStateEnum.STANDING,
61+
pose=pose,
62+
dimensions=OBSTACLE_DIMENSIONS[attributes['type']],
63+
outline=None
64+
)
65+
66+
# Add the velocity attribute directly
67+
68+
obstacles[name] = obstacle_state
69+
70+
return obstacles
71+
72+
def rate(self):
73+
return 4.0
74+
75+
def state_inputs(self):
76+
return ['vehicle']
77+
78+
def state_outputs(self):
79+
return ['obstacles']
80+
81+
def update(self, vehicle: VehicleState) -> Dict[str, ObstacleState]:
82+
"""
83+
Called every simulation step, updates the timestamp and publishes the obstacle states.
84+
"""
85+
if self.t_start is None:
86+
self.t_start = self.vehicle_interface.time()
87+
88+
t = self.vehicle_interface.time() - self.t_start
89+
90+
# Update all obstacle poses with the current simulation time
91+
res = {}
92+
for name, obstacle in self.obstacles.items():
93+
obstacle.pose.t = t
94+
res[name] = obstacle
95+
rospy.loginfo(f"[FakeObstacleDetector] Simulated Obstacle Detected: {name} at {obstacle.pose.x}, {obstacle.pose.y}")
96+
97+
return res

GEMstack/onboard/perception/parking_detection.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from sensor_msgs.msg import PointCloud2
44
from typing import Dict
55
from ..component import Component
6-
from ...state import AgentState, ObjectPose, ObjectFrameEnum, Obstacle, ObstacleMaterialEnum, VehicleState, AllState
6+
from ...state import AgentState, ObjectPose, ObjectFrameEnum, Obstacle, ObstacleMaterialEnum, VehicleState, AllState, ObstacleState
77
from ..interface.gem import GEMInterface
88
from .utils.detection_utils import *
99
from .utils.parking_utils import *
@@ -60,7 +60,7 @@ def rate(self) -> float:
6060
return 10.0 # Hz
6161

6262
def state_inputs(self) -> list:
63-
return ['agents']
63+
return ['obstacles']
6464

6565
def state_outputs(self) -> list:
6666
return ['goal', 'obstacles']
@@ -121,7 +121,7 @@ def visualize(self,
121121
self.pub_cones_centers_pc2.publish(ros_cones_centers_pc2)
122122

123123

124-
def update(self, agents: Dict[str, AgentState]):
124+
def update(self, agents: Dict[str, ObstacleState]):
125125
# Initial variables
126126
goal_parking_spot = None
127127
parking_obstacles_pose = []
@@ -154,6 +154,7 @@ def update(self, agents: Dict[str, AgentState]):
154154
parking_obstacles = {}
155155
for o_pose, o_dim in zip(parking_obstacles_pose, parking_obstacles_dim):
156156
x, y, z, yaw = o_pose
157+
print("CONSTRUCTING OBSTACLE POSE")
157158
obstacle_pose = ObjectPose(
158159
t=current_time,
159160
x=x,

GEMstack/onboard/planning/route_planning_component.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ def update(self, state: AllState):
100100
print("I am in SCANNING mode")
101101
desired_points = [(state.vehicle.pose.x, state.vehicle.pose.y),
102102
(state.vehicle.pose.x + 1, state.vehicle.pose.y)]
103-
desired_path = Path(ObjectFrameEnum.CURRENT, desired_points)
103+
desired_path = Path(ObjectFrameEnum.START, desired_points)
104104

105105
# @TODO these are constants we need to get from settings
106106
desired_path = desired_path.to_frame(state.vehicle.pose.frame, current_pose=state.vehicle.pose, start_pose_abs=state.start_vehicle_pose)

GEMstack/state/__init__.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
'Sign',
1313
'AgentState','AgentEnum','AgentActivityEnum',
1414
'SceneState',
15+
'ObstacleState','ObstacleMaterialEnum','ObstacleStateEnum',
1516
'VehicleIntent','VehicleIntentEnum',
1617
'AgentIntent',
1718
'EntityRelationEnum','EntityRelation','EntityRelationGraph',
@@ -24,6 +25,7 @@
2425
from .trajectory import Path,Trajectory
2526
from .vehicle import VehicleState,VehicleGearEnum
2627
from .roadgraph import Roadgraph, RoadgraphLane, RoadgraphCurve, RoadgraphRegion, RoadgraphCurveEnum, RoadgraphLaneEnum, RoadgraphRegionEnum, RoadgraphSurfaceEnum, RoadgraphConnectionEnum
28+
from .obstacle import Obstacle, ObstacleMaterialEnum, ObstacleState, ObstacleStateEnum
2729
from .obstacle import Obstacle, ObstacleMaterialEnum
2830
from .sign import Sign, SignEnum, SignalLightEnum, SignState
2931
from .roadmap import Roadmap
@@ -34,6 +36,6 @@
3436
from .relations import EntityRelation, EntityRelationEnum, EntityRelationGraph
3537
from .mission import MissionEnum,MissionObjective
3638
from .route import Route, PlannerEnum
37-
from .mission_plan import MissionPlan
39+
from .mission import MissionPlan
3840
from .predicates import PredicateValues
39-
from .all import AllState
41+
from .all import AllState

GEMstack/state/all.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from .agent_intent import AgentIntent,AgentIntentMixture
88
from .relations import EntityRelation
99
from .mission import MissionObjective
10-
from .mission_plan import MissionPlan
10+
from .mission import MissionPlan
1111
from .route import Route
1212
from .trajectory import Trajectory
1313
from .predicates import PredicateValues

GEMstack/state/mission.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
from dataclasses import dataclass
22
from ..utils.serialization import register
33
from enum import Enum
4+
from .route import PlannerEnum
5+
46

57
class MissionEnum(Enum):
68
IDLE = 0 # not driving, no mission
@@ -14,4 +16,15 @@ class MissionEnum(Enum):
1416
@register
1517
class MissionObjective:
1618
type : MissionEnum = MissionEnum.IDLE
19+
20+
@dataclass
21+
@register
22+
class MissionPlan:
23+
goal_x: float
24+
goal_y: float
25+
goal_orientation: float
26+
planner_type : PlannerEnum = PlannerEnum.RRT_STAR
27+
# other mission-specific parameters can be added here
28+
29+
1730

GEMstack/state/mission_plan.py

Lines changed: 0 additions & 15 deletions
This file was deleted.

0 commit comments

Comments
 (0)