最优轨迹生成(四)—— 带约束轨迹优化

   本系列文章是学习深蓝学院-移动机器人运动规划课程第五章最优轨迹生成 过程中所记录的笔记,本系列文章共包含四篇文章,依次介绍了微分平坦特性、无约束BVP轨迹优化、无约束BIVP轨迹优、 带约束轨迹优化等内容

   本系列文章链接如下:

   最优轨迹生成(一)—— 微分平坦

   最优轨迹生成(二)—— 无约束BVP轨迹优化

   最优轨迹生成(三)—— 无约束BIVP轨迹优化

   最优轨迹生成(四)—— 带约束轨迹优化


   四、带约束轨迹优化

在这里插入图片描述

   如果我们需要处理更一般的约束,并给定状态点的可行域约束,并且需要进一步优化轨迹的总时间以及轨迹在时间和空间上的形状,则上面介绍的BVP和BIVP就不再适应,且存在以下难点:

   ①、最佳参数化是未知的,即最优的轨迹不一定是2s-1阶多项式了。

   ②、时空剖面涉及多个自由度,我们即要优化轨迹的时域又要优化轨迹的空间域,轨迹的速度、加速度、jerk等都需要优化。

   ③、 G \mathcal{G} G可能包含是非凸的约束。

   ④、安全区域(环境中的可行域)可能是高复杂性。

   我们可以对以上问题进行一些可能的简化

   ①、虽然最优解不一定再是多项式曲线,但是我们能不能就在多项式曲线中去寻找最优解呢?

   ②、我们能不能把轨迹的飞行时间固定,从而不再对轨迹的时间进行优化?

   ③、我们能不能只把速度、加速度的幅值约束一下,不要管其他的角速率、推力等约束

   ④、我们能不能使安全约束凸化,从而得到一些局部凸区域约束。

   基于以上思路,我们可以把问题转换成凸优化问题,假设我们给定几个凸的问题,它们首尾相接,如下图所示的例子中,我们把轨迹分为首尾相接的三段,每段各自约束在各自的凸问题中,比如第一段 A 0 p < b 0 A_0p<b_0 A0p<b0、第二段 A 1 p < b 1 A_1p<b_1 A1p<b1

