Python深度强化学习实战 ——OpenAI Gym-CarRacing自动驾驶项目

news2024/11/25 22:38:17

     

  • 💭 写在前面:本篇是关于 OpenAI Gym-CarRacing 自动驾驶项目的博客,面向掌握 Python 并有一定的深度强化学习基础的读者。GYM-Box2D CarRacing 是一种在 OpenAI Gym 平台上开发和比较强化学习算法的模拟环境。它是流行的 Box2D 物理引擎的一个版本,经过修改以支持模拟汽车在赛道上行驶的物理过程。本篇是 CarRacing 系列博客的代码篇,提供 lane_dection 部分的完整代码。 

📜 本章目录:

Ⅰ. 项目环境准备

0x00 实验说明

0x01 模板下载

Ⅱ. 代码:车道检测功能的实现

 0x00 引入:lane_dection 部分的实现

0x01 完整代码

0x01 运行结果演示

0x02 转灰度图像:cur_gray

0x03 边缘检测:edge_detection

0x04 寻找边缘检测结果中的局部最大值:find_maxima_gradient_rowwise

🔗 OpenAI Gym-CarRacing 系列博客


Ⅰ. 项目环境准备

0x00 实验说明

🔗 Conda 安装:【Python】前置:Conda 安装教学

🔗 项目环境安装:Gym-CarRacing 环境安装

🚩 实践目标:实现一个模块化组件框架,落实简化版的模块化流水线。了解基本概念,并积累开发一个简单的自驱应用程序的经验。

🔨 环境选用:OpenAI GYM

  • https://www.gymlibrary.ml/
  • 我们将基于 Box2D CarRacing 实现,Box2D CarRacing 基本信息如下:
    • Action:转向、加速、刹车
    • Sensor input:96x96x3​​  屏幕(显示汽车的状态和路径信息)

​​

0x01 模板下载

* 提供基础框架,只需要在 TODO 位置填写代码即可!

🔗 模板下载:CSDN资源:Box2D CarRacing lane-dection 项目模板

Ⅱ. 代码:车道检测功能的实现

 0x00 引入:lane_dection 部分的实现

🚩 实践目标:

  • 实现一个模块化组件框架,落实简化版的模块化流水线。
  • 了解基本概念,并积累开发一个简单的自驱应用程序的经验。

​​​​​​​

📜 尝试:

  • 为汽车上方的部分找到一个好的裁剪,一个好的方法来分配车道边界的边缘,一个好的梯度阈值和样条平滑度的参数选择。
  • 尝试找到失败的案例。

0x01 完整代码

💬 参考代码:lane_detection.py

from turtle import distance
import numpy as np
import matplotlib.pyplot as plt
from scipy.signal import find_peaks
from scipy.interpolate import splprep, splev
from scipy.optimize import minimize
import time


