电梯模拟程序

2023-05-16

Qt5编写的电梯控制模拟程序 附源码

    • 源代码链接地址:
    • 系统架构
    • 逻辑实现
    • elevator.h
    • elevaotr.cpp
    • 未完待续、、、

用c++和qt5编写的单电梯模拟程序
简介:这是一个在Qt5中构建的小型电梯模拟程序。包括门控和电梯升降控制。因为我在其中使用win32 api, MSVC应该是构建的选择。目前,它仍然存在一个小bug,它总是由最近的呼叫面板信号引起的。还有一件事,当系统准备好启动时,必须首先单击启动按钮,否则将发生意外的错误。

开机图:
你好! 这是你第一次使用 **Markdown编辑器** 所展示的欢迎页。如果你想学习如何使用Markdown编辑器, 可以仔细阅读这篇文章,了解一下Markdown的基本语法知识。
启动图:

在这里插入图片描述

源代码链接地址:

GitHub源代码链接:Elevator-Simulation

Elevator-Simulation
This is an small elevator-simulation program builded in Qt5. Contains door control and elevator up-down control. Since I’m using win32 api in it, the MSVC should be choice for build. For now, a small bug is still exists in it which is always caused by nearest out-call panel signal. One more thing, you must click the Starting up button at first when system is ready for starting, otherwise a unexpected error will be happen.
构建说明
第一步:新建你的Qt项目
第二步:删除项目所有.cpp和.h和.ui文件
第三步:将.h添加进你项目中的Headers(注:头文件),将.cpp添加进你的Sources(源文件),将.ui文件添加进你的Forms(界面)中。
第四步:构建你的项目并运行
第五步:点击开机按钮,开始体验模拟电梯吧

系统架构

采用前后分离

电梯的状态机和控制系统分离
qt界面和电梯逻辑分离

逻辑实现

编写步骤:
第一步,在vs上编写纯逻辑实现核心代码:elevaotr.cpp和elevator.h
第二部,编写Qt5适配器,做可视化和接受控制信号:QtAdapter.h
状态机组成:
状态机由门和电梯两部分组成,实时扫描外界面板控制信号和内派信号。

具体画的状态机转换图纸在家放着,有时间补上

核心代码1:

elevator.h

#ifndef ELEVATOR_H
#define ELEVATOR_H

#include <QMainWindow>
#include<QObject>

/*
系统				电梯控制系统V2.1
编写时间          2021/1/29
编译环境          VS2017 X86 Debug模式  SDK:10.0.17763.0
作者			李照月
说明:			对比1.0系统,加入了门
收获:			按阶段编程,省时省力,一步到位
*/

#include<Windows.h>
#include<stdio.h>
#include<string.h>
#define LEVEL 6//楼层
//门的状态
enum eDoorState
{
    OPEN=1,	//已打开
    CLOSE,		//门关闭
    LOCK,		//门上锁
    OPENING,	//开门中
    CLOSING,	//关门中
};

//电梯的状态
enum eElevatorState
{
    STOP=1,
    UP,
    DOWN
};

//门控状态
enum eDoorButton
{
    NONE=0,
    OPENDOOR,
    CLOSEDOOR
};

enum eElevatorDirection
{
    LIFT=1,
    DROP,
    SUSPEND
};

//电梯高度
struct ElevatorHight
{
    ElevatorHight():nowHight(0), levelHigh(1000)	,fullLevel(LEVEL)	, moveSpeed(5){}
    int nowHight;	//当前高度
    const int levelHigh;	//每层楼高度
    const int fullLevel;		//总楼层
    const int moveSpeed;
};

//电梯宽度
struct DoorWidth
{
    DoorWidth() :nowWidth(0), fullWidth(1000),openSpeed(5),waitTime(100){}
    int nowWidth;
    const int fullWidth ;
    const int openSpeed ;
    const int waitTime;
};

