|
@@ -0,0 +1,268 @@
|
|
|
+package main
|
|
|
+
|
|
|
+import (
|
|
|
+ "awesomeProject/entity"
|
|
|
+ "awesomeProject/kinglong_msgs"
|
|
|
+ "fmt"
|
|
|
+ "github.com/bluenviron/goroslib/v2"
|
|
|
+ "math"
|
|
|
+ "os"
|
|
|
+ "os/signal"
|
|
|
+ "sort"
|
|
|
+ "time"
|
|
|
+)
|
|
|
+
|
|
|
+var (
|
|
|
+ Framenum int64 = 0
|
|
|
+ param entity.PjisuvParam
|
|
|
+ ObjectSlice = make(map[uint32][][]float32)
|
|
|
+ DriverSlice = [][]float64{{}, {}, {}}
|
|
|
+ AlgSlice = [][]float64{{}, {}, {}}
|
|
|
+
|
|
|
+ CutInFlag = false
|
|
|
+ CutOutFlag = false
|
|
|
+)
|
|
|
+
|
|
|
+func mannWhitneyU(x, y []float64) (float64, float64) {
|
|
|
+ n1 := len(x)
|
|
|
+ n2 := len(y)
|
|
|
+
|
|
|
+ combined := append(x, y...)
|
|
|
+ sort.Float64s(combined)
|
|
|
+
|
|
|
+ ranks := make(map[float64]float64)
|
|
|
+ for i := 0; i < len(combined); {
|
|
|
+ j := i
|
|
|
+ for j < len(combined) && combined[i] == combined[j] {
|
|
|
+ j++
|
|
|
+ }
|
|
|
+ rank := float64(i+j+1) / 2
|
|
|
+ for k := i; k < j; k++ {
|
|
|
+ ranks[combined[k]] = rank
|
|
|
+ }
|
|
|
+ i = j
|
|
|
+ }
|
|
|
+
|
|
|
+ r1 := sumRanks(x, ranks)
|
|
|
+ r2 := sumRanks(y, ranks)
|
|
|
+
|
|
|
+ u1 := r1 - float64(n1*(n1+1))/2
|
|
|
+ u2 := r2 - float64(n2*(n2+1))/2
|
|
|
+
|
|
|
+ u := math.Min(u1, u2)
|
|
|
+ meanU := float64(n1*n2) / 2
|
|
|
+ sdU := math.Sqrt(float64(n1*n2*(n1+n2+1)) / 12)
|
|
|
+
|
|
|
+ z := (u - meanU) / sdU
|
|
|
+ p := 2 * (1 - normCdf(math.Abs(z)))
|
|
|
+
|
|
|
+ return u, p
|
|
|
+}
|
|
|
+
|
|
|
+func sumRanks(arr []float64, ranks map[float64]float64) float64 {
|
|
|
+ sum := 0.0
|
|
|
+ for _, v := range arr {
|
|
|
+ sum += ranks[v]
|
|
|
+ }
|
|
|
+ return sum
|
|
|
+}
|
|
|
+
|
|
|
+func normCdf(x float64) float64 {
|
|
|
+ return 0.5 * (1 + math.Erf(x/math.Sqrt2))
|
|
|
+}
|
|
|
+
|
|
|
+func main() {
|
|
|
+ ticker := time.NewTicker(3 * time.Second)
|
|
|
+ defer ticker.Stop()
|
|
|
+ go listener()
|
|
|
+ for {
|
|
|
+ select {
|
|
|
+ case <-ticker.C:
|
|
|
+ FinalCallback()
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func isCuttingOut(ObjectSlice map[uint32][][]float32) {
|
|
|
+ CutOutFlag = false
|
|
|
+ for _, ObjectList := range ObjectSlice {
|
|
|
+ for i := 0; i < len(ObjectList[0]); i++ {
|
|
|
+ xi := ObjectList[0][i]
|
|
|
+ yi := math.Abs(float64(ObjectList[1][i]))
|
|
|
+ Type := ObjectList[4][0]
|
|
|
+ if xi >= 0 && yi <= 0.7 && math.Abs(param.AngularVelocityZOfCicvLocation) <= 0.4 && (Type == 0.0 || Type == 1.0) { //简化条件
|
|
|
+
|
|
|
+ for j := 0; j < len(ObjectList[0])-i-1; j++ {
|
|
|
+ xj := ObjectList[0][j]
|
|
|
+ yj := math.Abs(float64(ObjectList[1][j]))
|
|
|
+
|
|
|
+ if xj >= 0 && yj >= 2.0 && math.Abs(param.AngularVelocityZOfCicvLocation) <= 0.4 {
|
|
|
+ CutOutFlag = true
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+func isCuttingIn(ObjectSlice map[uint32][][]float32) {
|
|
|
+ CutInFlag = false
|
|
|
+ for _, ObjectList := range ObjectSlice {
|
|
|
+ for i := 0; i < len(ObjectList[0]); i++ {
|
|
|
+ xi := ObjectList[0][i]
|
|
|
+ yi := math.Abs(float64(ObjectList[1][i]))
|
|
|
+ Type := ObjectList[4][0]
|
|
|
+ if xi >= 0 && yi >= 2 && math.Abs(param.AngularVelocityZOfCicvLocation) <= 0.6 && (Type == 0.0 || Type == 1.0) { //简化条件
|
|
|
+
|
|
|
+ for j := 0; j < len(ObjectList[0])-i-1; j++ {
|
|
|
+ xj := ObjectList[0][j]
|
|
|
+ yj := math.Abs(float64(ObjectList[1][j]))
|
|
|
+
|
|
|
+ if xj >= 0 && yj <= 0.7 && math.Abs(param.AngularVelocityZOfCicvLocation) <= 0.6 {
|
|
|
+ CutInFlag = true
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+func FinalCallback() {
|
|
|
+ isCuttingOut(ObjectSlice)
|
|
|
+ isCuttingIn(ObjectSlice)
|
|
|
+ if CutOutFlag == true {
|
|
|
+ ObjectSlice = make(map[uint32][][]float32)
|
|
|
+ _, p1 := mannWhitneyU(DriverSlice[0], AlgSlice[0])
|
|
|
+ _, p2 := mannWhitneyU(DriverSlice[1], AlgSlice[1])
|
|
|
+ _, p3 := mannWhitneyU(DriverSlice[2], AlgSlice[2])
|
|
|
+ if p1 < 0.05 || p2 < 0.05 || p3 < 0.05 {
|
|
|
+ event_lable := "CutOutDifference"
|
|
|
+ fmt.Println(event_lable)
|
|
|
+ DriverSlice = [][]float64{{}, {}, {}}
|
|
|
+ AlgSlice = [][]float64{{}, {}, {}}
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+func CallbackCicvLocation(data *kinglong_msgs.PerceptionLocalization) {
|
|
|
+ param.YawOfCicvLocation = data.Yaw
|
|
|
+ param.AngularVelocityZOfCicvLocation = data.AngularVelocityZ
|
|
|
+}
|
|
|
+func CallbackTpperception(data *kinglong_msgs.PerceptionObjects) {
|
|
|
+ Framenum += 1
|
|
|
+ for _, obj := range data.Objs {
|
|
|
+ if math.Abs(float64(obj.X)) >= 80 || math.Abs(float64(obj.Y)) >= 30 {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ if _, ok := ObjectSlice[obj.Id]; !ok {
|
|
|
+ ObjectSlice[obj.Id] = [][]float32{{}, {}, {}, {}, {}}
|
|
|
+ }
|
|
|
+ //absspeed := math.Sqrt(math.Pow(float64(obj.Vxabs), 2)+math.Pow(float64(obj.Vyabs), 2)) * 3.6
|
|
|
+ ObjectSlice[obj.Id][0] = append(ObjectSlice[obj.Id][0], obj.X)
|
|
|
+ ObjectSlice[obj.Id][1] = append(ObjectSlice[obj.Id][1], obj.Y)
|
|
|
+ diffh := (float64(obj.Heading - float32(param.YawOfCicvLocation)))
|
|
|
+ if diffh < -180.0 {
|
|
|
+ diffh = 360.0 + diffh
|
|
|
+ } else if diffh > 180.0 {
|
|
|
+ diffh = 360.0 - diffh
|
|
|
+ } else {
|
|
|
+ diffh = math.Abs(diffh)
|
|
|
+ }
|
|
|
+ ObjectSlice[obj.Id][2] = append(ObjectSlice[obj.Id][2], float32(diffh))
|
|
|
+ ObjectSlice[obj.Id][3] = append(ObjectSlice[obj.Id][3], float32(Framenum))
|
|
|
+ ObjectSlice[obj.Id][4] = append(ObjectSlice[obj.Id][4], float32(obj.Type))
|
|
|
+
|
|
|
+ //ObjectSlice[obj.Id][3] = append(ObjectSlice[obj.Id][3], float32(absspeed))
|
|
|
+ if len(ObjectSlice[obj.Id][0]) >= 150 {
|
|
|
+ ObjectSlice[obj.Id][0] = ObjectSlice[obj.Id][0][1:]
|
|
|
+ ObjectSlice[obj.Id][1] = ObjectSlice[obj.Id][1][1:]
|
|
|
+ ObjectSlice[obj.Id][2] = ObjectSlice[obj.Id][2][1:]
|
|
|
+ ObjectSlice[obj.Id][3] = ObjectSlice[obj.Id][3][1:]
|
|
|
+ ObjectSlice[obj.Id][4] = ObjectSlice[obj.Id][4][1:]
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func CallbackDataRead(data *kinglong_msgs.Retrieval) {
|
|
|
+ DriverSlice[0] = append(DriverSlice[0], data.StrgAngleRealValue) //方向盘实际转角
|
|
|
+ DriverSlice[1] = append(DriverSlice[1], data.VcuAccelPosValue) //实际加速踏板位置
|
|
|
+ DriverSlice[2] = append(DriverSlice[2], data.VcuBrkPelPosValue) //实际制动踏板位置
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+func CallbackJinlongControlPub(data *kinglong_msgs.JinlongControlCommand) {
|
|
|
+ AlgSlice[0] = append(AlgSlice[0], data.ASStrgAngleReq) //算法输出方向盘转角
|
|
|
+ AlgSlice[1] = append(AlgSlice[1], data.ASAutoDAccelPosReq) //算法输出加速踏板位置
|
|
|
+ AlgSlice[2] = append(AlgSlice[2], data.ASAutoDBrkPelPosReq) //算法输出制动踏板位置
|
|
|
+}
|
|
|
+
|
|
|
+func listener() {
|
|
|
+ // create a node and connect to the master
|
|
|
+ n, err := goroslib.NewNode(goroslib.NodeConf{
|
|
|
+ Name: "goroslib_sub",
|
|
|
+ MasterAddress: "127.0.0.1:11311",
|
|
|
+ })
|
|
|
+ if err != nil {
|
|
|
+ panic(err)
|
|
|
+ }
|
|
|
+ defer n.Close()
|
|
|
+
|
|
|
+ // create a subscriber
|
|
|
+ subCicvLocation, err := goroslib.NewSubscriber(goroslib.SubscriberConf{
|
|
|
+ Node: n,
|
|
|
+ Topic: "/cicv_location",
|
|
|
+ Callback: CallbackCicvLocation,
|
|
|
+ })
|
|
|
+ if err != nil {
|
|
|
+ panic(err)
|
|
|
+ }
|
|
|
+ defer subCicvLocation.Close()
|
|
|
+
|
|
|
+ // create a subscriber
|
|
|
+ subTpperception, err := goroslib.NewSubscriber(goroslib.SubscriberConf{
|
|
|
+
|
|
|
+ Node: n,
|
|
|
+ Topic: "tpperception",
|
|
|
+ Callback: CallbackTpperception,
|
|
|
+ })
|
|
|
+ if err != nil {
|
|
|
+ panic(err)
|
|
|
+ }
|
|
|
+ defer subTpperception.Close()
|
|
|
+
|
|
|
+ // create a subscriber
|
|
|
+ subControl, err := goroslib.NewSubscriber(goroslib.SubscriberConf{
|
|
|
+
|
|
|
+ Node: n,
|
|
|
+ Topic: "/jinlong_control_pub",
|
|
|
+ Callback: CallbackJinlongControlPub,
|
|
|
+ })
|
|
|
+ if err != nil {
|
|
|
+ panic(err)
|
|
|
+ }
|
|
|
+ defer subControl.Close()
|
|
|
+
|
|
|
+ // create a subscriber
|
|
|
+ subDataRead, err := goroslib.NewSubscriber(goroslib.SubscriberConf{
|
|
|
+
|
|
|
+ Node: n,
|
|
|
+ Topic: "/data_read",
|
|
|
+ Callback: CallbackDataRead,
|
|
|
+ })
|
|
|
+ if err != nil {
|
|
|
+ panic(err)
|
|
|
+ }
|
|
|
+ defer subDataRead.Close()
|
|
|
+
|
|
|
+ // wait for CTRL-C
|
|
|
+ c := make(chan os.Signal, 1)
|
|
|
+ signal.Notify(c, os.Interrupt)
|
|
|
+ <-c
|
|
|
+}
|