Files
StarPilot/mapd_repo/extended_state.go
firestar5683 ab81464bd1 Maps
Add navigation and map matching providers with the vendored map service sources.

Co-authored-by: Daniel Koepping <elkoled@gmail.com>
Co-authored-by: Danny <dannyirwin31@yahoo.com>
Co-authored-by: Prabhaav Pillai <prabhaav@msu.edu>
Co-authored-by: dirwin31 <83434411+dirwin31@users.noreply.github.com>
2026-10-14 19:56:17 -05:00

178 lines
4.5 KiB
Go

package main
import (
"encoding/json"
"log/slog"
"time"
"pfeifer.dev/mapd/cereal"
"pfeifer.dev/mapd/cereal/custom"
m "pfeifer.dev/mapd/math"
ms "pfeifer.dev/mapd/settings"
"pfeifer.dev/mapd/utils"
)
type ExtendedState struct {
DownloadProgress ms.DownloadProgress
Pub cereal.Publisher[custom.MapdExtendedOut]
LoopRate utils.LoopRateTracker
lastSend time.Time
state *State
}
func (s *ExtendedState) Send() error {
s.state.ExpireGpsEvidence()
if time.Since(s.lastSend) > 1*time.Second {
s.lastSend = time.Now()
msg, out := s.Pub.NewMessage(true)
s.setDownloadProgress(out)
s.setSettings(out)
s.setPath(out)
s.setPosition(out)
s.setLoopRate(out)
s.Pub.Publish(msg)
return nil
}
return nil
}
func (s *ExtendedState) setPosition(out custom.MapdExtendedOut) {
if s.state.RoadStatus == custom.MapdOut_SampleStatus_noGps {
return
}
position, err := out.NewPosition()
if err == nil {
position.SetLatitude(s.state.Position.Lat())
position.SetLongitude(s.state.Position.Lon())
out.SetPosition(position)
}
}
func (s *ExtendedState) setPath(out custom.MapdExtendedOut) {
if !s.state.RoadMatched() {
_, _ = out.NewPath(0)
return
}
nodes := s.state.CurrentWay.Way.Nodes.Slice()
num_points := len(nodes)
all_nodes := [][]m.Position{nodes}
all_nodes_direction := []bool{s.state.CurrentWay.OnWay.IsForward}
for _, nextWay := range s.state.NextWays {
nwNodes := nextWay.Way.Nodes.Slice()
if len(nwNodes) > 0 {
num_points += len(nwNodes) - 1
}
all_nodes = append(all_nodes, nwNodes)
all_nodes_direction = append(all_nodes_direction, nextWay.IsForward)
}
path, err := out.NewPath(int32(num_points))
if err != nil {
slog.Warn("failed to create path in extended state")
return
}
all_nodes_idx := 0
nodes_idx := 0
for i := 0; i < num_points; i++ {
var index int
forward := all_nodes_direction[all_nodes_idx]
if forward {
index = nodes_idx
if all_nodes_idx > 0 {
index += 1
}
} else {
index = len(all_nodes[all_nodes_idx]) - nodes_idx - 1
if all_nodes_idx > 0 {
index -= 1
}
}
node := all_nodes[all_nodes_idx][index]
point := path.At(i)
point.SetLatitude(node.Lat())
point.SetLongitude(node.Lon())
nodes_idx += 1
if nodes_idx == len(all_nodes[all_nodes_idx]) || (nodes_idx == len(all_nodes[all_nodes_idx])-1 && all_nodes_idx > 0) {
all_nodes_idx += 1
nodes_idx = 0
}
}
point_idx := 0
for _, curvature := range s.state.Curvatures {
for ; point_idx < path.Len(); point_idx++ {
point := path.At(point_idx)
pos := m.NewPosition(point.Latitude(), point.Longitude())
if curvature.Pos.Equals(pos) {
point.SetCurvature(float32(curvature.Curvature))
point_idx++
break
}
}
}
point_idx = 0
for _, velocity := range s.state.TargetVelocities {
for ; point_idx < path.Len(); point_idx++ {
point := path.At(point_idx)
pos := m.NewPosition(point.Latitude(), point.Longitude())
if velocity.Pos.Equals(pos) {
point.SetTargetVelocity(float32(velocity.Velocity))
point_idx++
break
}
}
}
}
func (s *ExtendedState) setLoopRate(out custom.MapdExtendedOut) {
out.SetLoopRateAverage(float32(s.LoopRate.AverageRate()))
out.SetLoopRateMin(float32(s.LoopRate.MinRate()))
}
func (s *ExtendedState) setSettings(out custom.MapdExtendedOut) {
b, err := json.Marshal(ms.Settings)
if err != nil {
slog.Warn("failed to marshal settings for extended state")
return
}
if err := out.SetSettings(string(b)); err != nil {
slog.Warn("failed to set settings in extended state")
}
}
func (s *ExtendedState) setDownloadProgress(out custom.MapdExtendedOut) {
p, err := out.NewDownloadProgress()
if err != nil {
panic(err)
}
p.SetActive(s.DownloadProgress.Active)
p.SetCancelled(s.DownloadProgress.Canceled)
p.SetTotalFiles(uint32(s.DownloadProgress.TotalFiles))
p.SetDownloadedFiles(uint32(s.DownloadProgress.DownloadedFiles))
l, err := p.NewLocations(int32(len(s.DownloadProgress.LocationsToDownload)))
if err != nil {
panic(err)
}
for i, location := range s.DownloadProgress.LocationsToDownload {
err := l.Set(i, location)
if err != nil {
panic(err)
}
}
ld, err := p.NewLocationDetails(int32(len(s.DownloadProgress.LocationDetails)))
if err != nil {
panic(err)
}
idx := 0
for location, locationDetails := range s.DownloadProgress.LocationDetails {
d := ld.At(idx)
err := d.SetLocation(location)
if err != nil {
panic(err)
}
d.SetDownloadedFiles(uint32(locationDetails.DownloadedFiles))
d.SetTotalFiles(uint32(locationDetails.TotalFiles))
idx++
}
}