ArduPilot代码解析之四 — 姿态和位置控制

ArduPilot代码解析之二 — 载具基础系统(AP_Vehicle) AP_Vehicle是ArduPilot飞行器系统的核心基类,为Copter、Plane等各类飞行器提供通用架构。它包含初始化流程(setup/loop)、参数系统、调度器管理、传感器集成等基础功能,通过虚函数接口支持不同飞行器的特性扩展。系统采用分层设计,共享通用参数和任务,同时允许各飞行器实现特有的控制逻辑和模式管理。这种架构实现了代码复用和接口统一,支持多类型飞行器的灵活开发与维护。 阅读详情

目的和范围

本页面介绍了ArduPilot用于姿态(方向)和位置管理的级联控制架构。它解释了如何通过一系列控制回路将高级位置指令转换为电机输出,这些控制回路逐步细化期望状态,顺序为:位置→速度→加速度→姿态→角速率→电机指令。


控制架构概述

ArduPilot 采用级联控制系统,每一层都接收高层指令,并将其逐步转换为更低层级的目标。这种架构既能提供稳健的控制,又能实现平滑的轨迹跟踪。

主要特点:

  • 级联循环:每一层都接收来自上一层的目标值,并向下一层提供修正值。
  • 前馈:期望值直接传递,同时在每个阶段添加修正值。
  • 运动学整形:通过速度、加速度和加加速度限制来整形位置指令,以实现平滑的轨迹。
  • 解耦控制:水平轴 (NE) 和垂直轴 (U) 采用不同的增益独立控制。

位置控制 (AC_PosControl)

该类AC_PosControl实现了三维位置控制,具有独立的水平(东北平面)和垂直(上轴)控制器。每个轴都采用级联控制结构:位置误差驱动速度控制器,速度控制器再驱动加速度控制器。

级联控制结构

关键控制器类

控制器 类型 输入 输出 目的
_p_pos_ne_m AC_P_2D 位置误差(米) 速度目标(米/秒) 将水平位置误差转换为速度指令
_pid_vel_ne_cm AC_PID_2D 速度误差(厘米/秒) 加速度目标值(厘米/秒²) 将水平速度误差转换为加速度
_p_pos_u_m AC_P_1D 垂直位置误差(米) 速度目标(米/秒) 将高度误差转换为爬升率
_pid_vel_u_cm AC_PID_Basic 垂直速度误差(厘米/秒) 加速度目标值(厘米/秒²) 将爬升率误差转换为垂直加速度
_pid_accel_u_cm_to_kt AC_PID 垂直加速度误差(厘米/秒²) 油门输出 将垂直加速度转换为油门指令

输入整形和运动学路径生成

它不接受原始位置指令,而是AC_PosControl通过可配置的速度、加速度和加加速度限制来实现运动学路径整形。这确保了平滑的轨迹,避免了突变。

核心输入功能:

