【飞控算法】四旋翼飞行器控制原理与设计入门

2023-05-16

从动力学建模和几个四旋翼核心算法角度分析半自主飞控系统的建立,即实现传统四旋翼的姿态控制和高度控制的过程,文章主要借鉴了北航多旋翼设计课程、正点原子minifly微型四旋翼的资料、《四旋翼无人飞行器设计》清华出版社,代码示例来自正点原子。但是吧,后两个资料在理论部分都有点东拼西凑的感觉,有些错误,看起来很伤…总之,本文多处为个人理解,如有错误,感谢指出。

目录

一、相关理论知识

1.坐标系与欧拉角

2.旋转矩阵

3.四元数及其与欧拉角的关系

二、控制模型建立

1.四旋翼动力学模型

2.简化为控制模型

3.四旋翼控制分配模型

三、控制算法及实现

1.姿态解算

2.串级PID控制

3.控制分配


一、相关理论知识

1.坐标系与欧拉角

进行动力学建模之前首先建立坐标系,在此建立地球坐标系O_{e}-x_{e}y_{e}z_{e}和机体坐标系O_{b}-x_{b}y_{b}z_{b},如图所示,这里地球系z轴方向向下指向地心,机体系x轴为机头方向。

当描述一个三维空间内的刚体转动时,需要选用三个独立的角度来表示刚体的相对位置。即,刚体绕固定点的旋转可以看成是若干次旋转的合成,旋转方法不是唯一的,所以欧拉角有多种取法,不同的取法、不同的转动顺序都会对于不同的旋转矩阵。在研究四旋翼时,为了与四旋翼的滚转、俯仰、偏航相对应,可以取绕x旋转角度为φ(滚转,右滚为正),绕y轴旋转角度为θ(俯仰,仰头为正),绕z轴旋转为ψ(偏航,右偏为正)。

由地球坐标系转到机体坐标系为xyz旋转,又称卡尔丹角。实际上理论分析时,旋转顺序不是很重要,zyx、zxy都可以,虽然最后姿态解算时四元数与欧拉角的关系式不同,但是都可以进行解算。

2.旋转矩阵

绕x轴旋转的旋转矩阵为,

C_{x}(\phi )=\begin{bmatrix} 1 & 0 & 0\\ 0 &cos\phi &sin\phi \\ 0& -sin\phi & cos\phi \end{bmatrix}

绕y轴旋转的旋转矩阵为,

C_{y}(\theta )=\begin{bmatrix} \cos \theta & 0&-\sin \theta \\ 0& 1 &0 \\ \sin \theta & 0 &\cos \theta \end{bmatrix}

绕z轴旋转的旋转矩阵为,

C_{z}(\psi )=\begin{bmatrix} \cos \psi & \sin \psi &0 \\ -\sin \psi &\cos \psi&0 \\ 0& 0 &1 \end{bmatrix}

这样,xyz旋转时,一个向量由地球系的表示转为机体系的表示,可以写成,

\underset{b^{b}}{\rightarrow}=C_{z}( \phi )\cdot C_{y}(\theta )\cdot C_{x}(\phi )\cdot \underset{b^{e}}{\rightarrow}= C_{e}^{b}\cdot \underset{b^{e}}{\rightarrow}

C_{e}^{b}=\begin{bmatrix} \cos\theta \cos \psi &\sin \phi \sin \theta \cos \psi +\cos \phi \sin \psi & -\cos \phi \sin \theta \cos \psi +\sin \phi \sin \psi \\ -\cos \theta \sin \psi & -\sin \phi \sin \theta \sin \psi +\cos \phi \cos \psi & \cos \phi \sin \theta \sin \psi +\sin \phi \cos \psi \\ \sin \theta &- \sin \phi \cos \theta & \cos \phi\cos \theta \end{bmatrix}

由机体系转向地球系的姿态矩阵为,C_{b}^{e}=(C_{e}^{b})^{-1}=(C_{e}^{b})^{T}

{C_{x}(\phi )}^{-1}=C_{x}(-\phi )={C_{x}(\phi )}^{T}

3.四元数及其与欧拉角的关系

关于四元数的详细定义等参见秦永元的《惯性导航》,非常详细,这里不搬了。

以zyx旋转顺序为例,此时其旋转矩阵

