3d个数解决

泸州-视觉+扫码-昆船
LAPTOP-S9HJSOEB\昊天 2 years ago
parent ec77871c28
commit 82e048e56e

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

@ -19,6 +19,7 @@
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>com.zhehekeji</groupId> <groupId>com.zhehekeji</groupId>
<artifactId>common</artifactId> <artifactId>common</artifactId>
@ -107,6 +108,19 @@
<scope>system</scope> <scope>system</scope>
<systemPath>${project.basedir}/src/main/resources/libs/rxtx-2.1.7.jar</systemPath> <systemPath>${project.basedir}/src/main/resources/libs/rxtx-2.1.7.jar</systemPath>
</dependency> </dependency>
<!-- <dependency>-->
<!-- <groupId>gnu.io</groupId>-->
<!-- <artifactId>SerialPort</artifactId>-->
<!-- <version>1.0</version>-->
<!-- <scope>system</scope>-->
<!-- <systemPath>${project.basedir}/src/main/resources/libs/RXTXcomm.jar</systemPath>-->
<!-- </dependency>-->
<dependency>
<groupId>com.fazecast</groupId>
<artifactId>jSerialComm</artifactId>
<version>2.9.2</version>
</dependency>
</dependencies> </dependencies>
<build> <build>

@ -5,6 +5,8 @@ import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.util.List;
@Component @Component
@ConfigurationProperties @ConfigurationProperties
@Data @Data
@ -20,6 +22,8 @@ public class ConfigProperties {
*/ */
public static Integer JOYWARE_CAMERA = 0; public static Integer JOYWARE_CAMERA = 0;
private String ComConfig;
private CameraConfig cameraConfig; private CameraConfig cameraConfig;
private VideoStyleConfig videoStyleConfig; private VideoStyleConfig videoStyleConfig;
@ -51,6 +55,21 @@ public class ConfigProperties {
private Rfid rfid; private Rfid rfid;
private IntelliBink intelliBink; private IntelliBink intelliBink;
private String siteInventoryIp;
private String localIp;
private List<Template> template;
@Data
public static class Template {
private String name;
private String code;
private Integer id;
}
@Data @Data
public static class IntelliBink { public static class IntelliBink {
@ -90,9 +109,11 @@ public class ConfigProperties {
public Integer verticalAdjustmentTime = 2; public Integer verticalAdjustmentTime = 2;
private String industrialCamera; private List<String> industrialCamera;
private String camera3D; private String camera3D;
private String sickIp;
private Integer sickPort;
} }
@Data @Data
@ -105,6 +126,9 @@ public class ConfigProperties {
public static class SavePath{ public static class SavePath{
private String mediaPath; private String mediaPath;
private String mp4Path; private String mp4Path;
private String croppingPath;
private String winePreparationPath;
private String netPicPath;
} }
@Data @Data

@ -0,0 +1,27 @@
package com.zhehekeji.web.config;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
import java.time.Duration;
@EnableAsync
@EnableScheduling
@Configuration
public class FusionDesignApplication {
@Resource
//RestTemplateBuilder
private RestTemplateBuilder builder;
// 使用RestTemplateBuilder来实例化RestTemplate对象,spring默认已经注入了RestTemplateBuilder实例
@Bean
public RestTemplate restTemplate() {
return builder.setConnectTimeout(Duration.ofSeconds(20)) // 设置连接超时时间,单位毫秒
.setReadTimeout(Duration.ofSeconds(20)) // 设置读取超时时间,单位毫秒
.build();
}
}

@ -41,14 +41,14 @@ public class CameraControlController {
checkLogin(id); checkLogin(id);
return Result.success(); return Result.success();
} }
//
private NetSDKLib.LLong cameraLogin(Integer cameraId){ // private NetSDKLib.LLong cameraLogin(Integer cameraId){
log.info("相机登录 cameraId:{}",cameraId); // log.info("相机登录 cameraId:{}",cameraId);
Camera camera = cameraMapper.selectById(cameraId); // Camera camera = cameraMapper.selectById(cameraId);
Assert.notNull(camera,"球机不存在"); // Assert.notNull(camera,"球机不存在");
NetSDKLib.LLong lLong = loginControlModule.login(camera.getIp(),camera.getPort(),camera.getUser(),camera.getPassword()); // NetSDKLib.LLong lLong = loginControlModule.login(camera.getIp(),camera.getPort(),camera.getUser(),camera.getPassword());
return lLong; // return lLong;
} // }
@PostMapping("/up/{id}") @PostMapping("/up/{id}")
@ApiOperation(value = "球机控制向上") @ApiOperation(value = "球机控制向上")

@ -2,11 +2,13 @@ package com.zhehekeji.web.controller;
import com.zhehekeji.core.pojo.Result; import com.zhehekeji.core.pojo.Result;
import com.zhehekeji.web.config.ConfigProperties; import com.zhehekeji.web.config.ConfigProperties;
import com.zhehekeji.web.entity.KuKou;
import com.zhehekeji.web.entity.Street; import com.zhehekeji.web.entity.Street;
import com.zhehekeji.web.pojo.IndustrialCameraVO; import com.zhehekeji.web.pojo.IndustrialCameraVO;
import com.zhehekeji.web.pojo.stock.CheckLogSearch; import com.zhehekeji.web.pojo.stock.CheckLogSearch;
import com.zhehekeji.web.service.IndustrialCamera.HikSaveImage; import com.zhehekeji.web.service.IndustrialCamera.HikSaveImage;
import com.zhehekeji.web.service.IndustrialCamera.LxPointCloudSaveImage; import com.zhehekeji.web.service.IndustrialCamera.LxPointCloudSaveImage;
import com.zhehekeji.web.service.KuKouService;
import com.zhehekeji.web.service.PlcService; import com.zhehekeji.web.service.PlcService;
import com.zhehekeji.web.service.StreetService; import com.zhehekeji.web.service.StreetService;
import com.zhehekeji.web.service.algorithm.FeatureMatchingExample; import com.zhehekeji.web.service.algorithm.FeatureMatchingExample;
@ -14,22 +16,24 @@ import com.zhehekeji.web.service.algorithm.InventoryService;
import com.zhehekeji.web.service.algorithm.PcdPojo; import com.zhehekeji.web.service.algorithm.PcdPojo;
import com.zhehekeji.web.service.algorithm.PointCloudProcessor; import com.zhehekeji.web.service.algorithm.PointCloudProcessor;
import com.zhehekeji.web.service.client.TransmissionPojo; import com.zhehekeji.web.service.client.TransmissionPojo;
import com.zhehekeji.web.service.com.SerialPortExample;
import com.zhehekeji.web.service.sick.SickSocket;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.opencv.core.Mat; import org.opencv.core.Mat;
import org.opencv.imgcodecs.Imgcodecs; import org.opencv.imgcodecs.Imgcodecs;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.io.IOException; import java.io.IOException;
import java.nio.file.*; import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes; import java.nio.file.attribute.BasicFileAttributes;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID; import java.util.UUID;
import static com.zhehekeji.web.service.algorithm.FeatureMatchingExample.base642Mat; import static com.zhehekeji.web.service.algorithm.FeatureMatchingExample.base642Mat;
@ -51,31 +55,151 @@ public class IndustrialCameraController {
@Resource @Resource
ConfigProperties configProperties; ConfigProperties configProperties;
@Resource
SerialPortExample serialPortExample;
@Resource
KuKouService kuKouService;
@ApiOperation("拍照") @ApiOperation("拍照")
@PostMapping("pic") @PostMapping("pic")
public Result<String> pic(@RequestBody CheckLogSearch checkLogSearch){ public Result<List<String>> pic(){
Street street = streetService.streetById(checkLogSearch.getStreetId()); List<String> list = new ArrayList<>();
LocalDate currentDate = LocalDate.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
if(configProperties.getCameraConfig().getIndustrialCamera()!=null) {
for (String camera:configProperties.getCameraConfig().getIndustrialCamera()) {
String path = "industrialCamera/" +currentDate.format(formatter)+"/"+camera+ UUID.randomUUID() + ".jpeg";
hikSaveImage.saveImage(camera, configProperties.getSavePath().getMediaPath() + path, "sn");
list.add(path);
}
return new Result<>(list);
}else {
return new Result<>(list);
}
}
@ApiOperation("拍照")
@PostMapping("pic3D")
public Result<List<String>> pic3D(){
List<String> list = new ArrayList<>();
LocalDate currentDate = LocalDate.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
if(configProperties.getCameraConfig().getIndustrialCamera()!=null) {
String path = "industrialCamera/" +currentDate.format(formatter)+"/"+configProperties.getCameraConfig().getCamera3D()+ UUID.randomUUID() + ".pcd";
LxPointCloudSaveImage.saveImage(configProperties.getCameraConfig().getCamera3D(), path,1);
list.add(path);
return new Result<>(list);
}else {
return new Result<>(list);
}
}
@ApiOperation("拍照")
@GetMapping("task")
public Result<List<String>> task(int i){
List<String> list = new ArrayList<>();
String path = "task/"+i+"箱" +"/";
if(configProperties.getCameraConfig().getIndustrialCamera()!=null) {
LxPointCloudSaveImage.saveImage(configProperties.getCameraConfig().getCamera3D(), path+configProperties.getCameraConfig().getCamera3D() + ".pcd",1);
}else {
}
if(configProperties.getCameraConfig().getIndustrialCamera()!=null) { if(configProperties.getCameraConfig().getIndustrialCamera()!=null) {
String path = "industrialCamera/" + UUID.randomUUID() + ".jpeg"; for (String camera:configProperties.getCameraConfig().getIndustrialCamera()) {
hikSaveImage.saveImage(configProperties.getCameraConfig().getIndustrialCamera(), configProperties.getSavePath().getMediaPath() + path, "sn");
return new Result<>(path); //String path = "industrialCamera/" +currentDate.format(formatter)+"/"+camera+ UUID.randomUUID() + ".jpeg";
hikSaveImage.saveImage(camera, configProperties.getSavePath().getMediaPath() + path+camera + ".jpeg", "sn");
list.add(path);
}
}else { }else {
return new Result<>("");
}
return new Result<>();
}
@ApiOperation("打开光源")
@GetMapping("openLight")
public Result<String> openLight(int i){
serialPortExample.openLight(i);
return new Result<>("");
}
@ApiOperation("站点盘点")
@PostMapping("siteInventory")
public Result<KuKou> siteInventory(@RequestBody IndustrialCameraVO industrialCameraVo){
serialPortExample.openLight(1);
//2d图片保存
Result<List<String>> listResult = pic();
boolean re = false;
//sick识别
String code = SickSocket.readOCR(configProperties.getCameraConfig().getSickIp(), configProperties.getCameraConfig().getSickPort());
//2d识别
if (listResult.getData().size()!=0){
re = FeatureMatchingExample.matchTemplate(
InventoryService.readImagesInFolder(configProperties.getSavePath().getMediaPath() + "template/" + industrialCameraVo.getTypeMacth()),
configProperties.getSavePath().getMediaPath() +listResult.getData().get(0));
} }
//3d pcd保存
LocalDate currentDate = LocalDate.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
String pathPcd = configProperties.getSavePath().getMediaPath()
+"camera3D/"
+currentDate.format(formatter)+"/" +UUID.randomUUID()+"-";
int count = inventoryService.match3D(industrialCameraVo.getTypeMacth(),pathPcd+"-"+configProperties.getCameraConfig().getCamera3D()+".pcd","");
//3d识别
//保存信息
KuKou kuKou = new KuKou();
kuKou.setCreateTime(LocalDateTime.now());
if (re) {
kuKou.setFlag(1);
kuKou.setCategoryName(industrialCameraVo.getTypeMacthName());
}
kuKou.setCount(count);
kuKou.setCode(code);
kuKou.setPath(configProperties.getSavePath().getNetPicPath()+listResult.getData().get(0));
kuKouService.save(kuKou);
serialPortExample.openLight(0);
return new Result<>(kuKou);
} }
@ApiOperation("识别") @ApiOperation("识别")
@PostMapping("Macth") @PostMapping("Macth")
public Result<String> Macth(@RequestBody IndustrialCameraVO industrialCameraVo){ public Result<String> Macth(@RequestBody IndustrialCameraVO industrialCameraVo){
String srcImg = configProperties.getSavePath().getMediaPath() + industrialCameraVo.getPicImg(); LocalDate currentDate = LocalDate.now();
String srcImgRest = configProperties.getSavePath().getMediaPath() + industrialCameraVo.getPicImg(); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
String camera= configProperties.getCameraConfig().getIndustrialCamera().get(0);
String path = "industrialCamera/" + currentDate.format(formatter) + "/" + camera + UUID.randomUUID() + ".jpeg";
hikSaveImage.saveImage(camera, configProperties.getSavePath().getMediaPath() + path, "sn");
String srcImg = configProperties.getSavePath().getMediaPath() + path;
//识别结果 //识别结果
boolean re = FeatureMatchingExample.matchTemplate( boolean re = FeatureMatchingExample.matchTemplate(
InventoryService.readImagesInFolder(configProperties.getSavePath().getMediaPath() + "template/" + industrialCameraVo.getTypeMacth()), InventoryService.readImagesInFolder(configProperties.getSavePath().getMediaPath() + "template/" + industrialCameraVo.getTypeMacth()),
srcImg); srcImg);
if (re){ if (re){
return new Result<>(industrialCameraVo.getPicImg()+".jpg"); return new Result<>(srcImg+".jpg");
}else { }else {
return new Result<>(""); return new Result<>("");
@ -92,74 +216,10 @@ public class IndustrialCameraController {
String pathPcd = configProperties.getSavePath().getMediaPath() String pathPcd = configProperties.getSavePath().getMediaPath()
+"camera3D/" +"camera3D/"
+currentDate.format(formatter)+"/" +UUID.randomUUID()+"-"; +currentDate.format(formatter)+"/" +UUID.randomUUID()+"-";
Integer count = inventoryService.match3D(industrialCameraVo.getName(),pathPcd+"-"+configProperties.getCameraConfig().getCamera3D()+".pcd"); int count = inventoryService.match3D(industrialCameraVo.getTypeMacth(),pathPcd+"-"+configProperties.getCameraConfig().getCamera3D()+".pcd","");
return Result.success(count); return Result.success(count);
} }
@Resource @Resource
InventoryService inventoryService; InventoryService inventoryService;
//
// @ApiOperation("匹配所有")
// @PostMapping("matchFeatures")
// public Boolean matchFeatures(@RequestBody TransmissionPojo transmissionPojo) {
// //return true;
//
// return null;
// }
//
// @ApiOperation("随行")
// @PostMapping("actionType")
// public void action(@RequestBody TransmissionPojo transmissionPojo) {
//
// Street street = streetService.getStreetByPlcId(transmissionPojo.getStreetNumber());
//
//
// //随行地址
// String pcdPath1 =configProperties.getSavePath().getMediaPath() + street.getLeft3D()+"\\000\\"
// +transmissionPojo.getRow()+"-"+transmissionPojo.getColumn()+"-"+transmissionPojo.getDirection()+"-L"+".pcd";
//
// String pcdPath2 =configProperties.getSavePath().getMediaPath() + street.getRight3D()+"\\000\\"
// +transmissionPojo.getRow()+"-"+transmissionPojo.getColumn()+"-"+transmissionPojo.getDirection()+"-R"+".pcd";
// //拍照
// System.out.println(street.getLeft3D()+" 111211 "+ pcdPath1);
// LxPointCloudSaveImage lxPointCloudSaveImage = new LxPointCloudSaveImage();
// lxPointCloudSaveImage.saveImage(street.getLeft3D(), pcdPath1,1);
//
// LxPointCloudSaveImage lxPointCloudSaveImage1 = new LxPointCloudSaveImage();
// lxPointCloudSaveImage1.saveImage(street.getRight3D(), pcdPath2,2);
// }
// @ApiOperation("模板建立")
// @PostMapping("MacthCreate")
// public Result<Boolean> MacthCreate(@RequestBody IndustrialCameraVO industrialCameraVo){
// Path folder = Paths.get(configProperties.getSavePath().getMediaPath()+"template/"+industrialCameraVo.getTypeMacth());
// try {
// Files.walkFileTree(folder, new SimpleFileVisitor<Path>() {
// @Override
// public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
// Files.delete(file);
// return FileVisitResult.CONTINUE;
// }
//
// @Override
// public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
// Files.delete(dir);
// return FileVisitResult.CONTINUE;
// }
// });
// } catch (IOException e) {
// e.printStackTrace();
// }
// for (int i = 0; i < industrialCameraVo.getFileList().size(); i++){
// try {
// Mat template = base642Mat(industrialCameraVo.getFileList().get(i).getThumbUrl()
// .replace("data:image/jpeg;base64,","").replace("data:image/png;base64,",""));
//
// Imgcodecs.imwrite(configProperties.getSavePath().getMediaPath()+"template/"+industrialCameraVo.getTypeMacth()+"/"+i+".jpg", template);
// } catch (IOException e) {
// throw new RuntimeException(e);
// }
// }
// return new Result<>(true);
// }
} }

@ -9,10 +9,7 @@ import com.zhehekeji.web.service.KuKouService;
import com.zhehekeji.web.service.OrderService; import com.zhehekeji.web.service.OrderService;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource; import javax.annotation.Resource;
@ -34,7 +31,7 @@ public class KuKouController {
return Result.success(kuKouService.pageInfo(orderSearch)); return Result.success(kuKouService.pageInfo(orderSearch));
} }
@PostMapping("/latest") @GetMapping("/latest")
@ApiOperation(value = "最新数据") @ApiOperation(value = "最新数据")
//@SessionHandler //@SessionHandler
public Result<KuKou> latest() { public Result<KuKou> latest() {

@ -0,0 +1,90 @@
package com.zhehekeji.web.entity;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@Data
public class Interval3D {
private int storey;
private double maxX;
private double minX;
private double maxZ;
private double minZ;
private double maxY;
private double minY;
private Interval3D z;
private List<Interval3D> list;
public static void main(String[] args) {
// Interval3D interval3D = new Interval3D();
// interval3D.maxX = 2d;
// interval3D.minX = 2d;
// interval3D.maxY = 2d;
// interval3D.minY = 2d;
// interval3D.maxZ = 2d;
// interval3D.minZ = 2d;
// List<Map<List<Interval3D>,List<Interval3D>>> list1= new ArrayList<>();
// List<Interval3D> listZ= new ArrayList<>();
// listZ.add(interval3D);
// List<Interval3D> listXY= new ArrayList<>();
// listXY.add(interval3D);
// listXY.add(interval3D);
// list1.add(Map.of(listZ,listXY));
// ObjectMapper objectMapper = new ObjectMapper();
// try {
// String formattedJson = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(list1);
// System.out.println(formattedJson);
// } catch (JsonProcessingException e) {
// throw new RuntimeException(e);
// }
String jsonString = "\n" +
"[ {\n" +
" \"z\":{\"maxZ\":2.0, \"minZ\":2.0} ,\n" +
" \"list\": [ {\n" +
" \"maxX\" : 2.0,\n" +
" \"minX\" : 2.0,\n" +
" \"maxY\" : 2.0,\n" +
" \"minY\" : 2.0\n" +
" }, {\n" +
" \"maxX\" : 2.0,\n" +
" \"minX\" : 2.0,\n" +
" \"maxY\" : 2.0,\n" +
" \"minY\" : 2.0\n" +
" } ]\n" +
"} ,{\n" +
" \"z\":{\"maxZ\":2.0, \"minZ\":2.0} ,\n" +
" \"list\": [ {\n" +
" \"maxX\" : 2.0,\n" +
" \"minX\" : 2.0,\n" +
" \"maxY\" : 2.0,\n" +
" \"minY\" : 2.0\n" +
" }, {\n" +
" \"maxX\" : 2.0,\n" +
" \"minX\" : 2.0,\n" +
" \"maxY\" : 2.0,\n" +
" \"minY\" : 2.0\n" +
" } ]\n" +
"} ]";
ObjectMapper objectMapper = new ObjectMapper();
try {
// 将 JSON 字符串转换为 List<Person>
List<Interval3D> persons = objectMapper.readValue(jsonString, objectMapper.getTypeFactory().constructCollectionType(List.class, Interval3D.class));
// 打印结果
for (Interval3D person : persons) {
System.out.println(person);
}
} catch (JsonProcessingException e) {
e.printStackTrace();
}
}
}

@ -17,7 +17,8 @@ public class KuKou {
private int count; private int count;
private String code; private String code;
private String path; private String path;
private int flag; private String categoryName;
private int flag = 0;
@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss") @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss")
private LocalDateTime createTime; private LocalDateTime createTime;

@ -4,6 +4,7 @@ import com.zhehekeji.web.lib.joyware.NetSDKLib;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/** /**
* camera login handler * camera login handler
@ -14,13 +15,13 @@ public class CameraConnMap {
* key :cameraId * key :cameraId
* value: loginId * value: loginId
*/ */
public static Map<Integer, NetSDKLib.LLong> cameraMap = new HashMap<>(); public static Map<Integer, NetSDKLib.LLong> cameraMap = new ConcurrentHashMap<>();
/** /**
* key:loginId * key:loginId
* value: cameraId * value: cameraId
*/ */
public static Map<NetSDKLib.LLong,Integer> loginMap = new HashMap<>(); public static Map<NetSDKLib.LLong,Integer> loginMap = new ConcurrentHashMap<>();
public static void conn(Integer cameraId,NetSDKLib.LLong handlerId){ public static void conn(Integer cameraId,NetSDKLib.LLong handlerId){
synchronized (cameraId.toString().intern()){ synchronized (cameraId.toString().intern()){

@ -290,7 +290,7 @@ public class HikCameraControlModuleImpl implements CameraControlModule {
HCNetSDK.NET_DVR_JPEGPARA jpegpara = new HCNetSDK.NET_DVR_JPEGPARA(wPicSize, wPicQuality); HCNetSDK.NET_DVR_JPEGPARA jpegpara = new HCNetSDK.NET_DVR_JPEGPARA(wPicSize, wPicQuality);
boolean picResult = HikLoginModuleImpl.hcNetsdk.NET_DVR_CaptureJPEGPicture(lUserId, 1, jpegpara, path); boolean picResult = HikLoginModuleImpl.hcNetsdk.NET_DVR_CaptureJPEGPicture(lUserId, 1, jpegpara, path);
if (!picResult) { if (!picResult) {
log.error("pic error:{},cameraId:{}", HikLoginModuleImpl.hcNetsdk.NET_DVR_GetLastError(),cameraId); log.error("pic error:{},cameraId:{},lUserId{}", HikLoginModuleImpl.hcNetsdk.NET_DVR_GetLastError(),cameraId,lUserId);
} }
return picResult; return picResult;

@ -58,6 +58,7 @@ public class HikLoginModuleImpl implements CameraControlLoginModule {
//检测球机连接状态 //检测球机连接状态
public static Boolean connectStatus(int userId){ public static Boolean connectStatus(int userId){
return hcNetsdk.NET_DVR_RemoteControl(userId,20005,null,0); return hcNetsdk.NET_DVR_RemoteControl(userId,20005,null,0);
} }
@ -69,6 +70,7 @@ public class HikLoginModuleImpl implements CameraControlLoginModule {
* \endif * \endif
*/ */
public NetSDKLib.LLong login(String m_strIp, int m_nPort, String m_strUser, String m_strPassword) { public NetSDKLib.LLong login(String m_strIp, int m_nPort, String m_strUser, String m_strPassword) {
init(); init();
HCNetSDK.NET_DVR_USER_LOGIN_INFO m_strLoginInfo = new HCNetSDK.NET_DVR_USER_LOGIN_INFO();//设备登录信息 HCNetSDK.NET_DVR_USER_LOGIN_INFO m_strLoginInfo = new HCNetSDK.NET_DVR_USER_LOGIN_INFO();//设备登录信息
HCNetSDK.NET_DVR_DEVICEINFO_V40 m_strDeviceInfo = new HCNetSDK.NET_DVR_DEVICEINFO_V40();//设备信息 HCNetSDK.NET_DVR_DEVICEINFO_V40 m_strDeviceInfo = new HCNetSDK.NET_DVR_DEVICEINFO_V40();//设备信息
@ -84,7 +86,7 @@ public class HikLoginModuleImpl implements CameraControlLoginModule {
m_strLoginInfo.wPort = (short) m_nPort; m_strLoginInfo.wPort = (short) m_nPort;
m_strLoginInfo.bUseAsynLogin = true; //是否异步登录:0- 否,1- 是 m_strLoginInfo.bUseAsynLogin = false; //是否异步登录:0- 否,1- 是
m_strLoginInfo.write(); m_strLoginInfo.write();
HCNetSDK.NET_DVR_DEVICEINFO_V30 m_strDeviceInfo30 = new HCNetSDK.NET_DVR_DEVICEINFO_V30();//设备信息 HCNetSDK.NET_DVR_DEVICEINFO_V30 m_strDeviceInfo30 = new HCNetSDK.NET_DVR_DEVICEINFO_V30();//设备信息

@ -9,6 +9,7 @@ public class IndustrialCameraVO {
private String name; private String name;
private String picImg; private String picImg;
private String typeMacth; private String typeMacth;
private String typeMacthName;
//private List<ImgFile> fileList; //private List<ImgFile> fileList;
private String pcdPath; private String pcdPath;

@ -87,7 +87,9 @@ public class CronTab {
@Scheduled(cron = "0 0/1 * * * ?") @Scheduled(cron = "0 0/1 * * * ?")
public void cameraTimeUpdate() { public void cameraTimeUpdate() {
cameraService.cameraTimeUpdate(); if(configProperties.getKsec()!=null && configProperties.getKsec().getIp() != null) {
cameraService.cameraTimeUpdate();
}
} }
@Scheduled(cron = "0 0/1 * * * ?") @Scheduled(cron = "0 0/1 * * * ?")
public void lightStatus() { public void lightStatus() {
@ -115,6 +117,24 @@ public class CronTab {
} }
} }
} }
/*
球机归位
*/
@Scheduled(cron = "0 55 23 * * ? ")
public void cameraHoming() {
List<Camera> cameras = cameraMapper.selectList(new QueryWrapper<Camera>());
for (Camera camera : cameras){
cameraControlModule.ptzControlUpStart(camera.getId(),0,0,1);
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
cameraControlModule.ptzControlUpEnd(camera.getId(),0);
}
}
public static void checkFileTime(File dir,int days) { public static void checkFileTime(File dir,int days) {

@ -9,7 +9,6 @@ import com.sun.jna.ptr.PointerByReference;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
public interface DcLibrary extends Library { public interface DcLibrary extends Library {
DcLibrary INSTANCE = (DcLibrary) Native.load((System.getProperty("user.dir"))+"\\libs\\plc\\LxCameraApiR.dll", DcLibrary.class);
// 创建一个新的实例 // 创建一个新的实例
// 设备详细信息结构体 // 设备详细信息结构体

@ -13,7 +13,7 @@ import java.util.concurrent.ConcurrentHashMap;
@Slf4j @Slf4j
public class LxPointCloudSaveImage { public class LxPointCloudSaveImage {
static DcLibrary INSTANCER = (DcLibrary) Native.loadLibrary((System.getProperty("user.dir"))+"\\libs\\plc\\LxCameraApi.dll", DcLibrary.class); static DcLibrary INSTANCER = (DcLibrary) Native.loadLibrary((System.getProperty("user.dir"))+"\\libs\\lx\\LxCameraApi.dll", DcLibrary.class);
static Map<String, PointerByReference> handleMap = new ConcurrentHashMap<>(); static Map<String, PointerByReference> handleMap = new ConcurrentHashMap<>();
public static PointerByReference getHandle(String sn,int type ,DcLibrary INSTANCE){ public static PointerByReference getHandle(String sn,int type ,DcLibrary INSTANCE){
@ -40,7 +40,7 @@ public class LxPointCloudSaveImage {
}else { }else {
for (int ii=0;i<50;i++ ) { for (int ii=0;i<50;i++ ) {
result = INSTANCE.DcOpenDevice(1, sn, handleRef, info); result = INSTANCE.DcOpenDevice(1, sn, handleRef, info);
System.out.println(i + "次尝试"); System.out.println(i + "次尝试;"+"异常:"+result);
try { try {
Thread.sleep(500); Thread.sleep(500);
} catch (InterruptedException e) { } catch (InterruptedException e) {

@ -12,6 +12,7 @@ import com.zhehekeji.web.mapper.CameraMapper;
import com.zhehekeji.web.mapper.StreetMapper; import com.zhehekeji.web.mapper.StreetMapper;
import com.zhehekeji.web.service.client.ClientChanel; import com.zhehekeji.web.service.client.ClientChanel;
import com.zhehekeji.web.service.client.NettyServer; import com.zhehekeji.web.service.client.NettyServer;
import com.zhehekeji.web.service.com.SerialPortManager;
import com.zhehekeji.web.service.ksec.KsecNettyClient; import com.zhehekeji.web.service.ksec.KsecNettyClient;
import com.zhehekeji.web.service.putian.PuTianNettyClient; import com.zhehekeji.web.service.putian.PuTianNettyClient;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -79,35 +80,39 @@ public class InitService implements ApplicationRunner {
@Override @Override
public void run(ApplicationArguments args) throws Exception { public void run(ApplicationArguments args) throws Exception {
nettyServer.CreateNettyServer(configProperties.getServerPort());
//球机登录 SerialPortManager.connectSerialPort(configProperties.getComConfig());
List<Camera> cameras = cameraMapper.selectByMap(new HashMap<>(0));
cameras.forEach(camera -> {
LoginThread loginThread = new LoginThread(camera);
loginThread.start();
});
//所有客户端的IP 标识保存到map内存
List<Street> streets = streetMapper.selectByMap(new HashMap<>());
streets.forEach(street -> {
if(street.getPlcIp()!=null && "".equals(street.getPlcIp())) {
ClientChanel.putIp(street.getPlcIp(), street.getPlcId());
}
});
ConfigProperties.KSEC ksec = configProperties.getKsec(); ConfigProperties.KSEC ksec = configProperties.getKsec();
if(ksec != null){ if(ksec != null&& ksec.getIp()!=null&& !ksec.getIp().equals("")){
TaskDelayExecutor.runMp4DownloadExecutor();
nettyServer.CreateNettyServer(configProperties.getServerPort());
//球机登录
List<Camera> cameras = cameraMapper.selectByMap(new HashMap<>(0));
cameras.forEach(camera -> {
LoginThread loginThread = new LoginThread(camera);
loginThread.start();
});
//所有客户端的IP 标识保存到map内存
List<Street> streets = streetMapper.selectByMap(new HashMap<>());
streets.forEach(street -> {
if(street.getPlcIp()!=null && "".equals(street.getPlcIp())) {
ClientChanel.putIp(street.getPlcIp(), street.getPlcId());
}
});
StreetConn.init(1,"ksec"); StreetConn.init(1,"ksec");
try { try {
ksecNettyClient.createClient(ksec); ksecNettyClient.createClient(ksec);
}catch (Exception e){ }catch (Exception e){
log.error("kesc connect error,url:{},port:{}",ksec.getIp(),ksec.getPort()); log.error("kesc connect error,url:{},port:{}",ksec.getIp(),ksec.getPort());
//ksecNettyClient.reconnect(0); ksecNettyClient.reconnect(0);
} }
}else { }else {
log.error("ksec no config"); log.error("ksec no config");
} }
TaskDelayExecutor.runMp4DownloadExecutor();
} }
class LoginThread extends Thread{ class LoginThread extends Thread{

@ -25,7 +25,7 @@ public class KuKouService extends ServiceImpl<KukouMapper,KuKou> implements IS
} }
public KuKou latest(){ public KuKou latest(){
KuKou kuKou = getOne(new QueryWrapper<KuKou>().orderByDesc("createTime").last("limit 1")); KuKou kuKou = getOne(new QueryWrapper<KuKou>().orderByDesc("create_Time").last("limit 1"));
return kuKou; return kuKou;
} }

@ -6,6 +6,7 @@ import com.zhehekeji.web.config.ConfigProperties;
import com.zhehekeji.web.entity.*; import com.zhehekeji.web.entity.*;
import com.zhehekeji.web.lib.*; import com.zhehekeji.web.lib.*;
import com.zhehekeji.web.mapper.*; import com.zhehekeji.web.mapper.*;
import com.zhehekeji.web.pojo.IndustrialCameraVO;
import com.zhehekeji.web.pojo.OrderVO; import com.zhehekeji.web.pojo.OrderVO;
import com.zhehekeji.web.pojo.camera.CameraPtzPojo; import com.zhehekeji.web.pojo.camera.CameraPtzPojo;
import com.zhehekeji.web.pojo.stock.StockStatus; import com.zhehekeji.web.pojo.stock.StockStatus;
@ -21,9 +22,14 @@ import com.zhehekeji.web.service.lbScanCode.ReentrantLockExample;
import com.zhehekeji.web.service.sick.SickSocket; import com.zhehekeji.web.service.sick.SickSocket;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.time.Duration; import java.time.Duration;
@ -34,6 +40,7 @@ import java.util.*;
import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
/** /**
@ -356,6 +363,9 @@ public class PlcService {
@Resource @Resource
ReentrantLockExample reentrantLockExample; ReentrantLockExample reentrantLockExample;
@Resource
RestTemplate restTemplate;
String scan(PlcCmdInfo plcCmdInfo,Street street){ String scan(PlcCmdInfo plcCmdInfo,Street street){
Boolean trayCheck = Boolean.FALSE; Boolean trayCheck = Boolean.FALSE;
String trayCode = ""; String trayCode = "";
@ -397,29 +407,29 @@ public class PlcService {
} }
} }
}else { }else {
Integer cameraId; Integer cameraId=street.getCamera1Id();;
String code = "E1-DEEP-"; String code = "E1-DEEP-";
String path = ""; String path = "";
//使用同侧的camera //使用同侧的camera
if(plcCmdInfo.getLeftRight1() ==1){ if(plcCmdInfo.getLeftRight1() ==1){
cameraId = street.getCamera1Id();
code = code+"L"; code = code+"L";
}else { }else {
cameraId = street.getCamera2Id();
code = code+"R"; code = code+"R";
} }
path = PathUtil.createFileNameByRowColumn("jpg",cameraId,plcCmdInfo.getRow1(),plcCmdInfo.getColumn1()); path = PathUtil.createFileNameByRowColumn("jpg",cameraId,plcCmdInfo.getRow1(),plcCmdInfo.getColumn1());
gyrateCameraByCode(cameraId,code); gyrateCameraByCode(cameraId,code);
try { try {
Thread.sleep(1500L); Thread.sleep(5000L);
} catch (InterruptedException e) { } catch (InterruptedException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
path = cameraCapture(cameraId,false,0L,path); path = cameraCapture(cameraId,false,0L,path);
trayCode = reentrantLockExample.identify(path,configProperties.getIntelliBink().getIp(),configProperties.getIntelliBink().getPort()); trayCode = reentrantLockExample.identify( configProperties.getSavePath().getMediaPath() + path,configProperties.getIntelliBink().getIp(),configProperties.getIntelliBink().getPort());
if(trayCode != null && !"".equals(trayCode)){ if(trayCode != null && !"".equals(trayCode)){
if ("".equals(plcCmdInfo.getWmsCode())) { if ("".equals(plcCmdInfo.getWmsCode())) {
//托盘码为空,无货物 //托盘码为空,无货物
@ -447,9 +457,11 @@ public class PlcService {
} }
} }
plcCmdInfo.setTrayCode(trayCode); plcCmdInfo.setTrayCode(trayCode);
plcCmdInfo.setTrayCheck(trayCheck);
return trayCode; return trayCode;
} }
public boolean checkVision(KsecDataInfo dataInfo){ public boolean checkVision(KsecDataInfo dataInfo){
KuKou kuKou = new KuKou(); KuKou kuKou = new KuKou();
LocalDate currentDate = LocalDate.now(); LocalDate currentDate = LocalDate.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
@ -462,18 +474,44 @@ public class PlcService {
String pathPcd = configProperties.getSavePath().getMediaPath() String pathPcd = configProperties.getSavePath().getMediaPath()
+"camera3D/" +"camera3D/"
+currentDate.format(formatter)+"/" +UUID.randomUUID()+"-"; +currentDate.format(formatter)+"/" +UUID.randomUUID()+"-";
boolean flag2D =inventoryService.match2D(dataInfo.getCategoryName(),path+configProperties.getCameraConfig().getIndustrialCamera()+".jpeg"); boolean flag2D =inventoryService.match2D(dataInfo.getCategoryName(),path+configProperties.getCameraConfig().getIndustrialCamera().get(0)+".jpeg");
int count = inventoryService.match3D(dataInfo.getCategoryName(),pathPcd+"-"+configProperties.getCameraConfig().getCamera3D()+".pcd"); int count = inventoryService.match3D(dataInfo.getCategoryName(),pathPcd+"-"+configProperties.getCameraConfig().getCamera3D()+".pcd");
kuKou.setCreateTime(LocalDateTime.now()); kuKou.setCreateTime(LocalDateTime.now());
if (flag2D) { if (flag2D) {
kuKou.setFlag(1); kuKou.setFlag(1);
} }
kuKou.setCode(dataInfo.getCategoryName()); kuKou.setCategoryName(dataInfo.getCategoryName());
kuKou.setCount(count); kuKou.setCount(count);
kuKouService.save(kuKou); kuKouService.save(kuKou);
return true; return true;
} }
public void checkVision(KsecDataInfo dataInfo,Boolean flag){
try {
HttpHeaders headers = new HttpHeaders();
headers.set("Content-Type", "application/json");
headers.set("User-Agent", "Mozilla/5.0");
IndustrialCameraVO scTransmission = new IndustrialCameraVO();
scTransmission.setTypeMacth(dataInfo.getTypeNum());
// 创建 HttpEntity 对象
HttpEntity<IndustrialCameraVO> entity = new HttpEntity<>(scTransmission, headers);
Map<String, ConfigProperties.Template> map = configProperties.getTemplate().stream().collect(Collectors.toMap(k->k.getCode(), v->v));
// 发送 POST 请求
ResponseEntity<Boolean> response = restTemplate.exchange(
"http://" + configProperties.getSiteInventoryIp() + ":8099" + "/api/industrialCamera/siteInventory",
HttpMethod.POST,
entity,
Boolean.class
);
} catch (Exception e) {
log.error("3D get pcd error", e);
}
}
public Boolean check(PlcCmdInfo plcCmdInfo,String cmdCode,String wmsCode,String wmsTrayCode,String wmsCatagary){ public Boolean check(PlcCmdInfo plcCmdInfo,String cmdCode,String wmsCode,String wmsTrayCode,String wmsCatagary){
@ -518,68 +556,8 @@ public class PlcService {
//托盘码 //托盘码
String trayCode = ""; String trayCode = "";
Boolean trayCheck = Boolean.TRUE; Boolean trayCheck = Boolean.TRUE;
//扫托盘码 trayCode = scan(plcCmdInfo,street);
if(configProperties.getScanCodeMode().getTray() == 2) { trayCheck = plcCmdInfo.getTrayCheck();
log.info("扫码类型:" + configProperties.getScanCodeMode().getTray());
//托盘使用sick扫码枪
SensorGun sensorGun = sensorService.getSensorByPlc(street.getId(), plcCmdInfo.getLeftRight1());
if (sensorGun == null) {
trayCode = "扫码枪未配置";
trayCheck = Boolean.FALSE;
log.error("no sensor gun config in database ,street id:{},direction:{}", street.getId(), plcCmdInfo.getLeftRight1());
} else {
trayCode = SickSocket.readOCR(sensorGun.getIp(), sensorGun.getPort());
log.info("sensor tray code:{}", trayCode);
if ("".equals(wmsTrayCode)) {
//托盘码为空,无货物
//只要扫码枪未识别出条码,即认为盘点正确
if (StringUtils.isEmpty(trayCode) || trayCode.equals("NoRead")) {
trayCode = "无货物";
trayCheck = Boolean.TRUE;
} else {
trayCode = "扫码枪识别异常";
trayCheck = Boolean.FALSE;
log.warn("sick ocr error:{}", trayCode);
}
} else {
if (StringUtils.isEmpty(trayCode) || trayCode.equals("NoRead")) {
trayCode = "扫码枪识别异常";
trayCheck = Boolean.FALSE;
log.warn("sick ocr error:{}", trayCode);
} else {
//扫到就认为正常
trayCheck = Boolean.TRUE;
}
}
}
}else
if(configProperties.getScanCodeMode().getTray() == 3){
//扫到的码
Set<String> tags = new HashSet<>();
try {
RFIDCheck(plcCmdInfo);
Thread.sleep(1000 * configProperties.getRfid().getScanTime());
} catch (Exception e) {
e.printStackTrace();
} finally {
tags = RFIDStop(plcCmdInfo);
log.info("盘点rfid扫描结果:" + tags);
}
if (tags !=null && tags.contains(wmsTrayCode)) {
//托盘码为空,无货物
//只要扫码枪未识别出条码,即认为盘点正确
trayCode = wmsTrayCode;
trayCheck = Boolean.TRUE;
} else {
trayCode = trayCode+ "扫码枪识别异常";
trayCheck = Boolean.FALSE;
log.warn("rfid error:{}", trayCode);
}
}
Boolean trayGoodCheck = Boolean.TRUE;
OrderInfo orderInfo = new OrderInfo(street, plcCmdInfo, 1, cmdCode); OrderInfo orderInfo = new OrderInfo(street, plcCmdInfo, 1, cmdCode);
@ -592,7 +570,7 @@ public class PlcService {
//核对异常 //核对异常
Integer status = 1; Integer status = 1;
//托盘和货物都正确 //托盘和货物都正确
if (trayCheck && trayGoodCheck ) { if (trayCheck ) {
status = 2; status = 2;
} }
if (stock == null) { if (stock == null) {

@ -0,0 +1,58 @@
package com.zhehekeji.web.service.algorithm;
import java.util.ArrayList;
import java.util.List;
public class AreaUtil {
/**
* 使用鞋带公式计算多边形的面积。
* @param points 多边形顶点坐标列表
* @return 多边形的面积
*/
public static double calculatePolygonArea(List<double[]> points) {
int numPoints = points.size();
if (numPoints < 3) {
return 0.0;
}
double area = 0.0;
for (int i = 0; i < numPoints; i++) {
double[] current = points.get(i);
double[] next = points.get((i + 1) % numPoints); // 将最后一个点与第一个点相连
area += current[0] * next[1];
area -= next[0] * current[1];
}
return Math.abs(area) / 2.0;
}
// 计算多边形的面积
public static double calculateArea(double[][] points) {
double area = 0.0;
int n = points.length;
for (int i = 0; i < n; i++) {
int j = (i + 1) % n; // 下一个点,循环回到起点
area += points[i][0] * points[j][1];
area -= points[j][0] * points[i][1];
}
return Math.abs(area) / 2.0;
}
public static void main(String[] args) {
// 示例点(自交多边形的点)
double[][] points = {
{0, 0}, // 点 0
{4, 0}, // 点 1
{2, 2}, // 点 2
{4, 4}, // 点 3
{4, 0}, // 点 1
{0, 4}, // 点 4
{-1, -1} // 点 4
};
double area = calculateArea(points);
System.out.println("Self-intersecting polygon area: " + area);
}
}

File diff suppressed because one or more lines are too long

@ -48,7 +48,7 @@ public class InventoryService {
boolean flag = false; boolean flag = false;
//2d拍照并识别 //2d拍照并识别
cameraSaveUtil.saveImage(configProperties.getCameraConfig().getIndustrialCamera(),path,"sn"); cameraSaveUtil.saveImage(configProperties.getCameraConfig().getIndustrialCamera().get(0),path,"sn");
log.info(configProperties.getCameraConfig().getIndustrialCamera()+" 2d拍照路径:"+path); log.info(configProperties.getCameraConfig().getIndustrialCamera()+" 2d拍照路径:"+path);
if(category!=null && !category.equals("")) { if(category!=null && !category.equals("")) {
flag = FeatureMatchingExample.matchTemplate( flag = FeatureMatchingExample.matchTemplate(
@ -64,120 +64,21 @@ public class InventoryService {
} }
public int match3D(String category,String path){ public int match3D(String category,String path){
LocalDate currentDate = LocalDate.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
Boolean flag = false;
//拍照 //拍照
log.info("3D拍照pcd: "+path); log.info("3D拍照pcd: "+path);
LxPointCloudSaveImage.saveImage(configProperties.getCameraConfig().getCamera3D(), path,1); LxPointCloudSaveImage.saveImage(configProperties.getCameraConfig().getCamera3D(), path,1);
return 30; return 30;
} }
//
//
// public boolean matchFeatures(TransmissionPojo transmissionPojo){ public int match3D(String category,String path,String configPath){
// Street street = streetService.getStreetByPlcId(transmissionPojo.getStreetNumber()); //拍照
// log.info("3D拍照pcd: "+path);
// LocalDate currentDate = LocalDate.now(); LxPointCloudSaveImage.saveImage(configProperties.getCameraConfig().getCamera3D(), path,1);
// DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
// //路径 return PointCloudProcessor.getBaijiuBox(path,configProperties.getSavePath().getCroppingPath(),configProperties.getSavePath().getWinePreparationPath()+category+".json");
// String path = configProperties.getSavePath().getMediaPath() }
// +"industrialCamera/"
// +transmissionPojo.getStreetNumber()+"/"
// +currentDate.format(formatter)+"/"
// +transmissionPojo.getRow()+"-"
// +transmissionPojo.getColumn()+"-"
// +transmissionPojo.getDirection()+"-";
// //结果
// transmissionPojo.setResult(1);
// //2d拍照并识别
// if(street != null&& street.getIndustrialCamera()!=null){
// cameraSaveUtil.saveImage(street.getIndustrialCamera(),path+street.getIndustrialCamera()+".jpeg","sn");
// log.info(street.getIndustrialCamera()+" 2d拍照路径:"+path+street.getIndustrialCamera()+".jpeg");
// if(transmissionPojo.getCategory()!=null && !transmissionPojo.getCategory().equals("")) {
// boolean re = FeatureMatchingExample.matchTemplate(
// readImagesInFolder(configProperties.getSavePath().getMediaPath() + "template/" + transmissionPojo.getCategory()),
// path + street.getIndustrialCamera() + ".jpeg");
// log.info("2d识别结果:"+re);
// if (!re) {
// transmissionPojo.setResult(0);
// }
// }else {
// transmissionPojo.setResult(0);
// log.info("未识别到任何模板");
// }
// }
// //3d拍照盘点
// //盘点地址
// String pcdPath1 =configProperties.getSavePath().getMediaPath() + street.getLeft3D()+ "/"+currentDate.format(formatter)+"/"+transmissionPojo.getCheckId()+".pcd";
// String pcdPath2 =configProperties.getSavePath().getMediaPath() + street.getRight3D()+ "/"+ currentDate.format(formatter)+"/"+transmissionPojo.getCheckId()+".pcd";
// //随行地址
// //随行地址
// String pcdPath3 =configProperties.getSavePath().getMediaPath() + street.getLeft3D()+"\\000\\"
// +transmissionPojo.getRow()+"-"+transmissionPojo.getColumn()+"-"+transmissionPojo.getDirection()+"-L"+".pcd";
//
// String pcdPath4 =configProperties.getSavePath().getMediaPath() + street.getRight3D()+"\\000\\"
// +transmissionPojo.getRow()+"-"+transmissionPojo.getColumn()+"-"+transmissionPojo.getDirection()+"-R"+".pcd";
//
// //拍照
// log.info("3D拍照 左侧pcd: "+pcdPath1+" 右侧pcd:: "+pcdPath2);
//
// LxPointCloudSaveImage.saveImage(street.getLeft3D(), pcdPath1,1);
//
// LxPointCloudSaveImage.saveImage(street.getRight3D(), pcdPath2,2);
// //左侧比较
// PcdPojo pojo = new PcdPojo();
// pojo.setPcd1(pcdPath1);
// pojo.setPcd2(pcdPath3);
// pojo.setConfigPath("D://config//3DConfig/"+street.getLeft3D()+".json");
// log.info("对比左侧:"+pojo.toString());
//
// double leftScore = PointCloudProcessor.similarity(pojo,10);
// log.info("3D leftScore:"+leftScore);
//
// //右侧比较
// pojo.setPcd1(pcdPath2);
// pojo.setPcd2(pcdPath4);
// pojo.setConfigPath("D://config//3DConfig/"+street.getRight3D()+".json");
// log.info("对比右侧:"+pojo.toString());
//
// double rightScore = PointCloudProcessor.similarity( pojo,10);
//
// log.info("3D rightScore:"+rightScore);
// if(leftScore<0.87||rightScore<0.87){
// transmissionPojo.setResult(0);
// }
// log.info("最终结果:"+transmissionPojo.getResult());
// CheckLog checkLog = checkLogMapper.selectById(transmissionPojo.getCheckId());
// plcService.visualCalculationResults(transmissionPojo,checkLog);
//
// Stock stock = stockMapper.getByStreetAndDirectionAndSideAndRowColumn(street.getId(), transmissionPojo.getDirection(),1, transmissionPojo.getRow(), transmissionPojo.getColumn());
//
// checkLogMapper.updateById(checkLog);
// if (stock == null) {
// stock = Stock.builder()
// .streetId(street.getId())
// .row(transmissionPojo.getRow())
// .column(transmissionPojo.getColumn())
// .direction(transmissionPojo.getDirection())
// .side(1)
// .statusVision(checkLog.getStatusVision())
// .count(checkLog.getCount())
// .category(checkLog.getCategory())
// .exportTime(LocalDateTime.now()).build();
// stockMapper.insert(stock);
// } else {
// stock.setStatusVision(checkLog.getStatusVision());
// stock.setCount(checkLog.getCount());
// stock.setCategory(checkLog.getCategory());
// stockMapper.updateById(stock);
// }
// return !(transmissionPojo.getResult()==0);
//
// };
//
//
//
/** /**

@ -11,7 +11,7 @@ import java.nio.ByteOrder;
public class PCDReader { public class PCDReader {
public static void main(String[] args) { public static void main(String[] args) {
String filePath = "path/to/your/file.pcd"; String filePath = "E:\\泸州老窖3D相机取图\\泸州老窖特曲酒2019版(满垛90箱)\\10箱\\20240810_152222510_t.pcd";
try { try {
if (isBinaryFormat(filePath)) { if (isBinaryFormat(filePath)) {
readBinaryPCD(filePath); readBinaryPCD(filePath);
@ -74,4 +74,5 @@ public class PCDReader {
} }
} }

@ -29,6 +29,10 @@ public class PcdPojo {
private String cameraSn1; private String cameraSn1;
private String cameraSn2; private String cameraSn2;
private Integer count; private Integer count;
private int width;
private int[] height;
private int length;
private String arrangeType;
PcdPojo setPCDInfo(PcdPojo pojo) { PcdPojo setPCDInfo(PcdPojo pojo) {
this.setMinBounds(pojo.getMin_pt()); this.setMinBounds(pojo.getMin_pt());
this.setMaxBounds(pojo.getMax_pt()); this.setMaxBounds(pojo.getMax_pt());

@ -3,28 +3,28 @@ package com.zhehekeji.web.service.algorithm;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.zhehekeji.web.entity.Interval3D;
import lombok.Data;
import java.io.*; import java.io.*;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.ByteOrder; import java.nio.ByteOrder;
import java.text.DecimalFormat; import java.text.DecimalFormat;
import java.util.ArrayList; import java.util.*;
import java.util.Comparator; import java.util.concurrent.atomic.AtomicInteger;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public class PointCloudProcessor { public class PointCloudProcessor {
//
public static void main(String[] args) { // public static void main(String[] args) {
PcdPojo pojo = new PcdPojo(); // PcdPojo pojo = new PcdPojo();
pojo.setPcd1("D:\\WeChet\\WeChat Files\\wxid_ttkf0xgmyihv22\\FileStorage\\File\\2024-09\\8-6-2-L.pcd"); // pojo.setPcd1("E:\\泸州老窖3D相机取图\\泸州老窖特曲酒2019版(满垛90箱)\\11箱\\20240810_152837486_t.pcd");
pojo.setPcd2("D:\\WeChet\\WeChat Files\\wxid_ttkf0xgmyihv22\\FileStorage\\File\\2024-09\\369.pcd"); // //pojo.setPcd2("D:\\WeChet\\WeChat Files\\wxid_ttkf0xgmyihv22\\FileStorage\\File\\2024-09\\369.pcd");
pojo.setConfigPath("E:\\D91FCF1FAB3568DB.json"); // pojo.setConfigPath("E:\\D91FCF1FAB3568DB.json");
double i = similarity(pojo,10); // double i = similarity(pojo,10);
System.out.println("111 "+i); // System.out.println("111 "+i);
} // }
/** /**
* 计算两个pcd的相似性 * 计算两个pcd的相似性
@ -109,10 +109,10 @@ public class PointCloudProcessor {
Double xAge2 = clippedPoint2.keySet().stream().collect(Collectors.averagingDouble(v -> v)); Double xAge2 = clippedPoint2.keySet().stream().collect(Collectors.averagingDouble(v -> v));
Double yAge2 = clippedPoint2.values().stream().flatMap(map -> map.values().stream()).collect(Collectors.averagingDouble(v -> v)); Double yAge2 = clippedPoint2.values().stream().flatMap(map -> map.values().stream()).collect(Collectors.averagingDouble(v -> v));
//计算相似度 //计算相似度
return (Math.abs(yAge) < Math.abs(yAge2) ? Math.abs(yAge) / Math.abs(yAge2) : Math.abs(yAge2) / Math.abs(yAge)); return (Math.abs(yAge) < Math.abs(yAge2) ? Math.abs(yAge) / Math.abs(yAge2) : Math.abs(yAge2) / Math.abs(yAge));
} }
public static double similarity(PcdPojo pojo,int i) { public static double similarity(PcdPojo pojo, int i) {
ObjectMapper mapper = new ObjectMapper(); ObjectMapper mapper = new ObjectMapper();
try { try {
// 读取 JSON 文件并转换为 配置信息 // 读取 JSON 文件并转换为 配置信息
@ -144,18 +144,77 @@ public class PointCloudProcessor {
} }
//计算相似度 //计算相似度
return calculateTruncatedMeans(points,points2,pojo,i,new ArrayList<>()); return calculateTruncatedMeans(points, points2, pojo, i, new ArrayList<>());
}
public static double similarityLuZhou(PcdPojo pojo, int i) {
ObjectMapper mapper = new ObjectMapper();
try {
// 读取 JSON 文件并转换为 配置信息
PcdPojo pojoIn = mapper.readValue(new File(pojo.getConfigPath()), mapper.getTypeFactory().constructType(PcdPojo.class));
// 打印转换后的实体类列表
pojo = pojo.setPCDInfo(pojoIn);
//报错则认为没有配置文件,返回盘点失败
} catch (JsonMappingException e) {
e.printStackTrace();
return 0;
} catch (JsonProcessingException e) {
e.printStackTrace();
return 0;
} catch (IOException e) {
e.printStackTrace();
return 0;
}
//System.out.println(pojo.toString());
// 计算pcd1
List<double[]> points = readPCD(pojo.getPcd1());
if (points == null || points.isEmpty()) {
return 0;
}
//计算相似度
return calculateTruncatedMeans(points, pojo, false) / i;
} }
public static double similarity(PcdPojo pojo, int i, int j) {
ObjectMapper mapper = new ObjectMapper();
try {
// 读取 JSON 文件并转换为 配置信息
PcdPojo pojoIn = mapper.readValue(new File(pojo.getConfigPath()), mapper.getTypeFactory().constructType(PcdPojo.class));
// 打印转换后的实体类列表
pojo = pojo.setPCDInfo(pojoIn);
//报错则认为没有配置文件,返回盘点失败
} catch (JsonMappingException e) {
e.printStackTrace();
return 0;
} catch (JsonProcessingException e) {
e.printStackTrace();
return 0;
} catch (IOException e) {
e.printStackTrace();
return 0;
}
System.out.println(pojo.toString());
// 计算pcd1
List<double[]> points = readPCD(pojo.getPcd1());
if (points == null || points.isEmpty()) {
return 0;
}
return 0;
}
/** /**
* 计算每个子区域内的 y 坐标的截断均值 * 计算每个子区域内的 y 坐标的截断均值
* *
* @param pointCloud 点云列表 * @param pointCloud 点云列表
* @param divisions 每边分割的数量 * @param divisions 每边分割的数量
* @return 一个列表,其中每个元素是一个长度为3的一维数组,表示每个子区域的左下角坐标、右上角坐标和该区域内的 y 坐标的截断均值 * @return 一个列表,其中每个元素是一个长度为3的一维数组,表示每个子区域的左下角坐标、右上角坐标和该区域内的 y 坐标的截断均值
*/ */
public static double calculateTruncatedMeans(List<double[]> pointCloud, List<double[]> pointCloud2,PcdPojo pojo, int divisions,List<double[]> results) { public static double calculateTruncatedMeans(List<double[]> pointCloud, List<double[]> pointCloud2, PcdPojo pojo, int divisions, List<double[]> results) {
double width = (pojo.getMaxBounds()[0] - pojo.getMinBounds()[0]) / divisions; // 每个小方块的宽度 double width = (pojo.getMaxBounds()[0] - pojo.getMinBounds()[0]) / divisions; // 每个小方块的宽度
double depth = (pojo.getMaxBounds()[2] - pojo.getMinBounds()[2]) / divisions; // 每个小方块的深度 double depth = (pojo.getMaxBounds()[2] - pojo.getMinBounds()[2]) / divisions; // 每个小方块的深度
@ -171,7 +230,7 @@ public class PointCloudProcessor {
List<Double> yValues = new ArrayList<>(); List<Double> yValues = new ArrayList<>();
for (double[] point : pointCloud) { for (double[] point : pointCloud) {
point = rotatePoints(point, pojo.getRotationMatrix()); point = rotatePoints(point, pojo.getRotationMatrix());
if(clipPoints(point, pojo.getMinBounds(), pojo.getMaxBounds())) { if (clipPoints(point, pojo.getMinBounds(), pojo.getMaxBounds())) {
if (point[0] >= leftBottomX && point[0] < rightTopX && if (point[0] >= leftBottomX && point[0] < rightTopX &&
point[2] >= leftBottomZ && point[2] < rightTopZ) { point[2] >= leftBottomZ && point[2] < rightTopZ) {
yValues.add(point[1]); yValues.add(point[1]);
@ -182,7 +241,7 @@ public class PointCloudProcessor {
List<Double> yValues2 = new ArrayList<>(); List<Double> yValues2 = new ArrayList<>();
for (double[] point : pointCloud2) { for (double[] point : pointCloud2) {
point = rotatePoints(point, pojo.getRotationMatrix()); point = rotatePoints(point, pojo.getRotationMatrix());
if(clipPoints(point, pojo.getMinBounds(), pojo.getMaxBounds())) { if (clipPoints(point, pojo.getMinBounds(), pojo.getMaxBounds())) {
if (point[0] >= leftBottomX && point[0] < rightTopX && if (point[0] >= leftBottomX && point[0] < rightTopX &&
point[2] >= leftBottomZ && point[2] < rightTopZ) { point[2] >= leftBottomZ && point[2] < rightTopZ) {
yValues2.add(point[1]); yValues2.add(point[1]);
@ -191,16 +250,16 @@ public class PointCloudProcessor {
} }
double truncatedMean = calculateTruncatedMean(yValues, 0.1); // 截断比例为10% double truncatedMean = calculateTruncatedMean(yValues, 0.1); // 截断比例为10%
double truncatedMean2 = calculateTruncatedMean(yValues2, 0.1); // 截断比例为10% double truncatedMean2 = calculateTruncatedMean(yValues2, 0.1); // 截断比例为10%
double similarity = (truncatedMean - pojo.getMinBounds()[1])/(pojo.getMaxBounds()[1] - pojo.getMinBounds()[1]); double similarity = (truncatedMean - pojo.getMinBounds()[1]) / (pojo.getMaxBounds()[1] - pojo.getMinBounds()[1]);
double similarity2 = (truncatedMean2 - pojo.getMinBounds()[1])/(pojo.getMaxBounds()[1] - pojo.getMinBounds()[1]); double similarity2 = (truncatedMean2 - pojo.getMinBounds()[1]) / (pojo.getMaxBounds()[1] - pojo.getMinBounds()[1]);
countSum++; countSum++;
if(Double.isNaN(similarity) && Double.isNaN(similarity2)){ if (Double.isNaN(similarity) && Double.isNaN(similarity2)) {
break; break;
} }
System.out.println("similarity:"+similarity+"similarity2:"+similarity2); System.out.println("similarity:" + similarity + "similarity2:" + similarity2);
double max = Math.max(similarity, similarity2); // 获取较大数 double max = Math.max(similarity, similarity2); // 获取较大数
double min = Math.min(similarity, similarity2); // 获取较小数 double min = Math.min(similarity, similarity2); // 获取较小数
if(max-min<0.01){ if (max - min < 0.01) {
count++; count++;
} }
results.add(new double[]{leftBottomX, leftBottomZ, truncatedMean, truncatedMean2}); results.add(new double[]{leftBottomX, leftBottomZ, truncatedMean, truncatedMean2});
@ -208,14 +267,540 @@ public class PointCloudProcessor {
} }
System.out.println(count); System.out.println(count);
pojo.setCount(count); pojo.setCount(count);
return (double) count /countSum; return (double) count / countSum;
} }
//泸州z是高度
public static int calculateTruncatedMeans(List<double[]> pointCloud, PcdPojo pojo, boolean b, List<Interval3D> interval3DS) {
for (double[] point : pointCloud) {
if (clipPoints(point, pojo.getMinBounds(), pojo.getMaxBounds())) {
for (Interval3D interval3D : interval3DS) {
if (point[2] > interval3D.getZ().getMinZ() && point[2] < interval3D.getZ().getMaxZ()) {
for (Interval3D interval3D1 : interval3D.getList()) {
if (point[0] > interval3D1.getMinX() && point[0] < interval3D1.getMaxX()) {
if (point[1] > interval3D1.getMinY() && point[1] < interval3D1.getMaxY()) {
interval3D1.setStorey(interval3D1.getStorey() + 1);
}
}
}
}
}
}
}
int count = 0;
for (int i = 0; i < interval3DS.size(); i++) {
for (Interval3D interval3D1 : interval3DS.get(i).getList()) {
if (interval3D1.getStorey() >= 3) {
count++;
}
}
if (count > 0) {
count = count + interval3DS.get(i).getList().size() * (interval3DS.size() - i - 1);
}
}
return count;
}
//泸州z是高度
public static double calculateTruncatedMeans(List<double[]> pointCloud, PcdPojo pojo, boolean b) {
int count = 0;
//截断个数
int divisions = 10;
double width = (pojo.getMaxBounds()[0] - pojo.getMinBounds()[0]) / divisions; // 每个小方块的宽度
double depth = (pojo.getMaxBounds()[1] - pojo.getMinBounds()[1]) / divisions; // 每个小方块的深度
int[] c = new int[]{
2550,
2300,
2050,
1822,
1530};
int cc = 0;
Map<Integer, Integer> map = new HashMap<>();
//记录统计,其中[][]含义是[[x左下值,y左下值,z平均值,z记录个数]]
double[][] get = new double[divisions * divisions][4];
//z值平均
double averageZ = pointCloud.stream()
.filter(point -> clipPoints(point, pojo.getMinBounds(), pojo.getMaxBounds()))
.mapToDouble(p -> {
return pojo.getMaxBounds()[2] - p[2];
})
.average().orElse(0.0);
// for (double[] point :pointCloud){
// if(!clipPoints(point, pojo.getMinBounds(), pojo.getMaxBounds())){
// pointCloud.remove(point);
//
// }
// }
pointCloud = pointCloud.stream().filter(point -> clipPoints(point, pojo.getMinBounds(), pojo.getMaxBounds())).collect(Collectors.toList());
double area = AreaUtil.calculatePolygonArea(pointCloud);
System.out.println(area);
// for (double[] point :pointCloud){
// if(clipPoints(point, pojo.getMinBounds(), pojo.getMaxBounds())){
// get[(int)((point[0]-pojo.getMinBounds()[0])/width)][0]=1;
//
// //double z = pojo.getMaxBounds()[2]-point[2];
// count++;
// int index = findIntervalIndex(c, (int) point[2]);
// if(index!=-1){
// cc+=(index+1)*18;
// map.put(index,map.getOrDefault(index,0)+1);
// }
// }
// }
// System.out.println(gao*18/count);
// System.out.print(cc/(double)count+" count: "+count+";");
return averageZ;
}
private static int findIntervalIndex(int[] boundaries, int number) {
// 特殊情况:数字小于最小边界
if (number < boundaries[boundaries.length - 1]) {
return boundaries.length - 1;
}
// 特殊情况:数字大于最大边界
if (number > boundaries[0]) {
return -1;
}
// 查找区间索引
for (int i = 0; i < boundaries.length - 1; i++) {
if (number <= boundaries[i] && number > boundaries[i + 1]) {
return i;
}
}
// 如果未找到,返回 -1 表示不在任何区间内
return -1;
}
@Data
static class In {
Double start;
Double end;
Double max;
Double min;
Double interval;
int horizontalCount;//横向个数
int longitudinalCount;
}
public static void main(String[] args) {
// List<double[]> points = readPCD("E:\\泸州\\c88165e7-9ea6-493e-9130-e74342e5b639--192.168.40.11.pcd");
// PcdPojo pojo = new PcdPojo();
// pojo.setConfigPath("E:\\26.json");
// ObjectMapper mapper = new ObjectMapper();
// PcdPojo pcdPojo
// try {
// // 读取 JSON 文件并转换为 配置信息
// pcdPojo = mapper.readValue(new File("E:\\1.txt"), mapper.getTypeFactory().constructType(PcdPojo.class));
// // 打印转换后的实体类列表
// pojo = pojo.setPCDInfo(pojoIn);
// //报错则认为没有配置文件,返回盘点失败
// } catch (JsonMappingException e) {
// e.printStackTrace();
//
// } catch (JsonProcessingException e) {
// e.printStackTrace();
// } catch (IOException e) {
// e.printStackTrace();
// }
getBaijiuBox("E:\\泸州\\5a11d221-268a-4ed6-ad50-446fa481a56e--192.168.40.11.pcd" ,"E:\\26.json","E:\\1.txt");
{//getLongitudinalType(points, pojo, pcdPojo.getWidth(), pcdPojo.getLength(), pcdPojo.getHeight(),pcdPojo.getArrangeType());
//getLongitudinalType(points, pojo, 350, 297, new int[]{2443,2142,1750, 1420},"3w 4h 4h");
}
}
static int getBaijiuBox(String path,String configPath,String typeConfPath){
List<double[]> points = readPCD(path);
PcdPojo pojo = new PcdPojo();
PcdPojo pcdPojo = new PcdPojo();
pojo.setConfigPath(configPath);
ObjectMapper mapper = new ObjectMapper();
try {
// 读取 JSON 文件并转换为 配置信息
PcdPojo pojoIn = mapper.readValue(new File(pojo.getConfigPath()), mapper.getTypeFactory().constructType(PcdPojo.class));
// 打印转换后的实体类列表
pojo = pojo.setPCDInfo(pojoIn);
// 读取 JSON 文件并转换为 配置信息
pcdPojo = mapper.readValue(new File(typeConfPath), mapper.getTypeFactory().constructType(PcdPojo.class));
//报错则认为没有配置文件,返回盘点失败
} catch (JsonMappingException e) {
e.printStackTrace();
} catch (JsonProcessingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return getLongitudinalType(points, pojo, pcdPojo.getWidth(), pcdPojo.getLength(), pcdPojo.getHeight(),pcdPojo.getArrangeType());
}
/**
* 计算个数
* @param points 点云数据
* @param pojo 配置信息
* @param l 长度
* @param w 宽度
* @param heights 高度列表
* @param type 4w 4w 3l (w代表横宽,l代表竖长)
* @return
*/
static int seg = 5;
private static int getLongitudinalType(List<double[]> points, PcdPojo pojo, int l, int w, int[] heights,String type) {
double width = (pojo.getMaxBounds()[0] - pojo.getMinBounds()[0]) / seg; // 将整体分为5个小列,之后将计算每个列的最大最小,以及这个列有横向酒个数纵向酒个数
Map<Integer, In> map = new HashMap<>();
Map<Integer, Integer> heightMap = new HashMap<>();
points = points.stream()
.filter(point -> clipPoints(point, pojo.getMinBounds(), pojo.getMaxBounds()))
.peek(v ->{
for (int i = 0; i < heights.length; i++) {
if(v[2]>heights[i]-largeMargin&&v[2]<heights[i]+largeMargin){
heightMap.put(i,heightMap.getOrDefault(i,0)+1);
}
}
})
.collect(Collectors.toList());
int h = 0;
int layers = 0;
for (int i = 0; i < heights.length; i++){
if(heightMap.get(i)!=null && heightMap.get(i)>200){
h = heights[i];
layers = i;
}
}
for (double[] point : points) {
if (clipPoints(point, pojo.getMinBounds(), pojo.getMaxBounds())) {
if (!(point[2] < h + 50 && point[2] > h - 50)) {
continue;
}
// point[0]- pojo.getMinBounds()[0]/width;
int i = findIntervalIndex(point[0], pojo.getMinBounds()[0], pojo.getMaxBounds()[0], width);
In in = map.get(i);
if (in == null) {
in = new In();
in.setMax(point[1]);
in.setMin(point[1]);
}
in.setStart(pojo.getMinBounds()[0]+(i-1)*width);
in.setEnd(pojo.getMinBounds()[0]+(i-0)*width);
in.setMax(Math.max(in.getMax(), point[1]));
in.setMin(Math.min(in.getMin(), point[1]));
map.put(i, in);
}
}
int max =0;
int maW =0; //一层最多有几个横向排列
int maL =0; //一层最多有几个纵向排列
int layersCount = 0;
int maxW = 0;
int maxL = 0;
String[] types = type.split(" ");
//计算最大值
for (String s : types){
if (s.endsWith("w")){
max += w;
maW += 1;
maxW= Integer.parseInt(s.substring(0,1));
layersCount +=maxW;
}else if (s.endsWith("h")){
max += l;
maL += 1;
maxL= Integer.parseInt(s.substring(0,1));
layersCount +=maxL;
}
}
//总共多少列
int columns = 0;
double horizontalNumber = w/width; //一箱酒的横向个数
double longitudinalNumber = l/width; //一箱酒的纵向个数
int horizontalCount = 0;
int longitudinalCount = 0;
int minIndex =-1;
int maxIndex =-1;
//遍历所有列
for (int mapKey = 0; mapKey < seg; mapKey++) {
In in = map.get(mapKey);
if(in==null){
continue;
}
//计算高度
double d = in.getMax() - in.getMin();
in.setInterval(d);
if(d>max){
in.setLongitudinalCount(maL);
in.setHorizontalCount(maW);
}else {
//计算是否纵向个数
for (int i = (int) ((d+smallIntervals) / l); i >= 0; i--) {
//不存在大于2的纵向个数
if (i > 2) {
continue;
} else {
//有纵向的个数
int ii = 2;
for (; ii >= 0; ii--) {
if(in.getInterval()- i * l - ii * w > -smallIntervals && in.getInterval()- i * l - ii * w < smallIntervals){
in.setLongitudinalCount(i);
in.setHorizontalCount(ii);
break;
}
}
if (i == 0 && ii==0) {
//没有纵向个数
// 判断是否有横向个数
if (d + 10 > w && d - 10 < w) {
in.setLongitudinalCount(0);
in.setHorizontalCount(1);
break;
}
}
}
}
}
if(minIndex==-1 && maxIndex==-1){
minIndex = mapKey;
maxIndex = mapKey;
}
{
if(in.getHorizontalCount()+in.getLongitudinalCount()<map.get(minIndex).getHorizontalCount()+map.get(minIndex).getLongitudinalCount()){
minIndex = mapKey;
}else if(in.getHorizontalCount()+in.getLongitudinalCount()>map.get(maxIndex).getHorizontalCount()+map.get(maxIndex).getLongitudinalCount()){
maxIndex = mapKey;
}
}
horizontalCount+= in.getHorizontalCount();
longitudinalCount+= in.getLongitudinalCount();
}
System.out.println(map);
//计算多余高度的个数
int topCount =0;
if(map.size()>0){
topCount = getTopCount(points, pojo, l, w, map , minIndex, maxIndex, maxW, maxL,h);
}
long count =topCount + layers * layersCount;
System.out.println(count);
//计算相似度
return (int) count;
}
static int getTopCount(List<double[]> points, PcdPojo pojo, int l, int w,Map<Integer, In> map ,int minIndex,int maxIndex,int maxW,int maxL,int h){
int count = 0;
//列相等
//存在满列
if(map.size()==seg) {
count = map.get(minIndex).getHorizontalCount() * maxW + map.get(minIndex).getLongitudinalCount() * maxL;
}else {
if (map.get(maxIndex).getHorizontalCount()>0){
//横向
count +=getYCount(points,map.get(maxIndex).getMax(),map.get(maxIndex).getMin(),h,l);
}else {
//纵向
count +=getYCount(points,map.get(maxIndex).getMax(),map.get(maxIndex).getMin(),h,w);
}
}
//存在不足满列
if(minIndex!=maxIndex ){
//由于是满列之后计算,所以可以直接比较横向排列个数,如果横向排列是一样的,则认为多出的是纵向排列,如果不同,则为横向排列
if (map.get(minIndex).getHorizontalCount()<map.get(maxIndex).getHorizontalCount()){
//横向
if(Math.abs(map.get(maxIndex).getMax() - map.get(minIndex).getMax())>Math.abs(map.get(maxIndex).getMin() - map.get(minIndex).getMin())){
count += getYCount(points,map.get(maxIndex).getMax(),map.get(minIndex).getMax(),h,l);
}else {
count +=getYCount(points,map.get(maxIndex).getMin(),map.get(minIndex).getMin(),h,l);
}
}else {
//纵向
if(Math.abs(map.get(maxIndex).getMax() - map.get(minIndex).getMax())>Math.abs(map.get(maxIndex).getMin() - map.get(minIndex).getMin())){
count +=getYCount(points,map.get(maxIndex).getMax(),map.get(minIndex).getMax(),h,w);
}else {
count +=getYCount(points,map.get(maxIndex).getMin(),map.get(minIndex).getMin(),h,w);
}
}
}
return count;
}
static int largeMargin =50;//大间隔,用来减小误差
static int smallIntervals =30;//大间隔,用来减小误差
static int getYCount(List<double[]> points,double max,double min,int height,double inytick){
double maxY = -1000;
double minY = 1000;
for (double[] point : points) {
if(point[1]<Math.max(max,min)-largeMargin && point[1]>Math.min(max,min)+largeMargin) {
if(point[2]>height-largeMargin&&point[2]<height+largeMargin){
maxY = Double.max(maxY, point[0]);
minY = Double.min(minY, point[0]);
}
}
}
return (int) Math.round((maxY-minY+smallIntervals)/inytick);
}
public static int findMaxFrequencyAndValue(int[] data, int[] target) {
Map<Integer, Integer> frequencyMap = new HashMap<>();
// 统计每个数字出现的次数
for (int num : target) {
frequencyMap.put(num, frequencyMap.getOrDefault(num, 0) + 1);
}
int maxFrequency = 0;
int maxValue = Integer.MIN_VALUE;
// 找出出现次数最多且数值最大的数字
for (int num : data) {
int count = frequencyMap.getOrDefault(num, 0);
if (count > maxFrequency || (count == maxFrequency && num > maxValue)) {
maxFrequency = count;
maxValue = num;
}
}
return maxValue;
}
public static int[] solveExtendedEuclidean(int target, int factor1, int factor2) {
int[] gcdResult = extendedEuclidean(factor1, factor2);
int gcd = gcdResult[0];
int x = gcdResult[1];
int y = gcdResult[2];
if (target % gcd != 0) {
return null; // 无解
}
int k1 = x * (target / gcd);
int k2 = y * (target / gcd);
return new int[]{k1, k2};
}
public static int[] extendedEuclidean(int a, int b) {
if (b == 0) {
return new int[]{a, 1, 0};
} else {
int[] result = extendedEuclidean(b, a % b);
int gcd = result[0];
int x = result[1];
int y = result[2];
return new int[]{gcd, y, x - (a / b) * y};
}
}
public static int findIntervalIndex(double num, double start, double end, double intervalSize) {
// if (num < start || num > end) {
// return -1; // 数不在区间内
// }
// 计算所在的小份数
int index = (int) Math.floor((num - start) / intervalSize);
return index;
}
public static boolean isMultipleSum(int target, int factor1, int factor2) {
// 特殊情况处理
if (target == 0) {
return true;
}
if (factor1 == 0 || factor2 == 0) {
return false;
}
// 递归求解
for (int k1 = 0; ; k1++) {
int remainder = target - k1 * factor1;
if (remainder == 0) {
return true; // 找到了符合条件的 k1 和 k2
}
if (remainder < 0) {
break; // 退出循环
}
if (remainder % factor2 == 0) {
return true; // 找到了符合条件的 k1 和 k2
}
}
return false;
}
public static void aa(String[] args) {
PcdPojo pojo = new PcdPojo();
//pojo.setPcd2("D:\\WeChet\\WeChat Files\\wxid_ttkf0xgmyihv22\\FileStorage\\File\\2024-09\\369.pcd");
pojo.setConfigPath("E:\\25151.json");
// double i = similarityLuZhou(pojo,10);
//
// pojo.setPcd1("E:\\泸州\\task窖零酒\\task\\30箱\\192.168.40.11.pcd");
// //pojo.setPcd2("D:\\WeChet\\WeChat Files\\wxid_ttkf0xgmyihv22\\FileStorage\\File\\2024-09\\369.pcd");
// pojo.setConfigPath("E:\\25151.json");
// i = similarityLuZhou(pojo,10);
String directoryPath = "E:\\泸州\\task国窖\\task"; // 替换为实际路径
File directory = new File(directoryPath);
if (!directory.exists() || !directory.isDirectory()) {
System.out.println("指定路径不是一个有效的目录!");
return;
}
Map<Integer, String> map = new HashMap<>();
findPcdFiles(directory, map);
for (Integer count : map.keySet()) {
System.out.print(count + " ");
pojo.setPcd1(map.get(count));
double similarity = (similarityLuZhou(pojo, count));
// System.out.println(similarity);
}
}
public static void findPcdFiles(File directory, Map<Integer, String> listMap) {
File[] files = directory.listFiles();
if (files != null) {
for (File file : files) {
if (file.isDirectory()) {
// 递归处理子目录
findPcdFiles(file, listMap);
} else if (file.getName().endsWith(".pcd")) {
// 添加.pcd文件到结果列表
Integer parentName = Integer.valueOf(file.getParentFile().getName().replace("箱", ""));
listMap.put(parentName, file.getAbsolutePath());
}
}
}
}
/** /**
* 计算截断均值 * 计算截断均值
* *
* @param values 值列表 * @param values 值列表
* @param trimRatio 截断比例 * @param trimRatio 截断比例
* @return 截断均值 * @return 截断均值
*/ */
@ -267,11 +852,11 @@ public class PointCloudProcessor {
} }
while ((line = reader.readLine()) != null) { while ((line = reader.readLine()) != null) {
double[] point = new double[3]; double[] point = new double[3];
String[] values = line.split(" "); String[] values = line.split(" ");
point[0] = Double.parseDouble(values[0]); point[0] = Double.parseDouble(values[0]);
point[1] = Double.parseDouble(values[1]); point[1] = Double.parseDouble(values[1]);
point[2] = Double.parseDouble(values[2]); point[2] = Double.parseDouble(values[2]);
points.add(point); points.add(point);
} }
} }
@ -292,11 +877,12 @@ public class PointCloudProcessor {
} }
// Read binary data // Read binary data
while (buffer.hasRemaining()) { while (buffer.hasRemaining()) {
double x = buffer.getFloat(); float x = buffer.getFloat();
double y = buffer.getFloat(); double y = buffer.getFloat();
double z = buffer.getFloat(); double z = buffer.getFloat();
int rgb = buffer.getInt(); // Read 4 bytes for RGB int rgb = buffer.getInt(); // Read 4 bytes for RGB
double[] point = {x, y, z}; double[] point = {x, y, z};
//System.out.printf("x: %f, y: %f, z: %f, rgb: %d%n", x, y, z, rgb);
points.add(point); points.add(point);
} }
} catch (Exception e) { } catch (Exception e) {
@ -305,33 +891,8 @@ public class PointCloudProcessor {
return points; return points;
} }
static void getPCDArray(String filePath) {
}
static void getPCDArray(Map<Double, Map<Double, Double>> clippedPoint, String filePath) {
// 创建一个DecimalFormat对象,指定格式
DecimalFormat df = new DecimalFormat("#.####");
File file = new File(filePath + ".txt");
file.delete();
try (BufferedWriter bw = new BufferedWriter(new FileWriter(filePath + ".txt"))) {
bw.write("[");
for (Double x : clippedPoint.keySet()) {
for (Double y : clippedPoint.get(x).keySet()) {
double z = clippedPoint.get(x).get(y);
bw.write("[" + df.format(x) + ", " + df.format(y) + ", " + df.format(z) + "],\n");
}
}
bw.write("]");
} catch (IOException e) {
e.printStackTrace();
}
// 读取点云数据
}
//旋转
public static double[] rotatePoints(double[] point, double[][] rotationMatrix) { public static double[] rotatePoints(double[] point, double[][] rotationMatrix) {
double x = point[0]; double x = point[0];
@ -346,18 +907,6 @@ public class PointCloudProcessor {
return rotatedPoint; return rotatedPoint;
} }
public static List<double[]> clipPoints(List<double[]> points, double[] minBounds, double[] maxBounds) {
List<double[]> clippedPoints = new ArrayList<>();
for (double[] point : points) {
if (point[0] >= minBounds[0] && point[0] <= maxBounds[0] &&
point[1] >= minBounds[1] && point[1] <= maxBounds[1] &&
point[2] >= minBounds[2] && point[2] <= maxBounds[2]) {
clippedPoints.add(point);
}
}
return clippedPoints;
}
public static boolean clipPoints(double[] point, double[] minBounds, double[] maxBounds) { public static boolean clipPoints(double[] point, double[] minBounds, double[] maxBounds) {
return point[0] >= minBounds[0] && point[0] <= maxBounds[0] && //x轴截取 return point[0] >= minBounds[0] && point[0] <= maxBounds[0] && //x轴截取

@ -0,0 +1,21 @@
package com.zhehekeji.web.service.com;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* 蚂蚁舞
*/
public class SerialPortCallback {
public void dataAvailable() {
try {
//throw new Exception();
} catch (Exception e) {
System.out.println(e.toString());
}
}
}

@ -0,0 +1,137 @@
package com.zhehekeji.web.service.com;
import com.fazecast.jSerialComm.SerialPort;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import javax.annotation.PreDestroy;
import java.io.IOException;
import org.springframework.stereotype.Service;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@Service
public class SerialPortExample {
byte[] close= {(byte) 0xCA, 0x01 ,0x00 ,0x14 ,0x14 , (byte) 0xEB, (byte) 0x87, (byte) 0x85,0x00 ,0x00 ,0x00 ,0x02 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 };
byte[] open = {(byte) 0xCA, 0x01 ,0x00 ,0x14 ,0x14 , (byte) 0xEB, (byte) 0x86, (byte) 0x85,0x00 ,0x00 ,0x00 ,0x01 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 };
public static void main(String[] args) {
//SerialPortExample example = new SerialPortExample();
//example.sendData(da);
}
public static final int SERIAL_BAUD_RATE = 115200;
public static volatile boolean SERIAL_PORT_STATE = false;
public static volatile SerialPort SERIAL_PORT_OBJECT = null;
public void openLight(int i){
if(i==1) {
SerialPortManager.sendSerialPortData(open);
}else {
SerialPortManager.sendSerialPortData(close);
}
}
//查找所有可用端口
public static List<String> getSerialPortList() {
// 获得当前所有可用串口
SerialPort[] serialPorts = SerialPort.getCommPorts();
List<String> portNameList = new ArrayList<String>();
// 将可用串口名添加到List并返回该List
for(SerialPort serialPort:serialPorts) {
System.out.println(serialPort.getSystemPortName());
portNameList.add(serialPort.getSystemPortName());
}
//去重
portNameList = portNameList.stream().distinct().collect(Collectors.toList());
return portNameList;
}
// 连接串口
public static void connectSerialPort(String portName){
try {
SerialPort serialPort = SerialPortManager.openSerialPort(portName, SERIAL_BAUD_RATE);
TimeUnit.MILLISECONDS.sleep(2000);
//给当前串口对象设置监听器
serialPort.addDataListener(new SerialPortListener(new SerialPortCallback()));
if(serialPort.isOpen()) {
SERIAL_PORT_OBJECT = serialPort;
SERIAL_PORT_STATE = true;
System.out.println(portName+"-- start success");
}
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
// 打开串口
public static SerialPort openSerialPort(String portName, Integer baudRate) {
SerialPort serialPort = SerialPort.getCommPort(portName);
if (baudRate != null) {
serialPort.setBaudRate(baudRate);
}
if (!serialPort.isOpen()) { //开启串口
serialPort.openPort(1000);
}else{
return serialPort;
}
serialPort.setFlowControl(SerialPort.FLOW_CONTROL_DISABLED);
serialPort.setComPortParameters(baudRate, 8, SerialPort.ONE_STOP_BIT, SerialPort.NO_PARITY);
serialPort.setComPortTimeouts(SerialPort.TIMEOUT_READ_BLOCKING | SerialPort.TIMEOUT_WRITE_BLOCKING, 1000, 1000);
return serialPort;
}
// 关闭串口
public static void closeSerialPort() {
if (SERIAL_PORT_OBJECT != null && SERIAL_PORT_OBJECT.isOpen()){
SERIAL_PORT_OBJECT.closePort();
SERIAL_PORT_STATE = false;
SERIAL_PORT_OBJECT = null;
}
}
// 发送字节数组
public static void sendSerialPortData(byte[] content) {
if (SERIAL_PORT_OBJECT != null && SERIAL_PORT_OBJECT.isOpen()){
SERIAL_PORT_OBJECT.writeBytes(content, content.length);
}
}
// 读取字节数组
public static byte[] readSerialPortData() {
if (SERIAL_PORT_OBJECT != null && SERIAL_PORT_OBJECT.isOpen()){
byte[] reslutData = null;
try {
if (!SERIAL_PORT_OBJECT.isOpen()){return null;};
int i=0;
while (SERIAL_PORT_OBJECT.bytesAvailable() > 0 && i++ < 5) Thread.sleep(20);
byte[] readBuffer = new byte[SERIAL_PORT_OBJECT.bytesAvailable()];
int numRead = SERIAL_PORT_OBJECT.readBytes(readBuffer, readBuffer.length);
if (numRead > 0) {
reslutData = readBuffer;
}
} catch (InterruptedException e) {
e.printStackTrace();
}
return reslutData;
}
return null;
}
}

@ -0,0 +1,32 @@
package com.zhehekeji.web.service.com;
import com.fazecast.jSerialComm.SerialPort;
import com.fazecast.jSerialComm.SerialPortDataListener;
import com.fazecast.jSerialComm.SerialPortEvent;
/**
* 蚂蚁舞
*/
public class SerialPortListener implements SerialPortDataListener {
private final SerialPortCallback serialPortCallback;
public SerialPortListener(SerialPortCallback serialPortCallback) {
this.serialPortCallback = serialPortCallback;
}
@Override
public int getListeningEvents() { //必须是return这个才会开启串口工具的监听
return SerialPort.LISTENING_EVENT_DATA_AVAILABLE;
}
@Override
public void serialEvent(SerialPortEvent serialPortEvent) {
if (serialPortCallback != null) {
serialPortCallback.dataAvailable();
}
}
}

@ -0,0 +1,110 @@
package com.zhehekeji.web.service.com;
import com.fazecast.jSerialComm.SerialPort;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
* 蚂蚁舞
*/
public class SerialPortManager {
public static final int SERIAL_BAUD_RATE = 115200;
public static volatile boolean SERIAL_PORT_STATE = false;
public static volatile SerialPort SERIAL_PORT_OBJECT = null;
//查找所有可用端口
public static List<String> getSerialPortList() {
// 获得当前所有可用串口
SerialPort[] serialPorts = SerialPort.getCommPorts();
List<String> portNameList = new ArrayList<String>();
// 将可用串口名添加到List并返回该List
for(SerialPort serialPort:serialPorts) {
System.out.println(serialPort.getSystemPortName());
portNameList.add(serialPort.getSystemPortName());
}
//去重
portNameList = portNameList.stream().distinct().collect(Collectors.toList());
return portNameList;
}
// 连接串口
public static void connectSerialPort(String portName){
try {
SerialPort serialPort = SerialPortManager.openSerialPort(portName, SERIAL_BAUD_RATE);
TimeUnit.MILLISECONDS.sleep(2000);
//给当前串口对象设置监听器
serialPort.addDataListener(new SerialPortListener(new SerialPortCallback()));
if(serialPort.isOpen()) {
SERIAL_PORT_OBJECT = serialPort;
SERIAL_PORT_STATE = true;
System.out.println(portName+"-- start success");
}
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
// 打开串口
public static SerialPort openSerialPort(String portName, Integer baudRate) {
SerialPort serialPort = SerialPort.getCommPort(portName);
if (baudRate != null) {
serialPort.setBaudRate(baudRate);
}
if (!serialPort.isOpen()) { //开启串口
serialPort.openPort(1000);
}else{
return serialPort;
}
serialPort.setFlowControl(SerialPort.FLOW_CONTROL_DISABLED);
serialPort.setComPortParameters(baudRate, 8, SerialPort.ONE_STOP_BIT, SerialPort.NO_PARITY);
serialPort.setComPortTimeouts(SerialPort.TIMEOUT_READ_BLOCKING | SerialPort.TIMEOUT_WRITE_BLOCKING, 1000, 1000);
return serialPort;
}
// 关闭串口
public static void closeSerialPort() {
if (SERIAL_PORT_OBJECT != null && SERIAL_PORT_OBJECT.isOpen()){
SERIAL_PORT_OBJECT.closePort();
SERIAL_PORT_STATE = false;
SERIAL_PORT_OBJECT = null;
}
}
// 发送字节数组
public static void sendSerialPortData(byte[] content) {
if (SERIAL_PORT_OBJECT != null && SERIAL_PORT_OBJECT.isOpen()){
SERIAL_PORT_OBJECT.writeBytes(content, content.length);
}
}
// 读取字节数组
public static byte[] readSerialPortData() {
if (SERIAL_PORT_OBJECT != null && SERIAL_PORT_OBJECT.isOpen()){
byte[] reslutData = null;
try {
if (!SERIAL_PORT_OBJECT.isOpen()){return null;};
int i=0;
while (SERIAL_PORT_OBJECT.bytesAvailable() > 0 && i++ < 5) Thread.sleep(20);
byte[] readBuffer = new byte[SERIAL_PORT_OBJECT.bytesAvailable()];
int numRead = SERIAL_PORT_OBJECT.readBytes(readBuffer, readBuffer.length);
if (numRead > 0) {
reslutData = readBuffer;
}
} catch (InterruptedException e) {
e.printStackTrace();
}
return reslutData;
}
return null;
}
}

@ -214,7 +214,7 @@ public class KsecDecoder extends DelimiterBasedFrameDecoder {
log.info("盘点结束:"+ksecInfo.getData().toString()); log.info("盘点结束:"+ksecInfo.getData().toString());
}else if (Cmd.SC.name().equals(ksecInfo.getType())) { }else if (Cmd.SC.name().equals(ksecInfo.getType())) {
plcService.checkVision(dataInfo); plcService.checkVision(dataInfo,true);
} }
//找到该货位的最后一张照片与现在的照片比照 //找到该货位的最后一张照片与现在的照片比照
//plcService.recordStock(plcCmdInfo, dataInfo.getCode(), 0, 0); //plcService.recordStock(plcCmdInfo, dataInfo.getCode(), 0, 0);

@ -30,43 +30,37 @@ public class KsecNettyClient {
*/ */
private static int RECONNECT_NUM = 10; private static int RECONNECT_NUM = 10;
private static Bootstrap client ;; // 单例Bootstrap private static Bootstrap client;
; // 单例Bootstrap
private static final AtomicBoolean reconnecting = new AtomicBoolean(false); // 标记是否正在重连 private static final AtomicBoolean reconnecting = new AtomicBoolean(false); // 标记是否正在重连
private static Channel channel; private static Channel channel;
//次数 //次数
static int num = 0; static int num = 0;
public void createClient(ConfigProperties.KSEC ksec) throws InterruptedException { public void createClient(ConfigProperties.KSEC ksec) throws InterruptedException {
String lotnum = FileUtil.getText("lastLotnum"); String lotnum = FileUtil.getText("lastLotnum");
if (lotnum != null) { if (lotnum != null) {
KsecDecoder.setLastLotnum(lotnum); KsecDecoder.setLastLotnum(lotnum);
} }
if (StringUtils.isEmpty(ksec.getIp()) || ksec.getPort() == null) { if (StringUtils.isEmpty(ksec.getIp()) || ksec.getPort() == null) {
return; return;
} }
if (client == null) { if (client == null) {
Bootstrap c = new Bootstrap(); Bootstrap c = new Bootstrap();
c.group(group); c.group(group);
c.channel(NioSocketChannel.class); c.channel(NioSocketChannel.class);
KsecInfo heart = KsecInfo.heart(); KsecInfo heart = KsecInfo.heart();
c.handler(new KescFilter(heart, plcService, this)); c.handler(new KescFilter(heart, plcService, this));
client = c; client = c;
} }
try {
channel = client.connect(ksec.getIp(), ksec.getPort()).sync().channel(); channel = client.connect(ksec.getIp(), ksec.getPort()).sync().channel();
num = 0;
}catch (Exception e){
log.error("createClient error",e);
if (ksec.getReconnectNum() == -1 || num < ksec.getReconnectNum() && !reconnecting.get()) {
reconnect(0);
}
}
} }
/** /**
@ -87,29 +81,43 @@ public class KsecNettyClient {
e.printStackTrace(); e.printStackTrace();
} }
try {
Thread.sleep(ksec.getReconnectInterval()); try {
} catch (InterruptedException e) { //关闭之前连接
e.printStackTrace(); if (channel != null) {
channel.disconnect();
channel.close();
} }
try { num = 0;
//关闭之前连接 while (ksec.getReconnectNum() == -1 || num < ksec.getReconnectNum() && !reconnecting.get()) {
if (channel != null) { try {
channel.disconnect(); Thread.sleep(ksec.getReconnectInterval());
channel.close(); } catch (InterruptedException e) {
e.printStackTrace();
} }
//重连次数 //重连次数
log.info("reconnect num:{}", num);
num++; num++;
log.error("reconnect error num:{}", num); try {
createClient(ksec); createClient(ksec);
} catch (Exception e) { break;
//没连上 继续
} catch (Exception e) {
log.error("createClient error", e);
}
}
} catch (Exception e) {
//没连上 继续
// try{ // try{
// Thread.sleep(ksec.getReconnectInterval()); // Thread.sleep(ksec.getReconnectInterval());
// }catch (Exception ex){ // }catch (Exception ex){
// throw new RuntimeException(ex); // throw new RuntimeException(ex);
// } // }
} }
if (reconnecting.get()) { if (reconnecting.get()) {
log.info("plc reconnect success"); log.info("plc reconnect success");
} else { } else {
@ -117,10 +125,10 @@ public class KsecNettyClient {
} }
} }
public static void write(KsecInfo ksecInfo){ public static void write(KsecInfo ksecInfo) {
if(channel != null){ if (channel != null) {
channel.writeAndFlush(ksecInfo); channel.writeAndFlush(ksecInfo);
}else { } else {
log.error(" no connected upPc"); log.error(" no connected upPc");
} }

@ -50,18 +50,20 @@ public class ReentrantLockExample {
break; break;
} }
} }
return sb.toString();
return sb.toString().replace(";","");
} }
public static void main(String[] args) { public static void main(String[] args) {
String l =readOCR("127.0.0.1",6000);
System.out.println("111");
for (int i = 10 ;i < 100; i++){ try {
Thread thread = new Thread(() -> { sleep(3000);
System.out.println("111"); } catch (InterruptedException e) {
readOCR("127.0.0.1",6000); throw new RuntimeException(e);
});
thread.start();
} }
System.out.println(l);
} }

@ -0,0 +1,7 @@
package com.zhehekeji.web.service.visualQuantity;
import com.sun.jna.Library;
public interface VisualQuantityCameraApi extends Library {
int cameraapi(String cloudPath, String paramPath, int typeCode);
}

@ -0,0 +1,48 @@
package com.zhehekeji.web.service.visualQuantity;
import com.sun.jna.Native;
import com.zhehekeji.web.service.IndustrialCamera.DcLibrary;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.HashMap;
import java.util.Map;
import static com.zhehekeji.web.service.algorithm.PointCloudProcessor.findPcdFiles;
public class test {
static VisualQuantityCameraApi INSTANCER = (VisualQuantityCameraApi) Native.loadLibrary((System.getProperty("user.dir"))+"\\libs\\3d\\3ddll.dll", VisualQuantityCameraApi.class);
public static void main(String[] args) {
String directoryPath = "E:\\泸州\\task国窖\\task"; // 替换为实际路径
File directory = new File(directoryPath);
if (!directory.exists() || !directory.isDirectory()) {
System.out.println("指定路径不是一个有效的目录!");
return;
}
Map<Integer,String> map = new HashMap<>();
findPcdFiles(directory,map);
for (Integer count : map.keySet()) {
System.out.print(count +" ");
try {
Files.copy(Paths.get(map.get(count)), Paths.get("E:\\192.168.40.11.pcd"), StandardCopyOption.REPLACE_EXISTING);
} catch (IOException e) {
throw new RuntimeException(e);
}
System.out.println(1111);
int i = INSTANCER.cameraapi("E:\\192.168.40.11.pcd","E:\\2.json",3);
System.out.println(i);
// System.out.println(similarity);
}
}
}

@ -52,18 +52,26 @@ cameraConfig:
# 单位毫秒 # 单位毫秒
delayDownloadMp4: 10000 delayDownloadMp4: 10000
#工业相机编码sn #工业相机编码sn
industrialCamera: F223 industrialCamera:
- 1
- 2
#camera3D(ip来标注 #camera3D(ip来标注
camera3D: 114 camera3D: 114
sickIp: 127.0.0.1
sickPort: 2001
# ------------ # ------------
# -----图片 mp4下载地址 # -----图片 mp4下载地址
savePath: savePath:
mediaPath: d:\\data\media\ mediaPath: d:\\data\media\
mp4Path: d://data/mp4/ mp4Path: d://data/mp4/
#裁剪3d文件路径
croppingPath: d://data/mp4/
#酒箱配置文件路径
winePreparationPath: d://data/mp4/
netPicPath: "127.0.0.1:9008/api/pic/"
# ------------服务端类型 0:TCP(罗伯泰克) 1:KSEC(JSON)(昆船) # ------------服务端类型 0:TCP(罗伯泰克) 1:KSEC(JSON)(昆船)
serverMode: 1 serverMode: 1
ksec: ksec:
ip: 127.0.0.1
port: 3000 port: 3000
platformIp: 127.0.0.1 platformIp: 127.0.0.1
platformPort: 3000 platformPort: 3000
@ -75,6 +83,7 @@ ksec:
IP: 127.0.0.1 IP: 127.0.0.1
# 服务端TCP端口 # 服务端TCP端口
serverPort: 3001 serverPort: 3001
# ------------ 实时视频流 全部页面的格式 行列数量 # ------------ 实时视频流 全部页面的格式 行列数量
videoStyleConfig: videoStyleConfig:
videoStyleRow: 4 videoStyleRow: 4
@ -92,22 +101,26 @@ lightSource:
# 扫码模式 0:此处不盘点 1:球机扫码 2:sick扫码枪 3:南北达RFID # 扫码模式 0:此处不盘点 1:球机扫码 2:sick扫码枪 3:南北达RFID
scanCodeMode: scanCodeMode:
tray: 0 tray: 0
goods: 2 goods: 2x
goodsCodeTypes: goodsCodeTypes:
- 14 - 14
trayCodeTypes: trayCodeTypes:
- 14 - 14
# 照片 視頻保存多久 # 照片 視頻保存多久
deleteFileDays: 30 deleteFileDays: 30
#灵闪tcp服务地址 #灵闪tcp服务地址
intelliBlink: intelliBink:
ip: 127.0.0.1 ip: 127.0.0.1
port: 3002 port: 3002
#模版信息 #模版信息
template: template:
- id: 1 - id: 1
name: "模板一" name: "模板一"
code: "a1123" code: "a1123"
-
# 光源串口
comConfig: "COM2"
Loading…
Cancel
Save