【仿真建模-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);
}
相关推荐
云上码厂16 小时前
ANSYS Electronics 2025 R2(64 位):电磁与多物理场仿真全栈解决方案详解
仿真
Freak嵌入式20 小时前
亲测可用!可本地部署的 MicroPython 开源仿真器
ide·驱动开发·嵌入式·仿真·micropython·upypi
TianFuRuanJian2 天前
天洑智能仿真系列产品完成统信UOS适配,全面兼容国产操作系统
仿真·国产化·统信·结构·流体
湖南精循科技5 天前
Ansys Mechanical & Zemax STAR模块光机热耦合分析
仿真·ansys·光机·有限元分析·cae·工程师
yong99906 天前
双连杆机械臂阻抗控制仿真
算法·仿真
湖南精循科技9 天前
Ansys 案例研究 | 汽车悬架系统的谐波分析
仿真·ansys·机械·cae·工程师
智行众维11 天前
【学习笔记】SOTIF开发中的仿真测试
安全·仿真·安全开发·国标·仿真测试·sotif·gb/t 47025-2026
湖南精循科技13 天前
Ansys | 什么是表面等离子体光子学?
仿真·ansys·光学·光子学
汇智信科16 天前
汇智信科--军事物流仿真评估系统
仿真·汇智信科·dodaf建模
zxy284722530118 天前
使用正运动的仿真软件C#
c#·仿真·运动控制·正运动·无硬件