C_{e}^{b}=\begin{bmatrix} \cos\theta \cos \psi &\sin \psi \cos \theta &- \sin \theta \\\sin \phi \sin \theta \cos \psi -\cos \phi \sin \psi & \sin \phi \sin \theta \sin \psi +\cos \phi \cos \psi &\sin \phi \cos \theta\\ \cos \phi \sin \theta \cos \psi +\sin \phi \sin \psi & \cos \phi \sin \theta \sin \psi -\sin \phi \cos \psi & \cos \phi\cos \theta \end{bmatrix}

此时由四元数表示的旋转为

\begin{bmatrix} x_{b}\\ y_{b} \\ z_{b} \end{bmatrix}=\begin{bmatrix} q_{0}^{2}+ q_{1}^{2}- q_{2}^{2}- q_{3}^{2}&2(q_{1}q_{2}+q_{0}q_{3}) &2(q_{1}q_{3}-q_{0}q_{2}) \\ 2(q_{1}q_{2}-q_{0}q_{3}) &q_{0}^{2}- q_{1}^{2}+q_{2}^{2}- q_{3}^{2} &2(q_{2}q_{3}+q_{0}q_{1}) \\ 2(q_{1}q_{3}+q_{0}q_{2}) & 2(q_{2}q_{3}-q_{0}q_{1}) & q_{0}^{2}-q_{1}^{2}- q_{2}^{2}+q_{3}^{2} \end{bmatrix}\begin{bmatrix} x_{e}\\ y_{e} \\ z_{e} \end{bmatrix}

这样一一对应,可以求得后面姿态解算时要用到的一些式子,

①重力在机体坐标系下的表示:

\begin{bmatrix} Vx_{b}\\ Vy_{b} \\ Vz_{b} \end{bmatrix}\\=\begin{bmatrix} q_{0}^{2}+ q_{1}^{2}- q_{2}^{2}- q_{3}^{2}&2(q_{1}q_{2}+q_{0}q_{3}) &2(q_{1}q_{3}-q_{0}q_{2}) \\ 2(q_{1}q_{2}-q_{0}q_{3}) &q_{0}^{2}- q_{1}^{2}+q_{2}^{2}- q_{3}^{2} &2(q_{2}q_{3}+q_{0}q_{1}) \\ 2(q_{1}q_{3}+q_{0}q_{2}) & 2(q_{2}q_{3}-q_{0}q_{1}) & q_{0}^{2}-q_{1}^{2}- q_{2}^{2}+q_{3}^{2} \end{bmatrix}\begin{bmatrix} 0\\0\\1\end{bmatrix} \\=\begin{bmatrix} 2(q_{1}q_{3}-q_{0}q_{2})\\ 2(q_{2}q_{3}+q_{0}q_{1}) \\ q_{0}^{2}-q_{1}^{2}- q_{2}^{2}+q_{3}^{2} \end{bmatrix}

②四元数与欧拉角的关系:

\phi =\arctan \frac{2(q_{2}q_{3}+q_{0}q_{1})}{q_{0}^{2}-q_{1}^{2}- q_{2}^{2}+q_{3}^{2}}

\theta =-\arcsin 2(q_{1}q_{3}-q_{0}q_{2})

\psi =\arctan \frac{2(q_{1}q_{2}+q_{0}q_{3})}{q_{0}^{2}+q_{1}^{2}- q_{2}^{2}-q_{3}^{2} }

四元数具体的推导和计算太多了,详见《捷联式惯性导航原理》。关于四元数与旋转矩阵我查阅了很多资料,比较官方的书呢,推导都是用的zyx旋转顺序,推出上式中四元数与欧拉角的关系。其他资料呢,有用不同的旋转顺序,但是对应旋转矩阵时很容易搞错。我觉得四元数与欧拉角的关系不是唯一的,只取决于使用的四元数,旋转顺序不同,对应的四元数自然不同。这主要影响的是解算过程中,q的值可能是不同的,但解算出的欧拉角都是一样的。

二、控制模型建立

首先,建模的目的是基于这个模型设计控制器。四旋翼是一个非线性的多输入系统,但是,为了简化处理,在小角度时,可以将模型简化为线性的,进而就可以使用线性控制的方法处理。

1.四旋翼动力学模型

①欧拉角表示为,

\dot{p}_{e}=v_{e}

\dot{v}_{e}=ge_{3}-(\tfrac{f}{m})R\cdot e_{3}

\dot{\Theta }=W\cdot \omega _{b}

J\cdot\dot{\omega _{b}}=-\omega _{b}\times (J\times \omega _{b})+G_{a}+\tau

