**MIT Shuttle System** *6.08 Final Report - Team 74* # Overview The MIT shuttle system brings hundreds of students and staff to and from campus every day. It is a vital part of being an MIT student living in dorms. The shuttle system app, which shows the current location of the shuttles and predicted arrival times for all the stops, is well known to be inaccurate and unusable at times. This is because the NexBus trackers used on these shuttles update every minute which is very low temporal resolution for tracking and the predictor doesn’t take into account any traffic information. Shuttles+ is a shuttle tracking and prediction system that aims to solve these problems with three main goals: * Build and install custom hardware GPS trackers on shuttles. Broadcast the GPS location much more frequently than once every minute and provide a much smoother and accurate visual of where the shuttle is on the map. * Use traffic prediction algorithms on the location data to improve arrival prediction time. * Make the system operate with little maintenance and no recurring operating costs, effectively allowing the MIT community to benefit from the system for some time to come. We've deployed this at https://shuttle.io. Since the trackers are not on the shuttles right now, it might not be live though. [(Video Link Here If Not Loaded)](https://www.youtube.com/watch?v=wiJKNP4vbSU) # Design The system consists of the tracker, the gateway and the server. The tracker collects GPS information and transmits it to the gateway, which in turn sends this to the server. The server integrates this information, runs the prediction algorithm and serves the user-face web application to display all this information. ![Design](https://i.imgur.com/7c4yp8m.png) ## Tracker The tracker is responsible for collecting the GPS information and transmitting it to the gateway. ![TrackerHardware](https://i.imgur.com/GjFDEfX.jpg) ![TrackerSchematic](https://i.imgur.com/2XWQpg8.png) ### Connectivity We need a way to communicate the GPS data back to the server. Our first obvious choice was to rely on the shuttle’s WiFi: which we quickly discovered was non-existent. We then tried to instruct the ESP32 to very quickly switch WiFi networks and reconnect, leveraging the open MIT WiFi access points. This however was also very spotty, with us getting decent networking only over a few patches of our route. This was a major challenge, since without reliable connectivity our project would fail. We considered using cellular data, but that did not fit our design constraints as it would incur recurring costs. We decided to transmit our location data packets over the LoRa protocol. This is a radio protocol that is designed to be used over long ranges and operate on low power, with limited bandwidth: perfect for our design goals. The brains of the tracker hardware is a Heltec ESP32 LoRa WiFi dev board. These use the standard ESP32 that we’ve seen in 6.08 with a few additional bells and whistles we needed to meet our goals, including the RFM95 chip that we use to transmit our LoRa packets at 915 MHz. ### GPS We used a standard GPS modules communicating with our ESP32 over UART. We use the TinyGPS library to parse the raw NMEA strings from the GPS module and extract the latitude and longitude. We then construct our string transmission packet as follows: ``` ESP_ID,lat,lon*checksum ``` We use the `ESP.getEfuseMac()` interface to get a unique ID of the tracker. We then attach the float values of the latitude and longitude at the end. Since the LoRa protocol is an unreliable protocol, we tack on a CRC8 checksum and send off the packet every 500 ms. ### Power This was another challenge as the MIT shuttles don’t have any publicly usable power options and we didn’t want to recharge a battery every now and then. Our final design choice was to use a solar panel coupled with a lithium ion battery. A nice thing about the Heltec ESP32 boards is that they have built-in battery power sharing, voltage regulator, boost converter and a MCP73831 based lithium battery charger. We provide the charger with power through a 6 watt solar panel. Since the output of the solar panel ranges between 0 - 6 V, we added a boost/buck converter to maintain a steady 5V source to the charger. The following shows our solar output in Watts as measured on a normal tracker load over a full shuttle loop on an overcast day. ![SolarPower](https://i.imgur.com/FICjBPA.png) Our average power consumption for the tracker about 72 mA. Integrating over the solar power output and considering we use a 2000 mAh battery, we estimate the battery to charge from 0 to 100% in about 4 hours of the shuttle ride. With no solar power, our battery will last for ~27 hours. This is more than enough for our application. All our REST API routes were unencrypted HTTP endpoints so as to save power. HTTPS made us pay an extra 60 mA more than our average current consumption. ## Gateway The gateway is responsible for receiving the location data from the tracker and send it to the server. We needed to place the gateway at a place with the best chance of making line-of-site with the tracker to maximize our range. The best place to place the gateway was of course, on the roof of the Green Building (the tallest building in Cambridge). One of the 6.08 LAs, Daniel B Sheen, who’s also part of the MIT Radio Society, kindly gave us access to the roof where we deployed it. The gateway consists of a Heltec ESP32 LoRa board and a Raspberry Pi, communicating over USB Serial. There is no WiFi on the roof, since it would interfere with all the fancy radio stuff up there and thus the Raspberry Pi served as a LoRa to Ethernet bridge. It was also nice to be able to SSH into the Pi and perform firmware updates to the ESP32. The range we got with the gateway was about 1.7 km from the Green Building, which is more than enough for the main tech shuttle routes. The ESP32 receives data over the LoRa protocol and sends it to the Pi over serial, where a python script processes the raw packets, and filters packets with the correct CRC8 checksum, hitting our server’s API route. We wanted to minimize the amount of processing done here because it’s much easier to perform updates and iterate on the server rather than the gateway. The python script also runs a background thread to send periodic heartbeats with the IP address of the Pi, which is configured to run the script robustly against power cycles and interruptions. ## Server The server is responsible for receiving location data from the gateway, make predictions and serve the web app. The server is written using the [Flask](http://flask.pocoo.org/) web framework in Python and is deployed using [gunicorn](https://gunicorn.org/). It is backed by a PostgresSQL database for persistent storage. The server is running in the east campus basement. ### Web App The server delivers a resposive, progressive web app to the user. We use the MapBox API to draw a full screen map on the user's device and query their location using the HTML5 location API. The web app polls the server to fetch location, predictions and shuttle stop locations every second, and then updates the map markers to reflect the changes. We use a Kalman filter on the shuttle locations to try and smooth the location data for a better UX. We update the Kalman filter every 5 milliseconds and make use of the open source [Kalman.js](https://github.com/wouterbulten/kalmanjs) library. ![KalmanFilterInterface](https://media.giphy.com/media/YkhvHjkXrrp4PsDzsc/giphy.gif) ### Predictions ![PredictionInterface](https://i.imgur.com/wkIwRJN.png) We use the Google Traffic Matrix API to make the shuttle stop arrival predictions. We assume that the shuttle spends a minute waiting at each stop. We query the API every 30 minutes in a background thread, and in between two queries we update the times based on an open loop system; by reducing the actual time elapsed from the predictions. ### Routes The whole server-side system is tied together with the API routes: ``` GET /api/timings ``` Returns a JSON blob of timing predictions. ``` GET /api/readings ``` Gives us the last reading returned from the gateway. This is important for debugging purposes and making sure the trackers are healthy. ``` POST /api/gps ``` This is how the gateway updates the server with tracker latitude and longitude. ``` GET, POST /master/ip ``` This route updates the IP address from the gateway and also gets the IP address for SSHing into the gateway Pi. # Conclusions and Future Work There are a few things we want to add to make Shuttles+ deployable at scale and work for the MIT community, * Firstly, it is very hard to constantly access the green building for maintaining. A solution is to deploy a network of gateways at strategic points around the campus that act as nodes in our custom wide area network. Maybe even give the MIT community access to a LoRa WAN network for IOT devices. * Right now we assume 1 minute per stop. As we collect more data, we wish to integrate past data collected to further improve the predictions times. * Right now the ESP32 constantly broadcasts on LoRa, even overnight. We would ideally want to switch to deep sleep during inactive hours automatically to better optimize power. * We also want to make the UI for the app exteremly intuitive and easy to use. * If our system is used often on mobile devices, we could even crowdsource the shuttle's location by integrating those devices's GPS location with our own trackers to further improve data rates and accuracy. Regardless, with Shuttles+ we have proven that it is possible to track the MIT Shuttles and make accurate stop predictions using off the shelf hardware, without incurring recurring costs. We believe that with higher update rates and better traffic prediction we can provide a much better shuttles experience at MIT. ### Side🎵: Over-the-Air Updates While we were still planning to use WiFi, we wrote some code to push firmware updates to the trackers over WiFi. While this code is no longer of use since we're using LoRa, we still included our implementations since we thought it was cool 🙃. # Parts List For every tracker, we used, 1 x [Heltec LoRa ESP32](https://robotzero.one/heltec-wifi-lora-32/) 1 x [6W Solar Panel](https://www.adafruit.com/product/1525) 1 x [GPS Module](https://www.adafruit.com/product/746) 1 x [Boost/Buck Converter](https://www.adafruit.com/product/2190) 1 x Passive 915 MHz Antenna 1 x [3.7v Lithium Battery](https://www.adafruit.com/product/2011) For every gateway we used, 1 x [Heltec LoRa ESP32](https://robotzero.one/heltec-wifi-lora-32/) 1 x Passive 915 MHz Antenna 1 x [Raspberry Pi Model 3](https://www.adafruit.com/product/3055)