Skip to content

Commit 3893db2

Browse files
Merge branch 's2025_Simulation' into gazebo_agent_detection
2 parents cf75169 + 86637c4 commit 3893db2

11 files changed

Lines changed: 82 additions & 582 deletions

File tree

Lines changed: 3 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,7 @@
11
from ...utils.config import load_config_recursive
2-
import os,sys
3-
4-
5-
# Identify the vehicle used and load settings else default to vehicle config at current.yaml'
6-
# default currently uses GEM e4
7-
vehicle = "default"
8-
9-
for arg in sys.argv:
10-
if arg.startswith('--'):
11-
k,v = arg.split('=',1)
12-
k = k[2:]
13-
v = v.strip('"')
14-
if k == "vehicle":
15-
vehicle = v
16-
sys.argv.remove(arg)
17-
break
18-
19-
if(vehicle == 'e2'):
20-
vehicle_config = 'e2.yaml'
21-
elif(vehicle == 'e4'):
22-
vehicle_config = 'current.yaml'
23-
elif(vehicle == 'e2_gazebo'):
24-
vehicle_config = 'e2_gazebo.yaml'
25-
elif(vehicle == 'e4_gazebo'):
26-
vehicle_config = 'e4_gazebo.yaml'
27-
else:
28-
print("Unknown vehicle argument passed")
29-
vehicle = "default"
30-
vehicle_config = 'current.yaml'
31-
32-
SETTINGS_FILE = os.path.join(os.path.split(__file__)[0],vehicle_config)
2+
import os
3+
SETTINGS_FILE = os.path.join(os.path.split(__file__)[0],'current.yaml')
334
print("**************************************************************")
34-
print(f"Loading {vehicle} settings from",SETTINGS_FILE)
5+
print("Loading default settings from",SETTINGS_FILE)
356
print("**************************************************************")
367
SETTINGS = load_config_recursive(SETTINGS_FILE)
-6.25 MB
Binary file not shown.

GEMstack/mathutils/transforms.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,11 +72,11 @@ def point_segment_distance(x,a,b) -> Tuple[float,float]:
7272
udotv = np.dot(u,v)
7373
if udotv < 0:
7474
return vector_norm(u),0
75-
elif udotv > vnorm:
75+
elif udotv > vnorm**2:
7676
return vector_norm(vector_sub(x,b)),1
7777
else:
78-
param = udotv/vnorm
79-
return vector_norm(vector_sub(u,vector_mul(v,param/vnorm))),param
78+
param = udotv/vnorm**2
79+
return vector_norm(vector_sub(u,vector_mul(v,param))),param
8080

8181
def rotate2d(point, angle : float, origin=None):
8282
"""Rotates a point about the origin by an angle"""

GEMstack/onboard/perception/object_detection.py renamed to GEMstack/onboard/perception/test_yolo_gazebo_simulation.py

Lines changed: 34 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,16 @@
1+
"""
2+
Demo script to run YOLO object detection on a Gazebo simulation.
3+
4+
This code subscribes to the front camera feed from the GEM e2/e4 model and applies YOLO-based object detection to the incoming images.
5+
6+
Visualization:
7+
- Use RViz or rqt to monitor the topics.
8+
9+
ROS Topics:
10+
- Raw camera feed: /gem/debug
11+
- YOLO detection output: /gem/image_detection
12+
"""
13+
114

215
# Python
316
import os
@@ -26,41 +39,45 @@
2639

2740

2841
class ObjectDetection(Component):
29-
# TODO: Pull params into a JSON/yaml
30-
# TODO: Convert some lists into np.arrays, vectorize calculations
31-
# TODO: Implement logging instead of print, cleanup comments
32-
# TODO: Cleanup funcs + split into separate classes
33-
# TODO: Decide if we want to name dets "peds" or "objs"/"agents"
34-
# Maybe peds for now and Agents in agent_detection.py?
35-
def __init__(self, vehicle_interface : GEMInterface) -> None:
3642

43+
def __init__(self, vehicle_interface : GEMInterface) -> None:
44+
"""
45+
Initializes essential functions required to run the YOLO model.
46+
"""
3747

3848
# vehicle interface
3949
self.vehicle_interface = vehicle_interface
40-
41-
4250
# cv2 to ros converter
4351
self.bridge = CvBridge()
4452

45-
4653
# yolo model
4754
self.detector = YOLO(os.getcwd()+'/GEMstack/knowledge/detection/yolov8n.pt')
4855
self.confidence = 0.1
4956
self.classes_to_detect = 0
5057

5158

5259
def initialize(self):
60+
"""
61+
Defines callback functions for subscribing to the front camera image stream and sets up publishers for debugging purposes.
62+
"""
63+
5364
super().initialize()
5465
self.vehicle_interface.subscribe_sensor('front_camera',self.front_camera_callback, type = cv2.Mat)
55-
# self.pub_pedestrians_pc2 = rospy.Publisher("/point_cloud/pedestrians", PointCloud2, queue_size=10)
56-
# self.pub_obj_centers_pc2 = rospy.Publisher("/point_cloud/obj_centers", PointCloud2, queue_size=10)
57-
# self.pub_bboxes_markers = rospy.Publisher("/markers/bboxes", MarkerArray, queue_size=10)
5866
self.pub_image = rospy.Publisher("/gem/debug", Image, queue_size=1)
5967
self.pub_detimage = rospy.Publisher("/gem/image_detection", Image, queue_size=1)
6068

