Commit 28fd8c31 authored by p x's avatar p x
Browse files

增加车辆位姿接口

parent 6c7fe9df
...@@ -8,11 +8,11 @@ import org.springframework.web.bind.annotation.RestController ...@@ -8,11 +8,11 @@ import org.springframework.web.bind.annotation.RestController
/** /**
* 推送配置控制接口 * 推送配置控制接口
*/ */
@RestController //@RestController
//@RequestMapping("/api/push") //@RequestMapping("/api/push")
class PushConfigController( class PushConfigController(
// 注入PushConfig组件(Spring自动管理单例) // 注入PushConfig组件(Spring自动管理单例)
private val pushConfig: PushConfig // private val pushConfig: PushConfig
) { ) {
......
package com.inzy.wsmock.bean
/***车辆位姿*/
class CarVeh {
/**业务状态 park call park_com call_com**/
var status = "park"
/***车辆行驶的点位**/
var carPos = 0
/***全局路径**/
var rs: List<MutableList<Double>>? = null
}
\ No newline at end of file
...@@ -4,10 +4,11 @@ import com.alibaba.fastjson2.JSON ...@@ -4,10 +4,11 @@ import com.alibaba.fastjson2.JSON
import com.alibaba.fastjson2.JSONObject import com.alibaba.fastjson2.JSONObject
import com.inzy.wsmock.ChannelManager import com.inzy.wsmock.ChannelManager
import com.inzy.wsmock.RequestParamHandler import com.inzy.wsmock.RequestParamHandler
import com.inzy.wsmock.bean.MRoutes import com.inzy.wsmock.bean.CarVeh
import com.inzy.wsmock.bean.V2xStartBean import com.inzy.wsmock.bean.V2xStartBean
import com.inzy.wsmock.bean.VObject import com.inzy.wsmock.bean.VObject
import com.inzy.wsmock.utils.FileIoUtil import com.inzy.wsmock.utils.FileIoUtil
import com.inzy.wsmock.utils.MyMapUtils
import io.netty.channel.Channel import io.netty.channel.Channel
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame import io.netty.handler.codec.http.websocketx.TextWebSocketFrame
import jakarta.annotation.PostConstruct import jakarta.annotation.PostConstruct
...@@ -33,13 +34,15 @@ class AvpPushTask( ...@@ -33,13 +34,15 @@ class AvpPushTask(
private val channelManager = ChannelManager.instance private val channelManager = ChannelManager.instance
//车辆位姿,泊车 //车辆位姿,泊车
private var carDstPark = mutableListOf<String>() // private var carDstPark = mutableListOf<String>()
private var carVehPark: CarVeh? = null
//车辆位姿,召车 //车辆位姿,召车
private var carDstCall = mutableListOf<String>() // private var carDstCall = mutableListOf<String>()
private var carVehCall: CarVeh? = null
//车辆行驶的位置 //车辆行驶的位置
private var carPos = 0 private var carIndex = 0
//AVP状态 park call //AVP状态 park call
private var status = "" private var status = ""
...@@ -58,10 +61,14 @@ class AvpPushTask( ...@@ -58,10 +61,14 @@ class AvpPushTask(
// 读取文件内容(Kotlin简化写法) // 读取文件内容(Kotlin简化写法)
CoroutineScope(Dispatchers.IO).launch { CoroutineScope(Dispatchers.IO).launch {
//读取泊车数据 //读取泊车数据
FileIoUtil.getMockToList(classpathResource.inputStream, carDstPark) val parkStr = FileIoUtil.getFileDate(classpathResource.inputStream)
carVehPark = JSON.parseObject(parkStr, CarVeh::class.java)
//读取召车数据 //读取召车数据
classpathResource = resourceLoader.getResource("classpath:avpm/Car_fangzhen_call.txt") classpathResource = resourceLoader.getResource("classpath:avpm/Car_fangzhen_call.txt")
FileIoUtil.getMockToList(classpathResource.inputStream, carDstCall) val callStr = FileIoUtil.getFileDate(classpathResource.inputStream)
carVehCall = JSON.parseObject(callStr, CarVeh::class.java)
//读取感知物数据 //读取感知物数据
classpathResource = resourceLoader.getResource("classpath:avpm/PerTarget.txt") classpathResource = resourceLoader.getResource("classpath:avpm/PerTarget.txt")
FileIoUtil.getMockToList(classpathResource.inputStream, preDst) FileIoUtil.getMockToList(classpathResource.inputStream, preDst)
...@@ -71,8 +78,8 @@ class AvpPushTask( ...@@ -71,8 +78,8 @@ class AvpPushTask(
@PreDestroy @PreDestroy
fun destroy() { fun destroy() {
// logger.info("销毁 AdasPushTask 实例,ID: $instanceId") // logger.info("销毁 AdasPushTask 实例,ID: $instanceId")
carDstPark.clear() // carDstPark.clear()
carDstCall.clear() // carDstCall.clear()
preDst.clear() preDst.clear()
} }
...@@ -103,43 +110,75 @@ class AvpPushTask( ...@@ -103,43 +110,75 @@ class AvpPushTask(
*/ */
private fun pushCarPos(channel: Channel) { private fun pushCarPos(channel: Channel) {
CoroutineScope(Dispatchers.Default).launch { CoroutineScope(Dispatchers.Default).launch {
delay(8000) delay(10000)
status = "park" status = "park"
//开始推送泊车 //开始推送泊车
carDstPark.forEachIndexed { i, str -> if (carVehPark != null) {
val mRoutes = JSON.parseObject(str, MRoutes::class.java) carVehPark!!.status = status
mRoutes.status = status val total = carVehPark!!.rs?.count()
mRoutes.carPos = i for (i in 0 until total!!) {
sendMsg(channel, JSON.toJSONString(mRoutes)) carIndex = i
delay(300) carVehPark?.carPos = i
if (i > 0) {
var p1 = carVehPark?.rs!!.get(i - 1)
var pc = carVehPark?.rs!!.get(i)
var head = MyMapUtils.calculateBearing(
p1[0], p1[1],
pc[0], pc[1]
)
carVehPark!!.rs!!.get(i).add(head)
}
sendMsg(channel, JSON.toJSONString(carVehPark))
delay(300)
}
} }
//泊车完成 //泊车完成
val parkTemp=MRoutes().apply { status = "park_com"
status = "park_com" carVehPark?.apply {
this.status = this@AvpPushTask.status
carPos = 0
rs = listOf()
} }
sendMsg(channel, JSON.toJSONString(parkTemp)) sendMsg(channel, JSON.toJSONString(carVehPark))
delay(3000) delay(3000)
status = "call"
//开始推送召车 //开始推送召车
carDstCall.forEachIndexed { i, str -> status = "call"
val mRoutes = JSON.parseObject(str, MRoutes::class.java) if (carVehCall != null) {
mRoutes.status = status carVehCall!!.status = status
mRoutes.carPos = i val total = carVehCall!!.rs?.count()
sendMsg(channel, JSON.toJSONString(mRoutes)) for (i in 0 until total!!) {
delay(200) carIndex = i
carVehCall?.carPos = i
if (i > 0) {
var p1 = carVehCall?.rs!!.get(i - 1)
var pc = carVehCall?.rs!!.get(i)
var head = MyMapUtils.calculateBearing(
p1[0], p1[1],
pc[0], pc[1]
)
carVehCall!!.rs!!.get(i).add(head)
}
sendMsg(channel, JSON.toJSONString(carVehCall))
delay(300)
}
} }
//召车完成 //召车完成
val callTemp=MRoutes().apply { status = "call_com"
status = "call_com" carVehCall?.apply {
status = this@AvpPushTask.status
carPos = 0
rs = listOf()
} }
sendMsg(channel, JSON.toJSONString(callTemp)) sendMsg(channel, JSON.toJSONString(carVehCall))
//全部完成 //全部完成
val temp=MRoutes().apply { carIndex = 0
status = ""
}
sendMsg(channel, JSON.toJSONString(temp))
status = "" status = ""
carVehCall?.apply {
this.status = this@AvpPushTask.status
carPos = 0
rs = listOf()
}
sendMsg(channel, JSON.toJSONString(carVehCall))
} }
} }
...@@ -161,50 +200,53 @@ class AvpPushTask( ...@@ -161,50 +200,53 @@ class AvpPushTask(
private fun pushV2x(channel: Channel) { private fun pushV2x(channel: Channel) {
CoroutineScope(Dispatchers.Default).launch { CoroutineScope(Dispatchers.Default).launch {
while (isActive) { while (isActive) {
carPos = 8 // carPos = 0
// println("-------------carIndex = ${carIndex}")
if (carIndex == 0 || status.equals(""))
continue
if (status.equals("park")) { if (status.equals("park")) {
when (carPos) { when (carIndex) {
8 -> {//紧急制动预警 8 -> {//紧急制动预警
val v2x = V2xStartBean().apply { // val v2x = V2xStartBean().apply {
type = 6 // type = 6
objects = // objects =
listOf(VObject(""), VObject("f117fdfa-feff-0100-85dc-35850000acb0")) // listOf(VObject(""), VObject("f117fdfa-feff-0100-85dc-35850000acb0"))
} // }
pushV2xAtomic(channel, v2x) pushV2xAtomic(channel, 6,"f117fdfa-feff-0100-85dc-35850000acb0")
} }
30 -> {//前向碰撞 30 -> {//前向碰撞
val v2x = V2xStartBean().apply { /* val v2x = V2xStartBean().apply {
type = 1 type = 1
objects = objects =
listOf(VObject(""), VObject("f117fdfa-feff-0100-85dc-35850000acb0")) listOf(VObject(""), VObject("f117fdfa-feff-0100-85dc-35850000acb0"))
} }*/
pushV2xAtomic(channel, v2x) pushV2xAtomic(channel, 1,"f117fdfa-feff-0100-85dc-35850000acb0")
} }
60 -> {//弱势交通参与者 60 -> {//弱势交通参与者
val v2x = V2xStartBean().apply { /* val v2x = V2xStartBean().apply {
type = 12 type = 12
objects = objects =
listOf(VObject(""), VObject("50332456-3030-3030-3530-303334533955")) listOf(VObject(""), VObject("50332456-3030-3030-3530-303334533955"))
} }*/
pushV2xAtomic(channel, v2x) pushV2xAtomic(channel, 12,"50332456-3030-3030-3530-303334533955")
} }
} }
} else if (status.equals("call")) { } else if (status.equals("call")) {
when (carPos) { when (carIndex) {
70 -> {//盲区预警 70 -> {//盲区预警
val v2x = V2xStartBean().apply { /* val v2x = V2xStartBean().apply {
type = 4 type = 4
objects = objects =
listOf(VObject(""), VObject("2435")) listOf(VObject(""), VObject("2435"))
} }*/
pushV2xAtomic(channel, v2x) pushV2xAtomic(channel, 4,"2345")
} }
} }
} }
delay(300) delay(200)
} }
} }
} }
...@@ -221,6 +263,21 @@ class AvpPushTask( ...@@ -221,6 +263,21 @@ class AvpPushTask(
} }
} }
private fun pushV2xAtomic(channel: Channel, type: Int, id: String, change: Boolean = true) {
if (isV2x.compareAndSet(false, true)) {
val v2x = V2xStartBean().apply {
this.type = type
objects =
listOf(VObject(""), VObject(id))
}
val str = JSONObject.toJSONString(v2x)
sendMsg(channel, str)
if (change) {
isV2x.set(false)
}
}
}
private fun sendMsg(channel: Channel, msg: String) { private fun sendMsg(channel: Channel, msg: String) {
if (!channel.isActive()) { if (!channel.isActive()) {
......
...@@ -15,5 +15,17 @@ object FileIoUtil { ...@@ -15,5 +15,17 @@ object FileIoUtil {
} }
} }
/***一次读取全部内容**/
fun getFileDate(inputStream: InputStream): String {
// 方式1:手动逐行读取(推荐,Kotlin简洁写法)
inputStream.use { inputStream -> // use 自动关闭流(AutoCloseable)
val size = inputStream.available()
val bytes = ByteArray(size)
inputStream.read(bytes)
var str = String(bytes)
return str
}
}
} }
\ No newline at end of file
package com.inzy.wsmock.utils
import kotlin.math.atan2
import kotlin.math.cos
import kotlin.math.sin
object MyMapUtils {
/**
* 根据两个坐标点计算航向角
* @param fromLon 起始点经度
* @param fromLat 起始点纬度
* @param toLon 终点经度
* @param toLat 终点纬度
* @return 航向角(度),范围 0-360
*/
fun calculateBearing(fromLon: Double, fromLat: Double, toLon: Double, toLat: Double): Double {
// 将度转换为弧度
val lat1 = Math.toRadians(fromLat)
val lat2 = Math.toRadians(toLat)
val deltaLon = Math.toRadians(toLon - fromLon)
// 计算航向角
val y = sin(deltaLon) * cos(lat2)
val x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(deltaLon)
val bearing = Math.toDegrees(atan2(y, x))
// 确保航向角在 0-360 度范围内
return (bearing + 360) % 360
}
}
...@@ -3,7 +3,7 @@ spring: ...@@ -3,7 +3,7 @@ spring:
encoding: UTF-8 encoding: UTF-8
application: application:
name: wsmock name: avpmock
server: server:
port: 8088 port: 8088
servlet: servlet:
...@@ -28,7 +28,7 @@ logging: ...@@ -28,7 +28,7 @@ logging:
# 日志文件配置 # 日志文件配置
file: file:
name: logs/wsmock.log name: logs/avp.log
# 日志格式 # 日志格式
pattern: pattern:
...@@ -44,5 +44,5 @@ logging: ...@@ -44,5 +44,5 @@ logging:
# Netty WebSocket配置 # Netty WebSocket配置
netty: netty:
websocket: websocket:
port: 8089 # Netty WebSocket端口 port: 8090 # Netty WebSocket端口
package com.inzy.wsmock package com.inzy.wsmock
import com.alibaba.fastjson2.JSON
import kotlinx.coroutines.delay
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
import org.springframework.boot.test.context.SpringBootTest import org.springframework.boot.test.context.SpringBootTest
...@@ -8,6 +10,9 @@ class WsmockApplicationTests { ...@@ -8,6 +10,9 @@ class WsmockApplicationTests {
@Test @Test
fun contextLoads() { fun contextLoads() {
for (i in 0 until 3) {
println("i = ${i}")
}
} }
} }
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment