“mitao”
2026-03-01 4ba4f34d8046d565b7f958a58297f6b733bc42b2
Merge remote-tracking branch 'origin/master'
1个文件已添加
6个文件已修改
254 ■■■■■ 已修改文件
README.md 150 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/factory/order/XpOrderClientFallbackFactory.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/feignClient/order/XpOrderClient.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/vo/order/OrderTrajectoryVo.java 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-automatic-pilot-boot/src/main/java/com/xiaopeng/automaticPilot/controller/OrderMissionController.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/controller/XpOrderController.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/service/impl/XpOrderServiceImpl.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
README.md
@@ -1,4 +1,150 @@
## Robotaxi
# XPeng Robotaxi
小鹏汽车Robotaxi
基于 Spring Cloud Alibaba 的 Robotaxi 微服务系统,面向自动驾驶出行场景,包含账户、订单、地图、自动驾驶、远程驾驶等业务域,以及一组对应的 Spring Boot 应用(`xp-robotaxi-*-boot`)用于实际部署。
---
## 一、技术栈概览
- Java 8
- Spring Boot 2.7.7
- Spring Cloud 2021.0.5
- Spring Cloud Alibaba 2021.0.4.0
- Nacos(注册中心 / 配置中心)
- Sentinel(流量控制与熔断降级)
- Seata(分布式事务)
- MyBatis-Plus(ORM)
- Druid(数据库连接池)
- Swagger / Springfox(接口文档)
- Redis、MySQL、MongoDB 等
---
## 二、顶层模块结构
根工程 `robotaxi` 下包含以下子模块:
- `xp-robotaxi-api`:对外和内部共享的 API、DTO、proto 风格 VO 定义
- `xp-robotaxi-common`:公共能力(日志、权限、安全、数据源、Redis 等)
- 一组 `xp-robotaxi-*-boot`:每个业务域对应的 Spring Boot 应用,可独立部署
下面重点说明各个 `boot` 模块的功能职责。
---
## 三、Boot 应用模块职责
### 1. xp-robotaxi-gateway-boot(网关应用)
- 基于 Spring Cloud Gateway 的统一入口网关
- 负责路由转发、鉴权校验、限流熔断、灰度发布
- 统一接入层日志与基本安全控制
### 2. xp-robotaxi-account-boot(账户中心)
- 账户/用户域的对外应用
- 用户注册登录、账号信息管理、角色与权限管理
- 为管理后台和其他业务服务提供账户相关 REST 接口
### 3. xp-robotaxi-automatic-pilot-boot(自动驾驶业务)
- Robotaxi 自动驾驶业务对外应用
- 负责云端与 XPU 的消息交互(MQTT / Kafka),包括下行指令和上行状态
- 订单与自动驾驶系统联动(创建任务、控制任务、状态应答等)
- 封装自动驾驶相关业务接口,供运营平台和其他服务调用
### 4. xp-robotaxi-itinerary-boot(行程管理)
- 行程生命周期管理应用
- 行程创建、修改、取消
- 行程状态跟踪、历史行程查询
- 与订单、地图等服务协同进行路径规划与调度
### 5. xp-robotaxi-maintenance-boot(运维与车辆维护)
- 车辆运维与保障相关应用
- 车辆维护计划、保养记录、故障报修流程
- 保单管理和维修记录追踪
- 为运营平台提供车辆健康状态和维护数据
### 6. xp-robotaxi-map-boot(地图与位置服务)
- 地图与位置相关应用
- 路线规划、距离与时间预估
- POI 查询、地理围栏管理
- 与自动驾驶、行程、订单等服务协同提供位置能力
### 7. xp-robotaxi-operation-boot(运营管理)
- 平台运营域应用
- 车辆调度策略、运营数据统计与报表
- 价格策略配置、优惠活动管理
- 支持运营后台对 Robotaxi 业务进行集中管理
### 8. xp-robotaxi-order-boot(订单服务)
- 订单全生命周期管理应用
- 下单、改派、取消、完成等订单流程
- 订单状态机与状态变更通知
- 与支付、行程、自动驾驶等服务联动
### 9. xp-robotaxi-payment-boot(支付与结算)
- 支付结算域应用
- 集成微信等第三方支付渠道
- 支付请求、退款、对账、结算与发票管理
- 对订单服务提供支付能力,对财务提供对账数据
### 10. xp-robotaxi-push-message-boot(消息推送)
- 消息通知与推送应用
- 支持短信、APP 推送、邮件、站内信等多种渠道
- 提供统一消息模板与发送接口
- 与订单、行程、运营等服务集成,实现业务事件触达用户
### 11. xp-robotaxi-remote-driving-boot(远程驾驶)
- 云代驾 / 远程驾驶应用
- 远程控制指令下发、实时状态回传
- 支持紧急接管、远程辅助等场景
- 与自动驾驶、行程、车辆状态服务协同
### 12. xp-robotaxi-vehicle-convoy-boot(车队管理)
- 车队及编队管理应用
- 车队组建与成员管理
- 编队行驶控制与协同调度
- 提供面向车队运营场景的接口能力
### 13. xp-robotaxi-job-boot(定时任务)
- 统一定时任务调度应用
- 基于 Quartz,对多业务域的定时任务进行集中管理
- 任务配置、执行监控、失败重试等
### 14. xp-robotaxi-file-boot(文件服务)
- 文件上传/下载/存储应用
- 支持对象存储或分布式文件系统接入
- 提供统一的文件访问域名与权限控制能力
---
## 四、基础能力模块概览
虽然具体代码在 `xp-robotaxi-common` 与 `xp-robotaxi-api` 中,这里简要说明它们的角色,方便理解整体结构:
- `xp-robotaxi-common`:日志、安全、数据源、Redis、数据权限、分布式事务等通用能力
- `xp-robotaxi-api`:对各个 boot 应用暴露的统一 API/DTO/VO 定义,是服务间通信的契约层
---
## 五、运行与部署提示(概览)
- 所有 `xp-robotaxi-*-boot` 模块均为独立 Spring Boot 应用,可按需选择部署
- 网关(`xp-robotaxi-gateway-boot`)通常需要多实例部署以保证高可用
- 订单、支付、自动驾驶、运营等核心域建议根据业务量做水平扩展
- Nacos / Sentinel / Seata 等基础组件需先行部署,并在各 boot 应用中配置好连接信息
---
*文档更新时间: 2026-02-06*
xp-robotaxi-api/src/main/java/com/xiaopeng/api/factory/order/XpOrderClientFallbackFactory.java
@@ -6,6 +6,7 @@
import com.xiaopeng.api.dto.statistics.StatisticsQueryDTO;
import com.xiaopeng.api.feignClient.order.XpOrderClient;
import com.xiaopeng.api.model.order.XpOrder;
import com.xiaopeng.api.vo.order.OrderTrajectoryVo;
import com.xiaopeng.common.core.domain.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.openfeign.FallbackFactory;
@@ -94,6 +95,13 @@
                log.error("更新订单状态失败,原因: {}", cause.getMessage());
                return R.fail("更新订单状态失败");
            }
            @Override
            public R<String> saveVehicleLocation(OrderTrajectoryVo orderTrajectory) {
                log.error("保存订单轨迹数据失败,原因: {}", cause.getMessage());
                return R.fail("保存订单轨迹数据失败");
            }
        };
    }
}
xp-robotaxi-api/src/main/java/com/xiaopeng/api/feignClient/order/XpOrderClient.java
@@ -6,6 +6,7 @@
import com.xiaopeng.api.dto.statistics.StatisticsQueryDTO;
import com.xiaopeng.api.factory.order.XpOrderClientFallbackFactory;
import com.xiaopeng.api.model.order.XpOrder;
import com.xiaopeng.api.vo.order.OrderTrajectoryVo;
import com.xiaopeng.common.core.domain.R;
import com.xiaopeng.common.core.dto.ServiceNameConstantsEnum;
import org.springframework.cloud.openfeign.FeignClient;
@@ -111,6 +112,12 @@
                                       @RequestParam Integer status);
    /**
     * 保存订单轨迹数据
     * @param orderTrajectory
     * @return
     */
    @PostMapping("/inner/v1/order/saveVehicleLocation")
    R<String> saveVehicleLocation(@RequestBody OrderTrajectoryVo orderTrajectory);
}
xp-robotaxi-api/src/main/java/com/xiaopeng/api/vo/order/OrderTrajectoryVo.java
New file
@@ -0,0 +1,44 @@
package com.xiaopeng.api.vo.order;
import com.xiaopeng.common.core.web.domain.MongoBaseModel;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import org.springframework.data.mongodb.core.mapping.Document;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
public class OrderTrajectoryVo extends MongoBaseModel {
    /**
     * 订单id
     */
    private Long orderId;
    /**
     * 经纬度 坐标  (104.45645456,34.41564654)
     */
    private String location;
    /**
     * 方向角(0-359°)
     */
    private Integer direction;
    /**
     * 速度
     */
    private Double speed;
    /**
     * 时间戳 毫秒
     */
    private Long locatetime;
    /**
     * 距离 米
     */
    private Double distance;
}
xp-robotaxi-automatic-pilot-boot/src/main/java/com/xiaopeng/automaticPilot/controller/OrderMissionController.java
@@ -23,6 +23,7 @@
import com.xiaopeng.api.vo.automaticPilot.proto.down.cloudCreateOrder.TaskType;
import com.xiaopeng.api.vo.automaticPilot.protobuf.*;
import com.xiaopeng.api.vo.operation.RouteVo;
import com.xiaopeng.api.vo.order.OrderTrajectoryVo;
import com.xiaopeng.automaticPilot.util.XPUUtil;
import com.xiaopeng.common.core.domain.R;
import com.xiaopeng.common.core.enums.OrderStatusEnum;
@@ -41,7 +42,7 @@
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Date;import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.LinkedBlockingQueue;
@@ -418,6 +419,16 @@
                    dto.setDistance(10);
                    dto.setDirection(60);
                    xpPushMessageClient.pushOrderRoute(dto);
                    //存储历史轨迹
                    OrderTrajectoryVo orderTrajectory = new OrderTrajectoryVo();
                    orderTrajectory.setOrderId(orderId);
                    orderTrajectory.setLocation(longitude + "," + latitude);
                    orderTrajectory.setDirection(dto.getDirection());
                    orderTrajectory.setSpeed(0D);
                    orderTrajectory.setLocatetime(System.currentTimeMillis());
                    orderTrajectory.setCreateTime(new Date());
                    xpOrderClient.saveVehicleLocation(orderTrajectory);
                }
                //5秒钟循环一次
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/controller/XpOrderController.java
@@ -15,10 +15,7 @@
import com.xiaopeng.api.model.vehicleConvoy.XpVehicle;
import com.xiaopeng.api.vo.automaticPilot.VehiclePosition;
import com.xiaopeng.api.vo.operation.RouteVo;
import com.xiaopeng.api.vo.order.FareBreakdownVo;
import com.xiaopeng.api.vo.order.XpHistoryEndPointsVo;
import com.xiaopeng.api.vo.order.XpHistoryStartPointsVo;
import com.xiaopeng.api.vo.order.XpPointInfoVo;
import com.xiaopeng.api.vo.order.*;
import com.xiaopeng.common.core.constant.CacheConstants;
import com.xiaopeng.common.core.domain.R;
import com.xiaopeng.common.core.utils.WebUtils;
@@ -43,6 +40,7 @@
import io.swagger.annotations.ApiParam;
import lombok.RequiredArgsConstructor;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.mongodb.core.MongoTemplate;
@@ -474,7 +472,9 @@
     */
    @ApiOperation(value = "订单车辆定位实时存储")
    @PostMapping("/inner/v1/order/saveVehicleLocation")
    public R<String> saveVehicleLocation(@RequestBody OrderTrajectory orderTrajectory) {
    public R<String> saveVehicleLocation(@RequestBody OrderTrajectoryVo vo) {
        OrderTrajectory orderTrajectory = new OrderTrajectory();
        BeanUtils.copyProperties(vo, orderTrajectory);
        xpOrderService.saveVehicleLocation(orderTrajectory);
        return R.ok();
    }
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/service/impl/XpOrderServiceImpl.java
@@ -1880,10 +1880,11 @@
        if (StringUtils.isEmpty(oldLocation)) {
            // 首次定位
            xpOrder.setMileageKilometers(0D);
            xpOrder.setAppUserId(null);
            this.updateById(xpOrder);
            orderTrajectory.setDistance(0D);
            // 存储mongo数据
            orderTrajectoryService.create(orderTrajectory);
            mongoTemplate.save(orderTrajectory);
            // 存储首次定位
            redisService.setCacheObject(CacheConstants.ORDER_OLD_LOCATION + orderTrajectory.getOrderId(), orderTrajectory.getLocation());
        } else {
@@ -1892,11 +1893,12 @@
                Double distance1 = distance.get("WGS84");
                if (distance1 > 50 && xpOrder.getStatus() == 6) {//大于50米表示在移动,且在服务中的时候记录里程
                    xpOrder.setMileageKilometers(BigDecimal.valueOf(xpOrder.getMileageKilometers()).add(new BigDecimal(distance1)).setScale(2, RoundingMode.HALF_EVEN).doubleValue());
                    xpOrder.setAppUserId(null);
                    this.updateById(xpOrder);
                    // 存储本次距离
                    orderTrajectory.setDistance(distance1);
                    // 存储mongo数据
                    orderTrajectoryService.create(orderTrajectory);
                    mongoTemplate.save(orderTrajectory);
                }
            } else {
                log.error("调用高德计算距离出错");
@@ -1930,15 +1932,11 @@
            }
        }
//        List<OrderTrajectory> trajectories = mongoTemplate.find(
//                new Query(Criteria.where("orderId").is(orderId))
//                        .with(Sort.by(Sort.Direction.ASC, "locatetime")),
//                OrderTrajectory.class
//        );
        List<TaxiPricingDemoService.GpsPoint> mockGpsPoints = TaxiPricingDemoService.createMockGpsPoints(DateUtils.toDate(order.getCreateTime()));
        // 生成轨迹记录
        List<OrderTrajectory> trajectories = TrajectoryGenerator.generateTrajectory(mockGpsPoints);
        List<OrderTrajectory> trajectories = mongoTemplate.find(
                new Query(Criteria.where("orderId").is(orderId))
                        .with(Sort.by(Sort.Direction.ASC, "locatetime")),
                OrderTrajectory.class
        );
        orderDetailVo.setTrajectories(trajectories);
        if (order.getTripBegin() != null && order.getTripEnd() != null) {
            // 计算两个时间相差多少分钟