其中,W=\frac{1}{\cos \theta }\begin{bmatrix} \cos \theta &\sin \phi \sin \theta &\cos \phi \sin \theta \\ 0&\cos \phi \cos \theta &-\sin \phi \cos \theta \\ 0 & \sin \phi &\cos \phi \end{bmatrix}

②四元数表示为,

\dot{p}_{e}=v_{e}

\dot{v}_{e}=ge_{3}-(\tfrac{f}{m})R\cdot e_{3}

\dot{q_{0}}=-\frac{1}{2}{q_{v}}^{T}\cdot \omega _{b}

\dot{q_{v}}=\frac{1}{2}(q_{0}\cdot I_{3}+\begin{bmatrix} q_{v} \end{bmatrix}_{\times })\cdot \omega _{b}

(上面两个式子实际上是四元数运动学微分方程,后面姿态解算时会用到)

J\cdot\dot{\omega _{b}}=-\omega _{b}\times (J\times \omega _{b})+G_{a}+\tau

2.简化为控制模型

在这里研究给定期望姿态角,期望高度的控制模型,这样可以分为四个通道:高度通道、俯仰通道、滚转通道、偏航通道,俯仰通道、滚转通道、偏航通道模型是一样的,是姿态模型。

①先看高度通道(z方向)的化简,

\dot{p}_{e}=v_{e}

\dot{v}_{e}=ge_{3}-(\tfrac{f}{m})R\cdot e_{3}

变为,

\dot{p}_{z}=v_{z}

\dot{v}_{z}=g-\tfrac{f}{m}(俯仰、滚转都很小时)

②再看姿态通道的化简,

\dot{\Theta }=W\cdot \omega _{b}

J\cdot\dot{\omega _{b}}=-\omega _{b}\times (J\times \omega _{b})+G_{a}+\tau

变为,

\dot{\Theta }= \omega _{b}

J\cdot\dot{\omega _{b}}=\tau(角度小,速度小时)

3.四旋翼控制分配模型

控制分配模型是建立伪控制量与实际控制量之间关系的模型,以X4型传统四旋翼为例,其伪控制量实际是几个通道经过pid之后的输出值pidout,高度通道的输出可以看做是总拉力,.姿态通道可以看成是力矩(具体分析就涉及到pid控制器的设计了);其实际控制量可以看成是电机转速的平方。这几个伪控制量与实际控制量的对应关系如下:

\begin{bmatrix} f\\ \tau _{x} \\ \tau _{y} \\ \tau _{z} \end{bmatrix}= \begin{bmatrix} c_{T} & c_{T} &c_{T} &c_{T} \\ \frac{\sqrt{2}}{2}dc_{T} &-\frac{\sqrt{2}}{2}dc_{T} &-\frac{\sqrt{2}}{2}dc_{T} & \frac{\sqrt{2}}{2}dc_{T} \\ \frac{\sqrt{2}}{2}dc_{T} &\frac{\sqrt{2}}{2}dc_{T} &-\frac{\sqrt{2}}{2}dc_{T} & -\frac{\sqrt{2}}{2}dc_{T} \\ c_{M} & c_{M} &c_{M} & c_{M} \end{bmatrix}\begin{bmatrix} {\varpi _{1}}^{2}\\ {\varpi _{2}}^{2} \\ {\varpi _{3}}^{2} \\ {\varpi _{4}}^{2} \end{bmatrix}   ,其中c_{T}是电机转速平方与拉力之间的关系系数,c_{M}是电机转速平方与反扭力之间的关系系数,d是机臂长度。

控制分配模型在普通四旋翼上的分配基本是固定的,但是当伪控制量与实际控制量个数不一致时,控制分配就很重要。

三、控制算法及实现

全自主飞控的控制逻辑是从给定期望轨迹和期望偏航开始的,首先经过这一位置控制得到期望的拉力和期望的三个姿态角,在这里,我暂不考虑轨迹控制,即飞控的逻辑是从给定期望姿态角和期望高度开始。

这样,飞控底层框架大致如下图,

图比较乱,硬件、算法、数据都在里面了,基本能看懂…可以看出,四旋翼的三个核心算法:姿态解算算法、pid控制算法、控制分配算法。

1.姿态解算

四旋翼姿态解算的方法有很多,有基于四元数,有基于旋转矩阵,有互补滤波,有卡尔曼滤波,其实不管是哪种滤波解算的算法,思想都是利用加速度计解算出得数据去修正陀螺仪积分产生偏差。在这里我主要研究了一下最常用的,四元数互补滤波,这个资料已经比较全了,每一个步骤我只记录一下我的理解。

