【仿真建模-anylogic】动态生成ConveyorCustomStation
Author:赵志乾
Date:2024-06-18
Declaration:All Right Reserved!!!
0. 背景
直接使用Anylogic组件开发的模型无法动态改变运输网布局;目前需求是要将运输网布局配置化;运输网配置化的前提是将其标准化为仅包含辊道、自定义站点两种元素的网络;之后依据配置文件动态构建运输网;最后将自定义Agent逻辑关联到自定义站点实现流程串通;本次示例仅包含运输网中的辊道和自定义站点的动态生成以及组装过程;
1. 常用函数
| 函数 | 功能 |
|---|---|
| ConveyorCustomStation() | 构造函数 |
| addVertex(double x, double y) | 添加点以构建2D图形,注意点:需要至少三个点,且连起的图形不得自身有交叉;通常会将CustomStation的图形隐藏,而将其内部自定义逻辑封装成Agent,用Agent的presentation替补CustomStation本身的图形; |
| addConnection(ConveyorPath conveyor, PathType type) | 将CustomStation与conveyor连接起来 |
| onEnter(T agent) | 根据需要定义子类覆写该方法;当所运输物料进入CustomStation时,会自动执行该方法; |
2. 数据结构定义
{"points": [{"code": "", // 点编码"name": "", // 点名称"x": 0.0, // 点坐标"y": 0.0,"z": 0.0}],"conveyors": [{"code": "", // 辊道编码"name": "", // 辊道名称"pointCodes": [] // 辊道从起点至终点所经历的位置点编码列表}],"customStations": [{"code": "", // 自定义站点编码"name": "", // 自定义站点名称"inConveyorCodes": [], // 传入站点的辊道"outConveyorCodes": [] // 传出站点的辊道}]
}
3. 代码实现
// ************************数据对象定义****************************
public class PointDefinition implements Serializable {private String code;private String name;private Double x;private Double y;private Double z;// setter、getter
}public class ConveyorDefinition implements Serializable {private String code;private String name;// setter、getter
}public class LayoutDefinition implements Serializable {private List<PointDefinition> points;private List<ConveyorDefinition> conveyors;private List<CustomStationDefinition> customStations;// setter、getter
}public class CustomStationDefinition implements Serializable {private String code;private String name;private List<String> inConveyorCodes;private List<String> outConveyorCodes;// setter、getter
}//******************************子类*******************************
public class CustomStation<T extends Agent> extends ConveyorCustomStation<T> {// 持有站点定义,便于onEnter中依据站点不同做不同处理CustomStationDefinition customStationDefinition;public CustomStation(CustomStationDefinition customStationDefinition) {super();this.customStationDefinition = customStationDefinition;}public void onEnter(T agent ) {// 自定义逻辑}
}//**************************动态生成过程******************************
// step1: 转map,方便后续使用
Map<String,PointDefinition> codeToPointDefinitionMap = layoutDefinition.getPoints().stream().collect(Collectors.toMap(PointDefinition::getCode, Function.identity(), (a,b)->b));
Map<String,ConveyorDefinition> codeToConveyorDefinitionMap = layoutDefinition.getConveyors().stream().collect(Collectors.toMap(ConveyorDefinition::getCode, Function.identity(), (a,b)->b));
Map<ConveyorDefinition,ConveyorPath> definitionToConveyorMap = new HashMap<>();// step2: 定义网络对象
ConveyorNetwork conveyorNetwork = new ConveyorNetwork(this,"conveyorNetwork");// step3: 向网络添加conveyor
for(ConveyorDefinition conveyorDefinition : layoutDefinition.getConveyors()){ConveyorPath conveyor = new ConveyorPath();// 每个conveyor由若干段组成for(int index=0; index<conveyorDefinition.getPointCodes().size()-1; index++){PointDefinition startPoint = codeToPointDefinitionMap.get(conveyorDefinition.getPointCodes().get(index));PointDefinition endPoint = codeToPointDefinitionMap.get(conveyorDefinition.getPointCodes().get(index+1));double startX = scale.pixelsPerUnit(METER)*startPoint.getX();double startY = scale.pixelsPerUnit(METER)*startPoint.getY();double startZ = scale.pixelsPerUnit(METER)*startPoint.getZ();double endX = scale.pixelsPerUnit(METER)*endPoint.getX();double endY = scale.pixelsPerUnit(METER)*endPoint.getY();double endZ = scale.pixelsPerUnit(METER)*endPoint.getZ();MarkupSegmentLine segment = new MarkupSegmentLine(startX, startY, startZ, endX, endY, endZ);conveyor.addSegment(segment);}definitionToConveyorMap.put(conveyorDefinition, conveyor);conveyorNetwork.add(conveyor);
}// step4: 自定义站点添加
for(CustomStationDefinition customStationDefinition : layoutDefinition.getCustomStations()){// step4.1: 站点创建CustomStation<Agent> customStation = new CustomStation(customStationDefinition);List<PointDefinition> points = new ArrayList<>();// step4.2: 站点与辊道关联,并绘制站点图形 for(String conveyorCode : customStationDefinition.getInConveyorCodes()){customStation.addConnection(definitionToConveyorMap.get(codeToConveyorDefinitionMap.get(conveyorCode)), PathEndType.END);ConveyorDefinition conveyorDefinition = codeToConveyorDefinitionMap.get(conveyorCode);PointDefinition pointDefinition = codeToPointDefinitionMap.get(conveyorDefinition.getPointCodes().get(conveyorDefinition.getPointCodes().size()-1));points.add(pointDefinition);customStation.addVertex(scale.pixelsPerUnit(METER)*pointDefinition.getX(), scale.pixelsPerUnit(METER)*pointDefinition.getY());}for(String conveyorCode : customStationDefinition.getOutConveyorCodes()){customStation.addConnection(definitionToConveyorMap.get(codeToConveyorDefinitionMap.get(conveyorCode)), PathEndType.BEGIN);ConveyorDefinition conveyorDefinition = codeToConveyorDefinitionMap.get(conveyorCode);PointDefinition pointDefinition = codeToPointDefinitionMap.get(conveyorDefinition.getPointCodes().get(0));points.add(pointDefinition);customStation.addVertex(scale.pixelsPerUnit(METER)*pointDefinition.getX(), scale.pixelsPerUnit(METER)*pointDefinition.getY());}// step4.3: 站点图形补充int conveyorNum = customStationDefinition.getInConveyorCodes().size()+customStationDefinition.getOutConveyorCodes().size();if(conveyorNum==0){error("不允许无连接辊道的ConveyorCustomStation");}else if(conveyorNum==1){// 已有一个点,需要额外补充两个点customStation.addVertex(scale.pixelsPerUnit(METER)*(points.get(points.size()-1).getX()+0.1), scale.pixelsPerUnit(METER)*(points.get(points.size()-1).getY()+0.2));customStation.addVertex(scale.pixelsPerUnit(METER)*(points.get(points.size()-1).getX()+0.1), scale.pixelsPerUnit(METER)*(points.get(points.size()-1).getY()+0.4));}else if(conveyorNum==2){// 已有一个点,需要额外补充一个点,借助两点的法线寻找第三点double x1 = scale.pixelsPerUnit(METER)*points.get(0).getX();double y1 = scale.pixelsPerUnit(METER)*points.get(0).getY();double x2 = scale.pixelsPerUnit(METER)*points.get(points.size()-1).getX();double y2 = scale.pixelsPerUnit(METER)*points.get(points.size()-1).getY();double kAB; if (x2 - x1 == 0) { kAB = Double.POSITIVE_INFINITY;} else { kAB = (y2 - y1) / (x2 - x1); } double kPerp; if (kAB == Double.POSITIVE_INFINITY || kAB == Double.NEGATIVE_INFINITY || kAB == 0) { kPerp = kAB == 0 ? Double.POSITIVE_INFINITY : 0; } else { kPerp = -1 / kAB; } double xC = x1 + 0.5; double yC; if (kPerp == Double.POSITIVE_INFINITY || kPerp == Double.NEGATIVE_INFINITY) { yC = y1; } else { yC = y1 + kPerp * (xC - x1); } customStation.addVertex(xC,yC);}conveyorNetwork.add(customStation);
}// step5: 将生成的网络添加到演示中
Level customLevel = new Level(this,"customLevel",SHAPE_DRAW_2D3D,0);
customLevel.add(conveyorNetwork);
customLevel.initialize();
presentation.add(customLevel);
相关文章:
【仿真建模-anylogic】动态生成ConveyorCustomStation
Author:赵志乾 Date:2024-06-18 Declaration:All Right Reserved!!! 0. 背景 直接使用Anylogic组件开发的模型无法动态改变运输网布局;目前需求是要将运输网布局配置化;运输网配置化…...
如何使用idea连接Oracle数据库?
idea版本:2021.3.3 Oracle版本:10.2.0.1.0(在虚拟机Windows sever 2003 远程连接数据库) 数据库管理系统:PLSQL Developer 在idea里面找到database,在idea侧面 选择左上角加号,新建ÿ…...
谈谈kafaka的并行处理,顺带讲讲rabbitmq
简介 Kafka 是一个分布式流处理平台,它支持高效的并行处理。Kafka 的并行处理能力主要体现在以下几个方面: 分区(Partition)并行 Kafka 将数据存储在称为"分区"的逻辑单元中。每个分区可以独立地并行地进行读写操作。生产者可以根据分区策略,将数据写入到指定的分…...
P3056 [USACO12NOV] Clumsy Cows S
[USACO12NOV] Clumsy Cows S 题目描述 Bessie the cow is trying to type a balanced string of parentheses into her new laptop, but she is sufficiently clumsy (due to her large hooves) that she keeps mis-typing characters. Please help her by computing the min…...
智赢选品,OZON数据分析选品利器丨萌啦OZON数据
在电商行业的激烈竞争中,如何快速准确地把握市场动态、洞察消费者需求、实现精准选品,是每个电商卖家都面临的挑战。而在这个数据驱动的时代,一款强大的数据分析工具无疑是电商卖家们的得力助手。今天,我们就来聊聊这样一款选品利…...
Canal自定义客户端
一、背景 在Canal推送数据变更信息至MQ(消息队列)时,我们遇到了特定问题,尤其是当消息体的大小超过了MQ所允许的最大限制。这种限制导致数据推送过程受阻,需要相应的调整或处理。 二、解决方法 采用Canal自定义客户…...
20240621将需要自启动的部分放到RK3588平台的Buildroot系统的rcS文件中
20240621将需要自启动的部分放到RK3588平台的Buildroot系统的rcS文件中 2024/6/21 17:15 开发板:飞凌OK3588-C SDK:Rockchip原厂的Buildroot 缘起:在凌OK3588-C的LINUX R4系统启动的时候,需要拉高GPIO4_B5、GPIO3_B7和GPIO3_D0。…...
掌握数据魔方:Xinstall引领ASA全链路数据归因新纪元
一、引言 在数字化时代,数据是App推广和运营的核心驱动力。然而,如何准确获取、分析并应用这些数据,却成为了许多开发者和营销人员面临的痛点。Xinstall作为一款专业的App全渠道统计服务商,致力于提供精准、高效的数据解决方案&a…...
IIS代理配置-反向代理
前后端分离项目,前端在开发中使用proxy代理解决跨域问题,打包之后无效。 未配置前无法访问 部署环境为windows IIS,要在iis设置反向代理 安装代理模块 需要在iis中实现代理,需要安装Application Request Routing Cache和URL重…...
Flutter调用本地web
前言: 在目前Flutter 环境中,使用在线 webview 是一种很常见的行为 而在 app 环境中,离线使用则更有必要 1.环境准备 将依赖导入 2.引入前端代码 前端代码有两种情况 一种是使用打包工具 build 而来的前端代码 另一种情况是直接使用 HTML 文件 …...
AI大模型部署Ubuntu服务器攻略
一、下载Ollama 在线安装: 在linux中输入命令curl -fsSL https://ollama.com/install.sh | sh 由于在linux下载ollama需要经过外网,网络会不稳定,很容易造成连接超时的问题。 离线安装: 步骤一: 下载Ollama离线版本…...
vlan、vxlan、vpc学习
文章目录 前言VLAN (Virtual Local Area Network)定义工作原理优点应用场景限制 VXLAN (Virtual eXtensible Local Area Network)工作原理优点应用场景与VLAN的区别 VPC (Virtual Private Cloud)定义特点优势应用场景与VLAN/VXLAN的关联 总结 前言 VLAN(Virtual Lo…...
低代码开发:加速工业数智化转型发展
引言 在当今全球经济一体化和信息化的深度融合的大环境下,工业数智化转型已经成为推动制造业高质量发展的关键因素。这一转型不仅涉及生产过程的智能化、网络化,还涉及到企业管理、市场服务等全方位的数字化升级,其最终目标是为了实现更高效能…...
python“__main__“的解读
Tutorial Gross tutorial 有些模块包含了仅供脚本使用的代码,比如解析命令行参数或从标准输入获取数据。 如果这样的模块被从不同的模块中导入,例如为了单元测试,脚本代码也会无意中执行。 这就是 if name ‘main’ 代码块的用武之地。除非…...
Linux Debian12使用podman安装pikachu靶场环境
一、pikachu简介 Pikachu是一个带有漏洞的Web应用系统,在这里包含了常见的web安全漏洞。 二、安装podman环境 Linux Debian系统如果没有安装podman容器环境,可以参考这篇文章先安装podman环境, Linux Debian11使用国内源安装Podman环境 三…...
跑通并使用Yolo v5的源代码并进行训练—目标检测
跑通并使用Yolo v5的源代码并进行训练 摘要:yolo作为目标检测计算机视觉领域的核心网络模型,虽然到24年已经出到了v10的版本,但也很有必要对之前的核心版本v5版本进行进一步的学习。在学习yolo v5的时候因为缺少论文所以要从源代码入手来体验…...
需求虽小但是问题很多,浅谈JavaScript导出excel文件
最近我在进行一些前端小开发,遇到了一个小需求:我想要将数据导出到 Excel 文件,并希望能够封装成一个函数来实现。这个函数需要接收一个二维数组作为参数,数组的第一行是表头。在导出的过程中,要能够确保避免出现中文乱…...
phar反序列化及绕过
目录 一、什么是phar phar://伪协议格式: 二、phar结构 1.stub phar:文件标识。 格式为 xxx; *2、manifest:压缩文件属性等信息,以序列化存 3、contents:压缩文件的内容。 4、signature:签名&#…...
汽车IVI中控开发入门及进阶(三十):视频图像滚动问题分析(imx6+TVP5150+Camera)
前言: DA主控SOC采用imx6,TVP5150作为camera摄像头视频的解码decode芯片,imx6采用linux系统。 关于imx6,请参阅:汽车IVI中控开发入门及进阶(二十九):i.MX6-CSDN博客 Contributor III:...
给PDF添加书签的通解-姜萍同款《偏微分方程》改造手记
背景 网上找了一本姜萍同款的《偏微分方程》,埃文斯,英文版,可惜没有书签,洋洋七百多页,没有书签,怎么读?用福昕编辑器自然能手工一个个加上,可是劳神费力,非程序员所为…...
synchronized 学习
学习源: https://www.bilibili.com/video/BV1aJ411V763?spm_id_from333.788.videopod.episodes&vd_source32e1c41a9370911ab06d12fbc36c4ebc 1.应用场景 不超卖,也要考虑性能问题(场景) 2.常见面试问题: sync出…...
【Oracle APEX开发小技巧12】
有如下需求: 有一个问题反馈页面,要实现在apex页面展示能直观看到反馈时间超过7天未处理的数据,方便管理员及时处理反馈。 我的方法:直接将逻辑写在SQL中,这样可以直接在页面展示 完整代码: SELECTSF.FE…...
Xshell远程连接Kali(默认 | 私钥)Note版
前言:xshell远程连接,私钥连接和常规默认连接 任务一 开启ssh服务 service ssh status //查看ssh服务状态 service ssh start //开启ssh服务 update-rc.d ssh enable //开启自启动ssh服务 任务二 修改配置文件 vi /etc/ssh/ssh_config //第一…...
定时器任务——若依源码分析
分析util包下面的工具类schedule utils: ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类,封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz,先构建任务的 JobD…...
C++ 基础特性深度解析
目录 引言 一、命名空间(namespace) C 中的命名空间 与 C 语言的对比 二、缺省参数 C 中的缺省参数 与 C 语言的对比 三、引用(reference) C 中的引用 与 C 语言的对比 四、inline(内联函数…...
数据链路层的主要功能是什么
数据链路层(OSI模型第2层)的核心功能是在相邻网络节点(如交换机、主机)间提供可靠的数据帧传输服务,主要职责包括: 🔑 核心功能详解: 帧封装与解封装 封装: 将网络层下发…...
九天毕昇深度学习平台 | 如何安装库?
pip install 库名 -i https://pypi.tuna.tsinghua.edu.cn/simple --user 举个例子: 报错 ModuleNotFoundError: No module named torch 那么我需要安装 torch pip install torch -i https://pypi.tuna.tsinghua.edu.cn/simple --user pip install 库名&#x…...
Spring是如何解决Bean的循环依赖:三级缓存机制
1、什么是 Bean 的循环依赖 在 Spring框架中,Bean 的循环依赖是指多个 Bean 之间互相持有对方引用,形成闭环依赖关系的现象。 多个 Bean 的依赖关系构成环形链路,例如: 双向依赖:Bean A 依赖 Bean B,同时 Bean B 也依赖 Bean A(A↔B)。链条循环: Bean A → Bean…...
【电力电子】基于STM32F103C8T6单片机双极性SPWM逆变(硬件篇)
本项目是基于 STM32F103C8T6 微控制器的 SPWM(正弦脉宽调制)电源模块,能够生成可调频率和幅值的正弦波交流电源输出。该项目适用于逆变器、UPS电源、变频器等应用场景。 供电电源 输入电压采集 上图为本设计的电源电路,图中 D1 为二极管, 其目的是防止正负极电源反接, …...
基于Springboot+Vue的办公管理系统
角色: 管理员、员工 技术: 后端: SpringBoot, Vue2, MySQL, Mybatis-Plus 前端: Vue2, Element-UI, Axios, Echarts, Vue-Router 核心功能: 该办公管理系统是一个综合性的企业内部管理平台,旨在提升企业运营效率和员工管理水…...
