package com.xiaopeng.automaticPilot.util; import cn.hutool.http.HttpRequest; import cn.hutool.http.HttpResponse; import com.google.protobuf.util.JsonFormat; import com.xiaopeng.api.vo.automaticPilot.protobuf.*; import java.util.List; import java.util.UUID; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; /** * GPS路径模拟器 * 根据起点和终点生成路径,每秒发送一次包含GPS坐标的JSON消息 */ public class GpsPathSimulator { private static final JsonFormat.Printer jsonPrinter = JsonFormat.printer() .printingEnumsAsInts() .preservingProtoFieldNames(); /** * 推送XPU消息的接口地址 */ private static final String PUSH_MESSAGE_URL = "http://logan-gateway.aliyun-hd1-pre.logan.xiaopeng.inner/xp-robotaxi-automatic-pilot-boot/base/v1/pushXPUMessage"; /** * 运行模拟器 * * @param startLongitude 起点经度 * @param startLatitude 起点纬度 * @param endLongitude 终点经度 * @param endLatitude 终点纬度 * @param speed 速度(米/秒),默认10.5 * @param uid 用户ID * @param xpuId XPU设备ID * @param orderId 订单ID */ public static void runSimulator(double startLongitude, double startLatitude, double endLongitude, double endLatitude, double speed, long uid, String xpuId, String orderId) { // 生成路径点 List pathPoints = GpsPathGenerator.generatePath( startLongitude, startLatitude, endLongitude, endLatitude, 1, // 每秒一个点 speed ); System.out.println("===== GPS路径模拟器启动 ====="); System.out.println("起点: 经度=" + startLongitude + ", 纬度=" + startLatitude); System.out.println("终点: 经度=" + endLongitude + ", 纬度=" + endLatitude); System.out.println("速度: " + speed + " 米/秒"); System.out.println("总路径点数: " + pathPoints.size()); System.out.println("预计时长: " + pathPoints.size() + " 秒"); System.out.println("=============================\n"); // 创建定时任务 ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); AtomicInteger currentIndex = new AtomicInteger(0); AtomicInteger sequence = new AtomicInteger(1); scheduler.scheduleAtFixedRate(() -> { int index = currentIndex.getAndIncrement(); if (index >= pathPoints.size()) { System.out.println("\n===== 路径模拟完成 ====="); scheduler.shutdown(); return; } GpsPathGenerator.GpsPoint currentPoint = pathPoints.get(index); // 计算方位角 int course = 90; // 默认向东 if (index < pathPoints.size() - 1) { GpsPathGenerator.GpsPoint nextPoint = pathPoints.get(index + 1); course = GpsPathGenerator.calculateCourse( currentPoint.latitude, currentPoint.longitude, nextPoint.latitude, nextPoint.longitude ); } // 创建消息 MsgContent message = createMessage( currentPoint.longitude, currentPoint.latitude, course, speed, uid, sequence.getAndIncrement(), xpuId, orderId ); try { String json = jsonPrinter.print(message); System.out.println("【第 " + (index + 1) + " 秒】发送消息:"); System.out.println(json); System.out.println(); // 调用HTTP接口发送消息 sendMessageToServer(json, index + 1); } catch (Exception e) { System.err.println("JSON序列化失败: " + e.getMessage()); } }, 0, 1, TimeUnit.SECONDS); } /** * 创建系统运行状态消息(使用Protobuf对象) */ private static MsgContent createMessage(double longitude, double latitude, int course, double speed, long uid, int sequence, String xpuId, String orderId) { long timestamp = System.currentTimeMillis(); // 构建 MsgContent MsgContent.Builder msgContentBuilder = MsgContent.newBuilder(); // 构建 Header MsgHeader.Builder headerBuilder = MsgHeader.newBuilder(); headerBuilder.setTimestamp(timestamp); headerBuilder.setCmd(14001); // SYSTEM_STATUS_XPU headerBuilder.setSequence(sequence); headerBuilder.setType(MessageType.MESSAGE_TYPE_REQUEST); headerBuilder.setMsgId("MSG-UUID-" + UUID.randomUUID().toString().substring(0, 13)); headerBuilder.setSource(SourceType.XPU); msgContentBuilder.setHeader(headerBuilder.build()); // 构建 Wgs (GPS坐标) Wgs.Builder wgsBuilder = Wgs.newBuilder(); wgsBuilder.setLongitude(longitude); wgsBuilder.setLatitude(latitude); wgsBuilder.setCourse(course); wgsBuilder.setPosAcc(0.5); wgsBuilder.setAlt(10); // 构建 RealtimePose RealtimePose.Builder poseBuilder = RealtimePose.newBuilder(); poseBuilder.setTimestamp(timestamp); poseBuilder.setNaviPose(wgsBuilder.build()); // 构建 VehicleStaticInfo VehicleStaticInfo.Builder staticInfoBuilder = VehicleStaticInfo.newBuilder(); staticInfoBuilder.setXpuId(xpuId); staticInfoBuilder.setTimestamp(timestamp); // 构建 VehicleDynamicStatus VehicleDynamicStatus.Builder dynamicStatusBuilder = VehicleDynamicStatus.newBuilder(); dynamicStatusBuilder.setGearLevel(GearLevel.GEAR_D); dynamicStatusBuilder.setSteeringAngle(0.5f); dynamicStatusBuilder.setSpeed((float) speed); dynamicStatusBuilder.setTimestamp(timestamp); dynamicStatusBuilder.setBmsSocDisp(80); dynamicStatusBuilder.setDstBatDisp(400.5f); // 构建 VehicleStatus VehicleStatus.Builder vehicleStatusBuilder = VehicleStatus.newBuilder(); vehicleStatusBuilder.setStaticInfo(staticInfoBuilder.build()); vehicleStatusBuilder.setDynamicStatus(dynamicStatusBuilder.build()); // 构建 SystemStatus SystemStatus.Builder systemStatusBuilder = SystemStatus.newBuilder(); systemStatusBuilder.setPhase(SystemPhase.SYSTEM_NORMAL); systemStatusBuilder.setAbnormalReason(AbnormalReason.ABNORMAL_REASON_UNSPECIFIED); systemStatusBuilder.addAvailableServices(ServiceAvailability.ROBOTAXI_AVAILABLE); systemStatusBuilder.setIsEmergency(false); // 构建 OrderStatusInfo (运行中的订单状态信息) OrderStatusInfo.Builder orderStatusInfoBuilder = OrderStatusInfo.newBuilder(); orderStatusInfoBuilder.setOrderId(orderId); orderStatusInfoBuilder.setStatus(OrderStatus.ORDER_EN_ROUTE_TO_PICKUP); // 前往目的地 orderStatusInfoBuilder.setOrderPhase(OrderPhase.ROUTE_TO_PICKUP); orderStatusInfoBuilder.setChangeSource(OrderStateChangeSource.ORDER_STATE_CHANGE_SOURCE_VEHICLE); orderStatusInfoBuilder.setTimestamp(timestamp); // 构建 SystemRuntimeStatus SystemRuntimeStatus.Builder statusBuilder = SystemRuntimeStatus.newBuilder(); statusBuilder.setTimestamp(timestamp); statusBuilder.setUid(uid); statusBuilder.setVehicleStatus(vehicleStatusBuilder.build()); statusBuilder.setSystemStatus(systemStatusBuilder.build()); statusBuilder.setDrivingMode(DrivingMode.AUTONOMOUS); statusBuilder.setPose(poseBuilder.build()); statusBuilder.setRunningOrderStatusInfo(orderStatusInfoBuilder.build()); // 设置运行中的订单信息 // 设置 SystemRuntimeStatus 到 MsgContent msgContentBuilder.setSystemRuntimeStatus(statusBuilder.build()); return msgContentBuilder.build(); } /** * 发送消息到服务器 * * @param jsonMessage JSON格式的消息 * @param index 消息序号 */ private static void sendMessageToServer(String jsonMessage, int index) { try { HttpResponse response = HttpRequest.post(PUSH_MESSAGE_URL) .body(jsonMessage) .contentType("application/json") .timeout(5000) // 5秒超时 .execute(); if (response.isOk()) { System.out.println("✓ 消息发送成功,响应: " + response.body()); } else { System.err.println("✗ 消息发送失败,状态码: " + response.getStatus() + ", 响应: " + response.body()); } } catch (Exception e) { System.err.println("✗ 消息发送异常: " + e.getMessage()); } } /** * 主方法 - 示例用法 */ public static void main(String[] args) { // 示例:从广州天河区到珠江新城 double startLongitude = 113.382238; // 起点经度 double startLatitude = 23.156917; // 起点纬度 double endLongitude = 113.383838; // 终点经度 double endLatitude = 23.154817; // 终点纬度 double speed = 10.5; // 速度(米/秒) long uid = 8190544; // 用户ID String xpuId = "c47b405bee79000f282a36e800000000"; // XPU ID String orderId = "2031203246241185794"; // 订单ID // 如果有命令行参数,则使用命令行参数 if (args.length >= 7) { try { startLongitude = Double.parseDouble(args[0]); startLatitude = Double.parseDouble(args[1]); endLongitude = Double.parseDouble(args[2]); endLatitude = Double.parseDouble(args[3]); speed = Double.parseDouble(args[4]); uid = Long.parseLong(args[5]); xpuId = args[6]; if (args.length >= 8) { orderId = args[7]; } } catch (NumberFormatException e) { System.err.println("参数格式错误!"); printUsage(); return; } } runSimulator(startLongitude, startLatitude, endLongitude, endLatitude, speed, uid, xpuId, orderId); } private static void printUsage() { System.out.println("使用方法:"); System.out.println("java GpsPathSimulator <起点经度> <起点纬度> <终点经度> <终点纬度> <速度(米/秒)> <用户ID> [订单ID]"); System.out.println(); System.out.println("示例:"); System.out.println("java GpsPathSimulator 113.3245 23.1235 113.3350 23.1300 10.5 12345678 c47b405bee79000f282a36e800000000 XU100001"); } }