(1)初始化四元数

static float q0 = 1.0f;	
static float q1 = 0.0f;
static float q2 = 0.0f;
static float q3 = 0.0f;	

(2)加速度计低通滤波,去除一部分高频噪声,获取加速度计、陀螺仪值

(3)加速度计测量值规范化

normalise = invSqrt(acc.x * acc.x + acc.y * acc.y + acc.z * acc.z);
acc.x *= normalise;
acc.y *= normalise;
acc.z *= normalise;

(4)提取四元数的等效余弦矩阵中的重力分量

vecxZ = 2 * (q1 * q3 - q0 * q2);
vecyZ = 2 * (q0 * q1 + q2 * q3);
veczZ = q0s - q1s - q2s + q3s;	

(5)向量叉积得出偏差

ex = (acc.y * veczZ - acc.z * vecyZ);
ey = (acc.z * vecxZ - acc.x * veczZ);
ez = (acc.x * vecyZ - acc.y * vecxZ);

(6)PI修正陀螺仪

exInt += Ki * ex * dt ;  
eyInt += Ki * ey * dt ;
ezInt += Ki * ez * dt ;
gyro.x += Kp * ex + exInt;
gyro.y += Kp * ey + eyInt;
gyro.z += Kp * ez + ezInt;

解释一下(5)、(6),首先在(3)、(4)中保证了加速度计表示的重力分量和由四元数推算出的重力分量都是单位的,这样(5)中的偏差实际上可以理解为角度,且都是在机体坐标系中,我们知道,陀螺仪虽然噪音小,但是其值会有漂移,如果通过积分计算角度,随着时间,其值会累积,这样就得不到准确值了,越偏越多,而加速度计没有漂移,但是噪音很大,且测量值稳定后,即为实际的真值。这样就考虑用加速度计去修正陀螺仪的偏差。实际上,个人理解,这里的姿态误差就可以看成是输入pi控制器的ref-fdb,而通过pi修正之后,得出的out,就可以用了消除陀螺仪的漂移。那么,既然加计是参考值,为什么不能直接置信于加计呢?这里就扯到互补的思想了,加计并不是稳定的,是一直震荡的,不平滑,但值是没有漂移的,积分不会产生大的误差,这样也可以看做是,我们取了陀螺仪稳定的优点,又取了加计没有漂移的优点。

(7)更新四元数,并归一化

q0 += (-q1 * gyro.x - q2 * gyro.y - q3 * gyro.z) * halfT;
q1 += (q0 * gyro.x + q2 * gyro.z - q3 * gyro.y) * halfT;
q2 += (q0 * gyro.y - q1 * gyro.z + q3 * gyro.x) * halfT;
q3 += (q0 * gyro.z + q1 * gyro.y - q2 * gyro.x) * halfT;

normalise = invSqrt(q0 * q0 + q1 * q1 + q2 * q2 + q3 * q3);
q0 *= normalise;
q1 *= normalise;
q2 *= normalise;
q3 *= normalise;

这里在解释一下四元数更新的算法,这个实际上就是对四元数运动学方程套用龙格库塔方法,这里的计算过程就直接搬运了,没什么好说的。

(8)解算欧拉角

这里就是之前说的欧拉角与四元数的对应关系。

state->attitude.pitch = -asinf(vecxZ) * RAD2DEG; 
state->attitude.roll = atan2f(vecyZ, veczZ) * RAD2DEG;
state->attitude.yaw = atan2f(2 * (q1 * q2 + q0 * q3),q0s + q1s - q2s - q3s) * RAD2DEG;

2.串级PID控制

PID控制器的设计是基于控制模型的,在前面说过,我们设计的PID控制如下,

①姿态环

\large \\ e_{\Theta }= \Theta _{f}-\Theta _{r} \\ \omega_{d}=K_{\Theta p}e_{\Theta }+K_{\Theta i}\int e_{\Theta }+K_{\Theta d}\dot{e_{\Theta }} \\e_{\omega }=\omega -\omega _{d}\\ \tau _{d}=K_{\omega p}e_{\omega }+K_{\omega i}\int e_{\omega }+K_{\omega d}\dot{e}_{\omega }

void attitudeRatePID(Axis3f *actualRate,attitude_t *desiredRate,control_t *output)	
{
	output->roll = pidOutLimit(pidUpdate(&pidRateRoll, desiredRate->roll - actualRate->x));
	output->pitch = pidOutLimit(pidUpdate(&pidRatePitch, desiredRate->pitch - actualRate->y));
	output->yaw = pidOutLimit(pidUpdate(&pidRateYaw, desiredRate->yaw - actualRate->z));
}