class LaneDetection:
    '''
    Lane detection module using edge detection and b-spline fitting

    args: 
        cut_size (cut_size=65) cut the image at the front of the car
        spline_smoothness (default=10)
        gradient_threshold (default=14)
        distance_maxima_gradient (default=3)

    使用边缘检测和b样条拟合的车道检测模块
    参数:
        cut_size(cut_size=65)在汽车前部剪切图像
        spline_smoothness(默认值=10)
        gradient_threshold(默认值=14)
        distance_maxima_gradient(默认值=3)

    '''

    def __init__(self, cut_size=65, spline_smoothness=10, gradient_threshold=14, distance_maxima_gradient=3):
        self.car_position = np.array([48,0])
        self.spline_smoothness = spline_smoothness
        self.cut_size = cut_size
        self.gradient_threshold = gradient_threshold
        self.distance_maxima_gradient = distance_maxima_gradient
        self.lane_boundary1_old = 0
        self.lane_boundary2_old = 0

    ## 将状态图像转化为灰度图像
    def cut_gray(self, state_image_full):
        '''
        ##### TODO #####
        This function should cut the image at the front end of the car (e.g. pixel row 65) 
        and translate to gray scale

        input:
            state_image_full 96x96x3

        output:
            gray_state_image 65x96x1
        
        此功能应在汽车前端切割图像(例如像素行65),并转换为灰度
        输入:
            状态图像完整96x96x3
        输出:
            灰度_状态_图像65x96x1

        '''
        copy_img = state_image_full[:self.cut_size, :]   
        red, green, blue = 0.2989, 0.5870, 0.1140
        return np.dot(copy_img[...,:3], [red, green, blue])[::-1]


    def edge_detection(self, gray_image):
        '''
        ##### TODO #####
        In order to find edges in the gray state image, 
        this function should derive the absolute gradients of the gray state image.
        Derive the absolute gradients using numpy for each pixel. 
        To ignore small gradients, set all gradients below a threshold (self.gradient_threshold) to zero. 

        input:
            gray_state_image 65x96x1

        output:
            gradient_sum 65x96x1

        为了在灰度图像中找到边缘,
        该函数应导出灰度图像的绝对梯度。
        使用numpy为每个像素导出绝对梯度。
        要忽略小渐变,请将阈值(self.gradient_threshold)以下的所有渐变设置为0。
        '''

        gradient = np.gradient(gray_image)
        gradient_sum = abs(gradient[0]) + abs(gradient[1])
        gradient = gradient_sum < self.gradient_threshold
        gradient_sum[gradient] = 0

        return gradient_sum

    def find_maxima_gradient_rowwise(self, gradient_sum):
        '''
        ##### TODO #####
        This function should output arguments of local maxima for each row of the gradient image.
        You can use scipy.signal.find_peaks to detect maxima. 
        Hint: Use distance argument for a better robustness.

        input:
            gradient_sum 65x96x1

        output:
            maxima (np.array) shape : (Number_maxima, 2)

        这个函数应该为渐变图像的每一行输出局部最大值的参数。
        您可以使用scipy.signal。查找峰值以检测最大值。
        提示:使用距离参数可以获得更好的鲁棒性。

        
        # 距离参数cuz车道应至少相隔3像素
        # find_peaks返回`x`中满足所有给定条件的峰值指数。
        '''

        argmaxima = []
        pixel = 3        # 相隔参数
        i = 0
        while (i < gradient_sum.shape[0]):
            top, _ = find_peaks(gradient_sum[i], distance = pixel)
            argmaxima.append(top)

            i += 1

        return argmaxima


    def find_first_lane_point(self, gradient_sum):
        '''
        Find the first lane_boundaries points above the car.
        Special cases like just detecting one lane_boundary or more than two are considered. 
        Even though there is space for improvement ;) 

        input:
            gradient_sum 65x96x1

        output: 
            lane_boundary1_startpoint
            lane_boundary2_startpoint
            lanes_found  true if lane_boundaries were found
        
        找到汽车上方的第一个车道边界点。
        特殊情况下,如只检测一个或两个以上的车道边界。
        尽管还有改进的空间;)

        输入:
            梯度_总和65x96x1
        输出:
            车道边界1_起点
            车道边界2起点
            如果找到车道边界,则lanes_found为true
        '''
        
        # Variable if lanes were found or not
        lanes_found = False
        row = 0

        # loop through the rows
        while not lanes_found:
            
            # Find peaks with min distance of at least 3 pixel 
            argmaxima = find_peaks(gradient_sum[row],distance=3)[0]

            # if one lane_boundary is found
            if argmaxima.shape[0] == 1:
                lane_boundary1_startpoint = np.array([[argmaxima[0],  row]])

                if argmaxima[0] < 48:
                    lane_boundary2_startpoint = np.array([[0,  row]])
                else: 
                    lane_boundary2_startpoint = np.array([[96,  row]])

                lanes_found = True
            
            # if 2 lane_boundaries are found
            elif argmaxima.shape[0] == 2:
                lane_boundary1_startpoint = np.array([[argmaxima[0],  row]])
                lane_boundary2_startpoint = np.array([[argmaxima[1],  row]])
                lanes_found = True

            # if more than 2 lane_boundaries are found
            elif argmaxima.shape[0] > 2:
                # if more than two maxima then take the two lanes next to the car, regarding least square
                A = np.argsort((argmaxima - self.car_position[0])**2)
                lane_boundary1_startpoint = np.array([[argmaxima[A[0]],  0]])
                lane_boundary2_startpoint = np.array([[argmaxima[A[1]],  0]])
                lanes_found = True

            row += 1
            
            # if no lane_boundaries are found
            if row == self.cut_size:
                lane_boundary1_startpoint = np.array([[0,  0]])
                lane_boundary2_startpoint = np.array([[0,  0]])
                break

        return lane_boundary1_startpoint, lane_boundary2_startpoint, lanes_found


    def lane_detection(self, state_image_full):
        '''
        ##### TODO #####
        This function should perform the road detection 

        args:
            state_image_full [96, 96, 3]

        out:
            lane_boundary1 spline
            lane_boundary2 spline

        此功能应执行道路检测
        参数:
            state_image_full [96, 96, 3]
        输出:
            lane_boundary1 spline
            lane_boundary2 spline
        '''

        # to gray
        gray_state = self.cut_gray(state_image_full)

        # edge detection via gradient sum and thresholding
        gradient_sum = self.edge_detection(gray_state)
        maxima = self.find_maxima_gradient_rowwise(gradient_sum)

        # first lane_boundary points
        lane_boundary1_points, lane_boundary2_points, lane_found = self.find_first_lane_point(gradient_sum)
        
        # if no lane was found,use lane_boundaries of the preceding step
        # l1 = lane_boundary1_points
        # l2 = lane_boundary2_points

        if lane_found:
            
            ##### TODO #####
            #  in every iteration: 
            # 1- find maximum/edge with the lowest distance to the last lane boundary point 
            # 2- append maximum to lane_boundary1_points or lane_boundary2_points
            # 3- delete maximum from maxima
            # 4- stop loop if there is no maximum left 
            #    or if the distance to the next one is too big (>=100)

            '''
            #在每次迭代中:
                #1-查找到最后一个车道边界点的最小距离的最大/边缘
                #2-将最大值附加到lane_boundary1_points或lane_boondary2_point斯
                #3-从maxima中删除maximum
                #4-如果没有最大剩余
                # ,则停止循环
                #或者如果到下一个的距离太大(>=100)
            '''
            l1 = lane_boundary1_points
            l2 = lane_boundary2_points

            row = 1
            lim = 65
            while (row < lim): 
                max_row = maxima[row]
                if len(max_row) < 2:
                    break
                #根据与先前车道预测的距离对点进行排序
                #此外,argsort还返回可以按顺序迭代的索引
                #因此,我们在排序后使用A[0]和B[0]

                arrayA, arrayB = np.argsort(pow(max_row - l1[0][0], 2)), np.argsort(pow(max_row - l2[0][0], 2))
                p1, p2 = np.array([[max_row[arrayA[0]], row]]), np.array([[max_row[arrayB[0]], row]])
                lane_boundary1_points, lane_boundary2_points = np.append(lane_boundary1_points, p1, axis=0), np.append(lane_boundary2_points, p2, axis=0)
            
                l1, l2 = p1, p2
                row += 1

            # lane_boundary 1
            # lane_boundary 2

            ################
            


            ##### TODO #####
            # spline fitting using scipy.interpolate.splprep 
            # and the arguments self.spline_smoothness
            # 
            # if there are more lane_boundary points points than spline parameters 
            # else use perceding spline
            '''
            使用 scipy.interpolate.splprep  进行样条拟合
                #以及自变量self.spline_splity
                #如果车道边界点比样条曲线参数多
                #否则使用perceding样条线
            '''

            

            if lane_boundary1_points.shape[0] > 4 and lane_boundary2_points.shape[0] > 4:

                # Pay attention: the first lane_boundary point might occur twice
                # lane_boundary 1
                lane_boundary1, _ = splprep([lane_boundary1_points[1:,0], lane_boundary1_points[1:,1]], s=self.spline_smoothness, k=2)

                # lane_boundary 2
                lane_boundary2, _ = splprep([lane_boundary2_points[1:,0], lane_boundary2_points[1:,1]], s=self.spline_smoothness, k=2)
                
            else:
                lane_boundary1 = self.lane_boundary1_old
                lane_boundary2 = self.lane_boundary2_old

            ################

        else:
            lane_boundary1 = self.lane_boundary1_old
            lane_boundary2 = self.lane_boundary2_old

        self.lane_boundary1_old = lane_boundary1
        self.lane_boundary2_old = lane_boundary2

        # output the spline
        return lane_boundary1, lane_boundary2


    def plot_state_lane(self, state_image_full, steps, fig, waypoints=[]):
        '''
        Plot lanes and way points
        '''
        # evaluate spline for 6 different spline parameters.
        t = np.linspace(0, 1, 6)
        lane_boundary1_points_points = np.array(splev(t, self.lane_boundary1_old))
        lane_boundary2_points_points = np.array(splev(t, self.lane_boundary2_old))
        
        plt.gcf().clear()
        plt.imshow(state_image_full[::-1])
        plt.plot(lane_boundary1_points_points[0], lane_boundary1_points_points[1]+96-self.cut_size, linewidth=5, color='orange')
        plt.plot(lane_boundary2_points_points[0], lane_boundary2_points_points[1]+96-self.cut_size, linewidth=5, color='orange')
        if len(waypoints):
            plt.scatter(waypoints[0], waypoints[1]+96-self.cut_size, color='white')

        plt.axis('off')
        plt.xlim((-0.5,95.5))
        plt.ylim((-0.5,95.5))
        plt.gca().axes.get_xaxis().set_visible(False)
        plt.gca().axes.get_yaxis().set_visible(False)
        fig.canvas.flush_events()