在这里插入图片描述

   arg ⁡ min ⁡ Φ J q = ∑ i = 0 n − 1 ∫ 0 Δ t i ∣ ∣ Φ i ( q ) ( t ) ∣ ∣ 2 d t Φ i ( k ) ( Δ t i ) = Φ i + 1 ( k ) ( 0 ) , k = 0 … q   a n d   i = 1 … N − 2 , Φ 0 ( k ) ( 0 ) = u s ( k ) , Φ N − 1 ( k ) ( Δ t N − 1 ) = u g ( k ) , k = 0 … q , A i T Φ i ( t ) ≤ b i , i = 0 … N − 1. \begin{aligned} \arg\operatorname*{min}_{\Phi}J^{q}& =\sum_{i=0}^{n-1}\intop_0^{\Delta t_i}||\Phi_i^{(q)}(t)||^2dt \\ \Phi_{i}^{(k)}(\Delta t_{i})& =\Phi_{i+1}^{(k)}(0),\quad k=0\ldots q\mathrm{~and~}i=1\ldots N-2, \\ \Phi_{0}^{(k)}(0)& =u_{s}^{(k)},\Phi_{N-1}^{(k)}(\Delta t_{N-1})=u_{g}^{(k)},k=0\ldots q, \\ \mathbf{A}_{i}^{T}\Phi_{i}(t)& \leq\mathbf{b}_{i},i=0\ldots N-1. \end{aligned} argΦminJqΦi(k)(Δti)Φ0(k)(0)AiTΦi(t)=i=0n10Δti∣∣Φi(q)(t)2dt=Φi+1(k)(0),k=0q and i=1N2,=us(k),ΦN1(k)(ΔtN1)=ug(k),k=0q,bi,i=0N1.

   该问题与BIVP问题最大的区别在于多了安全约束。上述目标函数中q=3时等价于BIVP中的最小化jerk,上面的第一个等式约束也与BIVP中两段相邻轨迹的连续性约束相似,所不同的是该问题中并不像BIVP中那样对中间位置点进行指定,而是通过优化去确定中间位置点,上面的第二个等式约束也与BIVP中对起始和终末状态进行指定相同。最后的不等式约束 A i T Φ i ( t ) ≤ b i \mathbf{A}_i^T\Phi_i(t)\leq\mathbf{b}_i AiTΦi(t)bi即该问题与BIVP问题的最大区别,对于该不等式约束,可以在每段轨迹的若干个时间点进行采样,看其是否满足。采样点越密集,安全约束就也稠密

   在BVP或BIVP中没有推导过代价泛函或代价函数具有什么样的形式,因为在BVP或BIVP中不需要去解最优解。但这里需要用到。

   我们先来看目标函数,对于一个多项式,我们求它的四阶导,得到snap,再将其平方,把snap多项式的系数进行卷积,在进行积分。然后,我们就可以将第j段轨迹的目标函数写成一个二次型的形式,流程如下所示:

   f ( t ) = ∑ p i t i ⟹ f ( 4 ) ( t ˙ ) ‾ = ∑ i ( i − 1 ) ( i − 2 ) ( i − 3 ) t i − 4 p i ⟹ ( f ( 4 ) ( t ) ) = 2 i ≥ 4 ∑ i ≥ 4 , l ≥ 4 i ( i − 1 ) ( i − 2 ) ( i − 3 ) l ( l − 1 ) ( l − 2 ) ( l − 3 ) t i + l − 8 p i p l ⟹ J ( T ) = ∫ T j − 1 T j ( f 4 ( t ) ) 2 d t = ∑ i ≥ 4 , l ≥ 4 i ( i − 1 ) ( i − 2 ) ( i − 3 ) j ( l − 1 ) ( l − 2 ) ( l − 3 ) i + l − 7 ( T j i + l − 7 − T j − 1 i + l − 7 ) p i p l    ⟹    J ( T ) = ∫ T j − 1 T j ( f 4 ( t ) ) 2 d t = [ ⋮ p i ⋮ ] T [ ⋯ i ( i − 1 ) ( i − 2 ) ( i − 3 ) l ( l − 1 ) ( l − 2 ) ( l − 3 ) i + l − 7 T i + l − 7 ⋯ ⋮ ⋮ ] [ ⋮ p l ⋮ ] ⇒ J j ( T ) = p j T Q j p j \begin{aligned} &f(t)=\sum p_{i}t^{i} \\ &\Longrightarrow f^{(4)}\overline{(\dot{t})}=\sum_{}i(i-1)(i-2)(i-3)t^{i-4}p_{i} \\ &\Longrightarrow\left(f^{(4)}(t)\right)\overset{2_{i\geq4}}{=}\sum_{i\geq4,l\geq4}i(i-1)(i-2)(i-3)l(l-1)(l-2)(l-3)t^{i+l-8}p_{i}p_{l} \\ &\Longrightarrow J(T)=\int_{T_{j-1}}^{T_{j}}\left(f^{4}(t)\right)^{2}dt=\sum_{i\geq4,l\geq4}\frac{i(i-1)(i-2)(i-3)j(l-1)(l-2)(l-3)}{i+l-7}(T_{j}^{i+l-7}-T_{j-1}^{i+l-7})p_{i}p_{l} \\ &\implies J(T)=\int_{T_{j-1}}^{T_{j}}\left(f^4(t)\right)^2dt \\ &=\begin{bmatrix}\vdots\\p_i\\\vdots\end{bmatrix}^T\begin{bmatrix}\cdots&\dfrac{i(i-1)(i-2)(i-3)l(l-1)(l-2)(l-3)}{i+l-7}T^{i+l-7}&\cdots\\\vdots&\vdots\end{bmatrix}\begin{bmatrix}\vdots\\p_l\\\vdots\end{bmatrix} \\ &\Rightarrow J_{j}(T)=\mathbf{p}_{j}^{T}\mathbf{Q}_{j}\mathbf{p}_{j} \end{aligned} f(t)=pitif(4)(t˙)=i(i1)(i2)(i3)ti4pi(f(4)(t))=2i4i4,l4i(i1)(i2)(i3)l(l1)(l2)(l3)ti+l8piplJ(T)=Tj1Tj(f4(t))2dt=i4,l4i+l7i(i1)(i2)(i3)j(l1)(l2)(l3)(Tji+l7Tj1i+l7)piplJ(T)=Tj1Tj(f4(t))2dt= pi T i+l7i(i1)(i2)(i3)l(l1)(l2)(l3)Ti+l7 pl Jj(T)=pjTQjpj

   其中Q是二次型矩阵,P是多项式的系数,所以给定一个多项式,给定 T j − 1 T_{j-1} Tj1 T j T_j Tj,给定轨迹的总时间 t j t_j tj、系数P,我们就可以把该段轨迹的能量或者说目标函数值的表达式。

   然后,我们再来看等式约束,比如给定的初始条件和终末条件,需要对多项式进行求导,然后把系数和对应的边界条件写出来,把权重和系数分离开,写成矩阵的形式,就可以获得等式约束,如下所示:

   f j ( k ) ( T j ) = x j ( k ) ⇒ ∑ i ≥ k i ! ( i − k ) ! T j i − k p j , i = x T , j ( k ) ⇒ [ ⋯ i ! ( i − k ) ! T j i − k ⋯ ] [ ⋮ p j , i ⋮ ] = x T , j ( k ) ⇒ [ . . . i ! ( i − k ) ! T j − 1 i − k . . . . . . i ! ( i − k ) ! T j i − k . . . ] [ ⋮ p j , i ⋮ ] = [ x 0 , j ( k ) x T , j ( k ) ] | ⇒ A j p j = d j \begin{aligned} &f_j^{(k)}(T_j)=x_j^{(k)} \\ &\Rightarrow\sum_{i\geq k}\frac{i!}{(i-k)!}T_{j}^{i-k}p_{j,i}=x_{T,j}^{(k)} \\ &\Rightarrow\begin{bmatrix}\cdots&\frac{i!}{(i-k)!}T_j^{i-k}&\cdots\end{bmatrix}\begin{bmatrix}\vdots\\p_{j,i}\\\vdots\end{bmatrix}=x_{T,j}^{(k)} \\ &\Rightarrow\begin{bmatrix}...&\dfrac{i!}{(i-k)!}T_{j-1}^{i-k}&...\\...&\dfrac{i!}{(i-k)!}T_j^{i-k}&...\\\end{bmatrix}\begin{bmatrix}\vdots\\p_{j,i}\\\vdots\end{bmatrix}=\begin{bmatrix}x_{0,j}^{(k)}\\x_{T,j}^{(k)}\end{bmatrix}& \text{|} \\ &\Rightarrow\mathbf{A}_j\mathbf{p}_j=\mathbf{d}_j \end{aligned} fj(k)(Tj)=xj(k)ik(ik)!i!Tjikpj,i=xT,j(k)[(ik)!i!Tjik] pj,i =xT,j(k) ......(ik)!i!Tj1ik(ik)!i!Tjik...... pj,i =[x0,j(k)xT,j(k)]Ajpj=dj|

   两段之间的连续性约束:当没有给出特定导数时,确保轨迹段之间的连续性

   f j ( k ) ( T j ) = f j + 1 ( k ) ( T j ) ⇒ ∑ i ≥ k i ! ( i − k ) ! T j i − k p j , i − ∑ l ≥ k l ! ( l − k ) ! T j l − k p j + 1 , l = 0 ⇒ [ ⋯ i ! ( i − k ) ! T j i − k ⋯ − l ! ( l − k ) ! T j l − k ⋯ ] [ ⋮ p j , i ⋮ p j + 1 , l ⋮ ] = 0 ⇒ [ A j − A j + 1 ] [ p j p j + 1 ] = 0 \begin{aligned} &f_{j}^{(k)}(T_{j})=f_{j+1}^{(k)}(T_{j}) \\ &\Rightarrow\sum_{i\geq k}\frac{i!}{(i-k)!}T_{j}^{i-k}p_{j,i}-\sum_{l\geq k}\frac{l!}{(l-k)!}T_{j}^{l-k}p_{j+1,l}=0 \\ &\Rightarrow\begin{bmatrix}\cdots&\frac{i!}{(i-k)!}T_j^{i-k}&\cdots&-\frac{l!}{(l-k)!}T_j^{l-k}&\cdots\end{bmatrix}\begin{bmatrix}\vdots\\p_{j,i}\\\vdots\\p_{j+1,l}\\\vdots\end{bmatrix}=0 \\ &\Rightarrow\begin{bmatrix}\mathbf{A}_j&-\mathbf{A}_{j+1}\end{bmatrix}\begin{bmatrix}\mathbf{p}_j\\\mathbf{p}_{j+1}\end{bmatrix}=0 \end{aligned} fj(k)(Tj)=fj+1(k)(Tj)ik(ik)!i!Tjikpj,ilk(lk)!l!Tjlkpj+1,l=0[(ik)!i!Tjik(lk)!l!Tjlk] pj,ipj+1,l =0[AjAj+1][pjpj+1]=0


   凸优化的全局最优解与局部最优解是一致的,凸函数中任意两点连线之间的值始终要比这两点要小,即下式成立

   f ( θ x + ( 1 − θ ) y ) ≤ θ f ( x ) + ( 1 − θ ) f ( y ) f(\theta x+(1-\theta)y)\leq\theta f(x)+(1-\theta)f(y) f(θx+(1θ)y)θf(x)+(1θ)f(y)

   对于一个集合,若任意两点连线都属于集合内部,则为凸集合

   θ x + ( 1 − θ ) y ∈ C . \theta x+(1-\theta)y\in C. θx+(1θ)yC.

   如果一个问题具有凸的函数,并且它的不等式约束构成的集合是一个凸集合,则将其称为凸优化问题

