- Team Members
- Project Overview
- Goals
- Robot Hardware
- Mechanical Design
- Accomplishments
- Lessons Learned
- Next Steps
- Gantt Chart
- Videos and Resources
- Project Reconstruction
| Name | Major | Year |
|---|---|---|
| Ahnaf H. | Mechanical Engineering | 2027 |
| Daniel G. | Computer Engineering | 2026 |
| Tracy T. | Mechanical Engineering | 2027 |
| Vincent S. | Computer Engineering | 2029 |
Thermal Patrol is an autonomous indoor security robot built ontop of UCSD's robocar platoform. The robot patrols a hallway using LiDAR based closed loop PID control, detects people using a thermal camera and triggers an alarm in response.
- Connect an ESP-32 based thermal camera with a Raspberri Pi using ROS2
- Detect people using the thermal camera, stop, and sound the alarm
- Autonomously patrol hallways and avoid obsticles using a LiDAR
- ESP-32 thermal camera integrated with ROS2 via a MQTT bridge
- LiDAR based hallway patroling
- Obsticle detection and avoidance
- Heat signature detection using a ML model running on the ESP-32
- Got SLAM to map a hallway although inconsistently
- full SLAM based mapping and autonomous navigation with waypoints
- Web application to notify the user of an intruder
- YOLO model integration to verify if a heat signature is infact a person
| Component | Description |
|---|---|
| LD19 LiDAR | Used for autonomous navigation including obsticle avoidance and SLAM mapping |
| Thermal Camera | Low resolution thermal sensor used for detecting human heat signatures |
| ESP-32 | Reads thermal camera data, runs a custom ML model and publishes the results over MQTT |
| Raspberry Pi | Our main computer running ROS2 Jazzy |
Our mechanical design consists of a few main components:
- Base plate made out of acrilic with slots to allow for easy mounting
- A multipurpose mount holding the LiDAR at the top and also housing the ESP-32 and thermal camera along with an adjustable mount for an OAK-D Lite camera
- At the back is our GPS mount also holding our on and off switch and containing mounting holes for our DC to DC converter
- Last at the back the speaker is mounted to the GPS mount using a custom case that twists onto the speaker
- An ESP-32 reads ther thermal camera's measurments and runs an on device ML model to detect heat signatures
- The ESP-32 publishes detections over MQTT through WiFi, allows for the reuse and scaling of the thermal detection module
- A ROS2 bridge node subscribes to the ESP-32's MQTT topic and converts that signal into standard ROS2 topics
- Our LD19 LiDAR measures the distance from the left and right wall
- The controller averages the two measurments to determine the center of the hallway
- Using closed loop PID control the car continously aims for the center of the hallway
- LiDAR detects objects infront of the robot
- The system checks left and right to check for obsticles and turns in the aproriate direction
- The robot waits until the path infront of it is clear again before turning back and returning to its original path
- Got SLAM mapping to work but had trouble with odometry drift and issues pattern matching in a symetrical hallway
| System | Challenge | Solution |
|---|---|---|
| GPS | Unreliable signal and inaccurate readings due to a lack of corrections | Determined it was a hardware issue and pivoted to an indoor LiDAR based solution |
| Odometry | Significant drift in odometry readings made it unreliable and impacted SLAM mapping | Relied more heavily on LiDAR and implemented closed loop control based on LiDAR measurements |
| SLAM | Generated noisy and inconsistent maps; unable to consistently map a symmetrical hallway | Tried filtering out bad poses; next step would be RTAB-Map with an OAK-D camera for visual anchors |
- Start early and test frequently: hardware and software issues come up frequently even the smallest things break
- Expect things to break: leave time for debugging and unexpected faliures
- Research before committing to a solution: the SLAM toolbox was a reaonable initial choice but RTAB mapping would have better fitted for mapping symmetric hallways from the start.
- Pivot decisively: when we were unable to get our GPS working after about a week pivoting to an indoor solution was the right call inorder to get things up and running.
If we had one more week we would have implemented...
- RTAB Mapping:
- Combine our existing LiDAR with an OAK-D camera to improve mapping in symmetrical hallways using visual landmarks
- Corrects for drift and current SLAM failure modes
- Web Application:
- Send notifications to users to create a more active autonomous ‘security guard’
- Allow them to use the web app to control the robot, draw maps, start patrol ect
- Higher Resolution Thermal Camera:
- Our current thermal camera has very low resolution allowing for misidentification of objects or animals as people
- YOLO Model Verification:
- Add a camera and light to run a YOLO model to detect to verify that an object is infact a person and send a notification to the user
![]() |
![]() |
| Origional Gantt Chart | New Gantt Chart |
Challenges & Changes :
- Around Week 8 or so we decided that it was necessary to expand the scope of our project from using GPS to LiDAR for indoor navigation.
- We spent a lot more time debugging and had far more hardware issues than we thought for example debugging the ROS2 laps.
- SLAM localization proved much harder to implement that we expected and forced us to focus on more alternative options.
Detecting a Heat Signature (Note: this video was fillmed before obsticle avoidance was fully implemented hence why it stops for the cone instead of going around it)
Here are a few steps on how to recreate our project:
- Raspberry Pi (running UCSD Robocar Framework)
- ESP32-S3
- Qwiic GRID-Eye Infrared Array (AMG88xx)
- LD-19 LiDAR sensor
Follow the full guide UCSD RoboCar Setup Guide
Step 1: SSH into your Raspberry Pi
ssh -Y pi@ucsdrobocar-148-XX.localUse
-YX11 forwarding as it is required for GUI tools to display on your laptop.
Step 2: Install Docker and pull the Robocar image
Follow Sections 01–02 of the framework guide. Once Docker is installed:
docker pull ghcr.io/ucsd-ecemae-148/ucsd_robocar:stableStep 3: Add the Docker run function to your Pi's ~/.bashrc
Step 3: Add the Docker run function to your Pi's ~/.bashrc
robocar_docker() {
docker run \
--name MY_CONTAINER_NAME \
-it \
--privileged \
--net=host \
-e DISPLAY=$DISPLAY \
-e ROS_DOMAIN_ID=YOUR_TEAM_NUMBER \
--volume /dev/bus/usb:/dev/bus/usb \
--device-cgroup-rule='c 189:* rmw' \
--device /dev/video0 \
--volume="$HOME/.Xauthority:/root/.Xauthority:rw" \
--volume /etc/passwd:/etc/passwd:ro \
--volume /etc/group:/etc/group:ro \
ghcr.io/ucsd-ecemae-148/ucsd_robocar:stable
}Then reload and launch:
source ~/.bashrc
robocar_docker MY_CONTAINER_NAMEStep 4: For all future sessions use these steps to start and enter the container
docker start MY_CONTAINER_NAME
docker exec -it MY_CONTAINER_NAME bash
source_ros2Then finish the steps in the instructions linked above.
For more details on setting up the UCSD robocar framework please refer to this link
Step 6: Set device permissions Specific to our project, you must set the following device permissiions:
sudo chmod 777 /dev/ttyACM0
sudo chmod 777 /dev/ttyUSB0
sudo chmod 777 /dev/ttyUSB1
sudo chmod 777 /dev/input/js0Before running the patrol system verify that the LiDAR is running and publishing correctly.
Step 1: Confirm the LiDAR is detected
dmesg | grep usbThe LD19P should appear as a USB device.
Step 2: Configure node_config.yaml
nano /home/projects/ros2_ws/src/ucsd_robocar_hub2/ucsd_robocar_nav2_pkg/config/node_config.yamlSet the following:
sub_lidar_launch: 1 # Enable LiDAR
camera_nav: 0 # Disable lane following
sensor_visualization: 1 # Enable for verificationStep 3: Build and launch
build_ros2
ros2 launch ucsd_robocar_nav2_pkg all_nodes.launch.pyStep 4: In a new terminal, verify scan data is publishing
docker exec -it MY_CONTAINER_NAME bash
source_ros2
ros2 topic echo /scanYou should see a continuous stream of range measurements. If nothing appears:
- Confirm
sub_lidar_launch: 1innode_config.yaml - Re-run
sudo chmod 777 /dev/ttyACM0and retry If it still does not work you may have a hardware issue, one quick check you can do is to verify that you LiDAR is spinning by looking at the rotating blue lights on the top of the LD19 LiDAR.
Once you recive updates from your LiDAR move on to part 3.
Step 1: Clone this repository
cd /home/projects/ros2_ws/src
git clone https://github.com/UCSD-ECEMAE-148/spring-2026-final-project-team-6.gitStep 2: Build the workspace
build_ros2Step 3: Launch the full patrol system
ros2 launch ucsd_robocar_nav2_pkg all_nodes.launch.pyThe robot will begin patrolling using PID control and should aim for the center of a hallway and also avoid obsticles autonomously.
The ESP32 runs an on-device ML model using the thermal sensor to detect heat signatures and communicates with the patrol system over MQTT.
Hardware Required:
- ESP32-S3
- Qwiic GRID-Eye Infrared Array (AMG88xx)
Software Required:
- VS Code with the PlatformIO extension
Step 1: Open the ESP32 code
Clone this repository on your local machine and open the esp32/ folder in VS Code using the PlatformIO extension.
git clone https://github.com/UCSD-ECEMAE-148/spring-2026-final-project-team-6.gitStep 2: Configure your environment
Create a .env file in the esp32/ folder:
nano esp32/.envThen paste in the following and fill in the blanks
UCSD_USERNAME=
UCSD_PASSWORD=
# UCSDProtected switched to 5GHz and no longer works — use a non-enterprise network instead
WIFI_SSID=
NON_ENTERPRISE_WIFI_PASSWORD=
# Note: if your password contains a #, enclose it in single or double quotes
MQTT_BROKER=broker.emqx.io
MQTT_CLIENT_ID=camera
MQTT_TOPIC=robocar
Step 3: Flash the ESP32
Connect your ESP32-S3 and flash using PlatformIO's upload button in VS Code. For more details see the PlatformIO ESP32 Upload Documentation.
| Problem | Fix |
|---|---|
| Device permissions denied | Re-run sudo chmod 777 on all /dev/tty* and /dev/input/js0 after every reboot |
| LiDAR scan not appearing | Check sub_lidar_launch: 1 in node_config.yaml and re-run permissions, verify the LiDAR is spinning |
| YAML changes have no effect | Always run build_ros2 after any config change — source_ros2 alone is not enough |
| Receiving another team's data | Verify ROS_DOMAIN_ID matches your team number with echo $ROS_DOMAIN_ID inside Docker |
| ESP32 not communicating | Ensure ESP32 and Raspberry Pi are on the same WiFi network |
| GUI windows not appearing | Reconnect SSH with -Y flag: ssh -Y pi@ucsdrobocar-148-XX.local |