# t = np.linspace(0, 1, 5) # t = [0, 0.25, 0.5, 0.75, 1]
# Interpolated_lane_boundary_points = np.array(splev(t, self.lane_boundary))


0x01 运行结果演示

cd 到 skeleton 文件夹的路径下,输入 python test_lane_detection 运行代码:

🚩 运行结果:

💻 GIF:

0x02 转灰度图像:cur_gray

cut_gray 函数需要我们实现将状态图像转化为灰度图像。

💬 参考代码:

 def cut_gray(self, state_image_full):
        copy_img = state_image_full[:self.cut_size, :]   
        red, green, blue = 0.2989, 0.5870, 0.1140
        return np.dot(copy_img[...,:3], [red, green, blue])[::-1]

0x03 边缘检测:edge_detection

💬 参考代码:

    def edge_detection(self, gray_image):
        '''
        ##### TODO #####
        In order to find edges in the gray state image, 
        this function should derive the absolute gradients of the gray state image.
        Derive the absolute gradients using numpy for each pixel. 
        To ignore small gradients, set all gradients below a threshold (self.gradient_threshold) to zero. 

        input:
            gray_state_image 65x96x1

        output:
            gradient_sum 65x96x1
        '''

        gradient = np.gradient(gray_image)
        gradient_sum = abs(gradient[0]) + abs(gradient[1])
        gradient = gradient_sum < self.gradient_threshold
        gradient_sum[gradient] = 0

        return gradient_sum

