如何自己编写一个交通仿真软件(二)原野。

本文介绍了如何构建交通仿真软件,包括静态交通模型的车道、道路和交叉口模型的详细设计。车道模型通过堵塞元胞模拟进口道展宽,道路模型是一组车道的容器,交叉口模型则采用矩形网格空间,用博弈论或随机方法处理车辆冲突。此外,文章还讨论了路网模型的表示,用无向图或有向图的邻接矩阵和邻接表来描述。
摘要由CSDN通过智能技术生成

该文章也同时在开源中国(www.oschina.net 发布:非广告)作者为:sapperjiang。版权:sapperjiang所有。   http://my.oschina.net/u/214547/admin/edit-blog?blog=358845


3      葵花宝典

首先,抛开理论。我将灌输一段心法(鄙视?心法也是理论)如下(感谢自己的硕士论文,我打字打够了,女票的小手在哪里?)

下面我们将就交通里面的几个基本要求进行建模:

静态交通模型:车道(RoadLane,在计算机这货看来是个队列,用于容纳元胞空间)、道路(试车道的集合,有方向的队列容器,内部有一系列车道)、交叉口(棋盘类似,用来容纳元胞空间或者说,车辆或者行人空间,计算机看来是个矩阵)、路网(NetWork,计算机看来是个图,为了表示交通中的单行道贺双行道的区别,注意,这个应该是有向图);

动态交通模型:车辆CAR 和行人(行人模型在本系统中为抽象的car没有体现,元胞自动机的粒度要小于车辆);

交通控制模型:信号灯、交通灯(信号控制,包含一组信号灯);

交通规则模型:速度限制(交通规则模型),可变信息板(vms)。

首先来看静态交通模型的表示:

1)车道和道路模型

这里面涉及到三个实体、车道、道路(有方向)

实际道路网络中的路段形式往往不是一直不变的,路段是由多条不同类型的车道组成的,如左转车道,右转车道,直行车道等等,而且,路段中进口道的宽度和出口道的宽度时不相等的,进口道往往进行了拓宽以增加交叉口的通行能力。在进行利用元胞自动机进行仿真系统建模的过程中,需要对这进口道展宽这一几何特征在元胞空间中进行描述。

在基于元胞自动机的交通仿真系统中,交通中的动态元素如车辆的移动是用不同位置处的元胞不断变化的状态来进行模拟的。为了模拟道路进口道展宽这一现象,需要引入特殊的元胞,这些元胞在仿真的任何时刻元胞状态都是被占用的状态(本文中称为堵塞元胞)。利用堵塞元胞(图中黑色格子),可以利用图4.1所示的方法来模拟进口道展宽。在进口道中,增加一条车道,该车道的一部分在起始状态全部由堵塞元胞占据,车道的剩余部分则是正常元胞空间网格,在正常元胞空间网格中如果元胞的状态为占用状态,则表示某一时刻该位置处被车辆占据,其他车辆不能进入。在被堵塞的元胞空间网格中(图中黑色部分),任何时刻都是被占用状态,这样就不能代表有表示车辆的状态变化,在宏观上表现为车俩不能进入这些空间。图4.1和图4.2 都是利用该方法建立的展宽渐变段元胞空间模型。

4.1 进口道左转展宽示意图

4.2 进口道右转展宽示意图

车道模型的代码:

namespace SubSys_SimDriving.TrafficModel
{
    /// <summary>
    /// ½»Í¨ÊµÌåÀïÃæµÄ³µµÀ
    /// </summary>
    public class RoadLane : RoadEntity, IComparable<RoadLane>, IComparer<RoadLane>
    {
        private static int iRoadLaneCount=0;
        / <summary>
        / Ã¿´Î¸üÐÂCurrTimeStepµÄʱºò¾Í×Ô¶¯´¦ÀíµÈ´ýÁбí
        / </summary>
        public override int iLength
        {
            get
            {
                return this.Container.iLength;
            }
        }
        public override int iWidth
        {
            get
            {
                return SimSettings.iCarWidth;
            }
        }

        public override EntityShape EntityShape
        {
            get
            {
                EntityShape eShape = base.EntityShape;

                if (eShape.Count == 0)//shape Ã»Óгõʼ»¯
                {
                    CreateShape(eShape);

                    //EntityShape es = this.Container.EntityShape;

                    //MyPoint pUnitNormVect = VectorTools.GetNormalVector(this.Container.ToVector());
                    //MyPoint mpOffset = new MyPoint(pUnitNormVect._X * (this.Rank - 1), pUnitNormVect._Y * (this.Rank - 1));
                    Æ½ÒÆ×ø±ê
                    //MyPoint pFirst = Coordinates.Offset(es[0], mpOffset);
                    ¼ÆËãÖÕµã
                    //MyPoint pFEnd = Coordinates.Offset( es[es.Count-1], mpOffset);

                    Ìí¼Óµ½shape
                    //eShape.Add(pFirst);
                    //eShape.Add(pFEnd);

                }
                return eShape;
            }
        }