void attitudeAnglePID(attitude_t *actualAngle,attitude_t *desiredAngle,attitude_t *outDesiredRate)	
{
	outDesiredRate->roll = pidUpdate(&pidAngleRoll, desiredAngle->roll - actualAngle->roll);
	outDesiredRate->pitch = pidUpdate(&pidAnglePitch, desiredAngle->pitch - actualAngle->pitch);

	float yawError = desiredAngle->yaw - actualAngle->yaw ;
	if (yawError > 180.0f) 
		yawError -= 360.0f;
	else if (yawError < -180.0) 
		yawError += 360.0f;
	outDesiredRate->yaw = pidUpdate(&pidAngleYaw, yawError);
}

姿态环,代码实现的时候还要加入饱和,另外,遥控器模式时,实际是控制yaw的的角速率,直接用单环速率控制。

②高度环

\large \\ e_{P_{z} }= P_{zf}-P _{zr} \\v_{z}_{d}=K_{P_{z}}e_{P_{z}}\\e_{v_{z}}=v_{z} -v_{z}_{d}\\ f _{d}=K_{v_{z} p}e_{v_{z} }+K_{v_{z} i}\int e_{v_{z} }+K_{\omega d}\dot{e}_{v_{z} }

void altholdPID(float* thrust, const state_t *state, const setpoint_t *setpoint)
{
	float newThrust = 0.0;	
	
	newThrust = THRUST_SCALE * runPidZ(&posPid.pidVZ, state->position.z, setpoint, POS_UPDATE_DT);
	
	if(getCommanderKeyFlight())
		detecWeight(*thrust, newThrust, state->velocity.z);
	
	*thrust = newThrust + posPid.thrustBase;
	
	if (*thrust > 60000) 
	{
		*thrust = 60000;
	}	
}

static float runPidZ(pidAxis_t *axis, float input, const setpoint_t *setpoint, float dt) 
{
	float out = 0.f;
	if (axis->preMode == false && setpoint->isAltHold == true)
	{
		positionResetAllPID();
		axis->setpoint = input + START_HIRHT;
		posPid.thrustBase = limitThrustBase(configParam.thrustBase);
	}
	axis->preMode = setpoint->isAltHold;

	if(setpoint->isAltHold == true)
	{
		axis->setpoint += setpoint->velocity.z * dt;
		out = pidUpdate(&axis->pid, axis->setpoint - input);
	}
	return out;
}

这里minifly高度环实际也是单环。

pid更新的代码,

float pidUpdate(PidObject* pid, const float error)
{
	float output;

	pid->error = error;   

	pid->integ += pid->error * pid->dt;
	if (pid->integ > pid->iLimit)
	{
		pid->integ = pid->iLimit;
	}
	else if (pid->integ < pid->iLimitLow)
	{
		pid->integ = pid->iLimitLow;
	}

	pid->deriv = (pid->error - pid->prevError) / pid->dt;

	pid->outP = pid->kp * pid->error;
	pid->outI = pid->ki * pid->integ;
	pid->outD = pid->kd * pid->deriv;

	output = pid->outP + pid->outI + pid->outD;

	pid->prevError = pid->error;

	return output;
}

pid算法虽然都是一样的,但是基于pid控制器,不同飞控实现的方式也不太一样,这里不过多解读minifly的飞控了,后面好好学学px4的源码。

3.控制分配

传统四旋翼中,控制分配算法很简单,因为伪控制量和实际控制量的个数是相同的,编号好电机之后,相应正负,分配给电机即可。

void powerControl(control_t *control)
{
	s16 r = control->roll / 2.0f;
	s16 p = control->pitch / 2.0f;
	
	motorPWM.m1 = limitThrust(control->thrust - r - p + control->yaw);
	motorPWM.m2 = limitThrust(control->thrust - r + p - control->yaw);
	motorPWM.m3 = limitThrust(control->thrust + r + p + control->yaw);
	motorPWM.m4 = limitThrust(control->thrust + r - p - control->yaw);	
}

传统四旋翼的控制量是四个,在一个三维控制内,自由度有六个,这样的控制就是欠驱动的。如果我的伪控制量有六个,实际控制量也有六个,那我可以实现三维空间内的解耦控制。如果我的伪控制量有六个,实际控制量大于六个,且这六个控制量可以实现对,六个伪控制量做的事情。后面两个种情况控制分配就很重要了,包括六轴啊这种,四个伪控制量,六个实际控制量,也需要合理的控制分配。关于控制分配呢,需要思考的还很多,在这里不多说了。

 

