Joshua’s Status Report 04/04/2026

Mechanical:

My method of developing the housing is iterative, where I make pieces, make sure they work, then move on to the next piece that uses the previous. I have gone through three different prints now (only the third having the “motor cap” once I was confident that the motor shape was form fitting), making adjustments as needed. I have gotten a housing that successfully houses the battery, snap fits together, all of the sensors and PCB boards have mounts. The only thing left is the gear box and wheels!

Here is the third print:

Here is a view of the current Full CAD assembly view:

Electrical:

We will be using the following empty PCB boards to hold our electrical components:

(Note that annotations of wirings are not yet completed, but they will be soon using our past diagram:)

We need to have a short meeting together still to discuss adjusting pins to make housing wiring easier, but since the housing specifics are mostly done by the end if this post, it should be done by Wednesday.

Next Steps:

I want to have a full bot up and running this wednesday!

Brooks’s Status Report 04/04/2026

This week, I made sure UWB locationing was working correctly and worked on setting up the anchor boards to automatically boot up as anchors. I also finished connecting UWB coordinate calculations to ROS, so now we have a complete range, trilaterate, publish flow that Adrian was able to connect to the UI. Lastly, I moved our project to using PlatformIO with Arduino as the framework. This gives us a number of QOL improvements, e.g. we can now use the rich libraries provided by Arduino and have PlatformIO handle dependencies for us. Unfortunately, there was a lot of work time that ended up getting eaten up resolving some strange UART behavior that was occurring when trying to send and receive CLI messages. This means I was unable to complete the survivor tag locationing.

Since I am now behind on survivor tag locationing, my plan is to spend the rest of tonight and tomorrow writing the pseudocode and initial implementation. I say “initial” implementation because this step, as well as implementing “on-the-fly” anchor calibration somewhat requires that we have a physical bot built. I intend on writing an implementation that essentially has the controller tell the UWB board to attempt ranging with a tag, and then separate those ranging requests and responses from the others with the anchors, however I anticipate needing to modify this code once we can test with a moving bot looking for the tag. Once I finish this, I will see if I can help Josh finish building the first bot and work on implementing Kalman filtering to fuse our IMU and UWB data to improve locationing accuracy. Essentially, I will keep working on survivor tag locationing, kalman filtering, and on the fly anchor calibration next week, but the first and last task won’t be able to be considered “finished” until we are able to verify with a real bot, although I will do as much as possible until then.

Adrian’s Status Report 04/04/2026

This week, I was able to complete the IMU and UWB integrations with the UI by publishing the corresponding ROS topics (/catombot/imu/heading_rad and /catombot/position) to the UI’s live ROS bridge with the micro-ROS agent docker container running. This closes the loop from multi-anchor ranging to something an operator can interpret in real time, which was the main integration milestone.

The remaining issue is the quality of the pose, not whether it appears on the screen. Raw UWB fixes are noisy as the bot’s positions appear jittery on the UI, so the next steps would be to have sensor fusion properly implemented. For UWB + IMU fusion, the IMU will be used for acceleration, which is integrated into position while letting UWB correct drift and anchor the global position. This can be done with a Kalman filter that can sooth UWB updates and uses IMU between fixes so the displayed pose and mapping see less high-frequency noise. 

UI displays the x, y, z coordinates of the bot/UWB’s location with respect to the 3 UWB anchors surrounding it.

The UI records and properly updates the bot’s position based on the latest coordinate recorded by the UWB. It does, however, vibrate despite the UWB being stationary. Hence, sensor fusion with Kalman filtering is needed.

Joshua’s Status Report 3/28/2026

Electrical Developments:

Before getting to the CADDing, I wanted to be sure how we were wiring this all up, and then therefore what wiring space I would need to take into account while making the housings.

IMU / I2C wirings:

H-Bridge specific Wirings:

All components wiring diagram updated to included capacitors:

Y-splitting the battery connector out so we can easily distribute to all other parts.

There’s more, and I believe we may have some videos for our team post, but basically I oversaw all the electrical work (so it was a group effort in soldering up all our parts, but I was delegating, as this is the part we’ve ascribed to me having ownership over), and it’s all looking great!! This last complicated one we only did for one battery, as it felt a bit sketchy, but all our motors and sensors have their wires and pins soldered up!

I know we spent a lot of time considering all components, and making sure that it would all work. However, I was pleasantly surprised that when we actually put it all together it just worked. Props to brooks for getting software working near first try!

Housing Developments:

Due to spending more time on the electrical work, the housings are unfortunately not finished yet. It is looking unlikely that a first print will be finished by Monday, but I want to still have a 3D model to show for the presentation (to also talk about improvements/extensions), then a print done Wednesday.

A few new things that also caused reworking:

1) our motors are 20 RPM, not 20 RPS. So a gear up is in order. Figured out how to make and port over gears, so now just need to figure out what ratio we actually want/need. (see double_helix gear below, using a plug-in for onshape I found:)