        private  void CreateShape(EntityShape eShape)
        {

            EntityShape es = this.Container.EntityShape;

            MyPoint pNorm = VectorTools.GetNormalVector(this.Container.ToVector());
            MyPoint mpOffset = new MyPoint(pNorm._X*(this.Rank - 0.5f),pNorm._Y * (this.Rank - 0.5f));
            //ƽÒÆ×ø±ê
            MyPoint pFirst = Coordinates.Offset(es[0], mpOffset);
            //¼ÆËãÖÕµã
            MyPoint pFEnd = Coordinates.Offset(es[es.Count - 1], mpOffset);

         
            MyPoint mp = new MyPoint(pFEnd._X-pFirst._X,pFEnd._Y-pFirst._Y);
            int iLoopCount = this.iLength;//Ôª°û³¤¶È£¬³õʼ»¯²Î¼ûregisterservice

            float xSplit = mp._X / iLoopCount;//×ÔÉíÓÐÕý¸ººÅ
            float ySplit = mp._Y / iLoopCount;//×ÔÉíÓÐÕý¸ººÅ

            //MyPoint tep=new MyPoint(pFirst._X + iLoopCount * xSplit, pFirst._Y + iLoopCount * ySplit);
            //System.Diagnostics.Debug.Assert(pFEnd==tep);
           
            eShape.Add(pFirst);
            for (int i = 1; i < iLoopCount; i++)//xÐÐ
            {   //Öеã
                eShape.Add(new MyPoint(pFirst._X + (i-0.5f) * xSplit, pFirst._Y + (i-0.5f) * ySplit));   
            }
            eShape.Add(pFEnd);
        }
     
        internal bool IsLaneBlocked(int iAheadSpace)
        {
            return this.iLastPos-1 <= iAheadSpace ;
        }
        /// <summary>
        /// ¹Û²ìÕßģʽÖиºÔð֪ͨÄÚ²¿Ôª°ûÐÞ¸Ä/±£´æ״̬µÄ´úÂë
        /// </summary>
     
   
        /// <summary>
        /// ³µµÀµÄ×îºóÒ»¸öÔª°ûµÄλÖã¬Ó¦µ±ÊÇY×ø±ê
        /// </summary>
        private int _ilastPos;

        /// <summary>
        /// »ñÈ¡³µµÀµÄ×îºóÒ»¸öÔª±¦µÄλÖã¬Èç¹ûûÓÐÔª°ûÔò·µ»Ø³µµÀ³¤¶È
        /// </summary>
        internal int iLastPos
        {
            get
            {
                Cell ce = this.cells.PeekLast();
                if (ce== null)
                {
                    this._ilastPos = this.iLength;
                }
                else //if (this._ilastPos > ce.RltPos.Y)
                {
                    this._ilastPos = ce.RltPos.Y;
                }
                return _ilastPos;
            
            }
        }

        /// <summary>
        /// ÅжϴӵÀ·Æðµã´¦µ½iAheadSpace´¦ÊÇ·ñÓÐÔª°û
        /// </summary>
        /// <param name="iAheadSpace"></param>
        /// <returns></returns>
        internal bool IsLaneEmpty(int iAheadSpace)
        {
            if (this.cells.PeekLast().RltPos.Y<iAheadSpace)
            {
                return false;//×îºóÒ»¸öÔª°ûµÄλÖÃСÓÚ³µÍ·Ê±¾à¾Í²»Îª¿Õ  
            }
            return true;
        }

        /// <summary>
        ///³µµÀµÄÅÅÐò£¬´ÓÄڲ೵µÀ¿ªÊ¼µÄµÚ¼¸¸ö³µµÀ,ÓÃÀ´¶Ô³µµÀ½øÐÐÅÅÐò
        /// </summary>
        public int Rank;

        public int[] PreCarPos;

        /// <summary>
        /// ·Ö³µµÀµÄÐźÅ
        /// </summary>
        internal SignalLight SignalLight;


        private RoadEdge GetContainer()
        {
            return this.Container as RoadEdge;
        }
        internal void PlaySignal(int iCrtTimeStep)
        {
            RoadNode rN = this.GetContainer().To;
            if (SignalLight == null)//ÎÞÐźŽ»²æ¿Ú
            {
                rN.Unbloc
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值