要点初见:用Python进行微观交通模型仿真——基于SUMO的伯克利开源项目Flow Project初探与拓展

2023-05-16

       后续拓展:要点初见:安装教程与二度拓展——基于SUMO的Flow Project(附代码链接)

通俗来讲,微观交通模型仿真就是从车辆个体的视角(看动画)进行交通流仿真,对车辆个体随时间、空间的变化进行跟踪描述。常用的微观交通仿真方法包括在Matlab中建立元胞自动机模型、在Vissim中画车道调参数。但前者存在仿真系统太简易粗糙,不足以体现复杂的交通影响因素;后者又存在太依赖GUI界面,COM接口编程只支持高版本正版(这东西贼难搞)、C++编程,只能获得车辆通过设定的检测点的时空坐标而非各个时刻各车辆的坐标,让后续能进行的坐标分析操作变得很局限。

       但就博主在Github上寻找(现成的)微观交通模型元胞自动机代码找到快要绝望的时候,Flow Project冒了出来,这是一个由加州大学伯克利分校的移动传感实验室使用亚马逊AWS机器学习研究基金,基于SUMO开发出的用于交通微观模拟深度强化学习和控制实验的计算框架,不仅开源,开发语言还是当下火热的Python,依赖的操作系统还是Ubuntu。博主仔细研读了一下项目源码、Document,真是相见恨晚,让人忍不住想说:

       Talk is cheap,show me the code. 先放链接:

       Flow Project的Github链接(或在Github中搜“Flow SUMO”)是:https://github.com/flow-project/flow

       Flow Project的官网链接是:https://flow-project.github.io/

       Flow Project的Document链接是:https://flow.readthedocs.io/en/latest/flow_setup.html#installing-flow-and-sumo

       对Flow Project有任何疑惑可以在StackOverflow的专题链接中提问(带上flow-project的标签,回的贼快):https://stackoverflow.com/questions/tagged/flow-project

       本博文主要从对Flow Project的介绍、Flow Project的安装、用Python运行模型输出坐标三个部分进行介绍,附加博主改源码增加改变车身长度功能的方法介绍。

 

1  Flow Project的介绍

       Flow Project是基于开源框架SUMO的二次开发项目(其也可基于收费软件Aimsun、强化学习库RLlib,此文中暂不介绍),SUMO的全称Simulation of Urban Mobility,是一款欧洲开源的微观交通仿真框架,但开源的另一面也意味着放养、不更新……所以单论SUMO相比于Vissim不仅功能少而且还难用。

       SUMO有个知名(难用)的Python接口TraCI(Traffic Control Interface),这个久远的接口博主至今也还没研究懂,但从源码中可以看出Flow Project的开发者们恰恰是利用这个接口,对SUMO进行了二次封装,从而让我们能通过短短几十行可读性强的Python代码创建出功能齐全的微观异质交通流仿真模型。Flow Project的核心在于完美接入强化学习,但Flow Project在仿真有人车辆上也完全绰绰有余,还能加入强化学习的自动驾驶车辆,可拓展性非常强,博主未来也会继续研究该项目。

       在Ubuntu系统中运行Flow Project,仿真界面大概如下:

 

2  Flow Project的安装

       Flow Project的安装方法主要参考官方Document:https://flow.readthedocs.io/en/latest/flow_setup.html#testing-your-installation,简单说就是在Terminal中:

(1)下载Flow Project项目:

git clone https://github.com/flow-project/flow.git

cd flow