2) we need to order wheels / a ball caster. I thought we could 3D print them, for some reason, but for good grip we really should just order them. I found a good set that should work for all 4 bots, and submitted an order to them. It will take some fenagling to get it on nicely.

3) our electrical components are rather loose. I was thinking we would make use of the pins as a sort of holder for them, and then use female to female jumper cables, but this takes up a lot of space. Instead, we will be using a series of empty holed PCB boards with mounting holes. This makes it much easier to connect all our components together and hold them in a compact fashion.

current tentative placement of all electrical components (plus wheels) in onshape:

Team’s Status Report for 03/28/2026

Risks:

There are no major new risks at the moment. We are proactively mitigating the primary risks associated with full robot assembly by continuing our strategy of modular integration testing. For example, this week we successfully wired up both the IMU and the TF-Luna LiDAR to run simultaneously on the ESP32-S3 using the same shared I2C GPIO pins. This important step confirms that our data interconnects and initial module interactions are stable before committing to final assembly. Looking ahead, we still need to begin soldering components directly to the PCBs and attach the buck converters to the remaining battery connectors. Therefore, our main remaining risk is the potential for unforeseen hardware or power distribution issues arising during this final, permanent physical integration phase.

Design and Schedule Changes:

There have been no fundamental changes to our overall design path or timeline. However, we did introduce a highly effective architectural enhancement: utilizing a micro-ROS middleware layer encapsulated in Docker to better bridge the raw, hardware-level sensor data with the live UI. This architectural enhancement solved a difficult integration problem without altering our core design. We remain on schedule overall; while UWB trilateration is still being finalized, we have successfully gotten the motors, H-Bridge, IMU, and LiDAR operational.

Adrian’s Status Report for 03/28/2026

The primary focus this week was bridging the gap between hardware-level sensor data and the live UI by getting real-time data to at least show up there rather than just the terminal/Arduino output. This involved stabilizing the ESP32-S3 firmware for distance sensing and implementing a robust micro-ROS middleware layer using Docker to ensure the frontend can reliably consume live LiDAR feeds without direct serial dependencies.

The metric on the bottom left represents the distance between the LiDAR and iPad, where the occupied cell is marked at around 30 cm. ESP32-S3 firmware (PlatformIO) reads a TF-Luna over I2C and publishes distance on micro-ROS (/catombot/lidar/front/distance_cm). Then the UI repo documents a live LiDAR bridge: micro-ROS agent in Docker, optional npm run bridge:lidar with ROS topic echo → Server-Sent Events, or --source=serial using PlatformIO serial monitor parsing. The UI can be opened in live mode (?lidar=live and related env vars).

A small read_serial.py script also helps validate raw serial timing and baud settings on macOS/Linux.

Additionally, micro-ROS Docker container was especially valuable because it turned a difficult hardware-to-browser integration problem into a much more manageable interface problem. Instead of trying to make the frontend understand ROS-native or serial-native behavior directly, the container provided a stable middleware layer that could ingest the live sensor feed, preserve useful metadata, and expose it in a form the UI could actually consume reliably.

The next steps are to calibrate LiDAR so ranges and geometry match the real map scale and robot frame, and to fuse IMU data into pose and speed estimates so on-screen motion reflects how the CatomBot actually moves. Depending on progress with UWB range triangulation, I will also surface that data in the UI (e.g. anchors and fused position) and use it to tighten FREE vs OCCUPIED classification and stabilize frontier cluster centroids that guide exploration

Brooks’s Status Report for 03/28/2026

This week I worked on getting UWB trilateration working, and my goal is to have it finished tomorrow. I also helped get the motors / H-Bridge and the IMU working. I also helped with soldering a lot more pin headers to all of our components, so we now have almost all the physical components together, we just need to start soldering to the PCBs and to solder some of the buck converters to the other battery connectors. We also did some basic integration testing where we wired up both the IMU and TFLuna together and ran them both at the same time. Both are connected to the ESP32S3 on the same GPIO pins to communicate over I2C. Lastly, I finally was able to figure out how to get ROS working on my groupmates’ computers so that they can now run the micro-ROS agent on their systems.

LiDAR and IMU Readings
LiDAR and IMU Wired Together

We are on schedule, but tomorrow the group as a whole needs to spend a lot of time together to ensure we are ready for the interim demo and that our systems are in a good spot to show off.

Next week I hope to complete locationing for the survivor tag, which will involve having one non-anchor UWB board being tracked in 2D space, and then having it also range with an AirTag or other UWB board to act as the survivor tag, and then produce the location of the tag by inferring position relative to the non-anchor or tag board.

Team’s Status Report for 03/21/2026

Risks:

There are no new risks at the moment. The biggest risk we anticipate has to do with potential issues coming out once we are able to assemble a bot, e.g. we find out that the voltage regulator is unable to support all the devices, etc.. The main way we are mitigating this is by testing components together when we can, such as testing UWB ranging where at least one UWB board is solely connected to the ESP32S3, which allows us to at least confirm that interconnect between individual modules works. At full bot assembly, this will save a lot of time debugging potential issues since we’ve verified which individual parts should work together.