结语:总之呢,关于四旋翼涉及的面太广了,这里只是把大致框架整理了一下,其实实现四旋翼控制的方法有很多,这里都是最简单的,像水平环的控制,解算时其他一些传感器的融合啊等等都还没说,一些更深入的东西也还没太研究明白,后面继续研究……

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

【飞控算法】四旋翼飞行器控制原理与设计入门 的相关文章

  • 再读 ucosII源码(邵贝贝):任务之间的通讯与同步--邮箱

    邮箱简介 xff1a 邮箱是 C OS II中另一种通讯机制 xff0c 它可以使一个任务或者中断服务子程序向另一个任务发送一个指针型的变量 该指针指向一个包含了特定 消息 的数据结构 为了在 C OS II中使用邮箱 xff0c 必须将O
  • 阿里云ubuntu 16.04安装图形界面

    1 VNC的安装与配置 安装之前先输入 span class pln apt span span class pun span span class kwd span class hljs keyword get span span spa
  • cmake/makefile 获取git版本信息并传入源码输出

    CMake获取git commitId CMakeLists txt cmake minimum required VERSION 2 8 project test set SRCS main cpp 执行git命令 xff0c 并把结果重
  • 为什么使用static的类方法不需要new

    文章目录 JAVA加载过程static静态成员从static学习java编译过程JVM加载顺序摘要 xff1a 稍稍延申一下 xff1a 对于此java给出了两个解决方案 xff1a 总结static下面说说静态的特点 xff1a 实例变量
  • CMake引入三方库

    做移动端的NDK开发经常需要引入三方库 xff0c 本文以常见的JSON库为例进行说明 jsoncpp源码下载地址https github com open source parsers jsoncpp 下载1 9 5的tag 1 纯源码依
  • C++中泛型算法详解5:面向泛型算法的迭代器类别

    前言 任何算法最基本的特性是要求迭代器提供那些操作 根据算法要求的迭代器操作 xff0c 可以分为如下迭代器类别 xff1a 1 input iterator 2 output iterator 3 forward iterator 4 b
  • CMake&CMakeList.txt

    1 各种关系 在各种开源项目中 xff0c 经常会发现项目中除了代码源文件 xff0c 还包含了 CMakeList txt Makefile 文件 xff0c 在项目的编译时候需要用到的命令有 cmake make 我们本次想搞清楚他们之
  • 使用Docker制作镜像并推送到镜像仓库

    本文会告诉你如何使用docker从远端下载一个镜像 xff0c 然后对镜像做修改 xff0c 最后再把镜像推送到你自己的镜像仓库 1 安装Docker 这个没啥说的 xff0c 根据你自己的环境下载对应的安装包安装就是了 docker官网下
  • Mac上几款免费的MySql客户端

    由于开发需要在Mac上连接MySql数据库 xff0c 虽然命令行也能用 xff0c 但是我还是喜欢用带UI的客户端去连 就用过的mysql客户端来说 xff0c 最好用的是Navicate xff0c 不过后来收费了 xff0c 还收的贼
  • Mac M1芯片安装 Numpy Pandas

    本文教你如何简单的在M1芯片的MacBook上安装Numpy和Pandas 刚入手了一个Mac Pro xff0c 是M1芯片的 xff0c 结果在安装Numpy和Pandas时遇到了各种莫名奇妙的问题 第1种报错 xff0c 很长 xff
  • addr2line

    1 符号表 1 1什么是符号表 符号表是内存地址与函数名 文件名 行号的映射表 符号表元素如下所示 xff1a lt 起始地址 gt lt 结束地址 gt lt 函数 gt lt 文件名 行号 gt 1 2为什么要配置符号表 为了能快速并准
  • 一些有用的Python库

    1 制作动态排序图的库 做出来像这种效果 https mp weixin qq com s DQf35t7PUcFmi3j942Q7A 2 基于matplotlib轻松绘制漂亮的表格 比自己在ppt或者excel中搞出来的表格好看多了 像这
  • Android创建杀不死的Service

    在Android开发中我们经常会遇到一些特殊的需求需要让我们的服务常驻内存 xff0c 但是会遇到各种清理软件或者用户在设置中手动停止程序的情况而导致我们的服务被异常的终止掉 虽然没有办法保证绝对的常驻内存 xff0c 但是通过策略我们还是
  • Mac 从Bash切换到Zsh的注意事项

    1 第一步要安装Zsh xff0c 可以参考现成的文章 xff0c 推荐一篇https zhuanlan zhihu com p 19556676 2 安装完成之后退出命令行重新进入 xff0c 就可以看到Zsh的效果啦 3 及得切换默认的
  • 数组求实际长度(逻辑长度)

    有很多情况下 xff0c 比如我们定义了一个数组 xff0c byte a 61 new byte 100 但是给数组赋值的时候只赋了10个 xff0c 虽然这个数组在内存中的长度仍然是100 xff0c 但是我们想得到的确实数组的实际长度
  • java清空数组

    定义一个数字byte a 61 new byte 20 如果给数组赋值后又想让数组恢复到初始的状态 xff0c 那如何做呢 xff0c 其实很简单 xff0c 直接上方法 将byte数组置空 public static byte reset
  • 使用gazebo的官方模型库文件

    首先下载所有的gazebo模型库文件 xff0c 我已经打包上传到csdn了 xff0c 可以从如下链接中下载 xff1a 下载link 然后将下载好的文件存放在如下目录 xff1a cd gazebo models 如果没有上述目录就自行
  • 作为一个普通的程序员,到底应不应该转型AI工程师?

    动不动就是50万的毕业生年薪 xff0c 动不动就是100万起步价的海归AI高级人才 xff0c 普通员到底应不应该转型AI工程师 xff0c 普通程序员到底应该如何转型AI工程师 xff1f 下面就分享几个特别典型的普通程序员成功转型AI
  • 树莓派Odroid等卡片式电脑上搭建NAS教程系列1-Ubuntu系统安装

    我用的是韩国hardkernel公司做的Odroid XU板子 xff0c 类似于树莓派香蕉派 xff0c 看下它的真面目 相关参数点他 gt Odroid XU 搭建NAS之前先来安装好Ubuntu系统 下载安装文件 在Odroid里安装
  • 立创eda学习笔记一:pcb板基础知识

    整理了一下零基础学习pcb板画图需要了解的一些基础知识 xff0c 否则后面画图很困扰 什么是pcb板 xff1f PCB xff08 Printed Circuit Board xff09 xff0c 中文名称为印制电路板 xff0c 又

