supply_point

package module
v0.1.22 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 8, 2023 License: LGPL-3.0 Imports: 14 Imported by: 0

README

  • 路径预处理
  1. 排除路径中连续重复的点
if points[i] == points[i-1] { 
	// 排除
	continue
}
  1. 将路径中所有点的经纬度都*1000000,转换为整数
    经纬度6位小数可以精确到1米,满足需求不需要更高精度
  2. 从坐标点集中找到边界点,即最小经度、最大经度、最小纬度、最大纬度,构建一个最小的矩形,并将经纬度转化为相对于矩形的坐标
// 从坐标点集中找到边界点
	// maxX, minX, maxY, minY 组成一个矩形,可以包含所有的坐标点
	var (
		maxX = -90000000
		minX = 90000000
		maxY = -180000000
		minY = 180000000
	)
	for _, p := range pathPoint {
		if p.X > maxX {
			maxX = p.X
		}
		if p.X < minX {
			minX = p.X
		}
		if p.Y > maxY {
			maxY = p.Y
		}
		if p.Y < minY {
			minY = p.Y
		}
	}
	// 适配maxX, minX, maxY, minY 组成的矩形,使坐标可以包含在一个矩形中
	for i := 0; i < len(pathPoint); i++ {
		pathPoint[i].X = pathPoint[i].X - minX
		pathPoint[i].Y = pathPoint[i].Y - minY
	}
  • 获取拐点 两点之间的距离采用欧式距离,即两点之间的直线距离
math.Sqrt(math.Pow(float64(p1.X-p2.X), 2) + math.Pow(float64(p1.Y-p2.Y), 2))

判断三点是否直线

var isLine = func(p1, p2, p3 int) bool {
		// 临边
		d0 := getEuclideanDistance(sp.p[p1], sp.p[p2])
		d1 := getEuclideanDistance(sp.p[p2], sp.p[p3])
		// 斜边
		d2 := getEuclideanDistance(sp.p[p1], sp.p[p3])
		// 计算三角形三边的比例
		criticalValue := 0.999 // 值越大,越敏感
		return d2/(d0+d1) > criticalValue
	}

计算拐点
从第二个点开始,依次遍历坐标集
遍历具有两种模式,一种是验证模式,一种是正常模式
验证模式:当遇到拐点时,需要验证多次,验证多次后,才能证明这个点是真的拐点。验证成功后,将回溯至拐点继续正常模式
正常模式:正常判断三点是否直线,如果是直线,则将当前点设置为上一个点,继续遍历
三点:取线段的开始点、上一个点(若当前是验证模式,则取当前线段最后一个点)、当前点,判断是否直线

// 用来找拐点的方法
	// p 所有的坐标集合
	// needRecallCount 需要验证的次数(需要经历多少个点才能证明这个点是真的拐点)
	var recall = func(p []*PathPoint, needRecallCount int) {
		var (
			recallCount    = 0 // 验证次数
			lineStart      = 0 // 直线的起点index
			prevPointIndex = 1 // 上一个点的index(遇到拐角时,这个就等于拐角的index)
		)
		// 从第三个点开始遍历坐标集合
		for i := 2; i < len(p); i++ {
			// 判断是否是直线
			isline := isLine(lineStart, prevPointIndex, i)
			if isline {
				prevPointIndex = i // 设置当前index为prevPointIndex
				recallCount = 0    // 验证次数清零
			} else {
				if recallCount >= needRecallCount {
					fmt.Println("corner", prevPointIndex)
					lineStart = prevPointIndex
					corner = append(corner, prevPointIndex)
					prevPointIndex, i = prevPointIndex+1, prevPointIndex+1
					recallCount = -1
				}
				recallCount++
			}
		}
	}
  • 拐点分组 遍历所有的拐点,将拐点分组