在这里插入图片描述

   一般来说要求等式约束是线性的,不等式约束是凸的

在这里插入图片描述


   如何把常见的轨迹优化转换成凸优化问题呢,应该转换成什么类的凸优化呢。最简单的就是线性规划LP,线性的目标函数和约束。然后是比较常用的二次规划QP,它的目标函数带有二次项,约束项跟LP类似是线性的。如果我们把QP的不等式约束也放松成二次的,则为QCQP规划。锥规划SOCP的目标函数和等式约束都是线性的,不等式约束是 ∥ A i x + b i ∥ ≤ c i T x + d i \|A_{i}x+b_{i}\|\leq c_{i}^{T}x+d_{i} Aix+biciTx+di的形式。另外LP、QP、QCQP都是可以转换成SOCP形式的。

在这里插入图片描述

   把轨迹优化转换成凸优化问题后,可以调用一些库来求解凸优化问题,比如锥规划中效率很高的库Mosek,再比如对线性求解效率比较高、稳定性很高的GLPK。此外,还有CVX、OOQP等

   CVX:http://cvxr.com/cvx/

   Mosek:https://www.mosek.com/

   OOQP:https://pages.cs.wisc.edu/~swright/ooqp/

   GLPK:https://www.gnu.org/software/glpk/

在这里插入图片描述


   凸优化也存在一些数值不稳定问题,我们可以采用相对时间来表示每一段的轨迹,并把每一段轨迹占有的时间归一化为1,来使得问题的条件数更好,我们把一个问题的数值缩放100倍、缩放1000倍和不缩放对凸优化而言它的效率是不一样的

