Skip to main content

Showing entries for: Geospatial (show all)

Depth Data Mapping & Processing

This past week I've been working with our data store at Canyon Runner to collect and process boat depth sensor readings from our fleet of boats.

Purpose

This work is preliminary research to determine if we have enough data to provide more real-time depth readouts and charts for our customers. The aim here is to provide more real time charting for inlets that often have rapidly changing underwater conditions after storm surges.

Approach

The approach here requires mapping our depth sensor readouts (which don't come with geo-coordinates) to the boats coordinate readouts aligned by time, with a sliding window of four seconds (an arbitrary time chosen to prevent data loss while still maintaining accuracy). These points then get mapped to a grid for consistency (see screenshots), and the median value is displayed and interpolated to create a relief chart.

This work is still ongoing, and is predominantly just research to see how feasible using this data will be to provide customers with more up-to-date depth readouts.

By the Numbers

A single inlet across a 6-month time span might have anywhere from 4-12 million data points depending on how much traffic is passing through that inlet. The goal here is to make it render on a map, while offering various data filters, and still keeping it performant.

Entry image Entry image Entry image

Viewport Filtering on Garmin OneHelm

Introduced an abstraction class to enable default filtering on contents only visible within the view port of the Garmin OneHelm Canyon Runner app.

Process

This was a fun problem to think through. After porting the functionality to the new Typescript codebase 1:1, I started testing various new overlays we introduced to the map. They loaded fine, but were laggy and made the Garmin go unresponsive for seconds at a time. I knew there had to be performance optimizations to be made by restricting the overall number of waypoints, but I didn't want to create these optimizations on a per-module basis. I created a basic proof of concept view port filter that takes any dataset containing coordinates, and returning it filtered for only items currently being viewed on the leaflet map.

Claude Information Gathering

To confirm the abstracting I created was going to be applicable across the code base, I utilized Claude to outline the functionality of the legacy code base, and compare it against our re-worked version. Seeing the repeated patterns, I worked through a series of updates to the PoC in order to make it more universal and extendable.

Performance Impact

By implementing the filter, we were able to stabilize load times and reduce the overall hangups the Garmin experienced. The above screenshot depicts our performance testing, with the largest peaks occurring before we introduced this filtering (around the 766 mark).

Entry image

Loran Lines on OneHelm

Introduced Loran lines for the Garmin OneHelm typescript application. Introduced various performance enhancements to reduce about 1kb of memory overhead to keep the application in-line with the OneHelm 150MB spec limit. Hyper-optimizations included reducing forced SVG layout counts from 2400 to 300, text alignment map pings from 600 to 300, and removed all 2100 event listeners entirely to reduce overhead further.

Event Listeners

Typically no one has to think about the overall number of web listeners their creating on their web page. Any modern device can support way more than even the most poorly optimized sites can truly throw at it; however, that's not the case for the Garmin device, which only allots 150MB of total RAM to any given OneHelm app. Removing the 2100 event listeners caused a noticeable drop in bootstrap times, and improved overall responsiveness (which unfortuntaely is still a work in progress overall).

Entry image