0x04 寻找边缘检测结果中的局部最大值:find_maxima_gradient_rowwise

为渐变图像的每一行输出局部最大值的参数,可以使用 scipy.signal 查找峰值以检测最大值。

* 提示:使用距离参数(distance)可以获得更好的鲁棒性。

  • 距离参数 cuz 车道应至少相隔 3 像素
  • find_peaks 返回 `x` 中满足所有给定条件的峰值指数。

💬 参考代码:

    def find_maxima_gradient_rowwise(self, gradient_sum):
        '''
        ##### TODO #####
        This function should output arguments of local maxima for each row of the gradient image.
        You can use scipy.signal.find_peaks to detect maxima. 
        Hint: Use distance argument for a better robustness.

        input:
            gradient_sum 65x96x1

        output:
            maxima (np.array) shape : (Number_maxima, 2)

        '''

        argmaxima = []
        pixel = 3        # 相隔参数
        i = 0
        while (i < gradient_sum.shape[0]):
            top, _ = find_peaks(gradient_sum[i], distance = pixel)
            argmaxima.append(top)

            i += 1

        return argmaxima


🔗 OpenAI Gym-CarRacing 系列博客:

【OpenAI】Python:基于 Gym-CarRacing 的自动驾驶项目(1) | 前置知识介绍 | 项目环境准备 | 手把手带你一步步实现

【OpenAI】Python:基于 Gym-CarRacing 的自动驾驶项目(2)| 车道检测功能的实现 | 边缘检测与分配 | 样条拟合

【OpenAI】Python:基于 Gym-CarRacing 的自动驾驶项目(3) | 路径训练功能的实现 | 规划与决策 | 路径平滑 | 利用公式进行目标速度预测

【OpenAI】Python:基于 Gym-CarRacing 的自动驾驶项目(4) | 车辆控制功能的实现 | 开环控制 | 闭环控制 | 启停式控制 | PID 控制 | Stanley 控制器

​​

📌 [ 笔者 ]   foxny, Akam
📃 [ 更新 ]   2023.7.8(recently)
❌ [ 勘误 ]   /* 暂无 */
📜 [ 声明 ]   由于作者水平有限,本文有错误和不准确之处在所难免,
              本人也很想知道这些错误,恳望读者批评指正!

📜 参考资料 

