【仿真建模-anylogic】动态生成轨道网络

复制代码
Author:赵志乾
Date:2024-06-07
Declaration:All Right Reserved!!!

**问题:**anylogic支持在图形编辑界面以拖拽方式搭建轨道网络,以该方法搭建的模型复用性低。

**解决方案:**轨道布局以配置文件进行描述,模型启动时依据配置文件动态绘制轨道网络。

复制代码
// step1: 定义配置文件数据结构
{
    "points": [
        {
            "code": "位置点编码",
            "name": "位置点名称",
            "x": 0, // 位置点坐标, 单位:米
            "y": 0, // 位置点坐标, 单位:米
            "z": 0  // 位置点坐标, 单位:米
        }
    ],
    "tracks": [
        {
            "code": "轨道编码",
            "name": "轨道名称",
            "pointCodes": [ // 轨道从起点至终点所经历的位置点编码
                "位置点编码" 
            ]
        }
    ]
}

// step2: 定义解析类
public class PointDefinition implements Serializable {
	private String code;
	private String name;
	private Double x;
	private Double y;
	private Double z;
    // setter、getter、constructor
}
public class TrackDefinition implements Serializable {
	 private String code;
	 private String name;
	 private List<String> pointCodes;
     // setter、getter、constructor
}
public class LayoutDefinition implements Serializable {
	private List<PointDefinition> points;
	private List<TrackDefinition> tracks;
    // setter、getter、constructor
}


// step3: 容器智能体中完成轨道绘制
Map<String,PointDefinition> codeToPointDefinitionMap = layoutDefinition.getPoints()
	.stream()
	.collect(Collectors.toMap(PointDefinition::getCode, Function.identity(), (a,b)->b));

RailwayNetwork rn = new RailwayNetwork(this, "railwayNetwork",SHAPE_DRAW_2D3D, 0);
Map<String,List<TrackDefinition>> switchCodeToTrackDefinitionsMap = new HashMap<>();
Map<TrackDefinition,RailwayTrack> trackDefinitionToRailwayTrackMap = new HashMap<>();
// 3.1: 轨道绘制
for(TrackDefinition trackDefinition : layoutDefinition.getTracks()){
	String startPointCode = trackDefinition.getPointCodes().get(0);
	List<TrackDefinition> trackDefinitions = switchCodeToTrackDefinitionsMap.getOrDefault(startPointCode, new ArrayList<>());
	trackDefinitions.add(trackDefinition);
	switchCodeToTrackDefinitionsMap.put(startPointCode, trackDefinitions);
	
	String endPointCode = trackDefinition.getPointCodes().get(trackDefinition.getPointCodes().size()-1);
	trackDefinitions = switchCodeToTrackDefinitionsMap.getOrDefault(endPointCode, new ArrayList<>());
	trackDefinitions.add(trackDefinition);
	switchCodeToTrackDefinitionsMap.put(endPointCode, trackDefinitions);
	
	RailwayTrack rt = new RailwayTrack();
	rt.setWidth(1, METER);
	rn.add(rt);
	trackDefinitionToRailwayTrackMap.put(trackDefinition,rt);
	for(int index = 0; index<trackDefinition.getPointCodes().size(); index++){
		String pointCode = trackDefinition.getPointCodes().get(index);
		PointDefinition pointDefinition = codeToPointDefinitionMap.get(pointCode);
		if(pointDefinition==null){
			error("轨道定义中包含未知点! trackCode="+trackDefinition.getCode()+" pointCode="+pointCode);
		}
		
		double x = scale.pixelsPerUnit(METER)*pointDefinition.getX();
		double y = scale.pixelsPerUnit(METER)*pointDefinition.getY();
		double z = scale.pixelsPerUnit(METER)*pointDefinition.getZ();
		if(index==0){
			rt.startDrawing(x, y, z);
		}else{
			rt.lineTo(x, y, z);
		}
	}
}
// 3.2: switch绘制
for(Map.Entry<String,List<TrackDefinition>> entry : switchCodeToTrackDefinitionsMap.entrySet()){
	List<TrackDefinition> trackDefinitions = entry.getValue();
	
	RailwaySwitch rs = new RailwaySwitch(this, SHAPE_DRAW_2D3D, true);
	rs.setRadius(scale.pixelsPerUnit(METER)*1);
	
	RailwayTrack[] tracks;
	if(trackDefinitions.size()>1){
		tracks = new RailwayTrack[trackDefinitions.size()];
		for(int index = 0; index<trackDefinitions.size(); index++){
			tracks[index] = trackDefinitionToRailwayTrackMap.get(trackDefinitions.get(index));
		}
	}else{
		rs.setVisible(false);
		tracks = new RailwayTrack[2];
		tracks[0] = trackDefinitionToRailwayTrackMap.get(trackDefinitions.get(0));
		String switchCode = entry.getKey();
		PointDefinition switchPointDefinition = codeToPointDefinitionMap.get(switchCode);
		
        // 额外添加轨道,自动解决后续开发轨道的路由问题
		RailwayTrack rt = new RailwayTrack();
		rt.setWidth(1, METER);
		rn.add(rt);
		
		double x = scale.pixelsPerUnit(METER)*switchPointDefinition.getX();
		double y = scale.pixelsPerUnit(METER)*switchPointDefinition.getY();
		double z = scale.pixelsPerUnit(METER)*switchPointDefinition.getZ();
		rt.startDrawing(x, y, z);
		
		PointDefinition endPointDefinition;
		if(trackDefinitions.get(0).getPointCodes().get(0).equals(switchCode)){
			endPointDefinition = codeToPointDefinitionMap.get(trackDefinitions.get(0).getPointCodes().get(1));
		}else{
			endPointDefinition = codeToPointDefinitionMap.get(trackDefinitions.get(0).getPointCodes().get(trackDefinitions.get(0).getPointCodes().size()-2));
		}
		
		double endX = scale.pixelsPerUnit(METER)*endPointDefinition.getX();
		double endY = scale.pixelsPerUnit(METER)*endPointDefinition.getY();
		double endZ = scale.pixelsPerUnit(METER)*endPointDefinition.getZ();
		rt.lineTo(2*x-endX, 2*y-endY, 2*z-endZ);
		rt.setVisible(false);
		
		tracks[1] = rt;
	}
	
	rs.setTracks(tracks);
	rs.setAllToAllType();
	rn.add(rs);	
}