(2)安装anaconda2(参考anaconda官网https://www.anaconda.com/),之后在flow目录下创建专属运行环境并安装依赖:

conda env create -f environment.yml

source activate flow

(3)安装Flow Project和SUMO:

pip install -e .

./scripts/setup_sumo_ubuntu1404.sh(对于Ubuntu 14.04)

./scripts/setup_sumo_ubuntu1604.sh(对于Ubuntu 16.04)

./scripts/setup_sumo_ubuntu1804.sh(对于Ubuntu 18.04)

./scripts/setup_sumo_osx.sh(对于Mac)

       检查SUMO是否安装成功:

which sumo

sumo --version

       启动SUMO图形界面:

sumo-gui

       如果系统显示未找到相关命令,则运行source ~/.bashrc或打开一个新的Terminal来更新环境变量。

(4)检查flow是否安装成功:

source activate flow

python examples/sumo/sugiyama.py

       这步大概率是不成功的,或是在重启后再运行不成功,会发生没法激活flow的问题亦或Python版本导致的报错,因为博主系统默认的python版本是/usr/bin下的Python2.7,但Flow Project又是依赖anaconda目录下的python3.5,而随便改系统的环境变量又容易把很多框架的依赖弄崩。博主找到的解决方法是:在每次开机第一次运行Flow Project的脚本前运行如下三句话(第三行的UBUNTU改成你的home目录名):

export PATH=/usr/local/anaconda2/bin:$PATH

source activate flow

export PYTHONPATH="/home/UBUNTU/.conda/envs/flow/lib/python3.5/site-packages:$PYTHONPATH"

       这之后在flow目录下的Terminal中输入python examples/sumo/sugiyama.py或examples/sumo/下的其他脚本即可成功运行仿真,这也意味着你的flow安装好了,欢迎来到用Python进行交通流仿真的时代~

 

3  用Python运行模型、输出坐标

       从官方新手教程中可以看到,仿真的核心在于examples/sumo/目录下的脚本,笔者就以该目录下的单向N车道高速公路仿真创建脚本highway.py的更改、拓展为例,介绍如何用Python运行仿真并输出各时刻各车辆在道路上的坐标。

       Flow Project中的道路形态有限,新道路的创建应该是基于SUMO底层进行定制,还有待未来研究。就在官方给出的几种道路形态中,N车道高速公路是较简单的一个模型,原脚本的运行效果如上文中仿真图像介绍部分。但博主因为论文研究需要,对该脚本进行了爆改:

(1)改源码增加改变车身长度的功能

       Flow Project的Python脚本里不能直接改变每辆输入车辆的车身长度,需要更改源码。参考博主在StackOverflow中提出的相关问题https://stackoverflow.com/questions/56891526/how-to-change-sizes-of-vehicle-in-flow-simulation,需要更改flow/flow/core目录下的params.py中的class VehicleParams中的def add()函数,增加加粗的这几行:

    def add(self,
            veh_id,
            length=5,
            acceleration_controller=(SimCarFollowingController, {}),
            lane_change_controller=(SimLaneChangeController, {}),
            routing_controller=None,
            initial_speed=0,
            num_vehicles=1,
            car_following_params=None,
            lane_change_params=None):
        """Add a sequence of vehicles to the list of vehicles in the network.

        Parameters
        ----------
        veh_id : str
            base vehicle ID for the vehicles (will be appended by a number)
        acceleration_controller : tup, optional
            1st element: flow-specified acceleration controller
            2nd element: controller parameters (may be set to None to maintain
            default parameters)
        lane_change_controller : tup, optional
            1st element: flow-specified lane-changer controller
            2nd element: controller parameters (may be set to None to maintain
            default parameters)
        routing_controller : tup, optional
            1st element: flow-specified routing controller
            2nd element: controller parameters (may be set to None to maintain
            default parameters)
        initial_speed : float, optional
            initial speed of the vehicles being added (in m/s)
        num_vehicles : int, optional
            number of vehicles of this type to be added to the network
        car_following_params : flow.core.params.SumoCarFollowingParams
            Params object specifying attributes for Sumo car following model.
        lane_change_params : flow.core.params.SumoLaneChangeParams
            Params object specifying attributes for Sumo lane changing model.
        """
        if car_following_params is None:
            # FIXME: depends on simulator
            car_following_params = SumoCarFollowingParams()

        if lane_change_params is None:
            # FIXME: depends on simulator
            lane_change_params = SumoLaneChangeParams()

        type_params = {}
        type_params.update(car_following_params.controller_params)
        type_params.update(lane_change_params.controller_params)

        # If a vehicle is not sumo or RL, let the minGap be zero so that it
        # does not tamper with the dynamics of the controller
        if acceleration_controller[0] != SimCarFollowingController \
                and acceleration_controller[0] != RLController:
            type_params["minGap"] = 0.0

        type_params['length'] = length

        # This dict will be used when trying to introduce new vehicles into
        # the network via a Flow. It is passed to the vehicle kernel object
        # during environment instantiation.
        self.type_parameters[veh_id] = \
            {"length": length,
             "acceleration_controller": acceleration_controller,
             "lane_change_controller": lane_change_controller,
             "routing_controller": routing_controller,
             "initial_speed": initial_speed,
             "car_following_params": car_following_params,
             "lane_change_params": lane_change_params}

        # TODO: delete?
        self.initial.append({
            "veh_id":
                veh_id,
            "length":
                length,

            "acceleration_controller":
                acceleration_controller,
            "lane_change_controller":
                lane_change_controller,
            "routing_controller":
                routing_controller,
            "initial_speed":
                initial_speed,
            "num_vehicles":
                num_vehicles,
            "car_following_params":
                car_following_params,
            "lane_change_params":
                lane_change_params
        })

        # This is used to return the actual headways from the vehicles class.
        # It is passed to the vehicle kernel class during environment
        # instantiation.
        self.minGap[veh_id] = type_params["minGap"]

        for i in range(num_vehicles):
            v_id = veh_id + '_%d' % i

            # add the vehicle to the list of vehicle ids
            self.ids.append(v_id)

            self.__vehicles[v_id] = dict()

            # specify the type
            self.__vehicles[v_id]["type"] = veh_id

            # update the number of vehicles
            self.num_vehicles += 1
            if acceleration_controller[0] == RLController:
                self.num_rl_vehicles += 1

        # increase the number of unique types of vehicles in the network, and
        # add the type to the list of types
        self.num_types += 1
        self.types.append({"veh_id": veh_id, "type_params": type_params})

       这样就可以在Python文件中改变输入车辆的长度了。

(2)让我们来更改Python脚本吧:

       先看一下highway.py改后的全貌:

"""Example of an open multi-lane network with human-driven vehicles."""

from flow.controllers import IDMController, SimLaneChangeController, ContinuousRouter, RLController
from flow.core.experiment import Experiment
from flow.core.params import SumoParams, EnvParams, \
    NetParams, InitialConfig, InFlows, SumoLaneChangeParams, SumoCarFollowingParams
from flow.core.params import VehicleParams
from flow.envs.loop.lane_changing import LaneChangeAccelEnv, \
    ADDITIONAL_ENV_PARAMS
from flow.scenarios.highway import HighwayScenario, ADDITIONAL_NET_PARAMS

#from flow.core.params import SimParams


def highway_example(render=None):
    """
    Perform a simulation of vehicles on a highway.

    Parameters
    ----------
    render : bool, optional
        specifies whether to use the gui during execution

    Returns
    -------
    exp: flow.core.experiment.Experiment
        A non-rl experiment demonstrating the performance of human-driven
        vehicles on a figure eight.
    """
    sim_params = SumoParams(restart_instance=True, sim_step=0.1, emission_path="./data/",render=True, sight_radius=30, pxpm=3, show_radius=True)

    if render is not None:
        sim_params.render = render

    vehicles = VehicleParams()
    
    vehicles.add(
        veh_id="rlcar",# Lincoln MKC 4552*1864*1654
        length = 4.552,
        acceleration_controller=(RLController, {}),
        car_following_params=SumoCarFollowingParams(
            speed_mode="obey_safe_speed",
        ),
        initial_speed=0,
        num_vehicles=1)
    
    vehicles.add(
        veh_id="humancar",# Volkswagen LAVIDA 4670*1806*1474 max:120km/h
        length = 4.67,
        #v0 : desirable velocity, in m/s (default: 30) in flow/flow/controllers/car_following_models.py 352
        acceleration_controller=(IDMController,{'v0':32}),# 115km/h
        lane_change_controller=(SimLaneChangeController, {}),
        lane_change_params=SumoLaneChangeParams(
            lane_change_mode="strategic",# Human cars make lane changes in accordance with SUMO to provide speed boosts
        ),
        num_vehicles=1)
    
    vehicles.add(
        veh_id="humanbus_lane2",# YUTONG ZK6826BEV 8245*2500*3240 max:100km/h
        length = 8.245,
        acceleration_controller=(IDMController, {'v0':26.4}),# 95km/h
        #lane_change_controller=(SimLaneChangeController, {}),
        #lane_change_params=SumoLaneChangeParams(
        #    lane_change_mode="strategic",# Human cars make lane changes in accordance with SUMO to provide speed boosts
        #),
        num_vehicles=1)
    vehicles.add(
        veh_id="humanbus_lane1",# YUTONG ZK6826BEV 8245*2500*3240 max:100km/h
        length = 8.245,
        acceleration_controller=(IDMController, {'v0':26.4}),# 95km/h
        num_vehicles=1)
    vehicles.add(
        veh_id="humanbus_lane0",# YUTONG ZK6826BEV 8245*2500*3240 max:100km/h
        length = 8.245,
        acceleration_controller=(IDMController, {'v0':26.4}),# 95km/h
        num_vehicles=1)
        
    vehicles.add(
        veh_id="humantruck_lane2",# FOTON BJ5319XXY-AB 12000*2550*3950 max:100km/h
        length = 12,
        acceleration_controller=(IDMController, {'v0':25}),# 90km/h
        #lane_change_controller=(SimLaneChangeController, {}),
        #lane_change_params=SumoLaneChangeParams(
        #    lane_change_mode="strategic",# Human cars make lane changes in accordance with SUMO to provide speed boosts
        #),
        num_vehicles=1)
    vehicles.add(
        veh_id="humantruck_lane1",# FOTON BJ5319XXY-AB 12000*2550*3950 max:100km/h
        length = 12,
        acceleration_controller=(IDMController, {'v0':25}),# 90km/h
        num_vehicles=1)
    vehicles.add(
        veh_id="humantruck_lane0",# FOTON BJ5319XXY-AB 12000*2550*3950 max:100km/h
        length = 12,
        acceleration_controller=(IDMController, {'v0':25}),# 90km/h
        num_vehicles=1)

    env_params = EnvParams(additional_params=ADDITIONAL_ENV_PARAMS)

    inflow = InFlows()
    
    inflow.add(
        veh_type="rlcar",
        edge="highway_0",
        #probability=0.025,# 0.25 probability for emitting a vehicle each second (not together with vehsPerHour or period)
        vehs_per_hour=250,
        departLane=3,# the index of the lane, starting with rightmost=0
        departSpeed=30)
    
    inflow.add(
        veh_type="humancar",
        edge="highway_0",
        #probability=0.85,# 0.25 probability for emitting a vehicle each second (not together with vehsPerHour or period)
        vehs_per_hour=15000,
        departLane="random",#free random allowed best first
        departSpeed=30)
    
    inflow.add(
        veh_type="humanbus_lane2",
        edge="highway_0",
        #probability=0.1,
        vehs_per_hour=486,
        departLane=2,
        departSpeed=26.4)
    inflow.add(
        veh_type="humanbus_lane1",
        edge="highway_0",
        #probability=0.1,
        vehs_per_hour=486,
        departLane=1,
        departSpeed=26.4)
    inflow.add(
        veh_type="humanbus_lane0",
        edge="highway_0",
        #probability=0.1,
        vehs_per_hour=486,
        departLane=0,
        departSpeed=26.4)
    
    inflow.add(
        veh_type="humantruck_lane2",
        edge="highway_0",
        #probability=0.05,
        vehs_per_hour=486,
        departLane=2,
        departSpeed=25)
    inflow.add(
        veh_type="humantruck_lane1",
        edge="highway_0",
        #probability=0.05,
        vehs_per_hour=486,
        departLane=1,
        departSpeed=25)
    inflow.add(
        veh_type="humantruck_lane0",
        edge="highway_0",
        #probability=0.05,
        vehs_per_hour=486,
        departLane=0,
        departSpeed=25)

    initial_config = InitialConfig(spacing="uniform", shuffle=True)# initial position in road

    scenario = HighwayScenario(#3:110-120 2:90-120 3:90-120 4:60-120 [G1503 2019.5 daily car:180000 bus/truck:70000]
        name="highway",
        vehicles=vehicles,
        net_params=NetParams(
                inflows=inflow,
                additional_params={
                    'length': 6000,
                    'lanes': 4,
                    'speed_limit': 33.3,
                    'num_edges': 1
                }),
        initial_config=initial_config)
    

    env = LaneChangeAccelEnv(env_params, sim_params, scenario)

    return Experiment(env)


if __name__ == "__main__":
    # import the experiment variable
    exp = highway_example()

    # run for a set number of rollouts / time steps
    #exp.run(1, 1000, convert_to_csv = False)
    exp.run(1, 5000, convert_to_csv = True)

       分解到单步,用Flow Project创建微观交通流主要分为设定全局参数、添加既有车辆、添加输入流、设定道路场景、开始仿真5个步骤:

a.设定全局参数

    sim_params = SumoParams(restart_instance=True, sim_step=0.1, emission_path="./data/",render=True, sight_radius=30, pxpm=3, show_radius=True)

    if render is not None:
        sim_params.render = render

       此处restart_instance的作用是避免先前有未关闭的SUMO窗口,设定为True后每次运行脚本时会在点击仿真界面播放键后关闭窗口再重新开一个。

       sim_step是记录坐标的间隔时间,此处为0.1s记录一次所有道路上车辆的当前坐标;

       emission_path决定了坐标文件的保存位置,运行自然结束后(车辆跑完还会有一段较长的记录时间)会在flow/data/目录下找到一个csv和一个xml文件。

       后续的参数是对网络仿真功能生效的参数,会在网络仿真中在每辆车周身显示一圈“探测范围圈”,在此仿真中未涉及,保持上述参数即可。

b.添加既有车辆

    vehicles = VehicleParams()
    
    vehicles.add(
        veh_id="rlcar",# Lincoln MKC 4552*1864*1654
        length = 4.552,
        acceleration_controller=(RLController, {}),
        car_following_params=SumoCarFollowingParams(
            speed_mode="obey_safe_speed",
        ),
        initial_speed=0,
        num_vehicles=1)
    
    vehicles.add(
        veh_id="humancar",# Volkswagen LAVIDA 4670*1806*1474 max:120km/h
        length = 4.67,
        #v0 : desirable velocity, in m/s (default: 30) in flow/flow/controllers/car_following_models.py 352
        acceleration_controller=(IDMController,{'v0':32}),# 115km/h
        lane_change_controller=(SimLaneChangeController, {}),
        lane_change_params=SumoLaneChangeParams(
            lane_change_mode="strategic",# Human cars make lane changes in accordance with SUMO to provide speed boosts
        ),
        num_vehicles=1)

       此段的作用是在刚开始仿真时于既有道路上添加车辆,同时此处设定的该种类车辆的长度也会作用于后续添加的flow中。车辆将会以相同的间隔在道路上均匀分布,避免刚开始仿真时道路上无车的情况(让车流充分混合)。

       vehicles即为创建的对象,add里的参数veh_id代表车辆的类型,需和后方创建flow时对应车辆的类型名相同,在最后生成的坐标文件中该类型名也是搜索遍历的关键变量。

       length是车辆的长度,单位是m。

       acceleration_controller是该种车辆的加速控制逻辑,可以选择RL、IDM等加速控制逻辑,并在各加速控制逻辑函数中用字典的形式设置初始车速(单位为m/s)等变量(具体变量详见flow/flow/core目录下的params.py中的VehicleParams源码)。

       car_following_params设定了该种车辆的跟车逻辑,其中speed_mode有"right_of_way"(默认)、"obey_safe_speed"、"no_collide"、"aggressive"、"all_checks"几种模式,具体解释同样见flow/flow/core目录下的params.py中的VehicleParams源码。

       lane_change_controller设定了该种车辆的换道逻辑,具体的换道参数在lane_change_params中设定,lane_change_mode同样包括"no_lat_collide"(默认)、"strategic"、"aggressive"这几种选择,具体见params.py。

       initial_speed设定了这些在道路上的既有车辆的初始速度,和后续在flow中添加的车流的出发速度无关。num_vehicles则是添加既有车辆的数量,因博主的仿真不依赖初始的车辆,故随便设了个1。

       因为Flow Project暂时还没有设定各条车道车速上下限的功能,只能同时设定四条车道的最大车速,故博主选择在各条车道上建立不同初速度、期望速度的不同种类车流,在c中将有所体现。

c.添加输入流

    inflow = InFlows()
    
    inflow.add(
        veh_type="rlcar",
        edge="highway_0",
        #probability=0.025,# 0.25 probability for emitting a vehicle each second (not together with vehsPerHour or period)
        vehs_per_hour=250,
        departLane=3,# the index of the lane, starting with rightmost=0
        departSpeed=30)

       仿真模型不能只有道上车辆而没有输入,故Inflow()函数就是为在道路上建立输入车流而准备的。

       inflow作为创建的对象,add函数中veh_type对应上文中VehicleParams()创建的车流,必须使用上文中创建过的车辆种类。

       edge是选择车辆输入的道路端,_0一般是左边,另一边自然就是_1啦。

       关于输入车流的车流量,这里存在probability和vehs_per_hour两种方式进行车流量设定。probabilty是一种基于概率的车流生成方式,代表每秒生成车流的概率,最大为1,也只能为1了……所以这种生成方法存在着一个生成上限的问题(然而一秒一辆的路还能开车?)为了解决这种不太自由的限制,Flow Project还借助TraCI给出了vehs_per_hour的参数,就是喜闻乐见的每小时输入车辆数。

       departLane则是选择该种车流的初始车道,它有着“free”、“ random”、“ allowed”、“ best”和“first”这几种选择(具体见http://sumo.dlr.de/wiki/Definition_of_Vehicles,_Vehicle_Types,_and_Routes),但这里还可以选择车道数字,譬如四车道就是从左到右0到3,这样这辆车就会不停地在这条车道上生成。

       departSpeed是该种车流的出发速度,单位为m/s。

d.设定道路场景

    initial_config = InitialConfig(spacing="uniform", shuffle=True)# initial position in road

    scenario = HighwayScenario(#3:110-120 2:90-120 3:90-120 4:60-120 [G1503 2019.5 daily car:180000 bus/truck:70000]
        name="highway",
        vehicles=vehicles,
        net_params=NetParams(
                inflows=inflow,
                additional_params={
                    'length': 6000,
                    'lanes': 4,
                    'speed_limit': 33.3,
                    'num_edges': 1
                }),
        initial_config=initial_config)
    

    env = LaneChangeAccelEnv(env_params, sim_params, scenario)

       这里是Flow Project最强大,也最不自由的地方,通过这么一小段话就能构建出一个系统中既有的复杂场景。emmm……系统中既有之外的不行。

       HighwayScenario()可以看出这是专门为单向四车道高速公路场景设立的函数。因为Flow Project本意是用来训练简单场景下的强化学习车辆(复杂场景请考虑GTA等等游戏),因此没有太复杂的车辆网络(官方:有待诸位改源码扩展)。

       其中inflow输入先前创建的InFlow()对象即可,length指的是道路长度(单位:m,千万别太长,否则运行后的数据记录会中断),lanes是车道数,可以增减,speed_limit是这整条道路每条车道上车辆不会超过的最大车速(单位:m/s),num_edges指的是道路的端口数(没尝试增加过,或许可以变成双向?)。

e.开始仿真

exp.run(1, 5000, convert_to_csv = True)

       主函数中的这句话代表着仿真开始,其中1指的是仿真的次数(不是仿真的开始时刻!!),5000指的是仿真的秒数(太长的话数据记录会中断),convert_to_csv指是否把仿真产生的xml文件自动转为csv文件。如果仿真网络一定要大的话,就不要选择自动转换了,会崩而且极其占内存,可以考虑自己写程序将仿真产生的xml文件转成csv(博主没试过……)。

 

       后续博主还会在后续博客中给出对Flow Project产生的csv文件进行处理的Python脚本,关于Flow Project或有什么其他更方便的微观交通流仿真模型代码创建方法,欢迎交流讨论!Flow Project好像比较小众,Github上就300+Stars,加州伯克利他们组是不是快要放弃这个项目了呢……

 

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

要点初见:用Python进行微观交通模型仿真——基于SUMO的伯克利开源项目Flow Project初探与拓展 的相关文章

  • python tkinter实现侧面弹出窗口,(tkinter侧拉窗口,tkinter滑动窗口),连续多次点击弹窗按钮,重复打开窗口问题

    文章目录 xff11 xff0c 效果 xff12 xff0c 代码 xff13 xff0c 连续多次点击弹窗按钮 xff0c 重复打开窗口问题 xff11 xff0c 效果 xff12 xff0c 代码 span class token
  • pugixml使用笔记

    https pugixml org docs manual html dom tree pugixml官方使用手册 1 创建xml文件信息 例如 xff1a pugi xml document xmldoc pugi xml node de
  • QQ情话糖果情话内容获取并保存

    1 下载夜神模拟器 xff0c 打开应用商店下载xposed和qq xff0c xposed里面安装trustmealready 2 打开模拟器里面的wifi设置代理 xff0c 电脑fiddler抓包 设置代理方法 1 电脑打开fiddl
  • Qscrollarea去除边框的办法

    1 代码去除 QScrollArea是派生于QFrame xff0c 如果设置QFrame的FrameShape值为NoFrame那么就可以实现边框去除 ui gt scrollArea gt setFrameShape QFrame No
  • 简单VS问题 VS2017 文件高级保存选项显示设置

    在用VS2015的时候可以在文件 文件高级保存选项中 但是在VS2017中 xff0c 这个功能不见了 xff0c 按下面方法就可以给弄出来了 1 工具 自定义 xff1b 2 点击 命令 标签 xff1b 3 在上方单选区选中 菜单栏 x
  • Qt程序启动画面播放(gif与swf两种动画格式)

    学习Qt有一段时间了 xff0c 发现一个小问题 xff0c 网上关于Qt的资料或者总结性的学习及应用文章有点少 比如 xff0c Qt完整的API xff0c 程序运行之前的启动画面如何按理想效果播放等 xff0c 每次想在项目中添加一些
  • 自己总结的QT相关资料和网址汇总

    QT官网 xff1a http www qt io download QT项目源码 xff1a http download qt io QT编程指南 xff1a https lug ustc edu cn sites qtguide QTD
  • QT程序异常结束 处理方式

    运行几个网上的程序都出现如下程序异常结束 xff0c 感觉没有任何错误 xff0c 所以就去网上搜索解决方案 xff1a 很多人都说是 xff1a 1 环境问题 2 要不就是编译器选择不符 3 还有就是有的人是在动态编译的时候提示缺少一些d
  • 【Windows版】CMake安装教程

    一 参考资料 windows 43 cmake 43 mingw 搭建c c 43 43 开发环境 二 步骤 1 官网下载CMake安装包 CMake官网 2 解压安装包 D 360Downloads Software CMake cmak
  • GNSS入门2-RTD, RTK,精度

    2 1 RTD vs RTK RTD xff08 Real Time Differential xff09 xff1a 实时码 xff08 C A码 P码 xff09 相位差分技术 xff0c 流动站与基站距离需小于100km xff0c
  • 关于嵌入式开发的C语言基础总结

    一 位操作 C语言支持的6种位操作符如下 xff1a 1 不改变其他位的值的状况下 xff0c 对某几个位进行设值 方法 xff1a 先对需要设置的位用 amp 操作符 xff08 对应位 amp 0 xff09 进行清零操作 xff0c
  • STM32 ASSERT断言机制

    调试代码经常会有跑崩的时候 xff0c 当整机调试是出问题特别让人崩溃 xff0c 断言机制能很好的定位由于参数错误导致的系统异常的情况 在代码重要的代码区 xff0c 添加断言 xff0c 相当于对出入参数做了预判操作 xff0c 当参数
  • 舵机抖动的原因分析

    舵机抖动 舵机在很多场合都会用到 xff0c 比如航模 云台等 但有时候舵机会莫名的出现抖动 xff0c 最近我也遇到了这个问题 xff0c 花了两天的时间终于解决了 舵机抖动的原因主要有以下几点 xff1a 1 电源电压不足 xff1a
  • ubuntu系统python实现串口通信

    我使用的是USB TTL串口 xff0c 下面是测试之前的一些准备工作 span class token function ls span dev span class token comment 查看设备 xff0c 插拔串口设备注意有没
  • __FILE__,__func__,__LINE__用法举例

    C语言中 xff0c FILE func LINE 常用于logout xff0c 打trace xff0c debug调试 注意 xff1a 其使用不需要定义 xff0c FILE 指示当前文件名 func 指示当前函数名 LINE 指示
  • STM32 串口超时中断+DMA接收不定长数据 比 空闲中断(IDLE)更加灵活、稳定(一)

    前言 xff1a 最近项目有使用串口接收大段不定长GPS数据的需求 xff0c 调试了很久 xff0c 终于找到一个比较好的解决办法 我觉得这个项目需求 xff08 高波特率 大段数据 不定长 xff09 十分典型 xff0c 所以在这里记
  • STM32串口通信(基于缓冲区)

    一 串口的初始化和中断设置 1 初始化GPIO xff1a 根据手册的8 1 11节 xff0c 我们可以找到下表 xff1a 在全双工的模式下 xff0c 发送引脚需要设置为推挽复用输出 xff0c 接收引脚则设置为浮空输入或带上拉的输入
  • STM32与C#上位机串口通信示例

    1 概述 串口通信是一种非常常用的通信方式 xff0c 本文首先介绍了串口硬件和协议的相关内容 xff0c 然后给出一个STM32与C 上位机通过串口通信的示例 2 串口介绍 参考这份文档 3 通信协议 为了方便数据传输 xff0c 定义了
  • 【转】23个常用的VSCode快捷键(动图演示)

    尽管我们经常使用 VS Code中的许多快捷方式 xff0c 但是我们有可能会忘记它们 这里用可视化制作了一些GIF xff0c 以便更好地记住它们 xff0c 希望对你有所帮助 VSCode中的每个命令也可以通过使用CTRL 43 SHI
  • HI3531编码h.264文件播放偏慢分析随笔

    现象 xff1a 编码h 264文件播放时 xff0c 无论帧率是30fps还是60fps xff0c 播放器显示帧率为25 fps 探索过程 xff1a cat proc umap venc 显示得知 xff0c 编码的的确是30fps和

随机推荐

  • C++ const用法详解

    const 是C 43 43 中常用的类型修饰符 常类型是指使用类型修饰符const说明的类型 xff0c 常类型的变量或对象的值是不能被更新的 目录 一 const的作用 二 const修饰普通类型的变量 三 const修饰指针变量 四
  • Source Insight 4.0打开一会就闪退 解决方法

    遇到Source Insight 4 0打开直接闪退 xff0c 请不要着急卸载 xff0c 在Source Insight 4 0快捷键上 xff0c 点击属性 xff0c 选择兼容性如下 xff1a
  • secureCRT连接ubuntu18.04

    1 安装ssh服务器 sudo apt get install openssh server 2 ssh服务器安装失败 错误提示 xff1a 下列软件包有未满足的依赖关系 xff1a openssh server 原因 xff1a 系统预置
  • STM32——USART串口通信与串口重定向

    简介 UART 通用异步收发传输器 xff08 Universal Asynchronous Receiver Transmitter xff0c 通常称 作 UART 它将要传输的资料在串行通信与并行通信之间加以转换 作为把并行输入信 号
  • 海思文件系统缺少文件himm 、i2c_read 、i2c_write 、ssp_read 、ssp_write

    原因 xff1a 海思根文件默认没有把himm i2c read i2c write ssp read ssp write工具集成在bin里 xff0c 但是在sdk中 解决办法 xff1a cd osdrv tools board reg
  • Ubuntu 18.04 Samba服务器的安装和配置(详解)

    具体步骤 xff1a 1 设置为静态IP xff1a 点击静态IP设置链接 2 更新当前软件 sudo apt get upgrade sudo apt get update sudo apt get dist upgrade 3 安装sa
  • C52单片机(AT89C52)—流水灯

    本文重点 xff1a C52流水灯代码编写 xff0c keil如何生存hex文件和proteus如何导入hex文件 1 打开keil xff0c 建立工程 xff0c 编写如下代码 include lt reg52 h gt includ
  • Hi3516EV200图像调优

    一 平台搭建 1 将Hi3516EV200 PQ V1 0 0 3 tgz放到nfs挂载目录下解压 xff0c 进入Hi3516EV200 PQ V1 0 0 3 执行StartControl sh 2 执行HiPQTools exe xf
  • Qt低延时/可集成嵌入的网络播放器 –soundTouch的使用

    背景 在观看直播的过程中 xff0c 保不齐网络出现卡的现象 xff0c 可能导致音频数据包累积了好几秒的数据 xff0c 这时候要么丢直接播放新的 xff0c 要么直接播放基音 xff0c soundTouch可以加速播放并不要变调 主要
  • 超低延时直播rtmp推流

    项目起源 xff1a 改项目主要是基于类qt av的模式 xff0c 快速集成 xff0c 将ffmpeg融入到插件当中 xff0c 并提供本地的音频设备和视频设备的查找输出 xff0c 并可以采集各类虚拟摄像头 xff0c 酷狗直播助手
  • minio 使用aws c++ 多线程下载

    C 43 43 下载 Minio 文件 下载 aws sdk cpp git clone recurse submodules GitHub aws aws sdk cpp AWS SDK for C 43 43 麒麟上编译AWS cmak
  • 拉流推流服务器设计

    背景 该服务器也是基于一个客户的需求产生的 客户那边使用的是腾讯的直播sdk xff0c 将不同终端的流推到腾讯云平台 xff0c 但是又想推到其他平台 xff0c 基于此需求 xff0c 该产品产生了 该产品通讯协议使用的是WebSock
  • 开发实现C++ RTMP直播推流sdk

    前言 rtmp即Real Time Messaging Protocol xff08 实时消息传输协议 xff09 的首字母缩写 xff0c 它是由Adobe公司提出的一种应用层的协议 xff0c 用来解决多媒体数据传输流的多路复用 xff
  • 开发实现C++ RTMP直播拉流播放器

    背景 该直播播放器的背景是来源于 拉流推流服务器设计 的一个分支 xff0c 它的重点是把拉下来的流进行解码显示播放 设计点 要实现跨平台 xff0c 目前支持的平台linux和windows要模块化和结构化可以拉各个平台的直播流要音视频同
  • 校验和计算原理

    校验和思路 首先 xff0c IP ICMP UDP和TCP报文头都有检验和字段 xff0c 大小都是16bit xff0c 算法基本上也是一样的 在发送数据时 xff0c 为了计算数据包的检验和 应该按如下步骤 xff1a 1 把校验和字
  • gb 28181的20位编码简介

    图解Python数据结构与算法 实战篇 举例 xff1a 36030000042000000003 设备的20位编码组成 国标编码由中心编码 xff08 8位 xff09 行业编码 xff08 2位 xff09 类型编码 xff08 3位
  • 继承的构造析构函数&&父类子类同名函数,变量的调用

    include lt iostream gt include 34 string 34 using namespace std class Base public int m A int m B 61 20 Base m A 61 100
  • CMake 之静态库依赖动态库,如何使用该静态库

    参考 xff1a xff08 参考文章用的Makefile 我自己用的CMake xff09 静态库链接动态库时 xff0c 如何使用该静态库 newchenxf的专栏 CSDN博客 链接静态库 1 先建立如下工程目录文件 下载 xff08
  • 单片机堆栈小知识

    目录 一 关于单片机堆栈的基础知识 1 STM32程序数据分类 2 STM32内存 RAM 分配 3 经典例子分析 xff1a 4 STM32堆栈位置 5 STM32栈增长方式 三 如何设置STM32的堆栈大小 1 MDK编译环境下 2 I
  • 要点初见:用Python进行微观交通模型仿真——基于SUMO的伯克利开源项目Flow Project初探与拓展

    后续拓展 xff1a 要点初见 xff1a 安装教程与二度拓展 基于SUMO的Flow Project xff08 附代码链接 xff09 通俗来讲 xff0c 微观交通模型仿真就是从车辆个体的视角 xff08 看动画 xff09 进行交通