mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-10-27 16:43:59 +08:00
ab81464bd1
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>
180 lines
6.1 KiB
Go
180 lines
6.1 KiB
Go
package main
|
|
|
|
import (
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"pfeifer.dev/mapd/maps"
|
|
m "pfeifer.dev/mapd/math"
|
|
ms "pfeifer.dev/mapd/settings"
|
|
"pfeifer.dev/mapd/utils"
|
|
)
|
|
|
|
type SpeedLimitState struct {
|
|
Limit utils.Float32Tracker
|
|
Suggestion utils.Float32Tracker
|
|
SetSpeedWhenAccepted float32
|
|
OverrideSpeed float32
|
|
AcceptedLimit float32
|
|
NextLimit Upcoming[float32]
|
|
}
|
|
|
|
func (s *SpeedLimitState) Init() {
|
|
s.Limit.AllowNullLastValue = false
|
|
s.Suggestion.AllowNullLastValue = true
|
|
|
|
s.NextLimit = NewUpcoming(10, 0, checkWayForSpeedLimitChange)
|
|
}
|
|
|
|
func (s *SpeedLimitState) Update(currentWay CurrentWay, car CarState) {
|
|
if ms.Settings.SpeedLimitSettings.PressGasToOverrideSpeedLimit && car.GasPressed && car.VEgo > s.AcceptedLimit {
|
|
s.OverrideSpeed = car.VEgo
|
|
}
|
|
if s.OverrideSpeed < s.AcceptedLimit {
|
|
s.OverrideSpeed = 0
|
|
}
|
|
if car.SetSpeedChanging {
|
|
s.OverrideSpeed = 0
|
|
}
|
|
s.UpdateLimitAcceptedState(car)
|
|
s.UpdateAcceptedLimitValue(currentWay, car)
|
|
}
|
|
|
|
func (s *SpeedLimitState) UpdateLimitAcceptedState(car CarState) {
|
|
timeout := ms.Settings.SpeedLimitSettings.AcceptSpeedLimitTimeout
|
|
if timeout > 0 && time.Since(s.Limit.UpdatedTime) > time.Duration(timeout)*time.Second {
|
|
return
|
|
}
|
|
if ms.Settings.SpeedLimitSettings.PressGasToAcceptSpeedLimit && car.GasPressed {
|
|
ms.Settings.AcceptSpeedLimit()
|
|
}
|
|
if ms.Settings.SpeedLimitSettings.AdjustSetSpeedToAcceptSpeedLimit && car.SetSpeed.UpdatedTime.After(s.Limit.UpdatedTime) {
|
|
if ms.Settings.SpeedLimitAccepted() && s.SetSpeedWhenAccepted != car.SetSpeed.Value {
|
|
ms.Settings.ResetSpeedLimitAccepted()
|
|
}
|
|
if s.SetSpeedWhenAccepted == 0 {
|
|
s.SetSpeedWhenAccepted = car.SetSpeed.Value
|
|
ms.Settings.AcceptSpeedLimit()
|
|
}
|
|
}
|
|
}
|
|
|
|
func (s *SpeedLimitState) UpdateAcceptedLimitValue(currentWay CurrentWay, car CarState) {
|
|
suggestedSpeedUpdated := s.Suggestion.Update(s.SuggestNewSpeedLimit(currentWay, car))
|
|
if suggestedSpeedUpdated {
|
|
ms.Settings.ResetSpeedLimitAccepted()
|
|
s.SetSpeedWhenAccepted = 0
|
|
}
|
|
if ms.Settings.SpeedLimitAccepted() {
|
|
if s.AcceptedLimit != s.Suggestion.Value {
|
|
s.OverrideSpeed = 0
|
|
}
|
|
s.AcceptedLimit = s.Suggestion.Value
|
|
}
|
|
}
|
|
|
|
func (s *SpeedLimitState) SpeedLimitFinalSuggestion(enableSpeedActive bool, setSpeedChanging bool, vEgo float32) float32 {
|
|
slSuggestedSpeed := s.AcceptedLimit
|
|
if s.OverrideSpeed > 0 && s.OverrideSpeed > slSuggestedSpeed {
|
|
slSuggestedSpeed = s.OverrideSpeed
|
|
}
|
|
if !ms.Settings.SpeedLimitUseEnableSpeed || enableSpeedActive {
|
|
return slSuggestedSpeed
|
|
} else if setSpeedChanging && ms.Settings.SpeedLimitSettings.HoldSpeedLimitWhileChangingSetSpeed && vEgo-1 < s.AcceptedLimit {
|
|
return slSuggestedSpeed
|
|
}
|
|
return 0
|
|
}
|
|
|
|
func (s *SpeedLimitState) SuggestNewSpeedLimit(currentWay CurrentWay, car CarState) float32 {
|
|
slSuggestedSpeed := ms.Settings.PrioritySpeedLimit(float32(currentWay.EffectiveMaxSpeed()))
|
|
if slSuggestedSpeed == 0 && ms.Settings.SpeedLimitSettings.HoldLastSeenSpeedLimit {
|
|
slSuggestedSpeed = float32(s.Limit.LastValue)
|
|
}
|
|
if slSuggestedSpeed > 0 {
|
|
slSuggestedSpeed += ms.Settings.SpeedLimitSettings.SpeedLimitOffset
|
|
}
|
|
if s.NextLimit.Value > 0 {
|
|
offsetNextSpeedLimit := s.NextLimit.Value + ms.Settings.SpeedLimitSettings.SpeedLimitOffset
|
|
s.Limit.Update(ms.Settings.PrioritySpeedLimit(float32(currentWay.EffectiveMaxSpeed())))
|
|
nextIsLower := s.Limit.Value > s.NextLimit.Value
|
|
personality := ms.Settings.CurrentPersonality()
|
|
distanceToReachSpeed := m.CalculateJerkLimitedDistanceSimple(car.VEgo, car.AEgo, offsetNextSpeedLimit, personality.TargetSpeedAccel, personality.TargetSpeedJerk)
|
|
if nextIsLower {
|
|
distanceToReachSpeed += personality.SpeedLimitDecreaseTargetSpeedTimeOffset * (s.NextLimit.Value + ms.Settings.SpeedLimitSettings.SpeedLimitOffset)
|
|
} else {
|
|
distanceToReachSpeed += personality.SpeedLimitIncreaseTargetSpeedTimeOffset * (s.NextLimit.Value + ms.Settings.SpeedLimitSettings.SpeedLimitOffset)
|
|
}
|
|
if s.NextLimit.TriggerDistance > distanceToReachSpeed {
|
|
distanceToReachSpeed = s.NextLimit.TriggerDistance
|
|
}
|
|
if distanceToReachSpeed > s.NextLimit.TriggerDistance {
|
|
s.NextLimit.TriggerDistance = distanceToReachSpeed + 10
|
|
}
|
|
if !nextIsLower && personality.SpeedUpForNextSpeedLimit && s.NextLimit.Distance < distanceToReachSpeed {
|
|
slSuggestedSpeed = float32(offsetNextSpeedLimit)
|
|
} else if nextIsLower && personality.SlowDownForNextSpeedLimit && s.NextLimit.Distance < distanceToReachSpeed {
|
|
slSuggestedSpeed = float32(offsetNextSpeedLimit)
|
|
}
|
|
}
|
|
return slSuggestedSpeed
|
|
}
|
|
|
|
func ParseMaxSpeed(maxspeed string) float64 {
|
|
splitSpeed := strings.Split(maxspeed, " ")
|
|
if len(splitSpeed) == 0 {
|
|
return 0
|
|
}
|
|
|
|
numeric, err := strconv.ParseUint(splitSpeed[0], 10, 64)
|
|
if err != nil {
|
|
return 0
|
|
}
|
|
|
|
if len(splitSpeed) == 1 {
|
|
return ms.KPH_TO_MS * float64(numeric)
|
|
}
|
|
|
|
if splitSpeed[1] == "kph" || splitSpeed[1] == "km/h" || splitSpeed[1] == "kmh" {
|
|
return ms.KPH_TO_MS * float64(numeric)
|
|
} else if splitSpeed[1] == "mph" {
|
|
return ms.MPH_TO_MS * float64(numeric)
|
|
} else if splitSpeed[1] == "knots" {
|
|
return ms.KNOTS_TO_MS * float64(numeric)
|
|
}
|
|
|
|
return 0
|
|
}
|
|
|
|
func checkWayForSpeedLimitChange(state *State, parent *Upcoming[float32], way maps.NextWayResult) (valid bool, val float32) {
|
|
nextMaxSpeed := way.Way.MaxSpeed()
|
|
if way.IsForward && way.Way.MaxSpeedForward() > 0 {
|
|
nextMaxSpeed = way.Way.MaxSpeedForward()
|
|
} else if !way.IsForward && way.Way.MaxSpeedBackward() > 0 {
|
|
nextMaxSpeed = way.Way.MaxSpeedBackward()
|
|
}
|
|
if ms.Settings.ConditionalSpeedLimitControlEnabled {
|
|
rules := way.Way.ConditionalSpeedRules(way.IsForward)
|
|
if conditional := maps.ConditionalSpeedAt(rules, time.Now()); conditional > 0 {
|
|
nextMaxSpeed = conditional
|
|
}
|
|
}
|
|
|
|
if nextMaxSpeed != state.CurrentWay.EffectiveMaxSpeed() && nextMaxSpeed > 0 {
|
|
return true, float32(nextMaxSpeed)
|
|
}
|
|
|
|
return false, parent.DefaultValue
|
|
}
|
|
|
|
func checkWayForAdvisorySpeedChange(state *State, parent *Upcoming[float32], way maps.NextWayResult) (valid bool, val float32) {
|
|
nextAdvisorySpeed := way.Way.AdvisorySpeed()
|
|
|
|
if nextAdvisorySpeed != state.CurrentWay.Way.AdvisorySpeed() && nextAdvisorySpeed > 0 {
|
|
return true, float32(nextAdvisorySpeed)
|
|
}
|
|
|
|
return false, parent.DefaultValue
|
|
}
|