随机推荐

  • 立创eda学习笔记二:画pcb板流程(极简入门版)

    一般PCB基本设计流程如下 xff1a 前期准备 gt PCB结构设计 gt PCB布局 gt 布线 gt 布线优化和丝印 gt 网络和DRC检查和结构检查 gt 制版 一 画原理图 完成后检查元件的封装 连线是否正确 核实电路结构 xff
  • 立创eda学习笔记十一:立创eda、立创商城、嘉立创的区别

    简单来说 xff1a 立创eda是一个画原理图和pcb的eda软件 xff0c 类似于ad 立创商城是一个卖元器件网上平台 xff0c 类似于淘宝 嘉立创是一个生产pcb板 给pcb板贴片的生产厂家 一般情况下 xff0c 你可以在立创ed
  • 立创eda学习笔记十七:铺铜

    铺铜是pcb设计很常用的指令 xff0c 或者是必然用到的指令 xff0c 很多时候布线的时候不去画gnd的线 xff0c 把其他线画好了之后 xff0c 再统一铺铜作为gnd xff0c 这样方便很多 铺铜这个概念可以理解为大面积的布线
  • 立创eda学习笔记二十六:手把手教你使用立创eda的官方教程

    可以通过以下办法找到教程 xff1a 1 xff0c 在软件界面点帮助 使用教程 2 xff0c 在网站首页 帮助 教程进入 如何使用教程 xff1a 这里是一级目录 xff0c 其实对新手最有用的是前面3个部分 xff0c 后面的仿真先不
  • 立创eda学习笔记二十四:拼板

    这里主要是两部分 xff1a 自带拼板和手动拼板 xff0c 软件自带拼板功能 xff0c 那么手动拼板当然就是自己重新画图拼板了 一般用自带拼板功能就可以了 xff0c 把单板画好之后很容易就拼好了 xff0c 完全不用动任何器件和丝印编
  • Prometheus实战教程:监控mysql数据库

    今天我们使用prometheus 43 Grafana 43 mysql exporter实现监控mysql数据库各项指标数据 mysql exporter xff1a 采集mysql数据库各项指标数据 prometheus xff1a 获
  • prometheus常用exporter下载地址大全

    1 node exporter下载 https github com prometheus node exporter releases 2 blackbox exporter下载 https github com prometheus b
  • 论文润色 ‖ 一分钟教你如何写好SCI论文里的主题句,事半功倍

    今天 xff0c 小编来分享一下论文润色 xff0c SCI论文的主题句 xff08 Topic Sentences xff09 怎么写 xff1a 01什么是主题句 xff1f 主题句通常是段落开头的一句话 xff0c 是整个段落的小主题
  • Go xml文件处理

    在开发中会常遇到xml数据序列化和反序列化 xff0c 这里我们介绍go语言处理xml数据 encoding xml 包实现了一个简单的xml 1 0解析器 xff0c 可以理解xml名称空间 读取xml 示例 xff1a package
  • UC/OS-III 消息队列

    消息队列 一 消息队列基本概念讲解1 消息队列基本概念2 消息池2 1 消息池概念2 2 消息池初始化2 3 消息队列的运作机制2 4 消息队列的阻塞机制2 5 消息队列的应用场景 二 消息队列创建步骤1 定义消息队列2 创建消息队列 三
  • Altium Designer绘制stm32f103c8t6最小系统原理图

    文章目录 前言芯片封装自定义封装原理图绘制总结 前言 本文提供了初学者绘制stm32最小系统 xff0c 同时初学者的同学可以跟着小白学习绘制原理图哦 芯片封装 提示 xff1a 下载安装好Altium Designer之后才能进行以下操作
  • Jetson Xavier NX安装opencv3.x以及踩过的坑

    Jetson Xavier NX默认安装的是opencv4 x xff0c 在很多项目中其与opencv3 x xff0c 其中opencv3与opencv4中有部分函数是完全不同的 xff08 例如点一些Point的定义 xff0c Cv
  • 【导航算法】无人机路径跟踪L1导航算法

    L1导航算法是非常经典的非线性无人机路径跟随算法 xff0c 最早由MIT于2004年提出 xff0c 论文为 A New Nonlinear Guidance Logic for Trajectory Tracking xff0c 其导航
  • 【人工智能】1.问题求解:状态空间图和盲目搜索

    什么是问题求解 xff1f 问题求解可以理解为利用知识 xff0c 尽可能有效的找到问题的解 xff0c 或者最优解的过程 xff0c 主要包括 xff1a 1 xff09 问题描述方法 xff1a 状态空间法 xff0c 与或树表示法 x
  • 【路径规划】A*三维全局路径规划(附Python实现源码)

    1 A 启发式搜索 A 算法介绍 xff1a 启发式搜索算法 xff0c 除了wiki之外比较全的一个参考资料 xff1a A 启发式搜索算法详解 人工智能 这里是用Python写了一个简单的路径规划例子供参考 2 Matplotlib库
  • 【数据结构】3.图、最小生成树

    一 图的基本概念 1 什么是图 图表示一种多对多的关系 图包括 xff1a 1 xff09 一组顶点 xff1a 通常用 V Vertex 表示顶点集合 2 xff09 一组边 xff1a 通常用 E Edge 表示边的集合 3 xff09
  • 【NLP】主题模型文本分类

    自然语言处理之主题模型文本分类 LDA主题模型 1 主题模型 xff08 Topic Model xff09 主题模型是以非监督学习的方式对文集的隐含语义结构进行聚类的统计模型 主题模型主要被用于自然语言处理中的语义分析和文本挖掘问题 xf
  • 【NLP】Word2Vec模型文本分类

    自然语言处理之词向量模型聚类分析 Word Embedding 词嵌入向量 Word Embedding 是NLP里面一个重要的概念 xff0c 我们可以利用Word Embedding一个单词固定长度向量的表示一种表示形式 Word Em
  • (6.1)Kubernetes的Sevice服务间调用

    1 场景1 选择器 xff08 selector xff09 在k8s上运行了两个pod replicas 2 我们通过Service来整合这两个pod 在创建 Service 时 xff0c 就要通过选择器 xff08 selector
  • 【飞控算法】四旋翼飞行器控制原理与设计入门

    从动力学建模和几个四旋翼核心算法角度分析半自主飞控系统的建立 xff0c 即实现传统四旋翼的姿态控制和高度控制的过程 xff0c 文章主要借鉴了北航多旋翼设计课程 正点原子minifly微型四旋翼的资料 四旋翼无人飞行器设计 清华出版社 x