// 3.3: 添加至演示
Level customLevel = new Level(this, "customLevel", SHAPE_DRAW_2D3D, 0);
customLevel.add(rn);
customLevel.initialize();
presentation.add(customLevel);

// 3.4: 解决图形覆盖问题
for(RailwaySwitch rs : rn.getSwitches()){
	presentation.remove(rs);
	presentation.insert(0,rs);
}
for(RailwayTrack track : rn.getTracks()){
	presentation.remove(track);
	presentation.insert(0,track);
}
相关推荐
xipxiks10 天前
Visual Components 自定义工具创建吸附接口
仿真·工业机器人·vc·pnp·visual components·onetooneinterface
天才小小傲11 天前
【Comsol教程】如何求解指定范围的积分 或 在积分中去除奇异点/异常值
仿真·comsol
电力程序小学童12 天前
IEEE5节点系统潮流仿真模型(simulink+matlab全功能模型)
matlab·毕设·仿真·simulink·5节点系统·ieee 5·三相仿真模型
瓢儿菜201816 天前
Proteus8.17-LCD12864液晶屏幕仿真模型
单片机·proteus·环境配置·仿真
康谋自动驾驶23 天前
康谋方案 | 高精LiDAR+神经渲染3DGS的完美融合实践
数据采集·测试·雷达·仿真·建模
六六王1 个月前
仿真每日一练 | Workbench手机后盖壳体类静力学分析
仿真·ansys·workbench·结构振动·有限元仿真
BBTSOH159015160441 个月前
数控技术应用理实一体化平台VR实训系统
vr·虚拟现实·仿真·教学·课程·机床·课件
Altair澳汰尔1 个月前
成功案例丨从草图到鞍座:用先进的发泡成型仿真技术变革鞍座制造
仿真·制造业·cae·inspire·工业仿真·发泡成型
买了一束花2 个月前
MATLAB实现二氧化硅和硅光纤的单模光波特性与仿真
matlab·仿真·光纤·光纤模式
幻想御手2 个月前
关于μkeil v5.40(keil5) 如何使用STM32(ARM)虚拟下载器进行Proteus联调
proteus·仿真·keil5·联调