for i := 1; i < len(corner); i++ {
		// todo 根据经纬度的距离判断
	    // 若两个拐点之间的个数较小,但距离较大的话,当前判断方式会将其分在一组,存在问题
		if corner[i]-corner[i-1] < 4 {
			for j := corner[i-1] + 1; j <= corner[i]; j++ {
				g = append(g, j)
			}
		} else {
			// todo 根据曲率判断是否真的是拐点 - 防止噪音
			if len(g) >= 2 {
				// 拐点的个数大于等于2个,才能分组,否则当作噪音去掉
				group = append(group, g)
			}
			g = []int{corner[i]}
		}
	}
	if len(g) >= 2 {
		group = append(group, g)
	}
  • 从拐点分组的结果中找到正确的补给点位置
    假设拐点存在且只存在路径的两侧,并且按照规则一边一个依次排列
func (sp *supplyPoint) GetSupplyPoint(cornerGroup [][]int, referenceValue int) [][]int {
	// 取单数
	var (
		cornerGroupNew [][]int
		whichSide      = 0 // 假设拐点存在且只存在路径的两侧,并且按照规则一边一个依次排列(【cornerGroupIndex%2 == whichSide】)
	)
	if referenceValue >= 0 {
		// 寻找距离最近的点
		var (
			minDistance = getEuclideanDistance(
				&PathPoint{
					X: 0,
					Y: 0,
				},
				&PathPoint{
					X: sp.maxX - sp.minX,
					Y: sp.maxY - sp.minY,
				},
			)
			minDistanceIndex = 0
		)
		for i := 0; i < len(cornerGroup); i++ {
			d := getEuclideanDistance(sp.p[cornerGroup[i][0]], sp.p[referenceValue])
			if d < minDistance {
				minDistance = d
				minDistanceIndex = i
			}
		}
		whichSide = minDistanceIndex % 2
	}
	// todo 判断是否是按照规则一边一个依次排列,将异常的cornerGroup去掉
	for i := 0; i < len(cornerGroup); i++ {
		if i%2 == whichSide {
			cornerGroupNew = append(cornerGroupNew, cornerGroup[i])
		}
	}
	return cornerGroupNew
}

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func GetDistance added in v0.1.4

func GetDistance(lat1, lng1, lat2, lng2 float64) float64

GetDistance 根据经纬度获取距离

func GetDistanceByPoint added in v0.1.21

func GetDistanceByPoint(p1, p2 *PathPoint) float64

GetDistanceByPoint 根据经纬度获取距离

func NewSupplyPoint

func NewSupplyPoint(csv []byte) *supplyPoint

func NewSupplyPointByCsvPath added in v0.1.4

func NewSupplyPointByCsvPath(url string) (*supplyPoint, error)

Types

type PathPoint

type PathPoint struct {
	X, Y          int
	Lat, Lng      float64
	Tim           int64 // 毫秒时间戳
	IsSupplyPoint int   // 是否补给点
	Yaw           float64
}

type Putpixel

type Putpixel func(x, y int)

type SpaceCompute added in v0.1.21

type SpaceCompute struct {
	Points       []*PathPoint
	PrevDistance []float64
	PrevAngle    []float64
}

func GetSpaceCompute added in v0.1.21

func GetSpaceCompute(ps []*PathPoint) *SpaceCompute

func (*SpaceCompute) AbnormalAngleRepair added in v0.1.21

func (s *SpaceCompute) AbnormalAngleRepair()

func (*SpaceCompute) FindContinueMove added in v0.1.21

func (s *SpaceCompute) FindContinueMove(beginIndex int, decisionAngle, decisionDistance float64) int

FindContinueMove 找到同方向连续移动的点 decisionAngle 决策角度 decisionDistance 决策距离(单位米) return latest index of continue move

func (*SpaceCompute) GetCorner added in v0.1.21

func (s *SpaceCompute) GetCorner() []int

func (*SpaceCompute) NoZero added in v0.1.21

func (s *SpaceCompute) NoZero()

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL