Pair project II 群控电梯调度
2010-12-12 20:33
260 查看
电梯调度要求/article/4807272.html
Part 1 framework
分析群控电梯调度,需要以下对象:
1. 电梯
职责:记录内面板状态,判断收到命令是否符合物理规律,执行命令
2. 电梯群
职责:记录外面板状态(由于是群控电梯,外面板只有一个,由电梯群对象控制)
管理电梯,对外交互
3. 乘客
职责:维护在各个楼层,各电梯内的乘客信息
当电梯停止时,完成乘客上下电梯的乘客信息改变
给出某段时间内乘客对电梯内外面板的操作信息
4. 时钟
职责:维护一个系统时间
5. 建筑或者说God
职责:控制以上对象,辅助完成各方交互
除了以上基本状态之外,我们需要确定一种程序的时间/逻辑控制方法,两种选择
1. 一个实时调度程序,对时钟每个Tick,完成相应调度
优点:逻辑相对简单
缺点:重复调用调度程序,较为耗时
2. 由建筑操纵时间,因为一般情况下电梯调度是一个只与电梯状态(包括历史状态,即可分析上班、下班等状态)有关的算法,没有随机性,所以电梯调度程序的结果只会在有新的外部请求来和电梯停下、乘客上下时才会发生改变。基于以上论断建筑只需在以上两种情况下调用电梯调度算法,其余没有事件发生的时间段皆可压缩。
优点:节省时间
缺点:对随机调度算法无效
最后需要给调度程序两个接口
1. interface IScheduler
功能:让调度程序决定电梯目的地,及电梯停下时外部指示灯状态
2. interface IElevators
功能:给调度程序电梯的状态
以下我们实现的采用第二种时间控制方法的框架
电梯调度框架
下面是第一种采用时间按控制方法的框架的详细UML类图(by Sen Xiang):
Part 2 Scheduler
I. 首先我们考虑每一部电梯的调度策略
对于向上的电梯,响应请求的优先级如下(从高到低):
1. 电梯所在楼层以上向上的请求
2. 电梯所在楼层以上向下的请求
3. 电梯所在楼层以下向下的请求
4. 电梯所在楼层以下向上的请求
对于向下的电梯,同理对称可得
由以上优先级可以找到一个优先级最高的调度目标,或者将电梯置为禁止
II. 然后我们从全局考虑对所有电梯的调度顺序
目的是如果某个电梯外部请求被响应,要将这个请求派给代价最小的电梯
由于只有外部请求被电梯公用,此部分只需考虑外部请求
1. 找出对所有未被调度电梯来说代价最小的一个未被响应外部请求,及相应电梯
2. 对该电梯调用(I) 中单部电梯调度算法,分配其目标,然后将该电梯置为已调度,如果目标是外部请求,将该请求置为已响应
3. 重复1过程,直至所有电梯调度完毕
III. 最后我们考虑对平时、上班、下班三种情况进行各自优化
这部分可以使用各种学习方法,鉴于时间原因,我们只实现了最简单的
首先我们统计请求的情况,当然没有利用framework的漏洞
具体来说统计是这样的,比如1楼有人要向上,OK,外部1楼向上这个请求加1,之后,重复的请求不计,然后电梯下到一楼接到人,将该1楼外部向上的请求指示灯熄灭,如果之后1楼又有人要向上,这个请求再加1
然后根据由0、1楼向上之类特殊请求与总请求的比例,我们可以估计是三种情况中的那一种,这里对于比例阈值我们采用了较保守的值,因为即使把上班判成平时也没有太大影响,而判成下班影响就会很大
对于上班时,我们修改了响应请求的优先级为:
对于向上的电梯,响应请求的优先级如下(从高到低):
1. 电梯所在楼层以上向上的请求
2. 电梯所在楼层以下向下的请求
3. 电梯所在楼层以下向上的请求
4. 电梯所在楼层以上向下的请求
5. 将电梯目标置为1楼
因为此时底楼来人较多,电梯的首要任务是到底楼接乘客,并把他们送到高层,至于高层向下的乘客会相对较少,方便的时候顺带接下即可
对于向下的电梯,我们没有进行相应优化,因为优化之后也没什么明显的效果
对于下班时,我们仿照上班进行了优化,结果没有上班时明显,应为下班时电梯目标较为分散,使得第5部置目标的效果不好
以上就是我们的具体设计
最后也是最重要的
非常非常感谢xuyong童鞋的耐心和细心,合作愉快
By Shaoqing
Part 1 framework
分析群控电梯调度,需要以下对象:
1. 电梯
职责:记录内面板状态,判断收到命令是否符合物理规律,执行命令
2. 电梯群
职责:记录外面板状态(由于是群控电梯,外面板只有一个,由电梯群对象控制)
管理电梯,对外交互
3. 乘客
职责:维护在各个楼层,各电梯内的乘客信息
当电梯停止时,完成乘客上下电梯的乘客信息改变
给出某段时间内乘客对电梯内外面板的操作信息
4. 时钟
职责:维护一个系统时间
5. 建筑或者说God
职责:控制以上对象,辅助完成各方交互
除了以上基本状态之外,我们需要确定一种程序的时间/逻辑控制方法,两种选择
1. 一个实时调度程序,对时钟每个Tick,完成相应调度
优点:逻辑相对简单
缺点:重复调用调度程序,较为耗时
2. 由建筑操纵时间,因为一般情况下电梯调度是一个只与电梯状态(包括历史状态,即可分析上班、下班等状态)有关的算法,没有随机性,所以电梯调度程序的结果只会在有新的外部请求来和电梯停下、乘客上下时才会发生改变。基于以上论断建筑只需在以上两种情况下调用电梯调度算法,其余没有事件发生的时间段皆可压缩。
优点:节省时间
缺点:对随机调度算法无效
最后需要给调度程序两个接口
1. interface IScheduler
功能:让调度程序决定电梯目的地,及电梯停下时外部指示灯状态
2. interface IElevators
功能:给调度程序电梯的状态
以下我们实现的采用第二种时间控制方法的框架
电梯调度框架
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Elevator_Scheduler_Design { public enum ELEVATOR_REAL_STATE { STOP, RUNNING }; public enum ELEVATOR_SHOW_STATE { UP, DOWN }; // show elevator will go up or down on the outerpanel public interface IScheduler { void GoToWhichFloor(out uint elevator, out uint destination, bool lastdecision_right); ELEVATOR_SHOW_STATE UpOrDownOnthePanel(uint elevator); // decide up or down to show on the outer panel } // if show up, passengers who want to go down will not get in public interface IElevators { // functions uint GetCurrentWeight(uint elevator); uint GetMaxWeight(uint elevator); float GetCurrentFloor(uint elevator); void GetOuterPanelState(out bool[] uppanelstate, out bool[] downpanelstate); void GetInnerPanelState(uint elevator, out bool[] panelstate); uint GetDestination(uint elevator); ELEVATOR_REAL_STATE GetElevatorState(uint elevator); // running or stop } public class cElevators : IElevators { cElevators() { for (int i = 0; i < E_NUMBER_OF_ELEVATORS; i++) { m_cElevators[i] = new cElevator(); //need passenger_Limit, weight_Limit, number_of_Floor } } public uint GetCurrentWeight(uint elevator) { return m_cElevators[elevator].GetCurrentWeight(); } public uint GetMaxWeight(uint elevator) { return m_cElevators[elevator].GetMaxWeight(); } public float GetCurrentFloor(uint elevator) { return m_cElevators[elevator].GetCurrentFloor(); } public ELEVATOR_REAL_STATE GetElevatorState(uint elevator) { return m_cElevators[elevator].GetElevatorState(); } public void GetOuterPanelState(out bool[] uppanelstate, out bool[] downpanelstate) { } public void GetInnerPanelState(uint elevator, out bool[] panelstate) { } public uint GetDestination(uint elevator) { return m_cElevators[elevator].GetDestination(); } private bool CanGotoOrNot(uint elevator, uint floor) { return false; //temp } public bool GoTo(uint elevator, uint floor) { if (CanGotoOrNot(elevator, floor) == false) return false; m_cElevators[elevator].SetElevatorState(ELEVATOR_REAL_STATE.RUNNING); m_cElevators[elevator].SetDestination(floor); return true; } public void Arrive_At(uint elevator, uint floor) //tell the scheduler elevator has arrived at which floor { m_cElevators[elevator].SetElevatorState(ELEVATOR_REAL_STATE.STOP); m_cElevators[elevator].SetCurrentFloor((float)floor); } public void UpdateOutPanelState(bool[] uppanels, bool[] downpanels) { } public void UpdateInnerPanelState(uint elevator, bool[] innerpanels) { } public void SetCurrentWeight(uint elevator, uint weight) { m_cElevators[elevator].SetCurrentWeight(weight); } public void SetCurrentFloor(uint elevator, float floor) { m_cElevators[elevator].SetCurrentFloor(floor); } private const int E_NUMBER_OF_ELEVATORS = 4; private const int E_NUMBER_OF_FLOORS = 21; private cElevator[] m_cElevators; //flags of panels on each floor private bool[] m_fGoUp = new bool[E_NUMBER_OF_FLOORS]; //flags for up_panel on each floor, true as pressed private bool[] m_fGoDown = new bool[E_NUMBER_OF_FLOORS]; //flags for down_panel on each floor, true as pressed } public struct Passenger_Information { public uint uFloorFrom; public uint uFloorTo; public double dWeight; public TimeSpan tpArriveTime; // Passenger arrive time }; public class cPassengers { cPassengers() { for (int i = 0; i < 4; i++) { m_liInnerPassengers[i] = new List<Passenger_Information>(); // list of passengers in the elevator } m_liOuterPassengers = new List<Passenger_Information>(); // list of passengers out of the elevators } public uint CurrentPassengersCount() // passenger count include in elevator and out { return 0; //temp } public void NewPassenger(Passenger_Information newone) // add new passenger { m_liOuterPassengers.Add(newone); } public void GetPassengersWaitingState(out bool[] goup, out bool[] godown) { } //get the outer panel state public void GetPassengersTravelingState(uint elevator, out bool[] innerpanel) { } //get the inner panel state public void PassengersExchange(uint elevator, uint floor, uint remainweight, ELEVATOR_SHOW_STATE showstate, out uint remainweightafter){} private List<Passenger_Information>[] m_liInnerPassengers; // list of passengers in the elevator private List<Passenger_Information> m_liOuterPassengers; // list of passengers out of the elevators } public class cElevator { public cElevator(uint passenger_Limit, uint weight_Limit, uint number_of_Floor) { m_uPassenger_Limit = passenger_Limit; m_uWeight_Limit = weight_Limit; m_fInnerPanel = new bool[number_of_Floor]; m_state = ELEVATOR_REAL_STATE.STOP; } public uint GetCurrentWeight() { return m_uCurrentWeight; } public uint GetMaxWeight() { return m_uWeight_Limit; } public float GetCurrentFloor() { return m_uCurrentFloor; } public uint GetDestination() { return m_uDestination; } public ELEVATOR_REAL_STATE GetElevatorState() { return m_state; } public void SetElevatorState(ELEVATOR_REAL_STATE state) { m_state = state; } public void SetDestination(uint destination) { m_uDestination = destination; } public void SetCurrentWeight(uint weight) { m_uCurrentWeight = weight; } public void SetCurrentFloor(float floor) { m_uCurrentFloor = floor; } private uint m_uPassenger_Limit; private uint m_uWeight_Limit; private bool[] m_fService_Floor; private bool[] m_fInnerPanel; //flags for panels in each elevator, true as pressed private float m_uCurrentFloor; //floor the elevator on private uint m_uCurrentWeight; private ELEVATOR_REAL_STATE m_state; //show the elevator is running or stop private uint m_uDestination; } public class cClock { private TimeSpan m_Time; public void Time_Cost(TimeSpan cost_time) { m_Time += cost_time; } public TimeSpan Get_Current_Time() { return m_Time; } } public class Building { private cClock m_clock; private cPassengers m_passengers; private cElevators m_elevators; private List<Passenger_Information> m_liAllPassengersInformation; private const int E_NUMBER_OF_ELEVATORS = 4; private const float E_MOVE_FLOORS_PER_MINUTE = 5; private void Load_Test(ref List<Passenger_Information> allPassengers) { } private Passenger_Information Earliest_Coming_Passenger() { } // get the passenge who come earliest from the test passengers private void New_Passengers_Coming() // set the earliest passengers to the out of elevator passengers { TimeSpan tpEarliestTime = Earliest_Coming_Passenger().tpArriveTime; while (tpEarliestTime == ((Passenger_Information)Earliest_Coming_Passenger()).tpArriveTime) { m_passengers.NewPassenger(Earliest_Coming_Passenger()); m_liAllPassengersInformation.Remove(Earliest_Coming_Passenger()); } m_clock.Time_Cost(tpEarliestTime - m_clock.Get_Current_Time()); } private TimeSpan Time_Calc() { } //calculate the time elevlater travel private void UpdatePassengerRequest() { bool[] fUpRequest; bool[] fDownRequest; bool[] fInnerRequest; m_passengers.GetPassengersWaitingState(out fUpRequest, out fDownRequest); // update the out panel state m_elevators.UpdateOutPanelState(fUpRequest, fDownRequest); for (uint i = 0; i < E_NUMBER_OF_ELEVATORS; i++) { m_passengers.GetPassengersTravelingState(i, out fInnerRequest); m_elevators.UpdateInnerPanelState(i, fInnerRequest); } } private float CalculateMovedFloors(TimeSpan duringtime) { return 0; //temp } public void main_control() { Load_Test(ref m_liAllPassengersInformation); //load test file, save to m_liAllPassengersInformation IScheduler scheduler = new cScheduler(); uint destination; uint elevator; while (m_liAllPassengersInformation.Count != 0 && m_passengers.CurrentPassengersCount() != 0) { if (m_passengers.CurrentPassengersCount() == 0) // if no passengers waiting elevators { New_Passengers_Coming(); // add earliest passengers and clocked the time to the passenger coming time } UpdatePassengerRequest(); scheduler.GoToWhichFloor(out elevator, out destination, true); // scheduler which floor to go if (m_elevators.GoTo(elevator, destination) == false) // if scheduler is wrong, one time to correct { scheduler.GoToWhichFloor(out elevator, out destination, false); m_elevators.GoTo(elevator, destination); } if (((Passenger_Information)Earliest_Coming_Passenger()).tpArriveTime //if during the elevator travel there is >= m_clock.Get_Current_Time() + Time_Calc()) { m_clock.Time_Cost(Time_Calc()); // elevator travel time uint remainweight = m_elevators.GetMaxWeight(elevator) - m_elevators.GetCurrentWeight(elevator); uint remainweightafter; m_elevators.Arrive_At(elevator, destination); m_passengers.PassengersExchange(elevator, destination, remainweight, scheduler.UpOrDownOnthePanel(elevator), out remainweightafter); m_elevators.SetCurrentWeight(elevator, m_elevators.GetMaxWeight(elevator) - remainweightafter); m_clock.Time_Cost(Time_Calc()); // passengers exchange time } else //else { TimeSpan movestarttime = m_clock.Get_Current_Time(); New_Passengers_Coming(); //add new passengers and go while update state and schedule TimeSpan traveledtime = m_clock.Get_Current_Time() - movestarttime; float currentfloor = m_elevators.GetDestination(elevator) > m_elevators.GetCurrentFloor(elevator)? m_elevators.GetCurrentFloor(elevator) + CalculateMovedFloors(traveledtime): m_elevators.GetCurrentFloor(elevator) - CalculateMovedFloors(traveledtime); m_elevators.SetCurrentFloor(elevator, currentfloor); } } } } }
下面是第一种采用时间按控制方法的框架的详细UML类图(by Sen Xiang):
Part 2 Scheduler
I. 首先我们考虑每一部电梯的调度策略
对于向上的电梯,响应请求的优先级如下(从高到低):
1. 电梯所在楼层以上向上的请求
2. 电梯所在楼层以上向下的请求
3. 电梯所在楼层以下向下的请求
4. 电梯所在楼层以下向上的请求
对于向下的电梯,同理对称可得
由以上优先级可以找到一个优先级最高的调度目标,或者将电梯置为禁止
II. 然后我们从全局考虑对所有电梯的调度顺序
目的是如果某个电梯外部请求被响应,要将这个请求派给代价最小的电梯
由于只有外部请求被电梯公用,此部分只需考虑外部请求
1. 找出对所有未被调度电梯来说代价最小的一个未被响应外部请求,及相应电梯
2. 对该电梯调用(I) 中单部电梯调度算法,分配其目标,然后将该电梯置为已调度,如果目标是外部请求,将该请求置为已响应
3. 重复1过程,直至所有电梯调度完毕
III. 最后我们考虑对平时、上班、下班三种情况进行各自优化
这部分可以使用各种学习方法,鉴于时间原因,我们只实现了最简单的
首先我们统计请求的情况,当然没有利用framework的漏洞
具体来说统计是这样的,比如1楼有人要向上,OK,外部1楼向上这个请求加1,之后,重复的请求不计,然后电梯下到一楼接到人,将该1楼外部向上的请求指示灯熄灭,如果之后1楼又有人要向上,这个请求再加1
然后根据由0、1楼向上之类特殊请求与总请求的比例,我们可以估计是三种情况中的那一种,这里对于比例阈值我们采用了较保守的值,因为即使把上班判成平时也没有太大影响,而判成下班影响就会很大
对于上班时,我们修改了响应请求的优先级为:
对于向上的电梯,响应请求的优先级如下(从高到低):
1. 电梯所在楼层以上向上的请求
2. 电梯所在楼层以下向下的请求
3. 电梯所在楼层以下向上的请求
4. 电梯所在楼层以上向下的请求
5. 将电梯目标置为1楼
因为此时底楼来人较多,电梯的首要任务是到底楼接乘客,并把他们送到高层,至于高层向下的乘客会相对较少,方便的时候顺带接下即可
对于向下的电梯,我们没有进行相应优化,因为优化之后也没什么明显的效果
对于下班时,我们仿照上班进行了优化,结果没有上班时明显,应为下班时电梯目标较为分散,使得第5部置目标的效果不好
以上就是我们的具体设计
最后也是最重要的
非常非常感谢xuyong童鞋的耐心和细心,合作愉快
By Shaoqing
相关文章推荐
- Pair Project II 电梯调度接口的实现
- 怎么开始做Pair Project II?
- Pair Project: 电梯调度问题API设计(by 谢俊源 & 陆元伟)
- Pair Project: API设计 by Xiao Li and Yishi Xing
- Pair Project: Elevator Scheduler Report By Hu Renjun
- Pair Project 2 电梯GUI by 韦昀,隋宇豪
- 关于STM32 uC/OS-II中任务调度和串口丢数据的原因
- PairProject 总结
- μC/OS-II与RT-Thread对比——任务调度
- uC/OS-II的任务调度与时钟
- 现代软件工程 结对编程 (II) 电梯调度 算法和测试框架
- 基于µC/OS-II的时间片调度法设计
- Prework Of Pair Project: Elevator Scheduler
- uCOS-II系统中的任务调度
- ucos-ii学习笔记1 创建任务&&任务调度
- 现代软件工程系列 结对编程 (II) 电梯调度程序
- ucos-ii的任务调度机制
- [Pair Project]拆弹部队(The Hurt Locker)---By 李蔚,刘阳威
- Project-Euler problem 60 Prime pair sets
- Pair project(刘昊岩11061156 黄明源11061186)