在这里插入图片描述


   如何把凸优化应用到实际的运动规划中去呢?

   首先,我们可以把障碍物进行栅格化,然后从栅格地图中寻找从起始点到目标点的一系列的由长方形构成的可行区域(搜索飞行走廊),然后把狭窄的可行区域进行扩大,获得更大的长方体,然后再在长方体构成的可行域内进行轨迹优化。在这里插入图片描述

   我们在进行轨迹优化时,需要让状态中的位置不要超出长方体构成的几何区域,同样求导后的速度也不要超过限制(也是一个长方体)依次类推,加速度也适应。

在这里插入图片描述


   ·前面为了简化问题,我们将每段轨迹的时间进行了任务分配,而时间分配显著影响最终轨迹。那么如何合理分配时间?

在这里插入图片描述

   时间分配问题是非凸优化问题,凸优化无法处理,一个比较好的方案是使用飞行走廊。飞行走廊的容错率比较高,比如我们有下面三个有重叠部分的长方体,我们只需要分配各个长方体中的飞行时间即可,由于长方体存在重叠部分,指定的时间就有了浮动范围,但该浮动也存在上限。我们也可以在每段轨迹上采用梯形的速度,先加速,再匀速,再减速
在这里插入图片描述


   在考虑安全约束、动力学约束,并且要优化时间分配的情况下,该怎样处理呢?

   轨迹p(t)可以被航时T和航点q决定,采用这种新的参数化的方式,直接调整航点q和时间向量T来使得,比如把某段轨迹的时间过短,超出了其最大速度,可以把时间拉伸,同样的轨迹的某段超出了安全区域,可以把航点q进行调整,使得轨迹变为安全轨迹。

   所以,一个轨迹需要有直接进行空间时间形变的能力,这样就可以处理一些列违背约束的情况

