《MATLAB实战训练营:从入门到工业级应用》高阶挑战篇-《用无人机仿真玩转PID控制:MATLAB四旋翼仿真建模全攻略》
《MATLAB实战训练营:从入门到工业级应用》高阶挑战篇-✈️ 用无人机仿真玩转PID控制:MATLAB四旋翼仿真建模全攻略 🚁
欢迎来到这篇超级详细的MATLAB四旋翼无人机仿真教程!无论你是控制理论爱好者、无人机发烧友,还是MATLAB编程新手,这篇文章都将带你从零开始,一步步构建一个完整的四旋翼无人机PID控制系统仿真模型。准备好开始这场空中冒险了吗?让我们开始这段有趣的旅程吧!Let’s go! 🎯
1. 四旋翼无人机基础入门 🚀
1.1 四旋翼无人机的工作原理
四旋翼无人机,顾名思义就是有四个旋翼的飞行器 ✨。它的飞行原理其实非常有趣:
- 四个电机(M1-M4)呈十字形排列
- 对角电机旋转方向相同(M1和M3同向,M2和M4同向)
- 通过改变四个电机的转速来实现各种飞行动作
1.2 基本运动控制
四旋翼有6个自由度,但只有4个控制输入(四个电机的转速),属于欠驱动系统。基本运动控制包括:
运动类型 | 控制方法 | 示意图 |
---|---|---|
垂直运动(升降) | 同时增加/减少所有电机转速 | ⬆️⬇️ |
俯仰运动(前后) | 增加前部/后部电机转速 | ✈️→ |
横滚运动(左右) | 增加左侧/右侧电机转速 | 🚁←→ |
偏航运动(旋转) | 增加对角线电机转速 | 🔄 |
💡 有趣的事实:四旋翼无人机本质上是一个不稳定的系统,这正是我们需要PID控制的原因!
2. 数学模型建立 📐
要仿真四旋翼,首先需要建立它的数学模型。我们采用牛顿-欧拉方程来描述四旋翼的动力学。
2.1 坐标系定义
我们定义两个坐标系:
- 地面坐标系(惯性系):固定在地面,用于描述无人机的位置
- 机体坐标系:固定在无人机上,随无人机一起运动
2.2 动力学方程
四旋翼的6自由度动力学方程可以表示为:
平移运动:
m d 2 x d t 2 = ( sin ψ sin ϕ + cos ψ sin θ cos ϕ ) U 1 m \frac{d^2x}{dt^2} = (\sin\psi \sin\phi + \cos\psi \sin\theta \cos\phi) U_1\ mdt2d2x=(sinψsinϕ+cosψsinθcosϕ)U1
m d 2 y d t 2 = ( − cos ψ sin ϕ + sin ψ sin θ cos ϕ ) U 1 m \frac{d^2y}{dt^2} = (-\cos\psi \sin\phi + \sin\psi \sin\theta \cos\phi) U_1 mdt2d2y=(−cosψsinϕ+sinψsinθcosϕ)U1
m d 2 z d t 2 = − m g + ( cos θ cos ϕ ) U 1 m \frac{d^2z}{dt^2} = -mg + (\cos\theta \cos\phi) U_1 mdt2d2z=−mg+(cosθcosϕ)U1
旋转运动:
I x x d 2 ϕ d t 2 = θ ˙ ψ ˙ ( I y y − I z z ) + l U 2 I_{xx} \frac{d^2\phi}{dt^2} = \dot{\theta}\dot{\psi}(I_{yy} - I_{zz}) + l U_2 Ixxdt2d2ϕ=θ˙ψ˙(Iyy−Izz)+lU2
I y y d 2 θ d t 2 = ϕ ˙ ψ ˙ ( I z z − I x x ) + l U 3 I_{yy} \frac{d^2\theta}{dt^2} = \dot{\phi}\dot{\psi}(I_{zz} - I_{xx}) + l U_3 Iyydt2d2θ=ϕ˙ψ˙(Izz−Ixx)+lU3
I z z d 2 ψ d t 2 = ϕ ˙ θ ˙ ( I x x − I y y ) + U 4 I_{zz} \frac{d^2\psi}{dt^2} = \dot{\phi}\dot{\theta}(I_{xx} - I_{yy}) + U_4 Izzdt2d2ψ=ϕ˙θ˙(Ixx−Iyy)+U4
其中:
m
:无人机质量l
:电机到质心的距离Ixx, Iyy, Izz
:转动惯量U₁-U₄
:控制输入
2.3 控制输入与电机转速关系
控制输入与电机转速的关系为:
[ U 1 U 2 U 3 U 4 ] = [ 1 1 1 1 0 − l 0 l l 0 − l 0 c − c c − c ] [ F 1 F 2 F 3 F 4 ] \begin{bmatrix} U_1 \\ U_2 \\ U_3 \\ U_4 \end{bmatrix} = \begin{bmatrix} 1 & 1 & 1 & 1 \\ 0 & -l & 0 & l \\ l & 0 & -l & 0 \\ c & -c & c & -c \end{bmatrix} \begin{bmatrix} F_1 \\ F_2 \\ F_3 \\ F_4 \end{bmatrix} U1U2U3U4 = 10lc1−l0−c10−lc1l0−c F1F2F3F4
其中F₁-F₄
是四个电机产生的升力,c
是反扭矩系数。
3. MATLAB仿真环境搭建 💻
现在让我们开始用MATLAB搭建仿真环境吧!
3.1 初始化参数
首先创建一个新的MATLAB脚本quadcopter_sim.m
,并添加以下初始化代码:
clear all; close all; clc;%% 无人机物理参数
params.m = 1.2; % 质量(kg)
params.g = 9.81; % 重力加速度(m/s^2)
params.l = 0.25; % 电机到质心的距离(m)% 转动惯量(kg·m^2)
params.Ixx = 0.0234;
params.Iyy = 0.0234;
params.Izz = 0.0468;params.c = 0.01; % 反扭矩系数
params.k = 1.2e-5; % 升力系数
params.b = 1e-6; % 阻力系数%% 仿真参数
tspan = [0 20]; % 仿真时间范围
params.dt = 0.01; % 时间步长(s)
t = tspan(1):params.dt:tspan(2);%% 初始状态
% [x y z x_dot y_dot z_dot phi theta psi phi_dot theta_dot psi_dot]
initial_state = zeros(12,1); % 全部初始化为0
3.2 实现动力学方程
创建一个函数文件quadcopter_ode.m
来实现动力学方程:
function state_dot = quadcopter_ode(t, state, params, U)% 解包状态变量x = state(1); y = state(2); z = state(3);x_dot = state(4); y_dot = state(5); z_dot = state(6);phi = state(7); theta = state(8); psi = state(9);phi_dot = state(10); theta_dot = state(11); psi_dot = state(12);% 解包控制输入U1 = U(1); U2 = U(2); U3 = U(3); U4 = U(4);% 平移加速度x_ddot = (sin(psi)*sin(phi) + cos(psi)*sin(theta)*cos(phi)) * U1 / params.m;y_ddot = (-cos(psi)*sin(phi) + sin(psi)*sin(theta)*cos(phi)) * U1 / params.m;z_ddot = -params.g + (cos(theta)*cos(phi)) * U1 / params.m;% 旋转加速度phi_ddot = theta_dot*psi_dot*(params.Iyy-params.Izz)/params.Ixx + params.l*U2/params.Ixx;theta_ddot = phi_dot*psi_dot*(params.Izz-params.Ixx)/params.Iyy + params.l*U3/params.Iyy;psi_ddot = phi_dot*theta_dot*(params.Ixx-params.Iyy)/params.Izz + U4/params.Izz;% 组装状态导数state_dot = zeros(12,1);state_dot(1) = x_dot;state_dot(2) = y_dot;state_dot(3) = z_dot;state_dot(4) = x_ddot;state_dot(5) = y_ddot;state_dot(6) = z_ddot;state_dot(7) = phi_dot;state_dot(8) = theta_dot;state_dot(9) = psi_dot;state_dot(10) = phi_ddot;state_dot(11) = theta_ddot;state_dot(12) = psi_ddot;
end
4. PID控制器设计 🎛️
现在我们来设计PID控制器,让无人机能够稳定飞行!
4.1 PID控制原理
PID控制器由三部分组成:
- 比例§:与当前误差成正比
- 积分(I):与误差的积分成正比,消除稳态误差
- 微分(D):与误差的变化率成正比,提供阻尼
PID控制器的输出公式为:
u ( t ) = K p e ( t ) + K i ∫ e ( t ) d t + K d d e ( t ) d t u(t) = K_p e(t) + K_i \int e(t) \, dt + K_d \frac{de(t)}{dt} u(t)=Kpe(t)+Ki∫e(t)dt+Kddtde(t)
4.2 实现PID控制器
创建一个函数文件pid_controller.m
:
function [U, errors, integral_errors] = pid_controller(state, desired_state, ...params, prev_errors, integral_errors)% PID参数Kp_z = 10; Ki_z = 2; Kd_z = 5; % 高度控制Kp_phi = 8; Ki_phi = 0.5; Kd_phi = 3; % 横滚控制Kp_theta = 8; Ki_theta = 0.5; Kd_theta = 3; % 俯仰控制Kp_psi = 8; Ki_psi = 0.5; Kd_psi = 3; % 偏航控制% 解包当前状态z = state(3); z_dot = state(6);phi = state(7); phi_dot = state(10);theta = state(8); theta_dot = state(11);psi = state(9); psi_dot = state(12);% 解包期望状态z_des = desired_state(3); z_dot_des = desired_state(6);phi_des = desired_state(7); phi_dot_des = desired_state(10);theta_des = desired_state(8); theta_dot_des = desired_state(11);psi_des = desired_state(9); psi_dot_des = desired_state(12);% 计算误差errors = zeros(4,1);errors(1) = z_des - z; % 高度误差errors(2) = phi_des - phi; % 横滚误差errors(3) = theta_des - theta; % 俯仰误差errors(4) = psi_des - psi; % 偏航误差% 计算误差导数error_dots = (errors - prev_errors) / params.dt;% 更新积分误差integral_errors = integral_errors + errors * params.dt;% 计算PID输出U1 = Kp_z * errors(1) + Ki_z * integral_errors(1) + Kd_z * error_dots(1);U2 = Kp_phi * errors(2) + Ki_phi * integral_errors(2) + Kd_phi * error_dots(2);U3 = Kp_theta * errors(3) + Ki_theta * integral_errors(3) + Kd_theta * error_dots(3);U4 = Kp_psi * errors(4) + Ki_psi * integral_errors(4) + Kd_psi * error_dots(4);% 限制控制输入U1 = max(min(U1, params.m*params.g*2), 0); % U1不能为负U2 = max(min(U2, 5), -5);U3 = max(min(U3, 5), -5);U4 = max(min(U4, 5), -5);U = [U1; U2; U3; U4];
end
5. 仿真主循环 🔄
现在我们把所有部分整合到一起,完成仿真主循环:
%% 初始化
state = initial_state;
states = zeros(length(t), length(state));
states(1,:) = state';
desired_state = [0; 0; 2; 0; 0; 0; 0; 0; 0; 0; 0; 0]; % 期望高度2米% PID控制器初始化
prev_errors = zeros(4,1);
integral_errors = zeros(4,1);%% 主仿真循环
for i = 1:length(t)-1% 获取当前控制输入[U, errors, integral_errors] = pid_controller(state, desired_state, ...params, prev_errors, integral_errors);prev_errors = errors;% 使用ode45求解ODE[~, temp_state] = ode45(@(t,state) quadcopter_ode(t, state, params, U), ...[t(i) t(i+1)], state);state = temp_state(end,:)';% 存储状态states(i+1,:) = state';% 显示进度if mod(i,100) == 0fprintf('仿真进度: %.1f%%\n', i/length(t)*100);end
endfprintf('仿真完成!\n');
6. 结果可视化 📊
仿真完成后,我们需要可视化结果来评估控制器的性能:
6.1 绘制3D轨迹
%% 3D轨迹图
figure('Name', '3D轨迹', 'Color', 'white');
plot3(states(:,1), states(:,2), states(:,3), 'b', 'LineWidth', 2);
hold on;
plot3(0, 0, desired_state(3), 'ro', 'MarkerSize', 10, 'MarkerFaceColor', 'r');
grid on;
xlabel('X (m)'); ylabel('Y (m)'); zlabel('Z (m)');
title('四旋翼无人机3D轨迹');
legend('实际轨迹', '目标位置');
view(30,30);
6.2 绘制高度变化曲线
%% 高度变化图
figure('Name', '高度控制', 'Color', 'white');
plot(t, states(:,3), 'b', 'LineWidth', 2);
hold on;
plot(t, desired_state(3)*ones(size(t)), 'r--', 'LineWidth', 2);
grid on;
xlabel('时间 (s)'); ylabel('高度 (m)');
title('高度控制响应');
legend('实际高度', '期望高度');
6.3 绘制姿态角变化
%% 姿态角变化图
figure('Name', '姿态角', 'Color', 'white', 'Position', [100 100 1200 800]);subplot(3,1,1);
plot(t, rad2deg(states(:,7)), 'b', 'LineWidth', 2);
grid on;
xlabel('时间 (s)'); ylabel('横滚角 (deg)');
title('横滚角响应');subplot(3,1,2);
plot(t, rad2deg(states(:,8)), 'b', 'LineWidth', 2);
grid on;
xlabel('时间 (s)'); ylabel('俯仰角 (deg)');
title('俯仰角响应');subplot(3,1,3);
plot(t, rad2deg(states(:,9)), 'b', 'LineWidth', 2);
grid on;
xlabel('时间 (s)'); ylabel('偏航角 (deg)');
title('偏航角响应');
由上面三张图可以发现,这些轨迹比较理想,然而实际情况中比这会复杂很多,比如风的作用、传感器产生噪声数据等等,别急,我们继续往下看。
7. 参数调优技巧 🛠️
PID控制器的性能很大程度上取决于参数的选取。这里分享一些调参技巧:
7.1 调参步骤
- 先调P:将I和D设为0,逐渐增大P直到系统开始振荡
- 再调D:增加D来抑制振荡,使系统稳定
- 最后调I:如果需要消除稳态误差,适当增加I
7.2 Ziegler-Nichols方法
这是一种经典的PID参数整定方法:
- 先设Ki=Kd=0
- 增加Kp直到系统开始等幅振荡,记录此时的Kp=Ku和振荡周期Tu
- 根据下表设置PID参数:
控制器类型 | Kp | Ti | Td |
---|---|---|---|
P | 0.5Ku | - | - |
PI | 0.45Ku | 0.83Tu | - |
PID | 0.6Ku | 0.5Tu | 0.125Tu |
7.3 我们的参数建议
对于四旋翼无人机,以下参数可以作为起点:
% 高度控制
Kp_z = 10; Ki_z = 2; Kd_z = 5;% 姿态控制
Kp_angle = 8; Ki_angle = 0.5; Kd_angle = 3;
8. 进阶内容:添加风扰和噪声 🌬️
为了让仿真更接近现实,我们可以添加一些环境干扰:
8.1 修改ODE函数添加风扰
function state_dot = quadcopter_ode(t, state, params, U)% ... (之前的代码保持不变)% 添加随机风扰 (在x和y方向)wind_gain = 0.2; % 风扰强度if t > 5 % 5秒后开始添加风扰x_ddot = x_ddot + wind_gain*randn();y_ddot = y_ddot + wind_gain*randn();end% ... (其余代码保持不变)
end
8.2 添加传感器噪声
在控制器中模拟传感器噪声:
function [U, errors, integral_errors] = pid_controller(state, desired_state, ...params, prev_errors, integral_errors)% 添加传感器噪声noise_gain = 0.02;state(3) = state(3) + noise_gain*randn(); % 高度噪声state(7:9) = state(7:9) + noise_gain*randn(3,1); % 姿态角噪声% ... (其余代码保持不变)
end
9. 完整代码整合 🏗️
为了便于使用,这里提供完整的整合代码。创建一个名为quadcopter_sim.m
的文件:
% 四旋翼无人机PID控制仿真 - 完整代码
% 作者: MATLAB技术大本营
% 日期: 2023年
% 版本: MATLAB 2016bfunction quadcopter_sim()%% 初始化参数clear all; close all; clc;% 无人机物理参数params.m = 1.2; % 质量(kg)params.g = 9.81; % 重力加速度(m/s^2)params.l = 0.25; % 电机到质心的距离(m)% 转动惯量(kg·m^2)params.Ixx = 0.0234;params.Iyy = 0.0234;params.Izz = 0.0468;params.c = 0.01; % 反扭矩系数params.k = 1.2e-5; % 升力系数params.b = 1e-6; % 阻力系数% 仿真参数tspan = [0 20]; % 仿真时间范围params.dt = 0.01; % 时间步长(s)t = tspan(1):params.dt:tspan(2);% 初始状态 [x y z x_dot y_dot z_dot phi theta psi phi_dot theta_dot psi_dot]initial_state = zeros(12,1);% 期望状态 [x y z x_dot y_dot z_dot phi theta psi phi_dot theta_dot psi_dot]desired_state = [0; 0; 2; 0; 0; 0; 0; 0; 0; 0; 0; 0]; % 期望高度2米%% 初始化仿真state = initial_state;states = zeros(length(t), length(state));states(1,:) = state';% PID控制器初始化prev_errors = zeros(4,1);integral_errors = zeros(4,1);%% 主仿真循环for i = 1:length(t)-1% 获取当前控制输入[U, errors, integral_errors] = pid_controller(state, desired_state, ...params, prev_errors, integral_errors);prev_errors = errors;% 使用ode45求解ODE[~, temp_state] = ode45(@(t,state) quadcopter_ode(t, state, params, U), ...[t(i) t(i+1)], state);state = temp_state(end,:)';% 存储状态states(i+1,:) = state';% 显示进度if mod(i,100) == 0fprintf('仿真进度: %.1f%%\n', i/length(t)*100);endendfprintf('仿真完成!\n');%% 可视化结果plot_results(t, states, desired_state);
endfunction state_dot = quadcopter_ode(t, state, params, U)% 解包状态变量x = state(1); y = state(2); z = state(3);x_dot = state(4); y_dot = state(5); z_dot = state(6);phi = state(7); theta = state(8); psi = state(9);phi_dot = state(10); theta_dot = state(11); psi_dot = state(12);% 解包控制输入U1 = U(1); U2 = U(2); U3 = U(3); U4 = U(4);% 平移加速度x_ddot = (sin(psi)*sin(phi) + cos(psi)*sin(theta)*cos(phi)) * U1 / params.m;y_ddot = (-cos(psi)*sin(phi) + sin(psi)*sin(theta)*cos(phi)) * U1 / params.m;z_ddot = -params.g + (cos(theta)*cos(phi)) * U1 / params.m;% 添加随机风扰 (在x和y方向)wind_gain = 0.2; % 风扰强度if t > 5 % 5秒后开始添加风扰x_ddot = x_ddot + wind_gain*randn();y_ddot = y_ddot + wind_gain*randn();end% 旋转加速度phi_ddot = theta_dot*psi_dot*(params.Iyy-params.Izz)/params.Ixx + params.l*U2/params.Ixx;theta_ddot = phi_dot*psi_dot*(params.Izz-params.Ixx)/params.Iyy + params.l*U3/params.Iyy;psi_ddot = phi_dot*theta_dot*(params.Ixx-params.Iyy)/params.Izz + U4/params.Izz;% 组装状态导数state_dot = zeros(12,1);state_dot(1) = x_dot;state_dot(2) = y_dot;state_dot(3) = z_dot;state_dot(4) = x_ddot;state_dot(5) = y_ddot;state_dot(6) = z_ddot;state_dot(7) = phi_dot;state_dot(8) = theta_dot;state_dot(9) = psi_dot;state_dot(10) = phi_ddot;state_dot(11) = theta_ddot;state_dot(12) = psi_ddot;
endfunction [U, errors, integral_errors] = pid_controller(state, desired_state, ...params, prev_errors, integral_errors)% PID参数Kp_z = 10; Ki_z = 2; Kd_z = 5; % 高度控制Kp_phi = 8; Ki_phi = 0.5; Kd_phi = 3; % 横滚控制Kp_theta = 8; Ki_theta = 0.5; Kd_theta = 3; % 俯仰控制Kp_psi = 8; Ki_psi = 0.5; Kd_psi = 3; % 偏航控制% 添加传感器噪声noise_gain = 0.02;state(3) = state(3) + noise_gain*randn(); % 高度噪声state(7:9) = state(7:9) + noise_gain*randn(3,1); % 姿态角噪声% 解包当前状态z = state(3); z_dot = state(6);phi = state(7); phi_dot = state(10);theta = state(8); theta_dot = state(11);psi = state(9); psi_dot = state(12);% 解包期望状态z_des = desired_state(3); z_dot_des = desired_state(6);phi_des = desired_state(7); phi_dot_des = desired_state(10);theta_des = desired_state(8); theta_dot_des = desired_state(11);psi_des = desired_state(9); psi_dot_des = desired_state(12);% 计算误差errors = zeros(4,1);errors(1) = z_des - z; % 高度误差errors(2) = phi_des - phi; % 横滚误差errors(3) = theta_des - theta; % 俯仰误差errors(4) = psi_des - psi; % 偏航误差% 计算误差导数error_dots = (errors - prev_errors) / params.dt;% 更新积分误差integral_errors = integral_errors + errors * params.dt;% 计算PID输出U1 = Kp_z * errors(1) + Ki_z * integral_errors(1) + Kd_z * error_dots(1);U2 = Kp_phi * errors(2) + Ki_phi * integral_errors(2) + Kd_phi * error_dots(2);U3 = Kp_theta * errors(3) + Ki_theta * integral_errors(3) + Kd_theta * error_dots(3);U4 = Kp_psi * errors(4) + Ki_psi * integral_errors(4) + Kd_psi * error_dots(4);% 限制控制输入U1 = max(min(U1, params.m*params.g*2), 0); % U1不能为负U2 = max(min(U2, 5), -5);U3 = max(min(U3, 5), -5);U4 = max(min(U4, 5), -5);U = [U1; U2; U3; U4];
endfunction plot_results(t, states, desired_state)%% 3D轨迹图figure('Name', '3D轨迹', 'Color', 'white', 'Position', [100 100 800 600]);plot3(states(:,1), states(:,2), states(:,3), 'b', 'LineWidth', 2);hold on;plot3(0, 0, desired_state(3), 'ro', 'MarkerSize', 10, 'MarkerFaceColor', 'r');grid on;xlabel('X (m)'); ylabel('Y (m)'); zlabel('Z (m)');title('四旋翼无人机3D轨迹');legend('实际轨迹', '目标位置');view(30,30);%% 高度变化图figure('Name', '高度控制', 'Color', 'white', 'Position', [200 200 800 400]);plot(t, states(:,3), 'b', 'LineWidth', 2);hold on;plot(t, desired_state(3)*ones(size(t)), 'r--', 'LineWidth', 2);grid on;xlabel('时间 (s)'); ylabel('高度 (m)');title('高度控制响应');legend('实际高度', '期望高度');%% 姿态角变化图figure('Name', '姿态角', 'Color', 'white', 'Position', [300 300 1200 800]);subplot(3,1,1);plot(t, rad2deg(states(:,7)), 'b', 'LineWidth', 2);grid on;xlabel('时间 (s)'); ylabel('横滚角 (deg)');title('横滚角响应');subplot(3,1,2);plot(t, rad2deg(states(:,8)), 'b', 'LineWidth', 2);grid on;xlabel('时间 (s)'); ylabel('俯仰角 (deg)');title('俯仰角响应');subplot(3,1,3);plot(t, rad2deg(states(:,9)), 'b', 'LineWidth', 2);grid on;xlabel('时间 (s)'); ylabel('偏航角 (deg)');title('偏航角响应');
end
以下是添加风扰和传感器噪声之后的效果,我们会发现轨迹图确实更贴合实际效果一些呢~
3D轨迹图
高度变化图
姿态角变化图
10. 总结与展望 🎯
恭喜你完成了这个四旋翼无人机PID控制的MATLAB仿真!🎉 通过这个项目,我们学到了:
- 四旋翼无人机的动力学建模
- PID控制器的原理与实现
- MATLAB仿真环境的搭建
- 控制参数的调优方法
- 如何处理现实中的干扰和噪声
未来改进方向
这只是一个起点,你还可以考虑以下扩展:
- 实现轨迹跟踪:让无人机跟随特定路径飞行
- 添加图像识别:结合计算机视觉实现目标跟踪
- 改用更先进的控制算法:如LQR、MPC或神经网络控制
- 硬件在环仿真:连接实际飞控硬件进行测试
希望这篇教程对你有所帮助!如果有任何问题或建议,欢迎留言讨论。Happy coding! 🚀
相关文章:
《MATLAB实战训练营:从入门到工业级应用》高阶挑战篇-《用无人机仿真玩转PID控制:MATLAB四旋翼仿真建模全攻略》
《MATLAB实战训练营:从入门到工业级应用》高阶挑战篇-✈️ 用无人机仿真玩转PID控制:MATLAB四旋翼仿真建模全攻略 🚁 欢迎来到这篇超级详细的MATLAB四旋翼无人机仿真教程!无论你是控制理论爱好者、无人机发烧友,还是M…...
GESP2024年3月认证C++八级( 第二部分判断题(1-5))
孙子定理参考程序: #include <iostream> #include <vector> using namespace std;// 扩展欧几里得算法:用于求逆元 int extendedGCD(int a, int b, int &x, int &y) {if (b 0) {x 1; y 0;return a;}int x1, y1;int gcd extende…...
PHP的现代复兴:从脚本语言到企业级服务端引擎的演进之路-优雅草卓伊凡
PHP的现代复兴:从脚本语言到企业级服务端引擎的演进之路-优雅草卓伊凡 一、PHP的历史误解与现实真相 1.1 被固化的陈旧认知 当卓伊凡浏览知乎上关于PHP的讨论时,发现大量回答仍然停留在十年前的刻板印象中。这些误解包括但不限于: “PHP只…...
手表功能RunModeTasks
RunModeTasks 功能解释 “RunModeTasks 执行特定于当前模式的功能 根据模式控制作行为”这句话是指 OV-Watch 智能手表项目中的一组任务,这些任务负责管理设备的运行模式并根据不同模式控制设备的行为。 主要组成部分 RunModeTasks 主要由以下三个部分组成&#…...
Qt6.8中进行PDF文件读取和编辑
1.环境配置 在 .pro 文件中添加 PDF 模块依赖: QT core gui pdf # 添加 pdf 模块 注意:独立 pdf 模块的起始版本是Qt 5.15,建议需要 PDF 功能的开发者优先选择此版本或更高版本 2.读取PDF 文件 核心类:QPdfDocument…...
Barrett Reduction算法优化:更紧的界限消除冗余的减法
1. 引言 Barrett Reduction 是一种被广泛使用的模 m m m 运算算法。在zkSecurity 受NEAR团队所委托的(针对RustCrypto: NIST P-256 (secp256r1) elliptic curve——https://github.com/RustCrypto/elliptic-curves/tree/master/p256)进行的 Rust p256 …...
Node.js 是什么?
Node.js 是什么? Node.js 是一个基于 Chrome V8 JavaScript 引擎 的 跨平台 JavaScript 运行时环境,用于在服务器端运行 JavaScript 代码。它使开发者能够使用 JavaScript 编写后端(服务端)程序,而不仅仅局限于浏览器端(前端)。 1. Node.js 的核心特点 (1) 基于 Chrom…...
数据结构中 数组、链表、图的概念
数据结构是计算机存储、组织数据的方式,数组、链表和图是三种常见的数据结构,下面为你详细介绍它们的概念: 数组 数组是一种线性数据结构,它由一组相同类型的元素组成,这些元素存储在连续的内存位置上。每个元素都可…...
基于PPO的自动驾驶小车绕圈任务
1.任务介绍 任务来源: DQN: Deep Q Learning |自动驾驶入门(?) |算法与实现 任务原始代码: self-driving car 在上一篇使用了DDPG算法完成自动驾驶小车绕圈任务之后,继续学习了PPO算法&…...
Three.js + React 实战系列 - 客户评价区细解教程 Clients 组件✨(回答式评价 + 评分星级)
对个人主页设计和实现感兴趣的朋友可以订阅我的专栏哦!!谢谢大家!!! 在这篇博客中,我们将实现一个简洁的 Hear from My Clients 客户评价区域。这个区块在个人主页中可以突显用户体验和专业度,帮…...
2048游戏(含Python源码)
前言 相关参考游戏: 像素飞机大战(含Python源码)-CSDN博客https://blog.csdn.net/weixin_64066303/article/details/147693018?spm1001.2014.3001.5501使用DeepSeek定制Python小游戏——以“俄罗斯方块”为例-CSDN博客https://blog.csdn.n…...
百度golang开发一面
讲一下数据库的事务机制?acid特性是靠什么实现的? 持久性 redo log 原子性 undo log 隔离性 MVCC或next-lock锁 四个隔离级别是什么,分别解决什么问题? 可串行化实现原理 mysql锁机制?介绍锁的类型,以及原理…...
【Springboot知识】Springboot计划任务Schedule详解
文章目录 Spring Boot 定时任务从原理到实现详解一、核心原理分析1. 架构分层2. 核心组件3. 线程模型 二、基础实现步骤1. 添加依赖2. 主类配置3. 定时任务类 三、高级配置技巧1. 自定义线程池2. 动态配置参数3. 分布式锁集成(Redis示例) 四、异常处理机…...
大模型推理--从零搭建大模型推理服务器:硬件选购、Ubuntu双系统安装与环境配置
自从大模型火了之后就一直想自己组装一台机器去深入研究一下大模型,奈何囊中羞涩,迟迟也没有行动。在下了很大的勇气之后,终于花了接近4万块钱组装了一台台式机,下面给大家详细介绍一下我的装机过程。 1.硬件配置 研究了一周&am…...
如何使用QWidgets设计一个类似于Web Toast的控件?
如何使用QWidgets设计一个类似于Web Toast的控件? 前言 笔者这段时间沉迷于给我的下位机I.MX6ULL做桌面,这里抽空更新一下QT的东西。这篇文章是跟随CCMoveWidget一样的文章,尝试分享自己如何书写这份代码的思考的过程,和笔者…...
博图V20编译报错:备不受支持,无法编译。请更改为受支持的设备。
使用高版本博图打开低版本博图的工程文件时,hmi编译报错不通过,报错提示:备不受支持,无法编译。请更改为受支持的设备。 原因:当前版本的博图软件没有或不支持该组态设备的固件版本。 解决办法:1、安装报错…...
凸性(Convexity)
凸性(Convexity)是一个跨学科的重要概念,广泛应用于数学、优化理论、金融等领域。其核心含义是描述某种结构(如函数、集合)在特定条件下的“无凹陷”性质。 1. 数学中的凸性 1.1 凸函数与凹函数 在数学分析中&#…...
Vuex使用指南:状态管理
一、什么是状态管理?为什么需要 Vuex? 1. 状态管理的基本概念 在 Vue 应用中,状态指的是应用中的数据。例如: 用户登录状态购物车中的商品文章列表的分页信息 状态管理就是对这些数据的创建、读取、更新和删除进行有效管理。 …...
kotlin中枚举带参数和不带参数的区别
一 ✅ 代码对比总结 第一段(带参数 工具方法) enum class SeatPosition(val position: Int) {DRIVER_LEFT(0),DRIVER_RIGHT(1),SECOND_LEFT(2),SECOND_RIGHT(3);companion object {fun fromPosition(position: Int): SeatPosition? {return SeatPosi…...
【Python】Python好玩的第三方库之二维码生成,操作xlsx文件,以及音频控制器
前言 🌟🌟本期讲解关于python的三种第三方库的使用介绍~~~ 🌈感兴趣的小伙伴看一看小编主页:GGBondlctrl-CSDN博客 🔥 你的点赞就是小编不断更新的最大动力 🎆那么…...
VTK 交互类介绍
基本概念 交互器(Interactor): 处理用户输入事件的基础类 交互样式(InteractorStyle): 定义具体的交互行为 Widgets: 可交互的UI组件,如滑块、按钮等 Picker: 用于选择场景中的对象 常用交互类 类名功能描述vtkRenderWindowInteractor渲染窗口交互器vtkInteractorStyle交互样式…...
在Window10 和 Ubuntu 24.04LTS 上 Ollama 在线或离线安装部署
Ollama 是一个开源的大型语言模型(LLM)服务框架,旨在通过轻量化、跨平台的设计,简化大模型在本地环境中的部署与应用。其基于 Go 语言开发,通过 Docker 容器化技术封装模型运行环境,提供类似命令行工具的交…...
语音合成之十一 提升TTS语音合成效果:低质量数据清洗、增强与数据扩增
低质量数据清洗、增强与数据扩增 1. 引言:TTS的基石——数据质量2. 基础:TTS数据准备工作流2.1 规划:定义蓝图2.2 执行:从原始数据到训练就绪格式2.3 最佳实践与可复现性 3. 攻克缺陷:低质量语音数据的清洗与增强3.2 手…...
RGB三原色
本文来源 : 腾讯元宝 RGB三原色(红绿蓝)详解 RGB(Red, Green, Blue)是光学的三原色,通过不同比例的混合可以产生人眼可见的绝大多数颜色。它是现代显示技术(如屏幕、投影仪)…...
BUUCTF 大流量分析(一) 1
BUUCTF:https://buuoj.cn/challenges 文章目录 题目描述:密文:解题思路:flag: 相关阅读 CTF Wiki BUUCTF:大流量分析(一) 题目描述: 某黑客对A公司发动了攻击,以下是一段时间内我们…...
虚幻引擎5-Unreal Engine笔记之显卡环境设置使开发流畅
虚幻引擎5-Unreal Engine笔记之显卡环境设置使开发流畅 code review! 文章目录 虚幻引擎5-Unreal Engine笔记之显卡环境设置使开发流畅1.电源管理2.显卡优先设置3.拯救者支持FnQ性能模式切换,建议开发前切至“野兽模式”或高性能模式。4.NVIDIA 驱动设置5.VS2022中…...
suna工具调用可视化界面实现原理分析(一)
这是一个基于React构建的工具调用侧边面板组件,主要用于展示和管理自动化工具调用流程。以下是代码功能解析及关键组件分析: 一、核心功能模块 多工具视图切换系统 • 动态视图加载:通过getToolView函数根据工具名称(如execute-c…...
【将你的IDAPython插件迁移到IDA 9.x:核心API变更与升级指南】
文章目录 将你的 IDAPython 插件迁移到 IDA 9.x:核心 API 变更与升级指南为什么 API 会变化?关键不兼容性一:数据库信息访问 (inf_structure)关键不兼容性二:窗口/视图类型判断 (BWN_* 和 form_type)其他可能的 API 变更迁移策略建…...
《Python星球日记》第31天:Django 框架入门
名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏:《Python星球日记》,限时特价订阅中ing 目录 一、Django…...
读《人生道路的选择》有感
读完戴维坎贝尔的《人生道路的选择》,深有感触,虽然只有短短的108也,但作者强调了在复杂的生活环境之中“选择”的重要性。这也是我想要探讨的话题,选择到底会对我们人生产生怎样的影响。 在我们人生当中,确实有许多的…...
opencv+opencv_contrib+cuda和VS2022编译
本文介绍使用OpenCV和OpenCV_Contrib源码及Cuda进行编译的过程,编译过程中会用到OpenCV、OpenCV_Contrib、Toolkit、Cmake、VS2022等工具,最终编译OpenCV的Cuda版本。 一、OpenCV下载地址 OpenCV官网下载地址:https://opencv.org/releases/#࿰…...
STC单片机与淘晶驰串口屏通讯例程之01【新建HDMI工程】
大家好,我是『芯知识学堂』的SingleYork,今天笔者给大家一起学习这款“SYK-0806-A2S1”控制板与淘晶驰串口屏通讯的例程,本例使用的是淘晶驰的4.3寸电阻触摸屏TJC4827T143_011R_I_P20,分辨率为480272,详细参数大家可以查看这个屏的手册。 先来看下本例程整体的效果: 那么…...
PE文件结构(导出表)
导出表 什么是导出表? 导出表是PE文件中记录动态链接库(DLL)对外提供的函数或数据的列表,包含函数名称、序号和内存地址等信息,供其他程序调用 我们写一个dll来查看一下导出函数 int exportFunc1(int a, int b) {ret…...
网络安全自动化:精准把握自动化边界,筑牢企业安全防
在当今数字化时代,网络攻击的威胁日益严峻,企业网络安全的重要性不言而喻。随着海量资产与复杂架构的出现,网络安全自动化成为了众多企业关注的焦点。网络安全维护看似简单的修补系统、删除旧账户、更新软件,在大型企业中却极易变…...
实战设计模式之中介者模式
概述 中介者模式是一种强大且灵活的设计模式,适用于需要优化对象间通信的场景。中介者模式通过引入一个中介对象,来封装一系列对象之间的交互。在没有中介者的情况下,这些对象之间可能会直接相互引用,导致系统中的类紧密耦合&…...
价格识别策略思路
该策略是一种基于价格形态和市场条件的交易算法,旨在通过识别特定的价格模式来生成买入和卖出信号。 价格形态识别 策略的核心在于识别价格的高点和低点形态。通过比较当前周期及其前几个周期的最高价和最低价, 策略定义了一系列条件来判断价格是否形成了…...
Kotlin带接收者的Lambda介绍和应用(封装DialogFragment)
先来看一个具体应用:假设我们有一个App,App中有一个退出应用的按钮,点击该按钮后并不是立即退出,而是先弹出一个对话框,询问用户是否确定要退出,用户点了确定再退出,点取消则不退出,…...
【NLP】32. Transformers (HuggingFace Pipelines 实战)
🤖 Transformers (HuggingFace Pipelines 实战) 本教程基于 Hugging Face 的 transformers 库,展示如何使用预训练模型完成以下任务: 情感分析(Sentiment Analysis)文本生成(Text …...
[ 设计模式 ] | 单例模式
单例模式是什么?哪两种模式? 单例模式就是一个类型的对象,只有一个,比如说搜索引擎中的索引部分,360安全卫士的桌面悬浮球。 饿汉模式和懒汉模式:饿汉模式是线程安全的,懒汉模式不是线程安全的…...
用网页显示工控仪表
一.起因 现在工控也越来越多的使用web页面来显示电压,电流,温度,转速等物理量.本例使用js控制网页显示速度仪表. 二.代码 <html> <head><script type"text/javascript">var ctx;var px0;var movePoint{x0:0,x1:0};function init(){drawFace();m…...
Spring项目改造Solon版,使用体验,对比
概述 对于Solon有些人可能并不了解,在官方概述中,称其是新一代Java企业级应用开发框架,从零开始构建,有自主的标准规范与开放生态。近16万行代码。 并有更快、更小、更简单的特点 什么样的Java项目用Solon好? 按正常…...
2.CFD 计算过程概述:Fluent在散热计算中的优势
1.主流散热软件 2.电子产品热设计的基本要求 3.失效率与温度之间的关系 4.电子产品热设计的基本要求 5.电子产品必须要做散热设计 6.主动散热与被动散热 7.高效山热方案 8.热交换模型 9.Fluent中传热模型...
【Java ee初阶】多线程(6)
一、阻塞队列 队列的原则:“先进先出”,队列分为普通队列,优先级队列等等。在数据结构中,堆是特殊的完全二叉树,一定不要把堆和二叉搜索树混淆。 阻塞队列是一种特殊的队列,也遵循“先进先出”的原则。 …...
Unity:Surface Effector 2D(表面效应器 2D)
目录 什么是表面效应器 2D? 🎯 它是做什么的? 🧪 从第一性原理解释它是怎么工作的 📦 重要参数解释 为什么不直接用 Rigidbody(刚体)来控制运动 ? 所以什么时候该用哪个&#…...
Spring 框架的底层原理
Spring 框架的底层原理主要包括以下几个方面: 核心容器(IoC 容器) IoC(控制反转)原理 : 依赖注入(DI) :这是 IoC 的实现方式之一。在传统的程序开发中,程序组…...
【Unity】AssetBundle热更新
1.新建两个预制体: Cube1:GameObject Material1:Material Cube1使用了Material1材质 之后设置打包配置 Cube1的打包配置为custom.ab Material1的打包配置为mat.ab 2.在Asset文件夹下创建Editor文件夹,并在Editor下创建BuildBundle…...
【算法笔记】动态规划基础(二):背包dp
目录 01背包例题状态表示状态计算初始化AC代码 完全背包例题状态表示状态计算初始化TLE代码 多重背包例题状态表示状态计算初始化AC代码 分组背包例题状态表示状态计算初始化AC代码 二维费用背包例题状态表示状态计算初始化AC代码 混合背包问题例题状态表示状态计算初始化TLE代…...
IP属地是我的定位吗?——解析两者区别
在互联网时代,我们经常看到社交媒体、论坛或APP上显示用户的“IP属地”,许多人会疑惑:IP属地是不是我的精确定位?它会不会暴露我的隐私? 本文将详细解析IP属地和定位的区别,并解答常见的相关问题&#…...
力扣每日一题1128等价多米诺骨牌对的数量
1128. 等价多米诺骨牌对的数量 题目: 给你一组多米诺骨牌 dominoes 。 形式上,dominoes[i] [a, b] 与 dominoes[j] [c, d] 等价 当且仅当 (a c 且 b d) 或者 (a d 且 b c) 。即一张骨牌可以通过旋转 0 度或 180 度得到另一张多米诺骨牌。 在 0 &l…...
SpringBoot集成CXF框架,实现WebService
SpringBoot官网地址:https://spring.io/projects/spring-ws 1、WebService服务端搭建 Maven依赖 <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.7.17&…...