passenger也可以debug

本文介绍了一种使用Passenger和ruby-debug插件在Rails应用中进行调试的方法。通过在development.rb配置文件中加入特定代码并创建restart.rake任务,实现了在需要调试的地方启动调试器。调试时,通过rdebug命令连接到调试会话。
最近在做一个东西,要用到subdomain,发现webrick不能支持,所以寻找passenger进行debug的方法。

方法比较土,但还是管用的。

首先,往development.rb里加入
if File.exists?(File.join(RAILS_ROOT,'tmp', 'debug.txt'))
require 'ruby-debug'
Debugger.wait_connection = true
Debugger.start_remote
File.delete(File.join(RAILS_ROOT,'tmp', 'debug.txt'))
end


接着在lib/task目录下新建restart.rake文件,内容为
task :restart do
system("touch tmp/restart.txt")
system("touch tmp/debug.txt") if ENV["DEBUG"] == 'true'
end


目前为止基本上搞定了,不过这些前提是已经安装了ruby-debug,rdebug这个命令可以执行。

这里是nginx,用development模式运行rails,在需要debug的地方加入一行"debugger",debug的时候在这里break。然后运行rake restart DEBUG=true。

打开浏览器,输入可以跑到刚刚输入debugger的url,会发现页面停止在那里。
这个时候,到terminal输入rdebug -c,怎么样,看到熟悉的debug界面了吧?