在这里插入图片描述

   利用上述时空形变的方法可以完成一系列高效的求解

在这里插入图片描述
在这里插入图片描述

   我们将这种时间空间形变的轨迹用在多面体或者球体空间中,都可以在很短的时间内达到 V m a x V_{max} Vmax,即下图中红色曲线,保持这样的最大速度均速飞行。

在这里插入图片描述
在这里插入图片描述


   参考资料:

   1、深蓝学院-移动机器人运动规划


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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【ChatGPT 默认强化学习策略】PPO 近端策略优化算法

PPO 近端策略优化算法 PPO 概率比率裁剪 演员-评论家算法演员-评论家算法&#xff1a;多智能体强化学习核心框架概率比率裁剪&#xff1a;逐步进行变化的方法PPO 目标函数的设计重要性采样KL散度 PPO 概率比率裁剪 演员-评论家算法 论文链接&#xff1a;https://arxiv.org…

12. 整数转罗马数字

罗马数字包含以下七种字符&#xff1a; I&#xff0c; V&#xff0c; X&#xff0c; L&#xff0c;C&#xff0c;D 和 M。 字符 数值 I 1 V 5 X 10 L 50 C 100 D 500 M 1000 …

Filezilla使用

服务端 点击安装包 点击我接受 点击下一步 点击下一步 点击下一步 点击安装即可 配置用户组&#xff0c;点击编辑&#xff0c;出现组点击 点击添加&#xff0c;点击确定即可 配置用户&#xff0c;点击编辑点击用户 点击添加&#xff0c;设置用户名&#xff…

打印9*9乘法口诀

一. main函数实现 1.参数n表示乘法口诀表总共有多少行 2.设定两个循环 外层循环控制总共有多少行 内层循环控制每行有多少个表达式以及表达式中的内容 #include<stdio.h> int main() {int n 0;scanf("%d", &n);for (int i 1; i < n; …

丢失VCRUNTIME140_1.dll怎么办,多种dll问题解决方法分享

丢失VCRUNTIME140_1.dll是许多计算机用户经常遇到的问题之一。VCRUNTIME140_1.dll是一个动态链接库文件&#xff0c;它是Visual C Redistributable Package的一部分。Visual C Redistributable Package是微软为了支持运行使用Visual C编写的软件而提供的一个可再发行组件包。当…

Django 学习教程- Hello world入门案例

系列 Django学习教程-介绍与安装 欢迎来到第Djagno学习教程第二章Hello World 入门案例。 在本教程中&#xff0c;我将引导您完成django的Hello World入门案例。 让我们开始吧&#xff01; 版本 Django 5.0Python 3.10 创建项目 安装 Django 之后&#xff0c;您现在应该…

RK3568平台开发系列讲解(Linux系统篇)PWM系统编程

🚀返回专栏总目录 文章目录 一、什么是PWM二、PWM相关节点三、PWM应用编程沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本篇将介绍 PWM 的系统编程。 一、什么是PWM PWM,即脉冲宽度调制(Pulse Width Modulation)

CSS 纵向底部往上动画

<template><div class"container" mouseenter"startAnimation" mouseleave"stopAnimation"><!-- 旋方块 --><div class"box" :class"{ scale-up-ver-bottom: isAnimating }"><!-- 元素内容 --&g…

线性代数基础知识

计算机视觉一些算法中常会用到线性代数的一些知识&#xff0c;为了便于理解和快速回忆&#xff0c;博主这边对常用的一些知识点做下整理&#xff0c;主要来源于如下这本书籍。 1. 矩阵不仅仅是数字排列而已&#xff0c;不然也不会有那么大精力研究它。其可以表示一种映射 关于…

