【仿真建模-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);
}
相关推荐
吃好睡好便好7 天前
MATLAB仿真框图4
开发语言·matlab·仿真·分段函数
吃好睡好便好10 天前
MATLAB仿真框图3
开发语言·matlab·仿真·simulink
CAE二次开发工程师10 天前
【流体力学考研精讲】基础篇
考研·二次开发·仿真·cae·流体力学·结构仿真·#ansa
Dr.kangder10 天前
嵌入式处理器虚拟化仿真技术(九)——SimpleScalar原理与应用
嵌入式硬件·架构·嵌入式·虚拟化·仿真
吃好睡好便好11 天前
MATLAB仿真框图2
开发语言·matlab·仿真·simulink
zxsz_com_cn11 天前
数字孪生+预测性维护:1+1>2的组合拳
数字孪生·工业4.0·仿真·预测性维护·虚拟调试
吃好睡好便好12 天前
MATLAB仿真框图
开发语言·matlab·仿真·simulink
刘步权25 天前
KY-RTI分布仿真技术:第十三章 基于Unity的多语言三维态势仿真——以 Island Assault(夺岛突击)想定为例
unity·游戏引擎·仿真·态势·ky-rti·hla·rti
zh路西法1 个月前
【10天速通ROS2-PX4无人机】(一) 从零搭建仿真环境,妈妈再也不用担心我炸机了!
无人机·仿真·px4·ros2·gazebo
云上码厂1 个月前
热转导仿真与分析
仿真