成形函数(位于库/AC_AttitudeControl/AC_PosControl.cpp2413-2682计算平滑轨迹的方法如下:

  1. 计算达到目标所需的加加速度需在加速度限制范围内
  2. 对加速度变化应用加加速度限制
  3. 对加速度进行积分即可得到速度
  4. 对速度进行积分以获得位置

ArduPilot飞控系统代码解读及架构分析 ArduPilot飞控系统是一个复杂而强大的系统,通过模块化设计和分层架构,实现了灵活的飞行控制功能。模块化设计: 各个功能模块相对独立,便于维护和扩展多种飞行模式: 满足不同的飞行需求强大的控制算法: 实现稳定的姿态和位置控制完善的安全机制: 保障飞行安全丰富的配置选项: 通过参数系统实现高度可定制性这种架构使ArduPilot能够适应从简单的多旋翼到复杂的自主飞行器等各种应用场景。类结构分析:Mode基类 (mode.h/mode.cpp) 阅读详情

相关推荐

ArduPilot导航算法详解:位置控制完整指南

深入剖析ArduPilot导航算法的核心机制,详解位置控制的实现原理与调参技巧,帮助开发者更好掌握ardupilot在实际飞行中的应用,提升系统稳定性与定位精度。

weixin_33597080的博客 599

Ardupilot姿态控制器 PID控制流程

APM的控制器主要分为attitude姿态控制器和pos位置控制器。这系列文章主要来讲一下姿态控制器内部的实现。本文主要目的是为了解析APM源码然后方便自己将其实现在自己的水下航行器控制器上的,因此将会以ArduCopter和ArduSub为例进行解析,其他无人机类型也是类似的,也可用作参考。 一、PID姿态控制器 1.1 Copter姿态控制官方原图 在真正开始解析源码之前,可以看一下Ardupilot官方网站上开发者手册对于直升机姿态控制器的描述(虽然官方的文档已经很久没更新了,4.x版本之后的..

moumde的博客 9554

ArduPilot代码解析之十一 — 多旋翼控制系统

本文介绍了ArduCopter多旋翼飞行器的控制系统架构,采用级联控制方式实现从位置指令到电机输出的完整控制流程。系统包含位置控制(50Hz)、姿态控制(400Hz)、速率控制和电机输出四个层级,通过嵌套回路实现精准飞行控制。详细说明了姿态控制系统的角度P控制器和速率PID控制器设计,以及位置控制系统的三级级联结构。同时介绍了电机混控算法和多种机架类型的支持,并阐述了飞行模式与控制系统的集成方式。最后通过ModeLoiter示例展示了从RC输入到电机输出的完整控制流程。

rainercool的专栏 688

ArduPilot代码解析之七 — 自动调谐系统

自动调谐系统通过执行受控飞行机动自动确定飞行器姿态控制回路的最佳PID增益,无需人工干预。系统采用多态类层次结构,针对多旋翼和直升机平台分别实现不同的调谐算法:多旋翼通过"抽搐"机动测量瞬态响应来调整参数,直升机则采用频域分析方法。调谐过程分为多个步骤,包括增益测试、验证和保存,最终应用安全裕度确保稳定性。系统支持通过飞行模式或辅助开关调用,并自动保存优化后的参数。该技术实现了飞行控制参数的智能化优化,显著提升了飞行性能和稳定性。

rainercool的专栏 1048

飞控四巨头:Pixhawk、PX4、APM与ArduPilot关系详解

飞控系统是无人机的核心,但Pixhawk、PX4、APM、ArduPilot这几个名词常让新手混淆。从计算机类比入手,说明Pixhawk是硬件主板,PX4与ArduPilot是运行其上的软件操作系统,而APM则是从早期硬件演变为ArduPilot的俗称。理解硬件与软件解耦的原理,才能正确选型。无论是想解决PX4源码仓库子模块未初始化的编译问题,还是希望借助WSL2在AirSim下搭建PX4仿真环境,或者对水下机器人使用APM固件感兴趣,都需要先理清这四者的关系。本文用一张谱系图和实操速查表,帮助你在飞控开发

weixin_34314962的博客 317

ArduPilot飞行模式深度解析:从Stabilize到Auto的9种模式全攻略

本文深度解析了ArduPilot飞控系统的9种核心飞行模式,从基础的Stabilize自稳模式到全自动的Auto任务模式。详细阐述了每种模式的控制逻辑、适用场景、切换时机及参数调优技巧,并结合代码解读与飞行日志分析,帮助用户深入理解飞控架构,实现更安全、高效的无人机操控与自动化作业。

qsc901234567的博客 868

ArduPilot代码解析之六 — GPS和位置传感

ArduPilot的GPS子系统支持多种GPS接收器类型,提供位置、速度和时间信息。该系统具有自动检测、多接收器并发连接、RTK校正和传感器数据融合等功能,支持标准GPS、DGPS和RTK定位方案。通过串行、CAN或网络接口连接,可配置多种卫星星座,实现厘米级精度。系统架构采用多实例管理,支持自动故障转移和混合模式,并能与AHRS集成进行位置估计。此外还提供GPS健康检查、航向计算和时间同步等功能,适用于从基本导航到高精度定位的各类应用场景。

rainercool的专栏 610

ArduSub程序学习(1)——ardupilot框架整理

AP_HAL层(硬件抽象层)是我们制作 ArduPilot 的方式可移植到许多不同的平台。有一个顶级AP_HAL libraries/AP_HAL,用于定义代码其余部分的接口 有针对具体的板子特性,然后就有了AP_HAL_XXX 子目录,例如,AP_HAL_AVR 用于基于 AVR 的 开发板,AP_HAL_PX4用于 Pixhawk 开发板和 AP_HAL_Linux 基于 Linux 开发板。工具目录tools directories工具目录是杂项支持目录。

weixin_49839886的博客 2811

ArduPilot代码解析之九 — ArduCopter(多旋翼飞行器)

ArduCopter是ArduPilot系统中的多旋翼飞行控制方案,支持四旋翼、六旋翼等飞行器。采用分层架构设计,包含400Hz主控制回路、25种飞行模式切换和级联控制结构(位置-姿态-速率)。系统集成共享控制库,实现传感器融合、导航算法和故障保护机制,支持MAVLink通信与全面日志记录。通过模块化设计和多速率调度,为各类多旋翼飞行器提供从手动到全自动的飞行控制解决方案。

rainercool的专栏 605

ardupilot开发 --- 代码解析 篇

代码解析,通过断点调试带你走进ardupilot,有图有真相!!

记录老板的每次pua,分享领导每天的毒鸡汤... 809

ardupilot开发 --- 位置控制与导航制导篇

ardupilot开发 --- 位置控制篇

记录老板的每次pua,分享领导每天的毒鸡汤... 2344

ArduPilot飞控源码级解析:从姿态环到位置环的控制逻辑

飞行控制器是无人机自主飞行的核心,其本质是一套分层闭环控制系统,涵盖感知、解算与执行三个关键阶段。理解姿态控制(Attitude Control)与位置控制(Position Control)的串级关系,是掌握飞控原理的基础——前者基于IMU反馈实现角速度PID闭环,后者则将GPS或视觉定位误差转化为期望姿态角。ArduPilot作为开源飞控代表,其C++类结构(如AC_AttitudeControl、AC_PosControl)清晰体现了外环-内环协同机制与硬实时调度约束。该架构广泛应用于多旋翼、固定翼等

weixin_29172963的博客 198

云漾AI创作平台实战:如何用GPT4.0+Midjourney快速生成商业级插画(附Prompt模板)

本文详细介绍了如何利用云漾AI创作平台结合GPT4.0和Midjourney快速生成商业级插画。通过智能文案生成与视觉化工作流,大幅提升创作效率,适用于电商、社交媒体等多种场景。文章包含实用Prompt模板和参数调整技巧,帮助设计师和内容创作者高效产出专业插画。

weixin_29251567的博客 216

auboi5 + d435i 使用easy handeye进行标定时,遇到相关问题记录。

解决办法:在easy_handeye默认的 calibrate.launch 文件中move group 的默认值为 "manipulator",但针对每个人的机械臂,这个值需要更改。以aubo_i5为例,需要将其改为"manipulator_i5",或者自己编写launch文件时,传入参数move group的值,便能顺利解决问题!easy_handeye_calibration_server 进程出现崩溃。

weixin_61025092的博客 957

从RTL到GDSII:DC综合里那些没人告诉你的时钟约束冷知识(附真实工程示例)

本文深入探讨数字IC设计中DC综合阶段的时钟约束冷知识,包括无毛刺时钟切换、寄存器分频时钟约束、虚拟时钟应用等关键技巧。通过真实工程示例,揭示常见约束误区及解决方案,帮助工程师提升时序收敛效率。特别针对input_delay和output_delay在多时钟域场景下的设置陷阱提供实用指南。

weixin_29306317的博客 429

AI应用架构师视角:AI技术引发的全球经济格局重构,你看懂了吗?

本文将从AI应用架构师的独特视角,拆解AI技术栈(算力/算法/数据)如何通过"架构渗透"重塑产业价值链,分析中美欧等主要经济体的AI战略差异如何改写全球分工格局,并为企业与个人提供一套可落地的"AI经济适应性框架"。当OpenAI的GPT-4在代码生成、多模态理解上展现出超越人类的能力,当英伟达的H100芯片成为全球科技巨头争抢的"数字石油",当中国的AI大模型在电商、金融等场景实现规模化落地——我们正站在一场由AI技术引发的全球经济重构的临界点上。AI重构全球经济格局的过程,既是挑战,更是机遇。

小白菜的博客 1258

LVGL(lv_canvas)

这篇文章介绍了LVGL图形库中的lv_canvas组件,主要内容包括: lv_canvas是一个绘图缓冲区对象,提供丰富的绘图API,可以理解为LVGL的"离屏画布"。 基本使用流程:创建缓冲区->创建canvas对象->设置缓存和尺寸->进行绘图操作。 详细列举了常用的绘图函数,如绘制线条、矩形、文字、图片等。 提供了示例代码展示如何创建画布并绘制一条红色线段。 介绍了canvas的典型应用场景,如动态波形绘制、自定义控件底图等。 对比了canvas与普通img的区别

m0_49476241的博客 1023

TC3XX - MCAL知识点(三十八):AURIX™ TC3xx 的EDSADC实现旋变解码功能(理论知识+手册阅读)

本文系统梳理了英飞凌AURIX系列芯片EDSADC模块的技术手册内容。首先概述了该模块的架构特点,包括模拟/数字输入通道和总线地址信息。重点解析了手册中的关键知识点:1)模拟量输入的差分/单端模式;2)数字量连接的触发、数据源和时钟源选择;3)功能配置中的寄存器操作注意事项;4)输入通道的三种数据来源模式;5)滤波器链的组成和工作原理;6)旋变应用中的载波信号生成和延迟补偿机制。最后对SRM、SAUL、SBLL等专业术语进行了详细解释。全文为理解EDSADC模块的硬件特性和配置方法提供了系统的技术参考。