[6] Montemerlo M, Becker J, Bhat S, et alJunior: The Stanford entry in the Urban Challenge

Slide Credit: Steven Waslander

LaValle: Rapidly-exploring random trees: A new tool for path planning. Techical Report, 1998

Dolgov et al.: Practical Search Techniques in Path Planning for Autonomous Driving. STAIR, 2008.

Microsoft. MSDN(Microsoft Developer Network)[EB/OL]. []. .

百度百科[EB/OL]. []. https://baike.baidu.com/.

. [EB/OL]. []. https://blog.waymo.com/2021/10/the-waymo-driver-handbook-perception.html.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/753840.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JS-20 ES5~ES13新特性;var/let/const对比;字符串模板;函数的默认/剩余参数;展开语法;进制表示;Symbol;Set;Map等

目录 1_新的ECMA代码执行描述1.1_词法环境&#xff08;Lexical Environments&#xff09;1.2_环境记录&#xff08;Environment Record&#xff09; 2_let/const2.1_基本使用2.2_let/const作用域提升 3_作用域对比3.1_var的块级作用域3.2_let/const的块级作用域3.3_var、let、c…

基于springboot+vue的疫情管理系统(前后端分离)

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战 主要内容&#xff1a;毕业设计(Javaweb项目|小程序等)、简历模板、学习资料、面试题库、技术咨询 文末联系获取 项目介绍…

C语言实现--通讯录管理系统+附详细代码分析过程

文章目录 初始化通讯录实现通讯录的各种功能添加一个联系人的信息删除一个联系人的信息查询指定联系人并打印其信息修改指定联系人的信息打印通讯录中的全部信息通过名字对通讯录中的联系人进行排序 通讯录完整代码示例 初始化通讯录 首先&#xff0c;通讯录中每个联系人的信息…

DAY47:动态规划(十)零钱兑换Ⅱ+组合总和Ⅳ(完全背包求方案总数类型,排列+组合)

文章目录 518.零钱兑换Ⅱ&#xff08;装满背包方案数&#xff0c;本题是组合方案数&#xff09;思路DP数组含义递推公式DP数组初始化遍历顺序&#xff08;重要&#xff0c;不能颠倒&#xff09;外层物品内层背包的情况外层背包内层物品的情况完全背包求排列数和组合数 完整版总…

HTTP进化史:从HTTP1的简单到HTTP3的强大

文章目录 &#x1f4c8;I. HTTP1⚡A. 基本特点⚡B. 特点⚡C. 优缺点 &#x1f4c8;II. HTTP2⚡A. 基本特点⚡B. 特点⚡C. 优缺点 &#x1f4c8;III. HTTP3⚡A. 基本特点⚡B. 特点⚡C. 优缺点 &#x1f4c8;IV. 总结&#x1f4c8;附录&#xff1a;「简历必备」前后端实战项目&am…

资深测试整理,APP专项测试方法总结,看这篇就够了...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 APP专项测试 1、…

我们建议您关注另外两个趋势性漏洞。

即 Windows 错误报告服务 (CVE-2023-36874) 和 Windows MSHTML 平台 (CVE-2023-32046) 中的权限提升漏洞。现实生活中就有利用这两个漏洞的案例。 危险之处 要利用 CVE-2023-36874&#xff0c;攻击者需要访问目标计算机&#xff0c;并能够在普通用户默认具有有限权限的计算机上…

ESP32 LVGL:使用图标解决图片过大存不下的问题

背景 在LVGL中&#xff0c;用将图片转为C语言数组的方式储存的时候&#xff0c;图片转换的数组过大&#xff0c;当图片过多时会出现存不下的问题。 因此&#xff0c;可以使用字库图标解决该问题。 方法 将PNG图片转为字库文件 首先&#xff0c;我们将图片通过PS转为SVG矢量…

鸟类识别系统python+TensorFlow+Django网页界面+卷积网络算法+深度学习模型

一、介绍 鸟类识别系统&#xff0c;使用Python作为主要开发语言&#xff0c;基于深度学习TensorFlow框架&#xff0c;搭建卷积神经网络算法。并通过对数据集进行训练&#xff0c;最后得到一个识别精度较高的模型。并基于Django框架&#xff0c;开发网页端操作平台&#xff0c;…

XPath 的基本概念