Design and Schedule Changes:

There have been no changes to our overall design, we are still following the same path as before. Similarly, no changes have been made to the overall schedule. Completion of global frame formation has been pushed to Monday, but the following deliverable of trilateration is on track to be finished at the same time. Therefore, we are still on track for the upcoming interim demo.

Photos:

Initiator board (connected to ESP32S3) returning TWR info
UWB Responder (Connected to computer via USB) Serial Output
UWB Ranging ~15cm away. Left board is responder (powered by USB), right board is initiator (controlled and powered by ESP32S3)

UI:

LiDAR Working:

LiDAR wired up to the ESP32S3. Confirmed ESP32S3 was able to read measurements.
Schematic for LiDAR wiring above.

Brooks’s Status Report for 03/21/2026

This week I was able to create the ranging UWB ranging pipeline between one of the UWB modules and an ESP32S3. In order to do so, I had to solder some header pins to the DWM3001CDK, and then hooked up the UART pins, 5V, and GND pins to the ESP32S3. The ESP32S3 sends CLI commands and then receives ranging data over UART. After this, I setup one DWM board to be an initiator for TWR while another was setup as a responder. The initiator was connected to and powered solely by the ESP32S3, while the responder was connected to my computer over USB. With this setup, I confirmed from the ESP32S3’s serial monitor that the ranging data was successfully being picked up. Lastly, I also set the UWB modules to be roughly 15cm away from each other and confirmed that the measurements were, on average, accurate.

TWR Ranging Setup. Left board is responder, right board is initiator
Initiator board (connected to ESP32S3) returning TWR info
UWB Responder (Connected to computer via USB) Serial Output

Regarding scheduling, I am behind on implementing formation of the global frame as this was supposed to be completed by today, however to compensate I plan on spending additional slack time tomorrow working on this. The primary concern in falling behind on this task is that the trilateration implementation requires the anchor boards to have coordinates assigned to them, and so a coordinate system is needed. However, this can technically be solved temporarily for trilateration testing purposes by assigning an arbitrary origin and axes. Therefore, my plan is to allow myself until Monday night to complete global frame formation. If I’m unable to completely finish it by this point, then I will move onto implementing the trilateration algorithm and plan to test by assigning a corner of the Hamerschlag room that our group works in, and define the axes myself. I gave myself longer than what should be necessary to implement trilateration (the algorithm is pretty straightforward), so I hope to finish that part early, giving me time to return to global frame formation if need be.

As mentioned above, the deliverables I hope to complete next week are global frame formation and trilateration, but I will prioritize trilateration if global frame formation takes me longer than Monday to complete.

Adrian’s Status Report for 03/21/2026

My plan this week was to wire Vector Field Histogram (VFH) into the live navigation loop and make frontier-based exploration visible on the tactical map so the operator can see both where coverage is growing and where the swarm is pushing next.

Across the four images, exploration grows from a small green pocket with a partial red wall outline to a fully mapped space whose OCCUPIED boundary cells form a complete red perimeter where LiDAR marks FREE interior and stamps OCCUPIED where rays hit the map edge. Teal trails stay in free space and skirt those red cells because VFH turns the global heading toward each frontier centroid into a locally safe steering angle via a polar obstacle histogram, then kinematics plus grid collision keep bots out of walls. The heatmap blooms track visit density and pile up at the leading edge of the dark UNKNOWN region, matching frontier detection (FREE cells next to UNKNOWN cells); as the frontier collapses, the map fills with green and the bright coverage fades, showing frontier-following exploration with obstacle-aware motion end to end. Once the entire map is covered with labeled/colored cells, the bots return to the base station without hitting OCCUPIED cells along the way.

VFH is implemented in src/exploration/vfh.ts, which builds a 72-sector polar obstacle-density histogram from nearby OCCUPIED cells, thresholds sectors into a blocked mask, finds contiguous free “valleys,” and picks a steering heading that stays aligned with the global goal while avoiding obstacles. The simulator (mockDataSimulator.ts) now uses this on every step: for each bot, it computes the heading toward the assigned frontier centroid, runs computeVfhHeading, then projects a short virtual waypoint along vfh.steeringHeading so the existing proportional kinematics controller tracks a VFH-safe direction. Map polygon bounds and grid-based collision resolution still apply after the move, so local avoidance and global feasibility stay consistent. Unit tests in vfh.test.ts cover histogram construction, valley finding, and end-to-end computeVfhHeading behavior.

Note that currently, the full histogram is not drawn as a separate UI panel; it powers motion in the sim. Exposing a small polar plot or debug overlay would be optional follow-on work.

Frontier logic is unchanged in principle, but the store now carries explorationGrid and frontierClusters each tick, and MapCanvas.tsx layers them so the algorithm is visible:

Status & next steps
Integration is on track: VFH is in the control loop, frontiers are fed from the same grid the sim uses, and the map reflects both. Next: optional debug visualization for the live histogram, tighter tests between VFH + multi-bot assignment under clutter, and (if needed) performance tuning of sector count / active radius for the target update rate.