14 Коммиты 233e716cbd ... 0474979670

Автор SHA1 Сообщение Дата
  dengsixing 0474979670 启动mq消费者之前检测是否挂上nas 2 дней назад
  dengsixing 8601717d6a Merge branch 'release' into project-jp 2 дней назад
  dengsixing 609b3af704 平面图ai识别优化 3 месяцев назад
  dengsixing 390d8b31c0 平面图ai识别优化 3 месяцев назад
  dengsixing 5357187511 平面图ai识别优化 3 месяцев назад
  dengsixing 9257a17f14 Merge remote-tracking branch 'origin/feature-去掉重复消费' into release 4 месяцев назад
  dengsixing 0fff46dadf Merge branch 'release-v4.14.0' into release 4 месяцев назад
  lyhzzz c65cb4b4cf type 5 месяцев назад
  lyhzzz 121440280d sdfdsfsdfsdfdsfsd 5 месяцев назад
  dengsixing d8c0100fff v4.14.0 增加ai识别 5 месяцев назад
  dengsixing 9496d9eaab 111 8 месяцев назад
  dengsixing acb2406c39 111 8 месяцев назад
  dengsixing f0da30e856 111 8 месяцев назад
  dengsixing 03685ff983 111 8 месяцев назад

+ 42 - 1
src/main/java/com/fdkankan/modeling/ModelingApplication.java

@@ -1,21 +1,62 @@
 package com.fdkankan.modeling;
 
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.io.FileUtil;
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.fdkankan.model.utils.CreateObjUtil;
+import com.fdkankan.modeling.constants.SysConstants;
+import com.fdkankan.modeling.entity.BuildLog;
+import com.fdkankan.modeling.service.IBuildLogService;
+import lombok.extern.slf4j.Slf4j;
 import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.CommandLineRunner;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
 import org.springframework.context.annotation.ComponentScan;
 import org.springframework.scheduling.annotation.EnableScheduling;
 
+import java.util.List;
+
 @SpringBootApplication
 @EnableScheduling
 @ComponentScan(basePackages = {"com.fdkankan.*"})
 @MapperScan("com.fdkankan.**.mapper")
 @EnableDiscoveryClient