//电梯类编写
class Elevator : public QObject
{
public: //属性
    char floorDownList[LEVEL];		//楼层下行按钮
    char floorUpList[LEVEL];			//楼层上行按钮
    char panelButtonList[LEVEL];	//电梯内面板楼层按钮

    enum eDoorState doorState;	//门的状态
    enum eElevatorState elevatorState;		//电梯状态
    enum eDoorButton doorButton;			//门控按钮
    enum eElevatorDirection liftDirection;	//电梯的运行方向


    struct ElevatorHight elevatorHight;	//电梯高度
    struct DoorWidth  doorWidth;			//门的宽度

    Elevator();
private://行为
    void doorClose();	//门关闭
    void doorLock();		//门上锁
    void doorOpening();	//门开机
    void doorClosing();		//门关闭
    void doorOpen();		//门打开

    void liftStop();
    void liftUp();
    void liftDown();

private: //线程
    static DWORD WINAPI doorThread(void* p);				//门线程
    static DWORD WINAPI elevatorThread(void* p);		//电梯线程

};

#endif // ELEVATOR_H

附核心代码2:

elevaotr.cpp

/*
 *文件                    电梯状态机
 * 版本:                  v2.2
 *最后修改日期:            2021/2/4
 *
*/

#include "elevator.h"
#include<QDebug>

#define HZ 10			//10HZ刷新速度

Elevator::Elevator()
{
    doorButton = NONE;
    doorState = CLOSE;
    elevatorState = STOP;
    liftDirection = SUSPEND;

    doorWidth.nowWidth = 0;
    elevatorHight.nowHight = 0;

    memset(floorDownList, 0, sizeof(floorDownList));
    memset(floorUpList, 0, sizeof(floorUpList));
    memset(panelButtonList, 0, sizeof(panelButtonList));

    CreateThread(NULL, 0, doorThread, this, 0, NULL);
    CreateThread(NULL, 0, elevatorThread, this, 0, NULL);
}

//门关闭态函数
void Elevator::doorClose()
{
    while (doorState == CLOSE)
    {
        if (doorButton == OPENDOOR)
        {
            doorState = OPENING;
            return;
        }

        if ((elevatorState == UP) || (elevatorState == DOWN))
        {
            doorState = LOCK;
            return;
        }

        if (doorButton == CLOSEDOOR)
        {
            doorButton = NONE;
        }

        Sleep(HZ);
    }
}

//门上锁
void Elevator::doorLock()
{
    while (true)
    {
        if (elevatorState == STOP)
        {
            doorState = OPENING;
            return;
        }
        Sleep(HZ);
    }
}

void Elevator::doorOpening()	//门开了
{
    while (true)
    {
        if (doorWidth.nowWidth < doorWidth.fullWidth)
        {
            doorWidth.nowWidth += doorWidth.openSpeed;
        }
        if (doorWidth.nowWidth == doorWidth.fullWidth)
        {
            if (doorButton == OPENDOOR)
                doorButton = NONE;
            doorState = OPEN;
            return;
        }

        if (doorButton == CLOSEDOOR)
        {
            doorState = CLOSING;
            return;
        }

        Sleep(HZ);
    }
}

void Elevator::doorClosing()		//门关闭
{
    while (true)
    {
        if (doorState == CLOSING)
        {
            doorWidth.nowWidth -= doorWidth.openSpeed;
        }

        if (doorWidth.nowWidth == 0)
        {
            doorState = CLOSE;
            return;
        }

        if (doorButton == OPENDOOR)
        {
            doorState = OPENING;
            return;
        }

        Sleep(HZ);
    }
}

void Elevator::doorOpen()		//门打开
{
    int	 delay = doorWidth.waitTime;
    while (delay > 0)
    {
        if (doorButton == CLOSEDOOR)
        {
            doorState = CLOSING;
            return;
        }
        if (doorButton == OPENDOOR)
        {
            delay = doorWidth.waitTime;
            continue;
        }
        delay--;
        Sleep(HZ);
    }
    doorState = CLOSING;
    if (doorButton == OPENDOOR)
    {
        doorButton = NONE;
    }
}

