From c6b871f2c5ae12f8e6527fb2fafb2ef7b572d6b5 Mon Sep 17 00:00:00 2001 From: zhaohe Date: Wed, 16 Oct 2024 18:54:19 +0800 Subject: [PATCH] update --- app.db | Bin 225280 -> 225280 bytes .../devicedriver/basectrl/PipetteCtrlModule.java | 4 + .../calibration/HbotConsumablePosCalibration.java | 173 ++++++++++++++++++ .../app/devicedriver/ctrl/HbotControler.java | 108 +++++++++++ .../app/devicedriver/pos/HbotConsumablePosMgr.java | 200 +++++++++++++++++++++ .../app/devicedriver/pos/HbotFixPosMgr.java | 61 +++++++ .../app/devicedriver/pos/HbotSamplePosMgr.java | 57 ++++++ src/main/java/a8k/type/HbotConsumablePos.java | 37 ++++ src/main/java/a8k/type/HbotSamplePos.java | 11 ++ src/main/java/a8k/utils/PlaneUtils.java | 50 ++++++ 10 files changed, 701 insertions(+) create mode 100644 src/main/java/a8k/service/app/devicedriver/calibration/HbotConsumablePosCalibration.java create mode 100644 src/main/java/a8k/service/app/devicedriver/ctrl/HbotControler.java create mode 100644 src/main/java/a8k/service/app/devicedriver/pos/HbotConsumablePosMgr.java create mode 100644 src/main/java/a8k/service/app/devicedriver/pos/HbotFixPosMgr.java create mode 100644 src/main/java/a8k/service/app/devicedriver/pos/HbotSamplePosMgr.java create mode 100644 src/main/java/a8k/type/HbotConsumablePos.java create mode 100644 src/main/java/a8k/type/HbotSamplePos.java create mode 100644 src/main/java/a8k/utils/PlaneUtils.java diff --git a/app.db b/app.db index 7f44262374a93c536c63b3041ac16ef7032f5446..c6c9b7bbdb64f6d42931c90c6fa36201282f77f4 100644 GIT binary patch delta 1926 zcmZp8z}xVEcY?HFEdv9CIS`uxF)ITDd*wtOW5(LXgw_PctqDwQfsB#c(*v2}7#SnB z9}8ky&&(J;y)2CBAY<6{51~xW+job9A*&{6YMx{EU2C_)_?6d7tz4^IGsc;A!L0;l9AVl-r-{C)Z*wU(WBG z3pt%Ro^o_>Xm3^&c*|ZNoyx{wYAhb_k(6KJoS#=*nwyxElNyj;?3-Q`P?VpP8eE!G zT#}fVoN8biZ)5_LFixpfs!*~r&{3)clT~1{qOu^rSjh@ms@W2yl-m|>JshQKrdN)#~H5|`>i zV(~lH0LiiS#3$yE7(&L9;aK5X&1j&p($f5h3^<)}A(Lc%R1_P7t|cUFf)jHKV3{(w zBtJhVB(=CCq!gGrVG^W;P(&oqY-rAb8v)GlPNg|HB|u{h0!-`S;v^a!f!}Du08^q& zuE#7*!oq<@8)AltZ)RSmQ%-(<3Q-1Qnj0DhG*=(Z+i^whlMN|50sXB*XEpsCP=7@WwITQJ>jIg?nufnN|CgStAz zHn+?Qpt(S+T#E7wd@>75GgC;m$2$;co+1|WfTbR$VS1p722WTh1prNhx*F)Z=?=@8 OL>LXWtJ*W)HUI$K&rk;d delta 131 zcmZp8z}xVEcY?H_5(5K+IS`uxF)ITDd-OydV@9RMgw_PctqDwQfs9_;(*v2}7#Tgc z9}8ky&&=pCy)2CBAfx;A51~xW+job9A*&{6YMxn-vv=`M0auGv77<0Gm%DW&i*H diff --git a/src/main/java/a8k/service/app/devicedriver/basectrl/PipetteCtrlModule.java b/src/main/java/a8k/service/app/devicedriver/basectrl/PipetteCtrlModule.java index ecfdab9..d7e0ef2 100644 --- a/src/main/java/a8k/service/app/devicedriver/basectrl/PipetteCtrlModule.java +++ b/src/main/java/a8k/service/app/devicedriver/basectrl/PipetteCtrlModule.java @@ -278,6 +278,10 @@ public class PipetteCtrlModule { return canBusService.callcmd(MId.PipetteMod.toInt(), CmdId.pipette_zmotor_read_zero_point_state.toInt()).getContentI32(0) == 1; } + public Boolean isHasTip() throws AppException { + return canBusService.moduleGetReg(MId.PipetteMod, RegIndex.kreg_pipette_tip_state) == 1; + } + // @EnginnerPageAction(name = "获取传感器采样数据数量", order = FnOrder.getSensorSampleDataNum) // public Integer getSensorSampleDataNum() throws HardwareException { diff --git a/src/main/java/a8k/service/app/devicedriver/calibration/HbotConsumablePosCalibration.java b/src/main/java/a8k/service/app/devicedriver/calibration/HbotConsumablePosCalibration.java new file mode 100644 index 0000000..849bdb3 --- /dev/null +++ b/src/main/java/a8k/service/app/devicedriver/calibration/HbotConsumablePosCalibration.java @@ -0,0 +1,173 @@ +package a8k.service.app.devicedriver.calibration; + + +import a8k.constant.AppConstant; +import a8k.extapi_controler.pagecontrol.ExtApiTabConfig; +import a8k.extapi_controler.utils.ExtApiFn; +import a8k.extapi_controler.utils.ExtApiTab; +import a8k.hardware.type.a8kcanprotocol.A8kEcode; +import a8k.service.app.devicedriver.basectrl.CodeScaner; +import a8k.service.app.devicedriver.basectrl.HbotBaseMoveControler; +import a8k.service.app.devicedriver.basectrl.HbotModule; +import a8k.service.app.devicedriver.basectrl.PipetteCtrlModule; +import a8k.service.app.devicedriver.ctrl.ConsumablesScanCtrl; +import a8k.service.app.devicedriver.ctrl.HbotControler; +import a8k.service.app.devicedriver.pos.Hbot2DCodeScanPos; +import a8k.service.app.devicedriver.pos.HbotConsumablePosMgr; +import a8k.service.app.devicedriver.pos.HbotSamplePosMgr; +import a8k.type.ConsumableGroup; +import a8k.type.ConsumableScanRawResult; +import a8k.type.HbotConsumablePos; +import a8k.type.cfg.Pos2d; +import a8k.type.cfg.Pos3d; +import a8k.type.exception.AppException; +import a8k.type.type.TipGroup; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import jakarta.annotation.Resource; +import org.slf4j.Logger; +import org.springframework.stereotype.Component; + +import java.util.Map; + +@ExtApiTab(cfg = ExtApiTabConfig.Hbot2DCodeScanPosCalibration) +@Component +public class HbotConsumablePosCalibration { + static Logger logger = org.slf4j.LoggerFactory.getLogger(HbotConsumablePosCalibration.class); + + @Resource + PipetteCtrlModule pipetteCtrlModule; + @Resource + HbotModule hbotModule; + + + @Resource + HbotControler hbotControler; + @Resource + HbotConsumablePosMgr hbotConsumablePosMgr; + + Boolean stopFlag = false; + + Boolean checkStopFlag() { + if (stopFlag) { + stopFlag = false; + return true; + } + return false; + } + + void resetStopFlag() { + stopFlag = false; + } + + void setStopFlag() { + stopFlag = true; + } + + + @ExtApiFn(name = "获取所有坐标", group = "基础", order = 1) + public Object getPoss() throws AppException { + return hbotConsumablePosMgr.getParams(); + } + + @ExtApiFn(name = "获取所有坐标中文说明", group = "基础", order = 2) + public Object getPossChName() throws AppException { + return hbotConsumablePosMgr.getParamsChName(); + } + + + // 测试工具 + @ExtApiFn(name = "归零", group = "测试工具", order = 11) + public void deviceReset() throws AppException { + enableModule(); + pipetteCtrlModule.zMotorMoveZeroBlock(); + hbotModule.moveToZeroBlock(); + } + + @ExtApiFn(name = "使能相关模块", group = "测试工具", order = 12) + public void enableModule() throws AppException { + pipetteCtrlModule.zMotorEnable(1); + hbotModule.enable(1); + } + + @ExtApiFn(name = "失能相关模块", group = "测试工具", order = 13) + public void disableModule() throws AppException { + pipetteCtrlModule.zMotorEnable(0); + hbotModule.enable(0); + } + + // + // 标定 + // + + @ExtApiFn(name = "标定HBOT坐标", group = "标定", order = 21) + void calibratePos(HbotConsumablePos hbotConsumablePos) throws AppException { + enableModule(); + Pos2d xypos = hbotModule.readPos(); + pipetteCtrlModule.zMotorMeasureDistance(); + Integer z = pipetteCtrlModule.zMotorReadMeasureDistanceResult(); + hbotConsumablePosMgr.setParam(hbotConsumablePos, new Pos3d(xypos.x, xypos.y, z)); + } + + + // + // 校验 + // + @ExtApiFn(name = "校验Tip坐标", group = "校验", order = 30) + public void testTakeTip() throws AppException { + resetStopFlag(); + enableModule(); + for (TipGroup tipGroup : TipGroup.values()) { + for (int i = 0; i < AppConstant.TIP_NUM; i++) { + hbotControler.testTakeTip(tipGroup, i); + if (checkStopFlag()) + return; + } + } + + } + + @ExtApiFn(name = "校验小瓶缓冲液坐标", group = "校验", order = 31) + public void testMoveToLittleBufferPos() throws AppException { + resetStopFlag(); + enableModule(); + for (ConsumableGroup group : ConsumableGroup.values()) { + for (int i = 0; i < AppConstant.CONSUMABLE_NUM; i++) { + hbotControler.moveToLittleBufferPos(group, i); + if (checkStopFlag()) + return; + } + } + + } + + @ExtApiFn(name = "校验探测物质坐标", group = "校验", order = 32) + public void testMoveToProbeSubstancePos() throws AppException { + resetStopFlag(); + enableModule(); + for (ConsumableGroup group : ConsumableGroup.values()) { + for (int i = 0; i < AppConstant.CONSUMABLE_NUM; i++) { + hbotControler.moveToProbeSubstancePos(group, i); + if (checkStopFlag()) + return; + } + } + } + + @ExtApiFn(name = "校验大瓶缓冲液坐标", group = "校验", order = 33) + public void testMoveToLargeBufferPos() throws AppException { + resetStopFlag(); + enableModule(); + for (ConsumableGroup group : ConsumableGroup.values()) { + hbotControler.moveToLargeBufferPos(group); + if (checkStopFlag()) + return; + } + } + + @ExtApiFn(name = "停止校验", group = "校验", order = 34) + public void stopTest() throws AppException { + setStopFlag(); + } +} diff --git a/src/main/java/a8k/service/app/devicedriver/ctrl/HbotControler.java b/src/main/java/a8k/service/app/devicedriver/ctrl/HbotControler.java new file mode 100644 index 0000000..5f65209 --- /dev/null +++ b/src/main/java/a8k/service/app/devicedriver/ctrl/HbotControler.java @@ -0,0 +1,108 @@ +package a8k.service.app.devicedriver.ctrl; + +import a8k.constant.AppConstant; +import a8k.hardware.type.a8kcanprotocol.A8kEcode; +import a8k.service.app.devicedriver.basectrl.HbotBaseMoveControler; +import a8k.service.app.devicedriver.basectrl.HbotModule; +import a8k.service.app.devicedriver.basectrl.PipetteCtrlModule; +import a8k.service.app.devicedriver.pos.HbotConsumablePosMgr; +import a8k.service.app.devicedriver.pos.HbotFixPosMgr; +import a8k.service.app.devicedriver.pos.HbotSamplePosMgr; +import a8k.type.ConsumableGroup; +import a8k.type.HbotSamplePos; +import a8k.type.cfg.Pos3d; +import a8k.type.exception.AppException; +import a8k.type.type.TipGroup; +import a8k.utils.HbotScanerPosComputer; +import jakarta.annotation.Resource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +@Component +public class HbotControler { + static Logger logger = LoggerFactory.getLogger(HbotControler.class); + + @Resource + HbotFixPosMgr hbotFixPosMgr; + @Resource + HbotSamplePosMgr hbotSamplePosMgr; + @Resource + HbotConsumablePosMgr hbotConsumablePosMgr; + + @Resource + PipetteCtrlModule pipetteCtrlModule; + @Resource + HbotBaseMoveControler hbotBaseMoveControler; + + public void checkTipIndex(TipGroup tipGroup, Integer index) throws AppException { + if (index >= AppConstant.TIP_NUM) { + throw new AppException(A8kEcode.CODEERROR_PARAM_OUT_OF_RANGE); + } + } + + public Boolean takeTip(TipGroup tipGroup, Integer index) throws AppException { + logger.info("takeTip groupId:{} index:{}", tipGroup.ordinal(), index); + checkTipIndex(tipGroup, index); + + Pos3d tipPos = hbotConsumablePosMgr.getTipPos(tipGroup, index); + hbotBaseMoveControler.hbotMoveTo(tipPos); + pipetteCtrlModule.zMotorMoveToZeroPointQuickBlock(); + + return pipetteCtrlModule.isHasTip(); + } + + public void testTakeTip(TipGroup tipGroup, Integer index) throws AppException { + checkTipIndex(tipGroup, index); + + Pos3d tipPos = hbotConsumablePosMgr.getTipPos(tipGroup, index); + hbotBaseMoveControler.hbotMoveTo(tipPos); + + //取tip + pipetteCtrlModule.zMotorMoveToBlock(tipPos.z - 100); + if (!pipetteCtrlModule.isHasTip()) { + throw new AppException(A8kEcode.APPE_TAKE_TIP_FAIL); + } + + //丢tip + pipetteCtrlModule.putTipBlock(); + if (pipetteCtrlModule.isHasTip()) { + throw new AppException(A8kEcode.APPE_PUT_TIP_FAIL); + } + + //z轴归零 + pipetteCtrlModule.zMotorMoveToZeroPointQuickBlock(); + } + + public void dropTip() throws AppException { + hbotBaseMoveControler.hbotMoveTo(hbotFixPosMgr.getDropTipPos()); + pipetteCtrlModule.putTipBlock(); + } + + public void moveToDropLiquidPos() throws AppException { + hbotBaseMoveControler.hbotMoveTo(hbotFixPosMgr.getDropLiquidPos()); + } + + /** + * 移动到取样位置 + * @param pos 取样位置 + * @throws AppException 异常 + */ + public void moveToTakeSamplePos(HbotSamplePos pos) throws AppException { + hbotBaseMoveControler.hbotMoveTo(hbotSamplePosMgr.getSamplePos(pos)); + } + + public void moveToLittleBufferPos(ConsumableGroup group, Integer off) throws AppException { + hbotBaseMoveControler.hbotMoveTo(hbotConsumablePosMgr.getLittleBufferPos(group, off)); + } + + public void moveToProbeSubstancePos(ConsumableGroup group, Integer off) throws AppException { + hbotBaseMoveControler.hbotMoveTo(hbotConsumablePosMgr.getProbeSubstancePos(group, off)); + } + + public void moveToLargeBufferPos(ConsumableGroup group) throws AppException { + hbotBaseMoveControler.hbotMoveTo(hbotConsumablePosMgr.getLargeBufferPos(group)); + } + + +} diff --git a/src/main/java/a8k/service/app/devicedriver/pos/HbotConsumablePosMgr.java b/src/main/java/a8k/service/app/devicedriver/pos/HbotConsumablePosMgr.java new file mode 100644 index 0000000..5e97e53 --- /dev/null +++ b/src/main/java/a8k/service/app/devicedriver/pos/HbotConsumablePosMgr.java @@ -0,0 +1,200 @@ +package a8k.service.app.devicedriver.pos; + +import a8k.extapi_controler.pagecontrol.ExtApiTabConfig; +import a8k.extapi_controler.utils.ExtApiParamsTab; +import a8k.extapi_controler.utils.ExtApiTab; +import a8k.service.db.LowerDeviceParameterDBService; +import a8k.service.db.utils.PosParameterReader; +import a8k.type.ConsumableGroup; +import a8k.type.HbotConsumablePos; +import a8k.type.cfg.Pos3d; +import a8k.type.type.TipGroup; +import a8k.utils.PlaneUtils; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.Resource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import java.util.Map; + +/** + * HBOT二维码扫描坐标参数 + */ +@Component +@ExtApiTab(cfg = ExtApiTabConfig.Hbot2DCodeScanPos) +@ExtApiParamsTab(service = HbotConsumablePosMgr.class) +public class HbotConsumablePosMgr { + static final Logger logger = LoggerFactory.getLogger(HbotConsumablePosMgr.class); + + @Resource + LowerDeviceParameterDBService lowerDeviceParameterDBService; + PosParameterReader posReader = null; + + static Integer nowParaVersion = 0; + + @PostConstruct + void initialize() { + posReader = lowerDeviceParameterDBService.getReader(this.getClass()); + Integer paraVersion = posReader.getVersion(); + if (!nowParaVersion.equals(paraVersion)) { + paramReset(); + } + } + + public void paramReset() { + logger.info("init param"); + posReader.setVersion(nowParaVersion); + posReader.updatePos(HbotConsumablePos.Tip00_000Pos.name(), new Pos3d(0, 0, 0)); + posReader.updatePos(HbotConsumablePos.Tip00_119Pos.name(), new Pos3d(0, 0, 0)); + posReader.updatePos(HbotConsumablePos.Tip01_000Pos.name(), new Pos3d(0, 0, 0)); + posReader.updatePos(HbotConsumablePos.Tip01_119Pos.name(), new Pos3d(0, 0, 0)); + posReader.updatePos(HbotConsumablePos.Tip02_000Pos.name(), new Pos3d(0, 0, 0)); + posReader.updatePos(HbotConsumablePos.Tip02_119Pos.name(), new Pos3d(0, 0, 0)); + + posReader.updatePos(HbotConsumablePos.LittleBufferPos00_00.name(), new Pos3d(0, 0, 0)); + posReader.updatePos(HbotConsumablePos.LittleBufferPos05_24.name(), new Pos3d(0, 0, 0)); + + posReader.updatePos(HbotConsumablePos.ProbeSubstance00_00.name(), new Pos3d(0, 0, 0)); + posReader.updatePos(HbotConsumablePos.ProbeSubstance05_24.name(), new Pos3d(0, 0, 0)); + } + + public Map getParams() { + Map map = new java.util.HashMap<>(); + for (HbotConsumablePos param : HbotConsumablePos.values()) { + map.put(param.name(), posReader.getPos(param.name(), Pos3d.class)); + } + return map; + } + + public Map getParamsChName() { + Map map = new java.util.HashMap<>(); + for (HbotConsumablePos param : HbotConsumablePos.values()) { + map.put(param.name(), param.chName); + } + return map; + } + + public void setParam(HbotConsumablePos param, Pos3d pos) { + posReader.updatePos(param.name(), pos); + } + + + public Pos3d getTipPos(TipGroup tipGroup, Integer tipoff) { + Pos3d tip000 = null; + Pos3d tip011 = null; + Pos3d tip108 = null; + Pos3d tip119 = null; + + if (tipGroup == TipGroup.GROUP0) { + tip000 = posReader.getPos(HbotConsumablePos.Tip00_000Pos.name(), Pos3d.class); + tip011 = posReader.getPos(HbotConsumablePos.Tip00_011Pos.name(), Pos3d.class); + tip108 = posReader.getPos(HbotConsumablePos.Tip00_108Pos.name(), Pos3d.class); + tip119 = posReader.getPos(HbotConsumablePos.Tip00_119Pos.name(), Pos3d.class); + + } else if (tipGroup == TipGroup.GROUP1) { + tip000 = posReader.getPos(HbotConsumablePos.Tip01_000Pos.name(), Pos3d.class); + tip011 = posReader.getPos(HbotConsumablePos.Tip01_011Pos.name(), Pos3d.class); + tip108 = posReader.getPos(HbotConsumablePos.Tip01_108Pos.name(), Pos3d.class); + tip119 = posReader.getPos(HbotConsumablePos.Tip01_119Pos.name(), Pos3d.class); + } else if (tipGroup == TipGroup.GROUP2) { + tip000 = posReader.getPos(HbotConsumablePos.Tip02_000Pos.name(), Pos3d.class); + tip011 = posReader.getPos(HbotConsumablePos.Tip02_011Pos.name(), Pos3d.class); + tip108 = posReader.getPos(HbotConsumablePos.Tip02_108Pos.name(), Pos3d.class); + tip119 = posReader.getPos(HbotConsumablePos.Tip02_119Pos.name(), Pos3d.class); + } + assert tip000 != null; + assert tip011 != null; + assert tip108 != null; + assert tip119 != null; + + //水平方向 + double dx = (tip119.x - tip000.x) / 12.0; + //前后方向 + double dy = (tip119.y - tip000.y) / 10.0; + + int xoff = tipoff % 12; + int yoff = tipoff / 12; + + double x = tip000.x + xoff * dx; + double y = tip000.y + yoff * dy; + double z = PlaneUtils.calculateZ(tip000, tip011, tip119, x, y); + + return new Pos3d((int) x, (int) y, (int) z); + } + + + private Pos3d getLittleBufferOrProbeSubstancePos( + Pos3d pos00_00, + Pos3d pos00_24, + Pos3d pos05_00, + Pos3d pos05_24, + ConsumableGroup group, Integer off) { + + + Integer groupNum = group.off; + Integer groupXOff = off % 3; + Integer groupYOff = off / 3; + + Integer xoff = off % 5; + Integer yoff = off / 5; + + Double gdx_0 = (pos05_00.x - pos00_00.x) / 3.0; + Double gdy_0 = (pos05_00.y - pos00_00.y) / 2.0; + + Double gdx_1 = (pos05_24.x - pos00_24.x) / 3.0; + Double gdy_1 = (pos05_24.y - pos00_24.y) / 2.0; + + Double gdx = (gdx_0 + gdx_1) / 2.0; + Double gdy = (gdy_0 + gdy_1) / 2.0; + + + Double dx_0 = (pos00_24.x - pos00_00.x) / 5.0; + Double dy_0 = (pos00_24.y - pos00_00.y) / 5.0; + + Double dx_1 = (pos05_24.x - pos05_00.x) / 5.0; + Double dy_1 = (pos05_24.y - pos05_00.y) / 5.0; + + Double dx = (dx_0 + dx_1) / 2.0; + Double dy = (dy_0 + dy_1) / 2.0; + + + double x = pos00_00.x + groupXOff * gdx + xoff * dx; + double y = pos00_00.y + groupYOff * gdy + yoff * dy; + double z = (pos00_00.z + pos00_24.z + pos05_00.z + pos05_24.z) / 4.0; + return new Pos3d((int) x, (int) y, (int) z); + + } + + public Pos3d getLittleBufferPos(ConsumableGroup group, Integer off) { + Pos3d pos00_00 = posReader.getPos(HbotConsumablePos.LittleBufferPos00_00.name(), Pos3d.class); + Pos3d pos00_24 = posReader.getPos(HbotConsumablePos.LittleBufferPos00_24.name(), Pos3d.class); + Pos3d pos05_00 = posReader.getPos(HbotConsumablePos.LittleBufferPos05_00.name(), Pos3d.class); + Pos3d pos05_24 = posReader.getPos(HbotConsumablePos.LittleBufferPos05_24.name(), Pos3d.class); + return getLittleBufferOrProbeSubstancePos(pos00_00, pos00_24, pos05_00, pos05_24, group, off); + } + + public Pos3d getProbeSubstancePos(ConsumableGroup group, Integer off) { + Pos3d pos00_00 = posReader.getPos(HbotConsumablePos.ProbeSubstance00_00.name(), Pos3d.class); + Pos3d pos00_24 = posReader.getPos(HbotConsumablePos.ProbeSubstance00_24.name(), Pos3d.class); + Pos3d pos05_00 = posReader.getPos(HbotConsumablePos.ProbeSubstance05_00.name(), Pos3d.class); + Pos3d pos05_24 = posReader.getPos(HbotConsumablePos.ProbeSubstance05_24.name(), Pos3d.class); + return getLittleBufferOrProbeSubstancePos(pos00_00, pos00_24, pos05_00, pos05_24, group, off); + } + + public Pos3d getLargeBufferPos(ConsumableGroup group) { + Pos3d pos00 = posReader.getPos(HbotConsumablePos.LargeBufferPos00.name(), Pos3d.class); + Pos3d pos05 = posReader.getPos(HbotConsumablePos.LargeBufferPos05.name(), Pos3d.class); + + int xoff = group.off % 3; + int yoff = group.off / 3; + + double dx = (pos05.x - pos00.x) / 3.0; + double dy = (pos05.y - pos00.y) / 2.0; + + double x = pos00.x + xoff * dx; + double y = pos00.y + yoff * dy; + double z = (pos00.z + pos05.z) / 2.0; + return new Pos3d((int) x, (int) y, (int) z); + } +} diff --git a/src/main/java/a8k/service/app/devicedriver/pos/HbotFixPosMgr.java b/src/main/java/a8k/service/app/devicedriver/pos/HbotFixPosMgr.java new file mode 100644 index 0000000..c15fcf3 --- /dev/null +++ b/src/main/java/a8k/service/app/devicedriver/pos/HbotFixPosMgr.java @@ -0,0 +1,61 @@ +package a8k.service.app.devicedriver.pos; + +import a8k.extapi_controler.pagecontrol.ExtApiTabConfig; +import a8k.extapi_controler.utils.ExtApiParamsTab; +import a8k.extapi_controler.utils.ExtApiTab; +import a8k.service.db.LowerDeviceParameterDBService; +import a8k.service.db.utils.PosParameterReader; +import a8k.type.cfg.Pos3d; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.Resource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +/** + * HBOT二维码扫描坐标参数 + */ +@Component +@ExtApiTab(cfg = ExtApiTabConfig.Hbot2DCodeScanPos) +@ExtApiParamsTab(service = HbotFixPosMgr.class) +public class HbotFixPosMgr { + static final Logger logger = LoggerFactory.getLogger(HbotFixPosMgr.class); + + enum Pos { + DropTipPos, + DropLiquidPos, + } + + ; + @Resource + LowerDeviceParameterDBService lowerDeviceParameterDBService; + PosParameterReader posReader = null; + + static Integer nowParaVersion = 0; + + @PostConstruct + void initialize() { + posReader = lowerDeviceParameterDBService.getReader(this.getClass()); + Integer paraVersion = posReader.getVersion(); + if (!nowParaVersion.equals(paraVersion)) { + paramReset(); + } + } + + public void paramReset() { + logger.info("init param"); + posReader.setVersion(nowParaVersion); + posReader.updatePos(Pos.DropTipPos.name(), new Pos3d(0, 0, 0)); + posReader.updatePos(Pos.DropLiquidPos.name(), new Pos3d(0, 0, 0)); + } + + public Pos3d getDropTipPos() { + return posReader.getPos(Pos.DropTipPos, Pos3d.class); + } + + public Pos3d getDropLiquidPos() { + return posReader.getPos(Pos.DropLiquidPos, Pos3d.class); + } + +} + diff --git a/src/main/java/a8k/service/app/devicedriver/pos/HbotSamplePosMgr.java b/src/main/java/a8k/service/app/devicedriver/pos/HbotSamplePosMgr.java new file mode 100644 index 0000000..105e32c --- /dev/null +++ b/src/main/java/a8k/service/app/devicedriver/pos/HbotSamplePosMgr.java @@ -0,0 +1,57 @@ +package a8k.service.app.devicedriver.pos; + +import a8k.extapi_controler.pagecontrol.ExtApiTabConfig; +import a8k.extapi_controler.utils.ExtApiParamsTab; +import a8k.extapi_controler.utils.ExtApiTab; +import a8k.service.db.LowerDeviceParameterDBService; +import a8k.service.db.utils.PosParameterReader; +import a8k.type.HbotSamplePos; +import a8k.type.cfg.Pos3d; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.Resource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +/** + * HBOT二维码扫描坐标参数 + */ +@Component +@ExtApiTab(cfg = ExtApiTabConfig.Hbot2DCodeScanPos) +@ExtApiParamsTab(service = HbotSamplePosMgr.class) +public class HbotSamplePosMgr { + static final Logger logger = LoggerFactory.getLogger(HbotSamplePosMgr.class); + + @Resource + LowerDeviceParameterDBService lowerDeviceParameterDBService; + PosParameterReader posReader = null; + + static Integer nowParaVersion = 0; + + @PostConstruct + void initialize() { + posReader = lowerDeviceParameterDBService.getReader(this.getClass()); + Integer paraVersion = posReader.getVersion(); + if (!nowParaVersion.equals(paraVersion)) { + paramReset(); + } + } + + public void paramReset() { + logger.info("init param"); + posReader.setVersion(nowParaVersion); + posReader.updatePos(HbotSamplePos.EmergencyTubePos.name(), new Pos3d(0, 0, 0)); + posReader.updatePos(HbotSamplePos.BloodTubeSamplePos.name(), new Pos3d(0, 0, 0)); + posReader.updatePos(HbotSamplePos.MiniTubeSamplePos.name(), new Pos3d(0, 0, 0)); + posReader.updatePos(HbotSamplePos.MiniBloodSamplePos.name(), new Pos3d(0, 0, 0)); + posReader.updatePos(HbotSamplePos.Bulltube1P5SamplePos.name(), new Pos3d(0, 0, 0)); + posReader.updatePos(HbotSamplePos.Bulltube0P5SamplePos.name(), new Pos3d(0, 0, 0)); + posReader.updatePos(HbotSamplePos.StoolTestTubeSamplePos.name(), new Pos3d(0, 0, 0)); + } + + + public Pos3d getSamplePos(HbotSamplePos pos) { + return posReader.getPos(pos, Pos3d.class); + } +} + diff --git a/src/main/java/a8k/type/HbotConsumablePos.java b/src/main/java/a8k/type/HbotConsumablePos.java new file mode 100644 index 0000000..6ce0a1d --- /dev/null +++ b/src/main/java/a8k/type/HbotConsumablePos.java @@ -0,0 +1,37 @@ +package a8k.type; + +public enum HbotConsumablePos { + Tip00_000Pos("Tip00_000Pos"), + Tip00_011Pos("Tip00_011Pos"), + Tip00_108Pos("Tip00_108Pos"), + Tip00_119Pos("Tip00_119Pos"), + + Tip01_000Pos("Tip01_000Pos"), + Tip01_011Pos("Tip01_011Pos"), + Tip01_108Pos("Tip01_108Pos"), + Tip01_119Pos("Tip01_119Pos"), + + Tip02_000Pos("Tip02_000Pos"), + Tip02_011Pos("Tip02_011Pos"), + Tip02_108Pos("Tip02_108Pos"), + Tip02_119Pos("Tip02_119Pos"), + + LittleBufferPos00_00("LittleBufferPos00_00"), + LittleBufferPos00_24("LittleBufferPos00_24"), + LittleBufferPos05_00("LittleBufferPos05_00"), + LittleBufferPos05_24("LittleBufferPos05_24"), + + ProbeSubstance00_00("ProbeSubstance00_00"), + ProbeSubstance00_24("ProbeSubstance00_24"), + ProbeSubstance05_00("ProbeSubstance05_00"), + ProbeSubstance05_24("ProbeSubstance05_24"), + + LargeBufferPos00("LargeBufferPos00"), + LargeBufferPos05("LargeBufferPos05"), + + ; + final public String chName; + HbotConsumablePos(String chName) { + this.chName = chName; + } +} diff --git a/src/main/java/a8k/type/HbotSamplePos.java b/src/main/java/a8k/type/HbotSamplePos.java new file mode 100644 index 0000000..96c697d --- /dev/null +++ b/src/main/java/a8k/type/HbotSamplePos.java @@ -0,0 +1,11 @@ +package a8k.type; + +public enum HbotSamplePos { + EmergencyTubePos, //急诊位取样位置 + BloodTubeSamplePos, //全血试管 + MiniTubeSamplePos, //迷你试管 + MiniBloodSamplePos, //阳普管 + Bulltube1P5SamplePos, //子弹头试管1.5mL + Bulltube0P5SamplePos, //子弹头试管0.5mL + StoolTestTubeSamplePos, //粪便试管 +} diff --git a/src/main/java/a8k/utils/PlaneUtils.java b/src/main/java/a8k/utils/PlaneUtils.java new file mode 100644 index 0000000..1432ecd --- /dev/null +++ b/src/main/java/a8k/utils/PlaneUtils.java @@ -0,0 +1,50 @@ +package a8k.utils; + +import a8k.type.cfg.Pos3d; + +public class PlaneUtils { + + // 计算平面方程的系数 + public static double[] calculatePlaneCoefficients(Pos3d p1, Pos3d p2, Pos3d p3) { + // 计算平面方程的A、B、C、D + double A = (p2.y - p1.y) * (p3.z - p1.z) - (p2.z - p1.z) * (p3.y - p1.y); + double B = (p2.z - p1.z) * (p3.x - p1.x) - (p2.x - p1.x) * (p3.z - p1.z); + double C = (p2.x - p1.x) * (p3.y - p1.y) - (p2.y - p1.y) * (p3.x - p1.x); + double D = -(A * p1.x + B * p1.y + C * p1.z); // 计算D + + return new double[]{A, B, C, D}; + } + + public static double calculateZ(double[] planeCoefficients, double x, double y) { + double A = planeCoefficients[0]; + double B = planeCoefficients[1]; + double C = planeCoefficients[2]; + double D = planeCoefficients[3]; + + // z = -(Ax + By + D) / C + if (C == 0) { + throw new ArithmeticException("C不能为零,无法求解z"); + } + return -(A * x + B * y + D) / C; + } + + public static double calculateZ(Pos3d p1, Pos3d p2, Pos3d p3, double x, double y) { + double[] planeCoefficients = calculatePlaneCoefficients(p1, p2, p3); + return calculateZ(planeCoefficients, x, y); + } + + + public static void main(String[] args) { + Pos3d p1 = new Pos3d(0, 0, 100); + Pos3d p2 = new Pos3d(100, 0, 105); + Pos3d p3 = new Pos3d(0, 100, 110); + + double[] planeCoefficients = calculatePlaneCoefficients(p1, p2, p3); + System.out.println("平面方程系数:" + planeCoefficients[0] + " " + planeCoefficients[1] + " " + planeCoefficients[2] + " " + planeCoefficients[3]); + + double x = 20; + double y = 80; + double z = calculateZ(planeCoefficients, x, y); + System.out.println("x=" + x + ", y=" + y + "时,z=" + z); + } +} \ No newline at end of file