lenovo联想拯救者8.8英寸掌上游戏机Legion Go 8APU1(83E1)原装出厂Windows11预装系统

链接&#xff1a;https://pan.baidu.com/s/1d586XWXcAWVxlLyV2Oku7Q?pwdd74t 提取码&#xff1a;d74t 系统自带所有驱动、出厂主题壁纸、Office办公软件、联想电脑管家等预装程序 所需要工具&#xff1a;16G或以上的U盘 文件格式&#xff1a;ISO 文件大小&#xff1a;…

Xgboost分类模型的完整示例

往期精彩推荐 数据科学知识库机器学习算法应用场景与评价指标机器学习算法—分类机器学习算法—回归PySpark大数据处理详细教程 定义问题 UCI的蘑菇数据集的主要目的是为了分类任务&#xff0c;特别是区分蘑菇是可食用还是有毒。这个数据集包含了蘑菇的各种特征&#xff0c;如…

vue3基础知识一,安装及使用

一、安装vue3 需要安装node&#xff0c;然后在项目所在目录命令行执行以下代码。 npm create vuelatest 回车后需要配置以下内容。 二、安装所需的依赖包并运行 cd到项目目录&#xff0c;执行以下代码安装依赖包 npm i 运行项目 npm run dev 打开浏览器查看结果 ok&#…

Linux系统安装DockerDocker-Compose

1、Docker安装 下载Docker依赖的组件 yum -y install yum-utils device-mapper-persistent-data lvm2 设置下载Docker服务的镜像源&#xff0c;设置为阿里云 yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo 安装Docker服务 …

LTPI协议的理解——4、LTPI链路初始化以及运行

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 LTPI协议的理解——4、LTPI链路初始化以及运行 前言状态图Link TrainingLink DetectLink SpeedLink Training Example Link ConfigurationAdvertiseConfigure & AcceptLi…

Git:常用命令(二)

查看提交历史 1 git log 撤消操作 任何时候&#xff0c;你都有可能需要撤消刚才所做的某些操作。接下来&#xff0c;我们会介绍一些基本的撤消操作相关的命令。请注意&#xff0c;有些操作并不总是可以撤消的&#xff0c;所以请务必谨慎小心&#xff0c;一旦失误&#xff0c…

Django 后台与便签

1. 什么是后台管理 后台管理是网页管理员利用网页的后台程序管理和更新网站上网页的内容。各网站里网页内容更新就是通过网站管理员通过后台管理更新的。 2. 创建超级用户 1. python .\manage.py createsuperuser 2. 输入账号密码等信息 Username (leave blank to use syl…

jsp结合servlet

servlet配置 环境配置2023.12.31 idea配置搭建 创建一个普通的java项目 由于新版idea去除了add framework support的ui显示&#xff0c;可以在左边项目栏中使用快捷键shiftk或者setting中搜索add framework support在修改对应的快捷键 点击ok然后应该就是下面这样的结果 这里…

大数据背景下基于联邦学习的小微企业信用风险评估研究

摘要&#xff1a; 小微企业信用风险评估难是制约其融资和发展的一个主要障碍。基于大数据的小微企业信用风险评估依然面临着单机构数据片面、跨机构数据共享难、模型不稳定等诸多挑战。针对相关问题和挑战&#xff0c;本项目拟在多主体所有权数据隐私保护与安全共享的背景下&am…

AI4Green开源ELN(电子实验记录本)

AI4Green是一个开源的电子实验记录本&#xff0c;官网&#xff1a;https://github.com/AI4Green/ai4green 国内镜像&#xff1a; skywalk163/AI4Green - AI4Green - OpenI - 启智AI开源社区提供普惠算力&#xff01; 论文地址&#xff1a;https://pubs.acs.org/doi/10.1021/…

Python开发环境[PycharmEclipseAnaconda]

Pycharm配置Python开发环境 每种语言的开发工具都有很多&#xff0c;如果写一些小的脚本或者小的工具&#xff0c;建议直接使用命令行或者Python自带的IDLE&#xff0c;如果进行大型的开发工作建议使用Pycharm&#xff0c;当然这属于个人喜好。 虽然Pycharm给了我们一个美观的…