//门控线程
DWORD WINAPI Elevator::doorThread(void* p)
{
    Elevator *elevator = (Elevator*)p;

    while (true)
    {
        switch (elevator->doorState)
        {
        case CLOSE:
            elevator->doorClose();
            break;
        case LOCK:
            elevator->doorLock();
            break;
        case OPENING:
            elevator->doorOpening();
            break;
        case CLOSING:
            elevator->doorClosing();
            break;
        case OPEN:
            elevator->doorOpen();
            break;
        }
        Sleep(1);
    }

    return 0;
}

void Elevator::liftDown()
{
    int level;
    do {
        elevatorHight.nowHight -= elevatorHight.moveSpeed;
        level = elevatorHight.nowHight / elevatorHight.levelHigh;

        int i;
        for (i = level; i >0; i--)			//检测目的楼层
        {
            if ((floorDownList[level] == 1) || (panelButtonList[level] == 1))
            {
                break;
            }
        }

        if (elevatorHight.nowHight % elevatorHight.levelHigh == 0)		//有信号,则停止
        {
            if ((floorDownList[level] == 1) || (panelButtonList[level] == 1))
            {
                floorDownList[level] = 0;
                panelButtonList[level] = 0;

                elevatorState = STOP;
                return;
            }
            if (i == elevatorHight.fullLevel)		//是否是最远端有目的楼层
            {
                if (floorUpList[level] == 1)
                {
                    floorUpList[level] = 0;

                    elevatorState = STOP;
                    return;
                }
            }
        }

        Sleep(HZ);
    } while (true);
}

void Elevator::liftUp()
{
    int level;
    do {
        elevatorHight.nowHight += elevatorHight.moveSpeed;
        level = elevatorHight.nowHight / elevatorHight.levelHigh;

        int i;
        for ( i = level + 1; i < elevatorHight.fullLevel; i++)			//检测目的楼层
        {
            if ((floorUpList[i] == 1) || (panelButtonList[i] == 1))
            {
                break;
            }
        }

        if (elevatorHight.nowHight % elevatorHight.levelHigh == 0)		//有信号,则停止
        {
            if ((floorUpList[level] == 1) || (panelButtonList[level] == 1))
            {
                floorUpList[level] = 0;
                panelButtonList[level] = 0;

                elevatorState = STOP;
                return;
            }
            if (i == elevatorHight.fullLevel)		//是否是最远端有目的楼层
            {
                if (floorDownList[level] == 1)
                {
                    floorDownList[level] = 0;

                    elevatorState = STOP;
                    return;
                }
            }
        }

        Sleep(HZ);
    } while (true);
}