-public class ModelingApplication {
+@Slf4j
+public class ModelingApplication implements CommandLineRunner {
+
+	@Autowired
+	private IBuildLogService buildLogService;
 
 	public static void main(String[] args) {
+
 		SpringApplication.run(ModelingApplication.class, args);
+
+		//进入计算之前,把上次未关闭的算法杀掉(主要是重启的问题)
+		CreateObjUtil.killMainLoader();
+
 	}
 
+	@Override
+	public void run(String... args) throws Exception {
+
+//		String lockPath = null;
+//		try {
+//			if(StrUtil.isNotEmpty(SysConstants.hostName)){
+//				List<BuildLog> list = buildLogService.list(new LambdaQueryWrapper<BuildLog>().eq(BuildLog::getHostName, SysConstants.hostName).eq(BuildLog::getStatus, 0).orderByDesc(BuildLog::getId));
+//				if(CollUtil.isNotEmpty(list)){
+//					BuildLog buildLog = list.get(0);
+//					lockPath = buildLog.getDataSource() + "/.lockdirectory";
+//					if(FileUtil.exist(lockPath)){
+//						FileUtil.del(lockPath);
+//					}
+//				}
+//			}
+//		}catch (Exception e){
+//			log.warn("删除上一计算中场景文件锁失败,logPath:{}", lockPath, e);
+//		}
+	}
 }

+ 3 - 0
src/main/java/com/fdkankan/modeling/bean/BuildSceneResultBean.java

@@ -2,6 +2,7 @@ package com.fdkankan.modeling.bean;
 
 import com.fdkankan.common.constant.ModelingBuildStatus;
 import java.util.HashMap;
+import java.util.LinkedHashMap;
 import java.util.Map;
 import lombok.AllArgsConstructor;
 import lombok.Builder;
@@ -51,6 +52,8 @@ public class BuildSceneResultBean {
      */
     private Long duration;
 
+    private LinkedHashMap<Integer, Boolean> detFloorplan;
+
 
 
 

+ 19 - 0
src/main/java/com/fdkankan/modeling/constants/CmdConstant.java

@@ -0,0 +1,19 @@
+package com.fdkankan.modeling.constants;
+
+
+/**
+ * Created by owen on 2020/12/31 0031 14:22
+ */
+public class CmdConstant {
+
+    /**
+     *
+     * @in :图片路径
+     * @model :模型路径
+     * @out 输出的json
+     */
+
+    public final static String LAYOUT_DETECT = "bash /home/ubuntu/bin/PotreeConverter.sh layout_detect @in @out";
+    public final static String PANO_DETECT = "bash /home/ubuntu/bin/PotreeConverter.sh pano_detect @in @out";
+
+}

+ 7 - 4
src/main/java/com/fdkankan/modeling/entity/MqEcs.java

@@ -1,9 +1,7 @@
 package com.fdkankan.modeling.entity;
 
-import com.baomidou.mybatisplus.annotation.IdType;
-import com.baomidou.mybatisplus.annotation.TableField;
-import com.baomidou.mybatisplus.annotation.TableId;
-import com.baomidou.mybatisplus.annotation.TableName;
+import com.baomidou.mybatisplus.annotation.*;
+
 import java.io.Serializable;
 import java.util.Date;
 import lombok.Getter;
@@ -54,5 +52,10 @@ public class MqEcs implements Serializable {
     @TableField("is_scaling")
     private Integer isScaling;
 
+    @TableField("rec_status")
+    @TableLogic(value = "A",delval = "I")
+    private String recStatus;
 
+    @TableField("type")
+    private String type;
 }

+ 5 - 0
src/main/java/com/fdkankan/modeling/receiver/QueueNameService.java

@@ -1,5 +1,6 @@
 package com.fdkankan.modeling.receiver;
 
+import cn.hutool.core.io.FileUtil;
 import com.fdkankan.modeling.constants.SysConstants;
 import com.fdkankan.modeling.entity.MqEcs;
 import com.fdkankan.modeling.service.IMqEcsService;
@@ -20,6 +21,10 @@ public class QueueNameService {
 
 
     public String getQueueName(){
+        String checkFilePath = "/mnt/dont_delete/nas_check.txt";
+        if(!FileUtil.exist(checkFilePath)){
+            return "modeling-no-nas";
+        }
         String queueName = queue;
         if(StringUtils.isBlank(SysConstants.hostName)){
             log.info("获取hostName失败,监听队列名为:{}",queueName);

+ 134 - 30
src/main/java/com/fdkankan/modeling/receiver/RabbitMqListener.java

@@ -1,17 +1,27 @@
 package com.fdkankan.modeling.receiver;
 
 import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.io.FileUtil;
+import cn.hutool.core.io.watch.WatchMonitor;
+import cn.hutool.core.io.watch.Watcher;
+import cn.hutool.core.lang.Console;
 import cn.hutool.core.util.StrUtil;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.fdkankan.common.constant.ModelingBuildStatus;
+import com.fdkankan.common.util.CmdUtils;
 import com.fdkankan.common.util.FileUtils;
 import com.fdkankan.model.utils.ComputerUtil;
+import com.fdkankan.model.utils.CreateObjUtil;
 import com.fdkankan.modeling.bean.BuildSceneResultBean;
+import com.fdkankan.modeling.constants.CmdConstant;
 import com.fdkankan.modeling.constants.RedisKey;
 import com.fdkankan.modeling.constants.SysConstants;
 import com.fdkankan.modeling.entity.BuildLog;
 import com.fdkankan.modeling.exception.BuildException;
 import com.fdkankan.modeling.handler.LaserSceneObjGenerateHandler;
+import com.fdkankan.modeling.service.IAiService;
 import com.fdkankan.modeling.service.IBuildLogService;
 import com.fdkankan.modeling.service.IBuildService;
 import com.fdkankan.modeling.service.IReverseE57Service;
@@ -36,10 +46,9 @@ import org.springframework.util.ObjectUtils;
 
 import java.io.File;
 import java.nio.charset.StandardCharsets;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Objects;
+import java.nio.file.Path;
+import java.nio.file.WatchEvent;
+import java.util.*;
 import java.util.concurrent.Future;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
@@ -86,6 +95,8 @@ public class RabbitMqListener {
     private IBuildService buildService;
     @Autowired
     private IReverseE57Service reverseE57Service;
+    @Autowired
+    private IAiService aiService;
 
     /**
      * 场景计算
@@ -131,6 +142,12 @@ public class RabbitMqListener {
             return;
         }
 
+        //进入计算之前,判断算法文件锁是否存在,如果存在,则删除
+        String lockPath = buildSceneMessage.getPath() + "/.lockdirectory";
+        if(FileUtil.exist(lockPath)){
+            FileUtil.del(lockPath);
+        }
+
         BuildLog buildLog = new BuildLog();
         log.info("场景计算开始,队列名:{},id:{},deliveryTag:{},消息体:{}", queueNameService.getQueueName(), messageId,deliveryTag,msg);
         buildLog.setMessageId(messageId);
@@ -204,6 +221,9 @@ public class RabbitMqListener {
             } else {
                 status = ModelingBuildStatus.FAILED;
             }
+        }finally {
+            //杀掉算法进程,否则有可能导致上一个超时的算法进程没终止,下一个场景算法进程启动,一台机器有两个算法进程在跑
+            CreateObjUtil.killMainLoader();
         }
         buildLog.setStatus(status.code());
         buildSceneResult.setCameraType(message.getCameraType());
@@ -286,7 +306,13 @@ public class RabbitMqListener {
             log.error("未检测到计算结果文件:upload.json");
             return ModelingBuildStatus.FAILED;
         }
-        log.info("八目上完oss结束修改数据:"+num);
+
+        //调用ai识别,但是报错也不影响计算结果
+        aiService.detectScenePano(path);
+
+        //平面图ai识别
+        buildSceneResult.setDetFloorplan(this.detFloorplan(path));
+
         return ModelingBuildStatus.SUCCESS;
     }
 
@@ -314,9 +340,85 @@ public class RabbitMqListener {
             log.error("未检测到计算结果文件:upload.json");
             return ModelingBuildStatus.FAILED;
         }
+
         return ModelingBuildStatus.SUCCESS;
     }
 
+    private LinkedHashMap<Integer, Boolean> detFloorplan(String path) throws Exception {
+        LinkedHashMap<Integer, Boolean> result = new LinkedHashMap<>();
+        String workDir = path + "/detFloorplan/";
+        if(FileUtil.exist(workDir)){
+            FileUtil.del(workDir);
+        }
+        String infoJsonPath = path + "/results/floorplan/info.json";
+        if(!FileUtil.exist(infoJsonPath)){
+            return result;
+        }
+
+        JSONObject infoObj = JSON.parseObject(FileUtil.readUtf8String(infoJsonPath));
+        JSONArray floors = infoObj.getJSONArray("floors");
+        if(CollUtil.isEmpty(floors)){
+            return result;
+        }
+        for (Object o : floors) {
+            JSONObject floor = (JSONObject) o;
+            Integer subgroup = floor.getInteger("subgroup");
+            String detectPath = workDir + subgroup + "/detect.json";
+            String floorKeyPath = path + "/results/floorplan/floor_" + subgroup + ".png";
+            String parent = FileUtil.getParent(detectPath, 1);
+            FileUtil.mkdir(parent);
+            result.put(subgroup, false);
+            if(!FileUtil.exist(floorKeyPath)){
+                continue;
+            }
+            String cmd = CmdConstant.LAYOUT_DETECT;
+            cmd = cmd.replace("@in", floorKeyPath);
+            cmd = cmd.replace("@out", detectPath);
+            CmdUtils.callLine(cmd, 50);
+            if (ComputerUtil.checkComputeCompleted(detectPath,5, 500)) {
+                result.put(subgroup, true);
+            }
+        }
+
+        return result;
+    }
+
+    public static void main(String[] args) {
+        File file = FileUtil.file("D:\\test\\111.txt");
+//这里只监听文件或目录的修改事件
+        WatchMonitor watchMonitor = WatchMonitor.create(file);
+        watchMonitor.setWatcher(new Watcher(){
+            @Override
+            public void onCreate(WatchEvent<?> event, Path currentPath) {
+                Object obj = event.context();
+                Console.log("创建:{}-> {}", currentPath, obj);
+            }
+
+            @Override
+            public void onModify(WatchEvent<?> event, Path currentPath) {
+                Object obj = event.context();
+                Console.log("修改:{}-> {}", currentPath, obj);
+            }
+
+            @Override
+            public void onDelete(WatchEvent<?> event, Path currentPath) {
+                Object obj = event.context();
+                Console.log("删除:{}-> {}", currentPath, obj);
+            }
+
+            @Override
+            public void onOverflow(WatchEvent<?> event, Path currentPath) {
+                Object obj = event.context();
+                Console.log("Overflow:{}-> {}", currentPath, obj);
+            }
+        });
+        watchMonitor.start();
+        for (int i= 0; i< 10; i++ ){
+            System.out.println(i);
+        }
+
+    }
+
     private void afterBuild(BuildSceneCallMessage message, BuildSceneResultBean buildSceneResult, BuildLog buildLog){
         ModelingBuildStatus buildStatus = null;
         try {
@@ -361,32 +463,33 @@ public class RabbitMqListener {
         buildLog.setUpdateTime(new Date());
         buildLog.setBuildType(0);
         buildLog.setStatus(0);
-        // 设置缓存锁
-        String key = SysConstants.SCENE_BUILDING + buildLog.getSceneNum();
-        // 如果是强制重新计算,则删除key。
-        if (StringUtils.equals(message.getRebuild(), "1")) {
-            redisUtil.del(key);
-        }
-
-        // 获取缓存锁,防止重复消费
-        Long building = redisUtil.incr(key, 1);
         buildLogService.save(buildLog);
-
-        if(!ObjectUtils.isEmpty(buildLog.getMessageId())){
-            // 设置消息id幂等性,防止消息重复消费
-            boolean lock = redisLockUtil.lock(SysConstants.SCENE_MESSAGE_BUILDING + buildLog.getMessageId(), SysConstants.modelTimeOut * 3600);
-            if (!lock) {
-                log.error("服务:{},消息重复消费:{}", SysConstants.hostName, buildLog.getMessageId());
-                throw new BuildException(ModelingBuildStatus.REPEAT);
-            }
-        }
-
-        if (building.compareTo(1L) > 0) {
-            log.error("服务:{},重复构建:{},构建次数:{}", SysConstants.hostName, buildLog.getSceneNum(),building);
-            throw new BuildException(ModelingBuildStatus.REPEAT);
-        } else {
-            redisUtil.expire(key, Integer.toUnsignedLong(SysConstants.modelTimeOut * 3600));
-        }
+//        // 设置缓存锁
+//        String key = SysConstants.SCENE_BUILDING + buildLog.getSceneNum();
+//        // 如果是强制重新计算,则删除key。
+//        if (StringUtils.equals(message.getRebuild(), "1")) {
+//            redisUtil.del(key);
+//        }
+//
+//        // 获取缓存锁,防止重复消费
+//        Long building = redisUtil.incr(key, 1);
+//        buildLogService.save(buildLog);
+//
+//        if(!ObjectUtils.isEmpty(buildLog.getMessageId())){
+//            // 设置消息id幂等性,防止消息重复消费
+//            boolean lock = redisLockUtil.lock(SysConstants.SCENE_MESSAGE_BUILDING + buildLog.getMessageId(), SysConstants.modelTimeOut * 3600);
+//            if (!lock) {
+//                log.error("服务:{},消息重复消费:{}", SysConstants.hostName, buildLog.getMessageId());
+//                throw new BuildException(ModelingBuildStatus.REPEAT);
+//            }
+//        }
+//
+//        if (building.compareTo(1L) > 0) {
+//            log.error("服务:{},重复构建:{},构建次数:{}", SysConstants.hostName, buildLog.getSceneNum(),building);
+//            throw new BuildException(ModelingBuildStatus.REPEAT);
+//        } else {
+//            redisUtil.expire(key, Integer.toUnsignedLong(SysConstants.modelTimeOut * 3600));
+//        }
     }
 
     /**
@@ -409,6 +512,7 @@ public class RabbitMqListener {
                 .build();
         buildResult.setBuildContext(message.getBuildContext());
         buildResult.setRebuild(message.getRebuild());
+        buildResult.setDetFloorplan(buildSceneResult.getDetFloorplan());
         rabbitMqProducer.sendByWorkQueue(buildSceneResult.getResultQueueName(),buildResult);
     }
 

+ 7 - 0
src/main/java/com/fdkankan/modeling/service/IAiService.java

@@ -0,0 +1,7 @@
+package com.fdkankan.modeling.service;
+
+public interface IAiService {
+
+    void detectScenePano(String path);
+
+}

+ 53 - 0
src/main/java/com/fdkankan/modeling/service/impl/AiServiceImpl.java

@@ -0,0 +1,53 @@
+package com.fdkankan.modeling.service.impl;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.io.FileUtil;
+import cn.hutool.core.util.ObjectUtil;
+import com.fdkankan.common.util.CmdUtils;
+import com.fdkankan.model.constants.ConstantFilePath;
+import com.fdkankan.model.utils.ComputerUtil;
+import com.fdkankan.model.utils.CreateObjUtil;
+import com.fdkankan.modeling.service.IAiService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+import java.io.File;
+import java.util.Date;
+import java.util.List;
+
+@Slf4j
+@Service
+public class AiServiceImpl implements IAiService {
+
+    public final static String PANO_DETECT = "bash /home/ubuntu/bin/PotreeConverter.sh pano_detect %s %s";
+
+    @Override
+    public void detectScenePano(String path) {
+        try {
+            String resultsPath = path + File.separator + "results" + File.separator;
+            String highPath = resultsPath + "high" + File.separator;
+            String aiWorkPath = highPath + "ai" + File.separator;
+            FileUtil.mkdir(aiWorkPath);
+            List<File> files = FileUtil.loopFiles(highPath);
+            if(CollUtil.isEmpty(files)){
+                return;
+            }
+            for (File file : files) {
+                String absolutePath = file.getAbsolutePath();
+                try {
+                    String name = FileUtil.getName(absolutePath);
+                    String prefix = FileUtil.getPrefix(name);
+                    String outPath = aiWorkPath + prefix + File.separator;
+                    FileUtil.mkdir(outPath);
+                    String detectPath = outPath + "detect.json";
+                    String cmd = String.format(PANO_DETECT, absolutePath, detectPath);
+                    CmdUtils.callLine(cmd, 50);
+                }catch (Exception e){
+                    log.error("ai识别报错,inPath:{}", absolutePath, e);
+                }
+            }
+        }catch (Exception e){
+            log.error("ai识别报错", e);
+        }
+    }
+}

+ 1 - 0
src/main/java/com/fdkankan/modeling/service/impl/MqEcsServiceImpl.java

@@ -35,6 +35,7 @@ public class MqEcsServiceImpl extends ServiceImpl<IMqEcsMapper, MqEcs> implement
         wrapper.isNull(MqEcs::getEcsName);
         wrapper.eq(MqEcs::getStatus,0);
         wrapper.eq(MqEcs::getIsScaling,1);
+        wrapper.eq(MqEcs::getType,"4dkk");
         wrapper.orderByAsc(MqEcs::getId);
         return this.list(wrapper);
     }