src/main/java/com/dji/sample/patches/xml/mode/XMLTemplateModel.java
@@ -1,10 +1,12 @@ package com.dji.sample.patches.xml.mode; import com.dji.sample.patches.model.entity.LotInfo; import com.dji.sample.patches.utils.GeoToolsUtil; import com.dji.sample.patches.xml.mode.share.ActionGroup; import com.dji.sample.patches.xml.mode.share.ActionMode; import com.dji.sample.patches.xml.mode.share.ActionTrigger; import com.dji.sample.patches.xml.mode.share.action.utils.*; import com.dji.sample.patches.xml.utils.CreateWaylineFileUtils; import freemarker.template.Configuration; import freemarker.template.Template; import lombok.Builder; @@ -56,9 +58,9 @@ // 增加事件组 ActionGroup actionGroup = new ActionGroup(); actionGroup.setActionGroupId(i);//动作组id从0开始单调连续递增。 actionGroup.setActionGroupStartIndex(i);//动作组开始生效的航点 actionGroup.setActionGroupEndIndex(i);//动作组结束生效的航点 actionGroup.setActionGroupId(i-1);//动作组id从0开始单调连续递增。 actionGroup.setActionGroupStartIndex(i-1);//动作组开始生效的航点 actionGroup.setActionGroupEndIndex(i-1);//动作组结束生效的航点 actionGroup.setActionGroupMode("sequence"); ActionTrigger at = new ActionTrigger(); at.setActionTriggerType("reachPoint"); @@ -107,4 +109,34 @@ return xtm; } public static void main(String[] args) { //测试 List<LotInfo> list = new ArrayList<>(); list.add(LotInfo.builder().dkbh("dkbh01").dkfw("POLYGON((115.866465564947 28.6344502965542, 115.86425430209 28.6357383285408, 115.864551734716 28.633120921433, 115.866977149064 28.6338435339976, 115.866465564947 28.6344502965542))").build()); list.add(LotInfo.builder().dkbh("dkbh02").dkfw("POLYGON((115.864006690605 28.6202713913694, 115.86002109342 28.6162025130492, 115.866374254306 28.6142037658042, 115.865912044006 28.6172001020759, 115.864006690605 28.6202713913694))").build()); list.add(LotInfo.builder().dkbh("dkbh03").dkfw("POLYGON((115.839366933455 28.6161999317332, 115.841288489469 28.6160843601496, 115.840931570318 28.6181544912247, 115.838147600941 28.618654178036, 115.839366933455 28.6161999317332))").build()); // list.add(LotInfo.builder().dkbh("dkbh04").dkfw("POLYGON((115.857499052697 28.6784702230642, 115.859109158101 28.6762273976226, 115.863677723232 28.6766081113836, 115.862154868188 28.6790827508297, 115.857499052697 28.6784702230642))").build()); // list.add(LotInfo.builder().dkbh("dkbh05").dkfw("POLYGON((115.834974056705 28.6659171428962, 115.833760531592 28.6634960413229, 115.832422084777 28.6624550271329, 115.829745191145 28.6631986086972, 115.831232354274 28.6608191476914, 115.833314382654 28.6603729987527, 115.835545127347 28.6618601618814, 115.837032290475 28.6639421902615, 115.834974056705 28.6659171428962))").build()); // list.add(LotInfo.builder().dkbh("dkbh06").dkfw("POLYGON((115.885622116006 28.5766308429787, 115.883936664461 28.5771582901683, 115.883365593819 28.5752547213636, 115.883555950699 28.5740174016407, 115.88365112914 28.5724945465969, 115.885364341064 28.5721138328361, 115.886696839227 28.5725897250371, 115.887458266749 28.5736366878797, 115.886792017668 28.5753498998039, 115.885622116006 28.5766308429787))").build()); // list.add(LotInfo.builder().dkbh("dkbh07").dkfw("POLYGON((115.857644341395 28.5750890964568, 115.857572957565 28.5729475815515, 115.858429563527 28.5728761977213, 115.859072017998 28.5738041875136, 115.859072017998 28.5748035611361, 115.857644341395 28.5750890964568))").build()); // list.add(LotInfo.builder().dkbh("dkbh08").dkfw("POLYGON((115.912181587649 28.6231542087745, 115.912181587649 28.6215123806805, 115.915893546818 28.6212268453598, 115.916036314478 28.6231542087745, 115.912181587649 28.6231542087745))").build()); // list.add(LotInfo.builder().dkbh("dkbh09").dkfw("POLYGON((115.842039042965 28.6314426646115, 115.840992080122 28.631252307731, 115.842324578286 28.6305860586493, 115.843181184248 28.6305860586493, 115.84403779021 28.6304908802091, 115.84394261177 28.6317281999322, 115.842039042965 28.6314426646115))").build()); // list.add(LotInfo.builder().dkbh("dkbh10").dkfw("POLYGON((115.807011889796 28.623935465138, 115.805869748513 28.6224126100944, 115.810247956764 28.6220318963334, 115.809581707682 28.623935465138, 115.807011889796 28.623935465138))").build()); // 机场经纬度 double airportLat = 28.624514734; // 机场纬度 double airportLon = 115.856725497; // 机场经度 // 解析图斑生成航点,按顺序返回 Coordinate[] coordinates = GeoToolsUtil.getRoutePointOrder(list, airportLat, airportLon); // 初始化模板对象 XMLTemplateModel xmlModel = XMLTemplateModel.init(coordinates, list); //生成航线文件 CreateWaylineFileUtils.createWaylineFile(xmlModel,"src\\main\\resources\\template\\template.xml","src\\main\\resources\\template\\wpmz\\template.xml","src\\main\\resources\\template\\waylines.xml","src\\main\\resources\\template\\wpmz\\waylines.xml"); } } src/main/java/com/dji/sample/patches/xml/mode/share/action/utils/PayloadParamUtils.java
@@ -12,6 +12,11 @@ public static PayloadParam setPayloadParam() { PayloadParam pp = PayloadParam.builder() .focusMode("firstPoint") .meteringMode("average") .returnMode("singleReturnFirst") .samplingRate("240000") .scanningMode("repetitive") .payloadPositionIndex(0) .imageFormat("wide,ir") .build(); src/main/java/com/dji/sample/patches/xml/mode/share/action/utils/PlacemarkUtils.java
@@ -21,6 +21,8 @@ placemark.setUseGlobalHeadingParam(1); placemark.setUseGlobalTurnParam(1); placemark.setGimbalPitchAngle(0D); placemark.setWaypointSpeed("10"); placemark.setUseStraightLine(1); return placemark; } src/main/java/com/dji/sample/wayline/controller/WaylineJobController.java
@@ -77,6 +77,18 @@ } /** * 断点任务 * @return */ @PostMapping("/{workspace_id}/breakpoint-tasks") @SysLogAnnotation(operModul = "计划库", operType = "断点续飞", operDesc = "创建航路任务(重复定时和连续执行)") public ResponseResult breakPointJob(HttpServletRequest request, @Valid @RequestBody BreakPointJobParam param, @PathVariable(name = "workspace_id") String workspaceId) throws SQLException { Optional<WaylineJobDTO> waylineJobDTO = waylineJobService.getJobByJobId(workspaceId, param.getJobId(),param.isBreakPoint()); return waylineJobService.publishOneFlightTask(waylineJobDTO.get()); } /** * 分页查询 * * @param page src/main/java/com/dji/sample/wayline/model/dto/BreakPointJobDTO.java
New file @@ -0,0 +1,24 @@ package com.dji.sample.wayline.model.dto; import com.baomidou.mybatisplus.annotation.TableField; import lombok.Builder; import lombok.Data; /** * @PROJECT_NAME: drone * @DESCRIPTION: * @USER: aix * @DATE: 2024/4/16 10:28 */ @Builder @Data public class BreakPointJobDTO { private Integer index; private Integer state; private Double progress; private Integer waylineId; } src/main/java/com/dji/sample/wayline/model/dto/WaylineJobDTO.java
@@ -1,5 +1,6 @@ package com.dji.sample.wayline.model.dto; import com.dji.sample.wayline.model.entity.WaylineJobBreakPointEntity; import com.dji.sample.wayline.model.enums.WaylineTaskTypeEnum; import com.dji.sample.wayline.model.enums.WaylineTemplateTypeEnum; import lombok.AllArgsConstructor; @@ -69,4 +70,8 @@ private String parentId; private String hasChildren; private WaylineJobBreakPointEntity waylineJobBreakPointEntity; private Boolean breakPoint; } src/main/java/com/dji/sample/wayline/model/dto/WaylineTaskCreateDTO.java
@@ -35,4 +35,7 @@ private WaylineTaskReadyConditionDTO readyConditions; private WaylineTaskExecutableConditionDTO executableConditions; private BreakPointJobDTO breakPoint; } src/main/java/com/dji/sample/wayline/model/param/BreakPointJobParam.java
New file @@ -0,0 +1,23 @@ package com.dji.sample.wayline.model.param; import lombok.Data; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; /** * @PROJECT_NAME: drone * @DESCRIPTION: * @USER: aix * @DATE: 2024/4/16 10:01 */ @Data public class BreakPointJobParam { @NotBlank private String jobId; @NotNull private boolean breakPoint;//是否断点续飞 } src/main/java/com/dji/sample/wayline/service/IWaylineJobBreakPointService.java
@@ -1,5 +1,6 @@ package com.dji.sample.wayline.service; import com.baomidou.mybatisplus.extension.service.IService; import com.dji.sample.wayline.model.entity.WaylineJobBreakPointEntity; /** @@ -8,7 +9,7 @@ * @USER: aix * @DATE: 2024/3/23 11:07 */ public interface IWaylineJobBreakPointService { public interface IWaylineJobBreakPointService extends IService<WaylineJobBreakPointEntity> { public boolean addWaylineJobBreakPoint(WaylineJobBreakPointEntity entity); } src/main/java/com/dji/sample/wayline/service/IWaylineJobService.java
@@ -112,6 +112,8 @@ */ Optional<WaylineJobDTO> getJobByJobId(String workspaceId, String jobId); Optional<WaylineJobDTO> getJobByJobId(String workspaceId, String jobId,Boolean isBreakPoint); /** * Update job data. * @param dto src/main/java/com/dji/sample/wayline/service/impl/WaylineJobBreakPointServiceImpl.java
@@ -1,5 +1,6 @@ package com.dji.sample.wayline.service.impl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.dji.sample.wayline.dao.IWaylineJobBreakPointMapper; import com.dji.sample.wayline.model.entity.WaylineJobBreakPointEntity; import com.dji.sample.wayline.service.IWaylineJobBreakPointService; @@ -15,7 +16,7 @@ */ @Service @Transactional public class WaylineJobBreakPointServiceImpl implements IWaylineJobBreakPointService { public class WaylineJobBreakPointServiceImpl extends ServiceImpl<IWaylineJobBreakPointMapper,WaylineJobBreakPointEntity> implements IWaylineJobBreakPointService { @Autowired private IWaylineJobBreakPointMapper mapper; src/main/java/com/dji/sample/wayline/service/impl/WaylineJobServiceImpl.java
@@ -3,6 +3,7 @@ import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper; @@ -44,10 +45,12 @@ import com.dji.sample.geo.utils.GeoUtils; import com.dji.sample.wayline.dao.IWaylineJobMapper; import com.dji.sample.wayline.model.dto.*; import com.dji.sample.wayline.model.entity.WaylineJobBreakPointEntity; import com.dji.sample.wayline.model.entity.WaylineJobEntity; import com.dji.sample.wayline.model.enums.*; import com.dji.sample.wayline.model.param.*; import com.dji.sample.wayline.service.IWaylineFileService; import com.dji.sample.wayline.service.IWaylineJobBreakPointService; import com.dji.sample.wayline.service.IWaylineJobService; import com.dji.sample.wayline.service.IWaylineRedisService; import com.fasterxml.jackson.core.type.TypeReference; @@ -112,6 +115,9 @@ @Autowired private IDroneFlightLogMapper flightLogMapper; @Autowired private IWaylineJobBreakPointService waylineJobBreakPointService; private Optional<WaylineJobDTO> insertWaylineJob(WaylineJobEntity jobEntity) { int id = mapper.insert(jobEntity); @@ -355,8 +361,7 @@ // get file url //获取航线文件地址 URL url = waylineFileService.getObjectUrl(waylineJob.getWorkspaceId(), waylineFile.get().getWaylineId()); WaylineTaskCreateDTO flightTask = WaylineTaskCreateDTO.builder() .flightId(waylineJob.getJobId()) WaylineTaskCreateDTO.WaylineTaskCreateDTOBuilder flightTaskBuilder = WaylineTaskCreateDTO.builder().flightId(waylineJob.getJobId()) .executeTime(waylineJob.getBeginTime().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()) .taskType(waylineJob.getTaskType()) .waylineType(waylineJob.getWaylineType()) @@ -365,8 +370,18 @@ .file(WaylineTaskFileDTO.builder() .url(MinioUrlUtils.getUrl(url)) .fingerprint(waylineFile.get().getSign()) .build()) .build(); .build()); WaylineJobBreakPointEntity entity = waylineJob.getWaylineJobBreakPointEntity(); if (null != entity) { flightTaskBuilder.breakPoint(BreakPointJobDTO.builder() .index(entity.getBpIndex()) .state(entity.getState()) .progress(entity.getProgress()) .waylineId(entity.getWaylineId()) .build()); } WaylineTaskCreateDTO flightTask = flightTaskBuilder.build(); //当任务类型为条件时 if (WaylineTaskTypeEnum.CONDITION == waylineJob.getTaskType()) { @@ -502,6 +517,25 @@ } @Override public Optional<WaylineJobDTO> getJobByJobId(String workspaceId, String jobId,Boolean isBreakPoint) { WaylineJobEntity jobEntity = mapper.selectOne( new LambdaQueryWrapper<WaylineJobEntity>() .eq(WaylineJobEntity::getWorkspaceId, workspaceId) .eq(WaylineJobEntity::getJobId, jobId)); WaylineJobDTO waylineJobDTO = entity2Dto(jobEntity); if (isBreakPoint) { QueryWrapper queryWrapper = new QueryWrapper(); queryWrapper.eq("job_id", jobId); WaylineJobBreakPointEntity waylineJobBreakPointEntity = waylineJobBreakPointService.getOne(queryWrapper); waylineJobDTO.setWaylineJobBreakPointEntity(waylineJobBreakPointEntity); } //设置当前时间为执行时间 waylineJobDTO.setBeginTime(LocalDateTime.now()); return Optional.ofNullable(waylineJobDTO); } @Override public Boolean updateJob(WaylineJobDTO dto) { try { @@ -538,6 +572,11 @@ .stream() .map(this::entity2Dto) .collect(Collectors.toList()); // 是否需要断点续飞 records.forEach(wjd -> wjd.setBreakPoint(waylineJobBreakPointService.count( new LambdaQueryWrapper<WaylineJobBreakPointEntity>().eq(WaylineJobBreakPointEntity::getJobId,wjd.getJobId())) > 0)); return new PaginationData<WaylineJobDTO>(records, new Pagination(pageData)); } @@ -916,7 +955,7 @@ @Override public WaylineJobCountDTO patrolStatistics(String workspaceId, String queryTime,String deviceSn) { WaylineJobCountDTO waylineJobCountDTO = new WaylineJobCountDTO(); List<DroneFlightLogEntity> list = flightLogMapper.patrolStatistics(workspaceId,queryTime,deviceSn); List<DroneFlightLogEntity> list = flightLogMapper.patrolStatistics(workspaceId,queryTime,deviceSn); if (!CollectionUtils.isEmpty(list)) { waylineJobCountDTO.setTotalNumber(list.size()); long totalTime = list.stream().filter(task -> task.getEndTime()!= null && task.getStartTime()!= null).mapToLong(s -> s.getEndTime() - s.getStartTime()).sum() / 1000; @@ -928,9 +967,9 @@ for (String sn : deviceSns) { Double totalFlightDistance = new LambdaQueryChainWrapper<>(flightLogMapper) .eq(DroneFlightLogEntity::getDeviceSn, sn).orderByDesc(DroneFlightLogEntity::getEndTime).last("limit 1").one().getTotalFlightDistance(); if (totalFlightDistance!= null){ sum+=totalFlightDistance; } if (totalFlightDistance!= null){ sum+=totalFlightDistance; } } waylineJobCountDTO.setTotalDistance((int) sum); } src/main/resources/template/template.xml
@@ -1,11 +1,9 @@ <?xml version="1.0" encoding="UTF-8"?> <kml xmlns="http://www.opengis.net/kml/2.2" xmlns:wpml="http://www.dji.com/wpmz/1.0.3"> <kml xmlns="http://www.opengis.net/kml/2.2" xmlns:wpml="http://www.dji.com/wpmz/1.0.5"> <Document> <!-- 步骤1:实现文件创建信息 --> <wpml:author>${author!''}</wpml:author> <wpml:createTime>${createTime!''}</wpml:createTime> <wpml:updateTime>${updateTime!''}</wpml:updateTime> <!-- 步骤2:设置任务配置 --> <wpml:missionConfig> <wpml:flyToWaylineMode>${missionConfig.flyToWaylineMode!''}</wpml:flyToWaylineMode> <wpml:finishAction>${missionConfig.finishAction!''}</wpml:finishAction> @@ -17,18 +15,15 @@ <wpml:globalTransitionalSpeed>${missionConfig.globalTransitionalSpeed!''}</wpml:globalTransitionalSpeed> <wpml:globalRTHHeight>${missionConfig.globalRTHHeight!''}</wpml:globalRTHHeight> <wpml:droneInfo> <!-- 用M30申报无人机型号 --> <wpml:droneEnumValue>${missionConfig.droneInfo.droneEnumValue!''}</wpml:droneEnumValue> <wpml:droneSubEnumValue>${missionConfig.droneInfo.droneSubEnumValue!''}</wpml:droneSubEnumValue> </wpml:droneInfo> <wpml:payloadInfo> <!-- 用M30声明有效载荷模型 --> <wpml:payloadEnumValue>${missionConfig.payloadInfo.payloadEnumValue!''}</wpml:payloadEnumValue> <wpml:payloadSubEnumValue>${missionConfig.payloadInfo.payloadSubEnumValue!''}</wpml:payloadSubEnumValue> <wpml:payloadPositionIndex>${missionConfig.payloadInfo.payloadPositionIndex!''}</wpml:payloadPositionIndex> </wpml:payloadInfo> </wpml:missionConfig> <!-- 步骤3:设置路径点模板文件夹 --> <Folder> <wpml:templateType>${folder.templateType!''}</wpml:templateType> <wpml:templateId>${folder.templateId!''}</wpml:templateId> @@ -54,7 +49,6 @@ <#list folder.placemarkList as placemark> <Placemark> <Point> <!-- 经度和纬度 --> <coordinates> ${placemark.coordinates!''} </coordinates> @@ -80,7 +74,6 @@ <wpml:useGlobalHeadingParam>${placemark.useGlobalHeadingParam!''}</wpml:useGlobalHeadingParam> <wpml:useGlobalTurnParam>${placemark.useGlobalTurnParam!''}</wpml:useGlobalTurnParam> <wpml:useStraightLine>${placemark.useStraightLine!''}</wpml:useStraightLine> <!-- 宣布航路点1#的行动组 --> <#if placemark.actionGroup??> <wpml:actionGroup> <wpml:actionGroupId>${placemark.actionGroup.actionGroupId!''}</wpml:actionGroupId> @@ -93,7 +86,6 @@ <#if placemark.actionGroup.actions??> <#assign idx = 0> <#list placemark.actionGroup.actions as action> <!-- 动作 --> <wpml:action> <wpml:actionId>${idx!''}</wpml:actionId> <wpml:actionActuatorFunc>${action.actionActuatorFunc!''}</wpml:actionActuatorFunc> @@ -163,10 +155,10 @@ </#if> </wpml:actionGroup> </#if> <wpml:isRisky>0</wpml:isRisky> </Placemark> </#list> </#if> <!-- 负载设置 --> <wpml:payloadParam> <wpml:payloadPositionIndex>${folder.payloadParam.payloadPositionIndex!''}</wpml:payloadPositionIndex> <wpml:focusMode>${folder.payloadParam.focusMode!''}</wpml:focusMode> src/main/resources/template/waylines.xml
@@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> <kml xmlns="http://www.opengis.net/kml/2.2" xmlns:wpml="http://www.dji.com/wpmz/1.0.3"> <kml xmlns="http://www.opengis.net/kml/2.2" xmlns:wpml="http://www.dji.com/wpmz/1.0.5"> <Document> <wpml:missionConfig> <wpml:flyToWaylineMode>${missionConfig.flyToWaylineMode!''}</wpml:flyToWaylineMode>