void Elevator::liftStop()
{
    while (true)
    {
        int level = elevatorHight.nowHight / elevatorHight.levelHigh;
        //当电梯门未关闭
        if (doorState != CLOSE)
        {
            Sleep(HZ*10);
            continue;
        }
        //当电梯门关闭时
        if (liftDirection == LIFT)
        {
            //确认上行信号,无信号则改为SUSPEND

            for (int i = level + 1; i < elevatorHight.fullLevel; i++)
            {
                if (floorUpList[i] || panelButtonList[i])
                {
                    liftDirection = LIFT;
                    elevatorState = UP;
                    return;
                }
            }
            for (int i = elevatorHight.fullLevel; i > level ; i--)	//最远端还有未完成的下行请求
            {
                if (floorDownList[i])
                {
                    liftDirection = LIFT;
                    elevatorState = UP;
                    return;
                }
            }
            floorDownList[level] = 0;
            liftDirection = SUSPEND;
        }
        else if (liftDirection == DROP)
        {
            //确认下行信号,无信号则改为SUSPEND
            for (int i = 0; i < level; i++)
            {
                if (floorDownList[i] || panelButtonList[i])
                {
                    liftDirection = DROP;
                    elevatorState = DOWN;
                    return;
                }
            }
            for (int i = 0; i < level; i++)	//最远端还有未完成的上行请求
            {
                if (floorUpList[i])
                {
                    liftDirection = DROP;
                    elevatorState = DOWN;
                    return;
                }
            }
            liftDirection = SUSPEND;
        }
        else
        {//当电梯悬停时
            //检测悬停楼层信号
            if (floorDownList[level] || floorUpList[level] || panelButtonList[level])
            {
                doorState = OPENING;
                floorDownList[level] = 0;
                floorUpList[level] = 0;
                panelButtonList[level] = 0;
                continue;
            }
            //检测悬停位置楼层上部分信号
            for (int i = level + 1; i < elevatorHight.fullLevel; i++)
            {
                if (floorDownList[i] || floorUpList[i] || panelButtonList[i])
                {
                    liftDirection = LIFT;
                }
            }
            //检测悬停楼层下部分信号
            for (int i = level - 1; i >= 0; i--)
            {
                if (floorDownList[i] || floorUpList[i] || panelButtonList[i])
                {
                    liftDirection = DROP;
                }
            }
        }
        Sleep(1);
    }
}

//电梯线程
DWORD WINAPI Elevator::elevatorThread(void* p)
{
    Elevator *elevator = (Elevator*)p;

    while (true)
    {
        switch (elevator->elevatorState)
        {
        case UP:
            elevator->liftUp();
            break;
        case DOWN:
            elevator->liftDown();
            break;
        case STOP:
            elevator->liftStop();
            break;
        }
        Sleep(1);
    }

    return 0;
}

未完待续、、、

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

电梯模拟程序 的相关文章

