mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-10-28 00:53:45 +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>
164 lines
4.8 KiB
Go
164 lines
4.8 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"math"
|
|
|
|
"github.com/pkg/errors"
|
|
m "pfeifer.dev/mapd/math"
|
|
ms "pfeifer.dev/mapd/settings"
|
|
)
|
|
|
|
func GetStateCurvatures(state *State) ([]m.Curvature, error) {
|
|
nodes := state.CurrentWay.Way.Nodes.Slice()
|
|
num_points := len(nodes)
|
|
all_nodes := [][]m.Position{nodes}
|
|
all_nodes_direction := []bool{state.CurrentWay.OnWay.IsForward}
|
|
all_nodes_is_merge_or_split := []bool{false}
|
|
lastWay := state.CurrentWay.Way
|
|
for _, nextWay := range 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)
|
|
all_nodes_is_merge_or_split = append(all_nodes_is_merge_or_split, lastWay.Lanes() < nextWay.Way.Lanes() || (lastWay.Lanes() > nextWay.Way.Lanes() && !lastWay.OneWay() && nextWay.Way.OneWay()))
|
|
lastWay = nextWay.Way
|
|
}
|
|
|
|
positions := make([]m.Position, num_points)
|
|
|
|
merge_or_split_nodes := []int{}
|
|
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]
|
|
positions[i] = node
|
|
|
|
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
|
|
if all_nodes_idx < len(all_nodes_is_merge_or_split) && all_nodes_is_merge_or_split[all_nodes_idx] {
|
|
merge_or_split_nodes = append(merge_or_split_nodes, i)
|
|
}
|
|
}
|
|
}
|
|
|
|
curvatures, err := GetCurvatures(positions)
|
|
if err != nil {
|
|
return []m.Curvature{}, errors.Wrap(err, "could not get curvatures from points")
|
|
}
|
|
|
|
// set the merge nodes to be straight to help balance out issues with map representation
|
|
for _, merge_or_split_node := range merge_or_split_nodes {
|
|
if merge_or_split_node >= 2 {
|
|
curvatures[merge_or_split_node-2].Curvature = 0.0015
|
|
curvatures[merge_or_split_node-1].Curvature = 0.0015
|
|
}
|
|
// also include nodes within 15 meters
|
|
for i := merge_or_split_node - 3; i >= 0; i-- {
|
|
|
|
if positions[merge_or_split_node].DistanceTo(positions[i]) > 15 {
|
|
break
|
|
}
|
|
curvatures[i].Curvature = 0.0015
|
|
}
|
|
// also include forward nodes within 15 meters
|
|
for i := merge_or_split_node; i < len(curvatures); i++ {
|
|
if positions[merge_or_split_node].DistanceTo(positions[i]) > 15 {
|
|
break
|
|
}
|
|
curvatures[i].Curvature = 0.0015
|
|
}
|
|
}
|
|
|
|
average_curvatures, err := GetAverageCurvatures(curvatures)
|
|
if err != nil {
|
|
return []m.Curvature{}, errors.Wrap(err, "could not get average curvatures from curvatures")
|
|
}
|
|
return average_curvatures, nil
|
|
}
|
|
|
|
type Velocity struct {
|
|
Pos m.Position
|
|
Velocity float64
|
|
TriggerDistance float32
|
|
}
|
|
|
|
func GetTargetVelocities(curvatures []m.Curvature, previousTargets []Velocity) (velocities []Velocity) {
|
|
velocities = make([]Velocity, len(curvatures))
|
|
for i, curv := range curvatures {
|
|
if curv.Curvature == 0 {
|
|
continue
|
|
}
|
|
velocities[i].Velocity = math.Pow(float64(ms.Settings.CurrentPersonality().MapCurveTargetLatA)/curv.Curvature, 1.0/2)
|
|
velocities[i].Pos = curv.Pos
|
|
for _, t := range previousTargets {
|
|
if velocities[i].Pos.Equals(t.Pos) {
|
|
velocities[i].TriggerDistance = t.TriggerDistance
|
|
}
|
|
}
|
|
}
|
|
return velocities
|
|
}
|
|
|
|
func GetAverageCurvatures(curvatures []m.Curvature) (average_curvatures []m.Curvature, err error) {
|
|
if len(curvatures) < 3 {
|
|
return []m.Curvature{}, errors.New("not enough curvatures to average")
|
|
}
|
|
|
|
average_curvatures = make([]m.Curvature, len(curvatures)-2)
|
|
|
|
for i := 0; i < len(curvatures)-2; i++ {
|
|
a := curvatures[i].Curvature
|
|
b := curvatures[i+1].Curvature
|
|
c := curvatures[i+2].Curvature
|
|
al := curvatures[i].ArcLength
|
|
bl := curvatures[i+1].ArcLength
|
|
cl := curvatures[i+2].ArcLength
|
|
|
|
if al+bl+cl == 0 {
|
|
average_curvatures[i] = curvatures[i+2]
|
|
continue
|
|
}
|
|
|
|
avg := m.Curvature{Pos: curvatures[i+1].Pos}
|
|
avg.Curvature = (a*al + b*bl + c*cl) / (al + bl + cl)
|
|
avg.ArcLength = (curvatures[i].ArcLength + curvatures[i+1].ArcLength + curvatures[i+2].ArcLength) / 3
|
|
avg.Angle = (curvatures[i].Angle + curvatures[i+1].Angle + curvatures[i+2].Angle) / 3
|
|
average_curvatures[i] = avg
|
|
}
|
|
|
|
return average_curvatures, nil
|
|
}
|
|
|
|
func GetCurvatures(positions []m.Position) (curvatures []m.Curvature, err error) {
|
|
if len(positions) < 3 {
|
|
return []m.Curvature{}, errors.New(fmt.Sprintf("not enough points to calculate curvatures. len(points): %d", len(positions)))
|
|
}
|
|
curvatures = make([]m.Curvature, len(positions)-2)
|
|
|
|
for i := 0; i < len(positions)-2; i++ {
|
|
curvature := m.CalculateCurvature(positions[i], positions[i+1], positions[i+2])
|
|
|
|
curvatures[i] = curvature
|
|
}
|
|
|
|
return curvatures, nil
|
|
}
|