梦想技术家 588

S32K324 Stack异常分析及解决方案

在项目开发过程中,在一次软件变更时,调整了task优先级之后导致应用层软件中的float数据经常性的变为NAN,导致应用层功能失效。本文记录下这个bug的分析及解决过程。该问题排查了好几天,最开始正向排查不出来,差点放弃了,ETAS OS也没有人支持,只能换一种思路,通过反向推,最终定位到问题,能完美解决,还是很欣慰的。遇到问题不可怕,Bug一直都会有,主要是在解决问题中的思路和方法,不断总结积累,总会越来越好的!

赞的博客 596

VAY 是 SAP 自动科目确定(OBYC-GBB)中的科目修改码,专用于带科目分配对象的销售订单发货场景,核心是触发 “Dr 成本要素科目(如销售费用 / 特定成本对象) Cr 库存商品” 的分录,

摘要:VAY是SAP中用于带科目分配对象(如成本中心、WBS)的销售订单发货的科目修改码,与标准VAX场景不同,它生成"借成本要素科目/贷库存商品"的分录。配置路径为OBYC-GBB-VAY,需确保借方科目为成本要素。典型业务场景包括免费样品、项目专用发货等。常见问题包括VAY未触发或科目记账错误,需检查销售订单科目分配、移动类型设置及OBYC配置。特殊场景建议单独配置科目以便费用分析。

金牌架构师 1251

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

上一篇: ArduPilot代码解析之二 — 载具基础系统(AP_Vehicle)
下一篇: ArduPilot代码解析之五 — 无线电控制(RC)输入
timmy-uav
博客等级 码龄26年 526粉丝 104原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

timmy-uav

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值