随机推荐

  • ubuntu18.04 安装librealsense并验证

    安装环境 OS Ubuntu 18 04 bionic Kernel x86 64 Linux 4 15 0 20 generic 安装Realsense SDK 参考https github com IntelRealSense libr
  • YOLOV3只显示一类检测结果,并输出位置信息

    YOLOV3批量检测图片 xff0c 只显示一类检测结果 xff0c 并输出位置信息保存到txt 第一步 xff1a 首先修改YOLOV3中src imge c中的void draw detections函数 这里的修改实现了保存检测类别的
  • 搭建PX4开发环境

    搭建PX4开发环境 官方网站PX4 IO xff0c 我使用的是ubuntu20 04 一 官方环境搭建 1 下载PX4固件 span class token function git span clone https github com
  • PX4二次开发——程序运行过程

    PX4二次开发 程序运行过程 一 写在前面 px4固件程序与最开始我们所学习的对单片机外设开发不同 xff0c 是因为飞行器控制系统是一个复杂的系统 xff0c 要求实时性好 xff0c 完成复杂的控制任务 xff0c 简简单单的按照之前所
  • PX4二次开发——编译与启动脚本的修改

    PX4二次开发 编译和启动脚本的修改 一 在修改之前我们先了解一下目录结构 1 1 总目录结构 上图 xff0c 是源码目录 Src xff1a 目录是源码目录存放所有的源码 xff0c 源码的查看都应该在这里 Mavlink xff1a
  • PX4二次开发——uorb订阅

    PX4二次开发 uorb订阅 一 写在前面 我们写了一个一个功能的模块 xff0c 这些模块并不是独立的 模块之间是有数据传递的 xff0c 这样才能组合到一起实现飞行控制的目的 那么解决模块之间的数据传递的方式就是通过uorb订阅的方式
  • PX4二次开发——PX4程序架构

    PX4程序架构 一 从RCS启动脚本可以看出哪些东西 启动脚本是一个神奇的东西 xff0c 它能够识别出你对应的飞机类型 xff0c 加载对应的混控器 xff0c 选择对应的姿态 位置估计程序以及控制程序 xff0c 初始化你需要的驱动程序
  • ROS

    ROS 1 ROS测试 启动ros master 打开一个终端roscore 启动小海龟仿真器 新打开一个终端rosrun turtlesim turtlesim node 启动海龟控制节点 新打开一个终端rosrun turtlesim
  • c++之vector 及 二维容器vector<vector<int>>初始化方法 及 三维数组初始化

    C 43 43 二维容器vector lt vector gt 初始化方法解析 遇到的问题 xff1a 在解决 求最大字串 问题时想到了用二位数组vector lt vector lt int gt gt table xff0c 但是不知道
  • react 中 setState( ) 的两种写法

    react 想要更新视图只能用 setState 方法 关于 setState 这里有三件事情需要知道 1 不要直接更新状态 xff0c 而是使用 setState 2 状态更新可能是异步的 React 可以将多个setState 调用合并
  • 在32位机器上实现64位数的除法

    概述 在32位机器上不能直接进行64位数据的除法 xff0c 比如a或b是64位的数据的时候 xff0c 要计算a b xff0c 不能直接data 61 a b 这样的计算 xff0c 编译器会报错 xff0c 缺少相关的指令 这就需要我
  • 基于Linux微计算机BBB的飞控开发之IMU数据获取与预处理

    基于Linux微计算机BBB的飞控开发之IMU数据获取与预处理 1 介绍2 Linux下调用I2C2 1 Shell下的调用方法2 2 使用C语言访问i2c设备 3 配置IMU4 读取IMU 1 介绍 最近在做Linux平台的飞控开发 xf
  • LINUX锁之读写锁(C++)

    读写信号量 rw semaphore 又叫读写锁 允许多个读者同时持有该信号量 xff1b 当有一个写者持有该信号量时 xff0c 其他读者跟写者不可持有该信号量 xff1b 当写者写完后 xff0c 可以降级为读者 读写信号量使用于读多写
  • px4中的mavlink协议

    原文地址 xff1a http blog csdn net oqqENvY12 article details 61615609 PX4 对Mavlink 协议提供了良好的原生支持 该协议既可以用于地面站 Ground ControlSta
  • px4姿态控制

    一 开篇 姿态控制篇终于来了 来了 来了 心情爽不爽 xff1f 愉悦不愉悦 xff1f 开心不开心 xff1f 喜欢的话就请我吃顿饭吧 xff0c 哈哈 其实这篇blog一周前就应该写的 xff0c 可惜被上一篇blog霸占了 但是也不算
  • APM飞行模式内部结构——以loiter为例

    飞行模式的架构我已经在上一篇博文中提到了 xff0c 本文将lotiter模式为例 xff0c 详细讲解一下lotier模式的内部控制链 lotier模式即为悬停模式 xff0c 也是GPS定点模式 在起飞前确保GPS是打开的 飞手控制的是
  • js中冒泡排序函数

    冒泡排序函数 function sort arr var len 61 arr length for var i 61 0 i lt len i 43 43 for var j 61 0 j lt len 1 i j 43 43 if ar
  • realsense install USB3.0

    sudo apt get update amp amp sudo apt get upgrade amp amp sudo apt get dist upgrade Navigate to librealsense root directo
  • 远程桌面teamViewer 和 远程控制MobaXterm软件

    1 teamViewer 官网下载 xff1a termViewer 注意 xff1a 安装teamViewer要选择个人非商业用途 xff0c 要不然安装不了 teamViewer有windows版本和linux版本 2 向日葵 Sunl
  • 电梯模拟程序

    Qt5编写的电梯控制模拟程序 附源码 图源代码链接地址 xff1a 系统架构逻辑实现elevator helevaotr cpp未完待续 用c 43 43 和qt5编写的单电梯模拟程序 简介 xff1a 这是一个在Qt5中构建的小型电梯模拟