6169

6270
def update(self, vehicle : VehicleState) -> Dict[str,AgentState]:
6371

72+
"""
73+
Displays vehicle statistics in the GLOBAL reference frame.
74+
75+
This function also allows switching between coordinate frames using the `VehicleState -> pose` method.
76+
77+
Returning an `AgentState` will automatically log detected objects.
78+
"""
79+
80+
6481
print(f"VEHICLE State at time: {vehicle.pose.t}")
6582

6683
print(f"x: {vehicle.pose.x}")
@@ -79,6 +96,10 @@ def update(self, vehicle : VehicleState) -> Dict[str,AgentState]:
7996

8097
def front_camera_callback(self, image: cv2.Mat):
8198

99+
"""
100+
A simple callback function that processes incoming images, runs them through a YOLO model, and visualizes the detections.
101+
"""
102+
82103

83104
ros_img = self.bridge.cv2_to_imgmsg(image, 'bgr8')
84105
self.pub_image.publish(ros_img)
@@ -132,10 +153,6 @@ def front_camera_callback(self, image: cv2.Mat):
132153

133154
ros_img = self.bridge.cv2_to_imgmsg(image, 'bgr8')
134155
self.pub_detimage.publish(ros_img)
135-
136-
137-
138-
139156

140157

141158
def rate(self):

GEMstack/utils/settings.py

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,33 @@
11
import json
2-
from ..knowledge import defaults
32
import copy
43
from typing import List,Union,Any
54

65
SETTINGS = None
76

8-
def load_settings():
7+
def load_settings(settings_file : str = None):
98
"""Loads the settings object for the first time.
109
11-
Order of operations is to look into defaults.SETTINGS, and then
12-
look through the command line arguments to determine whether the user has
13-
overridden any settings using --KEY=VALUE.
10+
Order of operations is:
11+
- If settings_file is given, load it.
12+
- Otherwise, get the settings from defaults.SETTINGS
13+
- Look through the command line arguments to determine whether the user has
14+
overridden any settings using --KEY=VALUE.
1415
"""
1516
global SETTINGS
1617
if SETTINGS is not None:
1718
return
1819
import os
1920
import sys
20-
SETTINGS = copy.deepcopy(defaults.SETTINGS)
21+
if settings_file is not None:
22+
from .config import load_config_recursive
23+
import os
24+
print("**************************************************************")
25+
print("Loading global settings from",settings_file)
26+
print("**************************************************************")
27+
SETTINGS = load_config_recursive(os.path.abspath(settings_file))
28+
else:
29+
from ..knowledge import defaults
30+
SETTINGS = copy.deepcopy(defaults.SETTINGS)
2131
for arg in sys.argv:
2232
if arg.startswith('--'):
2333
k,v = arg.split('=',1)

docs/Gazebo Simulation Documentation.md

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,15 +68,16 @@ In one terminal, run the Gazebo simulator (using the instructions provided in th
6868
Open a second terminal and launch GEMStack with your configured launch file.
6969

7070
```bash
71-
python3 main.py --variant=gazebo --vehicle=e4_gazebo launch/{your_file}.yaml
71+
python3 main.py --variant=gazebo --settings={your_file}.yaml launch/{your_file}.yaml
72+
7273
```
7374
- Make sure to set the variant to `gazebo`.
74-
- You can specify the vehicle type to be `e2_gazebo` or `e4_gazebo`.
75+
- You can specify the settings file to GEMstack/knowledge/defaults/e4_gazebo.yaml or e2_gazebo.yaml till we work on closing the sim to real gap.
7576

7677
Example command launching the fixed route with e4 vehicle:
7778

7879
```bash
79-
python3 main.py --variant=gazebo --vehicle=e4_gazebo launch/fixed_route.yaml
80+
python3 main.py --variant=gazebo --settings=GEMstack/knowledge/defaults/e4_gazebo.yaml launch/fixed_route.yaml
8081
```
8182
**Variants:**
8283
- sim
@@ -87,6 +88,18 @@ python3 main.py --variant=gazebo --vehicle=e4_gazebo launch/fixed_route.yaml
8788
- e4
8889
- e2_gazebo
8990
- e4_gazebo
91+
92+
**Setting:**
93+
94+
By default it takes GEMstack/knowledge/defaults/current.yaml which is GEM E4 Vehicle configuration settings.
95+
96+
Other available configuration files:
97+
98+
GEMstack/knowledge/defaults/
99+
- e2.yaml
100+
- e2_gazebo.yaml
101+
- e4_gazebo.yaml
102+
90103
---
91104

92105
## Agent Detection in Gazebo

docs/Safety and Comfort Metrics Documentation.md

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

launch/gazebo_simulation.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ variants:
7272
drive:
7373
perception:
7474
state_estimation : GNSSStateEstimator
75-
agent_detection : object_detection.ObjectDetection
75+
agent_detection : test_yolo_gazebo_simulation.ObjectDetection
7676
perception_normalization : StandardPerceptionNormalizer
7777

7878
planning:

launch/perception.yaml

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

0 commit comments

Comments
 (0)