另外,在home建立一个文件.rdebugrc,设置一下debugger效果会好一些
set autoeval
set autolist
set autoreload
@Slf4j @Component @EnableScheduling public class PeopleCountingDisappearsScheduleHandler { @Autowired private TrajectoryCache trajectoryCache; @Lazy @Autowired private PeopleCountingDebugHandler peopleCountingDebugHandler; @Lazy @Autowired private PeopleCountingGeneralHandler peopleCountingGeneralHandler; @Lazy @Autowired protected PeopleCountingResultCache peopleCountingResultCache; @Lazy @Autowired protected PeopleCountingCache peopleCountingCache; @Value("${peopleCounting.trajectory.algorithm:multi_segments}") private String trajectoryAlgorithm = "multi_segments"; @Scheduled(cron = "0/30 * * * * ?") public void scheduledTask() { if (Objects.equals(trajectoryAlgorithm, "multi_segments")) { log.debug("start identify disappearing trajectories by multi_segments algorithm"); identifyDisappearingTrajectories(AiModule.PASSENGER_FLOW_STATISTICS, 30, peopleCountingGeneralHandler); identifyDisappearingTrajectories(AiModule.PEOPLE_COUNTING_DEBUG, 30, peopleCountingDebugHandler); } else { log.debug("start identify disappearing trajectories by start_end_positions algorithm"); identifyDisappearingObjects(AiModule.PASSENGER_FLOW_STATISTICS, 30, peopleCountingGeneralHandler); identifyDisappearingObjects(AiModule.PEOPLE_COUNTING_DEBUG, 30, peopleCountingDebugHandler); } } private void identifyDisappearingTrajectories(AiModule aiModule, int seconds, AbstractPeopleCountingHandler handler) { Map<String, List<Line>> disappearsSegmentGeneral = trajectoryCache.getDisappearsSegment(aiModule, System.currentTimeMillis() - TimeUnit.SECONDS.toMillis(seconds)); if (CollectionUtil.isNotEmpty(disappearsSegmentGeneral)) { List<ResultEntity> collect = disappearsSegmentGeneral.keySet().stream().map(key -> { List<Line> lines = disappearsSegmentGeneral.get(key); Line start = lines.get(0); Line end = lines.get(lines.size() - 1); Optional<ResultEntity> resultEntity = handler.handleDisappearsData(key, start, end); return resultEntity.orElse(null); }).filter(Objects::nonNull).collect(Collectors.toList()); peopleCountingResultCache.offers(collect); } } private void identifyDisappearingObjects(AiModule aiModule, int seconds, AbstractPeopleCountingHandler handler) { List<HistoricalEntity> disappearsObjects = peopleCountingCache.getDisappearsObjects(aiModule, System.currentTimeMillis() - TimeUnit.SECONDS.toMillis(seconds)); if (CollectionUtil.isNotEmpty(disappearsObjects)) { List<ResultEntity> collect = disappearsObjects.stream() .map(history -> handler.handleDisappearsData(history).orElse(null)).filter(Objects::nonNull) .collect(Collectors.toList()); if (CollectionUtil.isNotEmpty(collect)) { peopleCountingResultCache.offers(collect); } } } } 添加行级注释
09-13
public abstract class AbstractPeopleCountingHandler implements AbstractSmartDataHandler { @Lazy @Autowired protected PeopleCountingCache peopleCountingCache; @Lazy @Autowired protected PeopleCountingResultCache peopleCountingResultCache; @Autowired private AiSwitchConfig aiSwitchConfig; @Autowired private TrajectoryCache trajectoryCache; @Autowired private DeviceInfoContextCacheService deviceInfoContextCacheService; @Value("${peopleCounting.trajectory.algorithm:multi_segments}") private String trajectoryAlgorithm = "multi_segments"; @Value("${peopleCounting.trajectory.sufficientDistanceTimes:2}") private int sufficientDistanceTimes = 2; protected static final Set<Long> NEED_LOG_DEVICE_IDS = new HashSet<>(); private static final DynamicObjectLogger<Long> log = new DynamicObjectLogger<Long>( AbstractPeopleCountingHandler.class) { @Override public boolean debugEnabled(Long deviceId) { // todo return true; // return NEED_LOG_DEVICE_IDS.contains(deviceId); } }; protected abstract AiCustomThreadPool getThreadPool(); public abstract <T extends DeviceEntity> Collection<PeopleCountingConfigEntity> getRealDeviceConfigs( T deviceEntity); protected abstract Boolean isBusinessTime(PeopleCountingConfigEntity deviceConfig); protected abstract Boolean isBusinessTime(HistoricalEntity history); public static void updateNeedLogDeviceIds(Collection<Long> deviceIds) { NEED_LOG_DEVICE_IDS.clear(); if (CollectionUtil.isNotEmpty(deviceIds)) { NEED_LOG_DEVICE_IDS.addAll(deviceIds); } } @PostConstruct public void init() { AiModule module = getModule(); log.info(1L, "peoples counting handler init, module {}, enabled {}.", module, aiSwitchConfig.isAiModuleEnabled(module)); if (aiSwitchConfig.isAiModuleEnabled(module)) { AiSmartDataProcessor.registerHandler(module, this); } } @Trace @Override public void handleSmartData(DeviceInfoContext deviceInfo, SmartDataFrame frame) { Integer threadPoolIndex = deviceInfo.getPassengerFlowStatisticsThreadPoolIndex(); Long deviceId = deviceInfo.getDeviceId(); if (Objects.isNull(threadPoolIndex)) { int execute = getThreadPool().execute(deviceInfo.getKey(), () -> doHandleSmartData(deviceInfo, frame)); log.info(deviceId, "ai thread pool index [passenger flow stat] {}, device id {}, dev id {}, channel {}.", execute, deviceId, CustomPIIMaskUtil.encrypt(deviceInfo.getDevId()), deviceInfo.getChannel()); deviceInfo.setPassengerFlowStatisticsThreadPoolIndex(execute); } else { getThreadPool().execute(threadPoolIndex, () -> doHandleSmartData(deviceInfo, frame)); } } @Trace private void doHandleSmartData(DeviceInfoContext deviceInfo, SmartDataFrame frame) { log.info(123L, "frame is {}", frame); if (!verified(deviceInfo, frame)) { log.debug(deviceInfo.getDeviceId(), "invalid data, DeviceInfoContext: {}, SmartDataFrame: {}.", deviceInfo, frame); return; } Long deviceId = deviceInfo.getDeviceId(); DeviceEntity deviceEntity = DeviceEntity.getDeviceEntity(deviceInfo); log.debug(deviceId, "deviceEntity is {}", deviceEntity); Collection<PeopleCountingConfigEntity> deviceConfigs = getDeviceConfigs(deviceEntity); if (CollectionUtil.isEmpty(deviceConfigs)) { log.debug(deviceId, "device config is empty"); return; } log.info(deviceId, "deviceConfigs is {}", deviceConfigs); List<DevicePointEntity> points = frame.getObjs().stream().map(DevicePointEntity::getDevicePointEntity) .filter(Objects::nonNull) .collect(Collectors.toList()); if (CollectionUtil.isEmpty(points)) { log.debug(deviceId, "points is empty, frame: {}.", frame); return; } Collection<ResultEntity> results = new HashSet<>(); long timeStamp = System.currentTimeMillis() / TimeUnit.MINUTES.toMillis(1); for (PeopleCountingConfigEntity deviceConfig : deviceConfigs) { // todo 并发处理 ResultEntity resultEntity = trajectoryRecognition(deviceEntity, deviceConfig, points); log.debug(deviceId, "resultEntity is {}.", resultEntity); if (Objects.nonNull(resultEntity)) { resultEntity.setTimeMinute(timeStamp); results.add(resultEntity); } } if (CollectionUtil.isEmpty(results)) { log.debug(deviceId, "results is empty, frame: {}.", frame); return; } peopleCountingResultCache.offers(results); } public Optional<ResultEntity> handleDisappearsData(HistoricalEntity history) { Long deviceId = history.getDeviceId(); CrossAreaWayEnum crossAreaWay = history.resetInside(sufficientDistanceTimes); if (Objects.equals(crossAreaWay, CrossAreaWayEnum.USELESS)) { return Optional.empty(); } ResultEntity resultEntity = history.generateResultEntity(); resultEntity.setBusinessTime(isBusinessTime(history)); switch (crossAreaWay) { case PASS_BY_STORE: resultEntity.setPassBy(1); return Optional.of(resultEntity); case ENTER_STORE: resultEntity.setEnter(1); return Optional.of(resultEntity); case LEAVE_STORE: resultEntity.setCheckOut(1); return Optional.of(resultEntity); default: log.debug(deviceId, "useless cross area way: {}", crossAreaWay); } return Optional.empty(); } public Optional<ResultEntity> handleDisappearsData(String key, Line start, Line end) { Optional<ResultEntity> resultEntity = PeopleCountingCache.parseKey(key); if (!resultEntity.isPresent()) { return Optional.empty(); } ResultEntity result = resultEntity.get(); Long deviceId = result.getDeviceId(); int passBy = 0; int enter = 0; int checkOut = 0; try { CrossAreaWayEnum crossAreaWay = identifyDisappearsTrajectory(key, start, end); log.debug(deviceId, "cross area way: {}, key: {}, start: {}, end: {}.", crossAreaWay, key, start, end); switch (crossAreaWay) { case PASS_BY_STORE: passBy++; break; case ENTER_STORE: enter++; break; case LEAVE_STORE: checkOut++; break; default: log.debug(deviceId, "useless cross area way: {}", crossAreaWay); } } catch (Exception e) { log.debug(deviceId, "trajectory recognition error, key: {}, start: {}, end: {}.", key, start, end, e); } if (passBy == 0 && enter == 0 && checkOut == 0) { return Optional.empty(); } OperationResponse<DeviceInfoContext> deviceInfoContextByDeviceId = deviceInfoContextCacheService.getDeviceInfoContextByDeviceId( deviceId); if (deviceInfoContextByDeviceId.isError() || Objects.isNull(deviceInfoContextByDeviceId.getResult())) { log.debug(deviceId, "device info context is null, device id: {}.", deviceId); return Optional.empty(); } AiModule module = getModule(); result.setModule(module); result.setDeviceEntity(DeviceEntity.getDeviceEntity(deviceInfoContextByDeviceId.getResult())); Optional<PeopleCountingConfigEntity> deviceConfigOptional = peopleCountingCache.getConfigOptional(module, deviceId, result.getConfigId()); if (!deviceConfigOptional.isPresent()) { return Optional.empty(); } PeopleCountingConfigEntity deviceConfig = deviceConfigOptional.get(); result.setConfigId(deviceConfig.getConfigId()); result.setBusinessTime(isBusinessTime(deviceConfig)); result.setPassBy(passBy); result.setEnter(enter); result.setCheckOut(checkOut); result.setTimeMinute(System.currentTimeMillis() / TimeUnit.MINUTES.toMillis(1)); log.debug(deviceId, "trajectory recognition result: {}.", result); return Optional.of(result); } public CrossAreaWayEnum identifyDisappearsTrajectory(String key, Line start, Line end) { HistoricalEntity historical = peopleCountingCache.getHistorical(getModule(), key); if (Objects.isNull(historical)) { return CrossAreaWayEnum.USELESS; } List<Point> polygon = historical.getCurrentConfig().getPolygon(); Point outside = polygon.get(polygon.size() - 2); if (Boolean.TRUE.equals(historical.getCurrentConfig().getEnterFromA2B())) { outside = polygon.get(0); } Point enter; IntersectionLineDTO enterIntersectionLine = historical.getEnterIntersectionLine(); if (Objects.isNull(enterIntersectionLine)) { enterIntersectionLine = GeometryUtils.findRayIntersection(historical.getCurrentConfig().getPolygon(), start.reverse()); } enter = enterIntersectionLine.getIntersection(); IntersectionLineDTO leaveIntersectionLine = historical.getLeaveIntersectionLine(); if (Objects.isNull(leaveIntersectionLine)) { leaveIntersectionLine = GeometryUtils.findRayIntersection( historical.getCurrentConfig().getPolygon(), end); } Point leave = leaveIntersectionLine.getIntersection(); Line cuttingLine = historical.getCurrentConfig().getCuttingLine(); CrossAreaWayEnum crossAreaWay = getCrossAreaWay(enter, leave, cuttingLine, outside); log.debug(12L, "[PassengerFlowStatistics] getCrossAreaWay enter = {}, leave = {}, cuttingLine = {}, outside = {}.", enter, leave, cuttingLine, outside); reset(historical); return crossAreaWay; } private boolean verified(DeviceInfoContext deviceInfo, SmartDataFrame frame) { if (Objects.isNull(deviceInfo) || Objects.isNull(frame)) { return false; } if (Objects.isNull(deviceInfo.getDeviceId())) { return false; } if (CollectionUtil.isEmpty(frame.getObjs())) { return false; } return true; } private Collection<PeopleCountingConfigEntity> getDeviceConfigs(DeviceEntity deviceEntity) { return peopleCountingCache.getDeviceConfigs(deviceEntity, getModule()); } @Trace private ResultEntity trajectoryRecognition(DeviceEntity deviceEntity, PeopleCountingConfigEntity deviceConfig, List<DevicePointEntity> points) { Long deviceId = deviceConfig.getDeviceId(); int passBy = 0; int enter = 0; int checkOut = 0; for (DevicePointEntity point : points) { HistoricalEntity historical = obtainHistorical(deviceEntity, deviceConfig, point.getObjectId()); log.debug(deviceId, "historical is {}", historical); if (Objects.isNull(historical)) { continue; } try { CrossAreaWayEnum crossAreaWay = identifyTrajectory(historical, point); log.debug(deviceId, "cross area way: {}, historical: {}, point: {}.", crossAreaWay, historical, point); switch (crossAreaWay) { case PASS_BY_STORE: passBy++; break; case ENTER_STORE: enter++; break; case LEAVE_STORE: checkOut++; break; default: log.debug(deviceId, "useless cross area way: {}", crossAreaWay); } } catch (Exception e) { log.debug(deviceId, "trajectory recognition error, historical: {}, point: {}.", historical, point, e); } } if (passBy == 0 && enter == 0 && checkOut == 0) { return null; } ResultEntity result = new ResultEntity(); result.setModule(getModule()); result.setDeviceEntity(deviceEntity); result.setConfigId(deviceConfig.getConfigId()); result.setBusinessTime(isBusinessTime(deviceConfig)); result.setPassBy(passBy); result.setEnter(enter); result.setCheckOut(checkOut); log.debug(deviceId, "trajectory recognition result: {}.", result); return result; } private HistoricalEntity obtainHistorical(DeviceEntity deviceEntity, PeopleCountingConfigEntity deviceConfig, Integer objectId) { return peopleCountingCache.getHistorical(deviceEntity, deviceConfig.getConfigId(), objectId, getModule()); } private CrossAreaWayEnum identifyTrajectory(HistoricalEntity historical, DevicePointEntity point) { Long deviceId = historical.getDeviceId(); log.debug(deviceId, "[PassengerFlowStatistics] Start processing passenger flow statistics,HistoricalEntity = {}, current = {}.", JsonUtils.bean2Json(historical), JsonUtils.bean2Json(point)); Point current = point.getPoint(); if (Objects.isNull(current)) { return CrossAreaWayEnum.USELESS; } historical.setPrevious(historical.getCurrent()); historical.setPreviousInside(historical.getCurrentInside()); historical.setCurrent(current); historical.setCurrentInside(getPosition(historical.getDeviceConfigs(), current)); CrossAreaWayEnum crossAreaWayEnum = CrossAreaWayEnum.USELESS; log.debug(deviceId, "[PassengerFlowStatistics] The current node is located at {}", historical.getCurrentInside()); if (Objects.nonNull(historical.getCurrentInside())) { DeviceConfigDTO currentDeviceConfigDTO = historical.getDeviceConfigs().get(historical.getCurrentInside()); if (point.getConfidence() + currentDeviceConfigDTO.getSensitivity() < 100) { log.debug(deviceId, "[PassengerFlowStatistics] The node confidence does not meet the requirements, confidence = {}, Sensitivity = historical.currentDeviceConfigDTO.getSensitivity()", historical.getCurrentInside()); // 越不灵敏越不能接受置信度小的数据,如此灵敏度和置信度都很小的数据,丢弃 historical.setCurrent(historical.getPrevious()); historical.setCurrentInside(historical.getPreviousInside()); return CrossAreaWayEnum.USELESS; } processTrajectoryCache(historical, point.getObjectId(), current, point.getBoxHeight()); historical.setCurrentConfig(currentDeviceConfigDTO); if (Objects.isNull(historical.getEnterIntersectionLine()) && ( Objects.equals(historical.getCurrentInside(), historical.getPreviousInside()) || Objects.isNull(historical.getPrevious()))) { log.debug(deviceId, "[PassengerFlowStatistics] There is no trajectory entering the area."); //判断是否在边界上,在边界上即为进入线 IntersectionLineDTO enterIntersectionLine = GeometryUtils.findIntersection( currentDeviceConfigDTO.getPolygon(), current); log.debug(deviceId, "[PassengerFlowStatistics] The result of judging whether current node is on the boundary is {}", enterIntersectionLine); if (Objects.isNull(enterIntersectionLine)) { // 没有进入边界的点,凭空出现在了区域内 return CrossAreaWayEnum.USELESS; } historical.setEnterIntersectionLine(enterIntersectionLine); } // 位于区域内,那离开的位置就得重新计算 historical.setLeaveIntersectionLine(null); historical.setCompleteLeave(false); } else { // 位于区域外,但是还没完全进入,那就得重新计算进入位置 if (Boolean.FALSE.equals(historical.getCompleteEnter())) { historical.setEnterIntersectionLine(null); historical.setCompleteEnter(false); } crossAreaWayEnum = historical.resetInside(sufficientDistanceTimes); } if (Objects.nonNull(historical.getCurrentInside()) && Objects.isNull(historical.getPreviousInside())) { // 进入区域 if (Objects.isNull(historical.getPrevious())) { return CrossAreaWayEnum.USELESS; } historical.setEnterIntersectionLine(GeometryUtils.findIntersection( historical.getCurrentConfig().getPolygon(), new Line(current, historical.getPrevious()))); log.debug(deviceId, "[PassengerFlowStatistics] The target enters the area from {}", historical.getEnterIntersectionLine()); } else if (Objects.isNull(historical.getCurrentInside()) && Objects.nonNull(historical.getPreviousInside())) { if (Objects.isNull(historical.getPrevious())) { return CrossAreaWayEnum.USELESS; } historical.setLeaveIntersectionLine(GeometryUtils.findIntersection( historical.getCurrentConfig().getPolygon(), new Line(current, historical.getPrevious()))); log.debug(deviceId, "[PassengerFlowStatistics] The target leaves the area from {}", historical.getLeaveIntersectionLine()); } if (Objects.nonNull(historical.getEnterIntersectionLine()) && !Boolean.TRUE.equals( historical.getCompleteEnter())) { historical.setCompleteEnter( GeometryUtils.distanceToLineSegment(historical.getEnterIntersectionLine().getLine(), current) > point.getHalfWidth()); } if (Objects.nonNull(historical.getLeaveIntersectionLine()) && !Boolean.TRUE.equals( historical.getCompleteLeave())) { historical.setCompleteLeave( GeometryUtils.distanceToLineSegment(historical.getLeaveIntersectionLine().getLine(), current) > point.getHalfWidth()); } log.debug(deviceId, "[PassengerFlowStatistics] completeEnter = {}, completeLeave = {}", historical.getCompleteEnter(), historical.getCompleteLeave()); if (Objects.nonNull(historical.getLeaveIntersectionLine()) && Boolean.TRUE.equals( historical.getCompleteLeave())) { if (Objects.isNull(historical.getEnterIntersectionLine())) { if (Objects.equals(trajectoryAlgorithm, "multi_segments")) { // 未知区域进入,从轨迹方向进行确认 List<Line> segment = trajectoryCache.getSegment(getModule(), deviceId, historical.getConfigId(), point.getObjectId()); if (CollectionUtil.isNotEmpty(segment)) { historical.setEnterIntersectionLine( GeometryUtils.findRayIntersection(historical.getCurrentConfig().getPolygon(), segment.get(0).reverse())); } } else { log.debug(deviceId, "[PassengerFlowStatistics] getCrossAreaWay crossAreaWayEnum = {}.", crossAreaWayEnum); reset(historical, point); return crossAreaWayEnum; } } if (Objects.nonNull(historical.getEnterIntersectionLine())) { // 完成了离开 List<Point> polygon = historical.getCurrentConfig().getPolygon(); Point outside = polygon.get(polygon.size() - 2); if (Boolean.TRUE.equals(historical.getCurrentConfig().getEnterFromA2B())) { outside = polygon.get(0); } Point enter = historical.getEnterIntersectionLine().getIntersection(); Point leave = historical.getLeaveIntersectionLine().getIntersection(); Line cuttingLine = historical.getCurrentConfig().getCuttingLine(); CrossAreaWayEnum crossAreaWay = getCrossAreaWay(enter, leave, cuttingLine, outside); log.debug(deviceId, "[PassengerFlowStatistics] getCrossAreaWay enter = {}, leave = {}, cuttingLine = {}, outside = {}.", enter, leave, cuttingLine, outside); reset(historical, point); return crossAreaWay; } } return CrossAreaWayEnum.USELESS; } private void processTrajectoryCache(HistoricalEntity historical, Integer objectId, Point current, Integer boxHeight) { Long deviceId = historical.getDeviceId(); String configId = historical.getConfigId(); try { if (Objects.equals(trajectoryAlgorithm, "multi_segments")) { trajectoryCache.addPoint(getModule(), deviceId, configId, objectId, current, boxHeight); } else { historical.updateInside(current, boxHeight); } } catch (Exception e) { log.error(deviceId, "trajectory cache add point error, ai module = {}, deviceId = {}, configId = {}, objectId = {}, current = {}.", getModule(), deviceId, configId, objectId, current, e); } } public boolean reset(HistoricalEntity historical, DevicePointEntity point) { trajectoryCache.reset(getModule(), historical.getDeviceId(), historical.getConfigId(), point.getObjectId()); return reset(historical); } public boolean reset(HistoricalEntity historical) { historical.setPrevious(null); historical.setPreviousInside(null); historical.setEnterIntersectionLine(null); historical.setCompleteEnter(null); historical.setLeaveIntersectionLine(null); historical.setCompleteLeave(null); return true; } public static Integer getPosition( Map<Integer, DeviceConfigDTO> deviceConfigs, Point point) { if (CollectionUtil.isEmpty(deviceConfigs) || point == null) { return null; } for (DeviceConfigDTO deviceConfig : deviceConfigs.values()) { if (GeometryUtils.isPointInPolygon(deviceConfig.getPolygon(), point)) { // 区域不重复,如果处于一个区域内,那必然不在另一个区域内 return deviceConfig.getId(); } } return null; } public static CrossAreaWayEnum getCrossAreaWay(Point enter, Point leave, Line cuttingLine, Point outside) { boolean fromOutside = GeometryUtils.arePointsOnSameSide(cuttingLine, enter, outside); boolean toOutside = GeometryUtils.arePointsOnSameSide(cuttingLine, leave, outside); if (fromOutside) { if (toOutside) { return CrossAreaWayEnum.PASS_BY_STORE; } return CrossAreaWayEnum.ENTER_STORE; } if (toOutside) { return CrossAreaWayEnum.LEAVE_STORE; } return CrossAreaWayEnum.USELESS; } } 添加行级注释
09-13
private CrossAreaWayEnum identifyTrajectory(HistoricalEntity historical, DevicePointEntity point) { Long deviceId = historical.getDeviceId(); log.debug(deviceId, "[PassengerFlowStatistics] Start processing passenger flow statistics,HistoricalEntity = {}, current = {}.", JsonUtils.bean2Json(historical), JsonUtils.bean2Json(point)); Point current = point.getPoint(); if (Objects.isNull(current)) { return CrossAreaWayEnum.USELESS; } historical.setPrevious(historical.getCurrent()); historical.setPreviousInside(historical.getCurrentInside()); historical.setCurrent(current); historical.setCurrentInside(getPosition(historical.getDeviceConfigs(), current)); CrossAreaWayEnum crossAreaWayEnum = CrossAreaWayEnum.USELESS; log.debug(deviceId, "[PassengerFlowStatistics] The current node is located at {}", historical.getCurrentInside()); if (Objects.nonNull(historical.getCurrentInside())) { DeviceConfigDTO currentDeviceConfigDTO = historical.getDeviceConfigs().get(historical.getCurrentInside()); if (point.getConfidence() + currentDeviceConfigDTO.getSensitivity() < 100) { log.debug(deviceId, "[PassengerFlowStatistics] The node confidence does not meet the requirements, confidence = {}, Sensitivity = historical.currentDeviceConfigDTO.getSensitivity()", historical.getCurrentInside()); // 越不灵敏越不能接受置信度小的数据,如此灵敏度和置信度都很小的数据,丢弃 historical.setCurrent(historical.getPrevious()); historical.setCurrentInside(historical.getPreviousInside()); return CrossAreaWayEnum.USELESS; } processTrajectoryCache(historical, point.getObjectId(), current, point.getBoxHeight()); historical.setCurrentConfig(currentDeviceConfigDTO); if (Objects.isNull(historical.getEnterIntersectionLine()) && ( Objects.equals(historical.getCurrentInside(), historical.getPreviousInside()) || Objects.isNull(historical.getPrevious()))) { log.debug(deviceId, "[PassengerFlowStatistics] There is no trajectory entering the area."); //判断是否在边界上,在边界上即为进入线 IntersectionLineDTO enterIntersectionLine = GeometryUtils.findIntersection( currentDeviceConfigDTO.getPolygon(), current); log.debug(deviceId, "[PassengerFlowStatistics] The result of judging whether current node is on the boundary is {}", enterIntersectionLine); if (Objects.isNull(enterIntersectionLine)) { // 没有进入边界的点,凭空出现在了区域内 return CrossAreaWayEnum.USELESS; } historical.setEnterIntersectionLine(enterIntersectionLine); } // 位于区域内,那离开的位置就得重新计算 historical.setLeaveIntersectionLine(null); historical.setCompleteLeave(false); } else { // 位于区域外,但是还没完全进入,那就得重新计算进入位置 if (Boolean.FALSE.equals(historical.getCompleteEnter())) { historical.setEnterIntersectionLine(null); historical.setCompleteEnter(false); } crossAreaWayEnum = historical.resetInside(sufficientDistanceTimes); } if (Objects.nonNull(historical.getCurrentInside()) && Objects.isNull(historical.getPreviousInside())) { // 进入区域 if (Objects.isNull(historical.getPrevious())) { return CrossAreaWayEnum.USELESS; } historical.setEnterIntersectionLine(GeometryUtils.findIntersection( historical.getCurrentConfig().getPolygon(), new Line(current, historical.getPrevious()))); log.debug(deviceId, "[PassengerFlowStatistics] The target enters the area from {}", historical.getEnterIntersectionLine()); } else if (Objects.isNull(historical.getCurrentInside()) && Objects.nonNull(historical.getPreviousInside())) { if (Objects.isNull(historical.getPrevious())) { return CrossAreaWayEnum.USELESS; } historical.setLeaveIntersectionLine(GeometryUtils.findIntersection( historical.getCurrentConfig().getPolygon(), new Line(current, historical.getPrevious()))); log.debug(deviceId, "[PassengerFlowStatistics] The target leaves the area from {}", historical.getLeaveIntersectionLine()); } if (Objects.nonNull(historical.getEnterIntersectionLine()) && !Boolean.TRUE.equals( historical.getCompleteEnter())) { historical.setCompleteEnter( GeometryUtils.distanceToLineSegment(historical.getEnterIntersectionLine().getLine(), current) > point.getHalfWidth()); } if (Objects.nonNull(historical.getLeaveIntersectionLine()) && !Boolean.TRUE.equals( historical.getCompleteLeave())) { historical.setCompleteLeave( GeometryUtils.distanceToLineSegment(historical.getLeaveIntersectionLine().getLine(), current) > point.getHalfWidth()); } log.debug(deviceId, "[PassengerFlowStatistics] completeEnter = {}, completeLeave = {}", historical.getCompleteEnter(), historical.getCompleteLeave()); if (Objects.nonNull(historical.getLeaveIntersectionLine()) && Boolean.TRUE.equals( historical.getCompleteLeave())) { if (Objects.isNull(historical.getEnterIntersectionLine())) { if (Objects.equals(trajectoryAlgorithm, "multi_segments")) { // 未知区域进入,从轨迹方向进行确认 List<Line> segment = trajectoryCache.getSegment(getModule(), deviceId, historical.getConfigId(), point.getObjectId()); if (CollectionUtil.isNotEmpty(segment)) { historical.setEnterIntersectionLine( GeometryUtils.findRayIntersection(historical.getCurrentConfig().getPolygon(), segment.get(0).reverse())); } } else { log.debug(deviceId, "[PassengerFlowStatistics] getCrossAreaWay crossAreaWayEnum = {}.", crossAreaWayEnum); reset(historical, point); return crossAreaWayEnum; } } if (Objects.nonNull(historical.getEnterIntersectionLine())) { // 完成了离开 List<Point> polygon = historical.getCurrentConfig().getPolygon(); Point outside = polygon.get(polygon.size() - 2); if (Boolean.TRUE.equals(historical.getCurrentConfig().getEnterFromA2B())) { outside = polygon.get(0); } Point enter = historical.getEnterIntersectionLine().getIntersection(); Point leave = historical.getLeaveIntersectionLine().getIntersection(); Line cuttingLine = historical.getCurrentConfig().getCuttingLine(); CrossAreaWayEnum crossAreaWay = getCrossAreaWay(enter, leave, cuttingLine, outside); log.debug(deviceId, "[PassengerFlowStatistics] getCrossAreaWay enter = {}, leave = {}, cuttingLine = {}, outside = {}.", enter, leave, cuttingLine, outside); reset(historical, point); return crossAreaWay; } } return CrossAreaWayEnum.USELESS; } 添加行级注释
09-18
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值