XPath 的基本概念 引言 1. XPath 的基本概念 1.1 节点 1.2 路径表达式 1.3 轴 2. XPath 的语法和使用方法 2.1 标签定位 2.2 属性定位 2.3 文本定位 2.4 谓语和运算符 3. 示例演示 3.1 示例 1 &#xff1a; Web 自动化测试 3.2 示例 2 &#xff1a;数据提取和处理 3.3 示例 3 &…

pdsh 2.29 安装

下载&#xff1a; wget https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/pdsh/pdsh-2.29.tar.bz2解包&#xff1a; tar jxvf pdsh-2.29.tar.bz2 cd pdsh-2.29/安装&#xff1a; ./configure --prefix/u01/isi/pdsh-2.29/ --with-timeout6…

Spark编程-共享变量(广播变量和累加器)

共享变量是什么 Spark中的两个重要抽象一个是RDD&#xff0c;另一个就是共享变量。 在默认情况下&#xff0c;当Spark在集群的多个不同节点的多个任务上并行运行一个函数时&#xff0c;它会把函数中涉及到的每个变量&#xff0c;在每个任务上都生成一个副本。 但是&…

基于STM32 ARM+FPGA伺服控制系统总体设计方案(一)

设计需求 一套完整的伺服控制方案包括了上位机、驱控一体控制器和功率板三者。操作人员 通过上位机发送各种不同指令&#xff0c;然后控制器解析指令后执行相应的伺服功能&#xff0c;其次控 制器将驱动信号传输至功率板驱动电机&#xff0c;最后控制器采集反馈信息进行闭环…

为你带来全新的UGC体验!

当我们开始向更多 UGC 开放元宇宙&#xff0c;你们将有机会发现我们社区在 The Sandbox 中创造的一些令人惊叹的体验。 需要从你们自己的体验中获得灵感&#xff0c;或者只是想玩一些新东西&#xff1f;以下是我们的一些建造者几个月来的工作成果——现在就可以玩&#xff01; …

JVM学习

文章目录 1 JVM与Java体系结构1.0 Java发展重大事件1.1 虚拟机和Java虚拟机1.3 JVM整体结构1.4 Java代码执行流程1.5 JVM架构模型1.6 JVM的生命周期1.7 JVM发展历程 2 类加载子系统2.1 ClassLoader2.2 用户自定义类加载器2.2.1 为什么需要自定义类加载器2.2.2 自定义类加载器的…

Kong 服务和路由的添加

管理服务 这里参考DB-less-Mode&#xff0c;因为使用的是yaml配置文件的形式&#xff0c;所以所有的相关配置只需要往初始化的kong.yml文件中添加就可以了&#xff0c;就像nginx的配置文件 DB-less-Mode 创建服务 vim /etc/kong/kong.yml services: - name: my-service #…

排查思路----CPU占用过高

1、top查看cpu占用情况 %Cpu(s): 29.4 us, 24.1 sy, 0.0 ni, 10.1 id, 20.4 wa, 0.0 hi, 16.0 si, 0.0 st 发现wa和si都比较高 2、查wa高的问题 iostat -x 1 10%util 接近 100%&#xff0c;说明产生的I/O请求太多&#xff0c;I/O系统已经满负荷&#xff0c;该磁盘存在瓶颈。…

数据库性能优化中的表结构优化

数据库性能优化中的表结构优化 在数据库应用中&#xff0c;表结构的设计直接影响着数据库的性能。合理的表结构设计可以提高数据库的查询效率和性能&#xff0c;而不合理的表结构设计则可能导致查询效率低下、数据冗余、数据不一致等问题。因此&#xff0c;表结构优化是数据库…

智慧园区如何搭乘数字孪生这列快车?

无论是2022年的火爆的元宇宙还是今年出圈的ChatGPT&#xff0c;都体现着数字技术嵌入社会生活是大趋势&#xff0c;数字孪生作为智能技术的一大亮点&#xff0c;它在智慧园区中的应用会是怎样呢&#xff1f;今天我们就来聊一聊&#xff01; &#xff08;全文3000字&#xff0c;…

Star CCM+ 202206 (17.04) 详细安装步骤

首先下载win系统的安装包 阿里云盘&#xff1a; https://www.aliyundrive.com/s/WFfyvFhGxwK 提取码: x57w 百度云盘&#xff1a;https://pan.baidu.com/s/1qKgxYf2DGURCTW0rga8Xkw?pwdeiqi 提取码&#xff1a;eiqi &#xff08;资源来自网络&#xff0c;仅供个人学习交流&…