PX4 是一款专业级飞控。 它由来自业界和学术界的世界级开发商开发,并得到活跃的全球社区的支持,为从竞速和物流无人机到地面车辆和潜水艇的各种载具提供动力。

目录

基本概念

QGroundControl(QGC地面站)

飞行控制系统

传感器

无线电控制(遥控)

动力系统及其他硬件设备

输出:电机,舵机,执行器

电调 & 电机

电池/电源

安全开关

数传电台

机载计算机

SD卡(可移除储存器)

开发指南

PX4开发指南Mac OS

下载 PX4 源代码

搭建第一个PX4应用

启动/构建 SITL 模拟

编译

代码测试

PX4 系统架构概述

顶层软件架构

飞行控制栈

中间件

参考资料


基本概念

首先,我们学习一些基本的概念~

PX4是与平台无关的自动驾驶仪软件(或称为固件),可以驱动无人机或无人车。它可以被烧写在某些硬件(如Pixhawk v2),并与地面控制站在一起组成一个完全独立的自动驾驶系统。

PX4 的一些主要功能包括:

  • 可控制许多不同的设备机架/类型,包括:飞机(多旋翼,固定翼和垂直起降),地面车辆和水下潜航器。
  • 适用于设备控制器,传感器和其他外围设备的硬件选择。
  • 灵活而强大的飞行模式和安全功能。
  • PX4 是一个大型无人机平台的核心部分,它们都包括 QGC 地面站,Pixhawk 硬件 (opens new window),还有MAVSDK (opens new window)用于与机载计算机集成,相机还有其他使用 MAVLink 协议的硬件。

PX4/ArduPilot两种都是开源的可以烧写到Pixhawk飞控中的自驾仪软件。

APM(Ardupilot Mega)早期也是一款自驾仪硬件,但是更新到了APM3.0版本后,这款自驾仪也就走到了终点。而ArduPilot是属于APM的原生固件,现在ArduPilot也全面支持Pixhawk,而大家也习惯将ArduPilot称为APM。

两个不同固件都是应用C++开发的,区别在于,PX4是Pixhawk的原生固件,它的架构更加清晰容易维护,但是功能比起APM来讲比较少;而APM相对而言,性能更加稳定成熟,功能也更加丰富,与之相对的就是架构不是太清晰所以不利于维护和修改。

QGroundControl(QGC地面站)

地面控制站称为 QGC 地面站 (opens new window)。 您可以使用QGroundControl 将PX4 加载(烧写)到飞行器控制硬件上,可以设置飞行器,更改不同参数,获取实时飞行信息以及创建和执行完全自主的任务。

QGC即在地面的基站,用于多旋翼飞行器起飞前对自驾行进行传感器校准和参数调整等初始化工作,以及在多旋翼飞行时,通过无线数据模块接受多旋翼的飞行状态并实时发送控制指令。(地面站有:QGC(QGround Control)和MP(Mission Planner)两种不同版本。一般来说,PX4固件使用QGC操作,APM固件配套MP使用。)

QGroundControl 可以在 Windows,Android,MacOS 或 Linux 上运行(直接下载安装即可,但mac上好像安装不了,可能是权限问题,打开设置,安全与隐私、通用设置一下即可)。

下载链接:http://qgroundcontrol.com/downloads/

注意:一旦选中并购买或组装了机架后,在对无人机的飞控初始化阶段,你需要从地面站QGroundControl中众多的机架模板中选择一款和你使用的构造类似的机架。

飞行控制系统

所谓无人机的飞控,就是无人机的飞行控制系统。无人机飞控能够稳定无人机飞行姿态,并能控制无人机自主或半自主飞行,是无人机的大脑。

PX4最初设计为在 Pixhawk 系列 飞控上运行(Pixhawk是第一款专门为PX4自驾软件而设计的无人机飞控),但现在可以在 Linux 计算机和其他硬件上运行。 选择飞行控制板时,您应当考虑飞行器的物理尺寸限制,想要执行的活动,还有必不可少的成本。

Pixhawk飞控是开源硬件架构,所以全世界很多公司出品了基于Pixhawk的飞控产品。他们都有共同的硬件架构和相同的连接方式、输出接口及功能,仅仅是具体形式不同而已,例如接口的位置不同、外壳不同等等。

所谓的Pixhawk是一款低成本高性能的飞控硬件平台,相当于一个载体,承载无人机运行的代码。

Pixhawk的构造:PIXHAWK拥有168MHz的运算频率,其中主处理器为STM32F427,协处理器STM32F103,主处理器和协处理器之间采用串口通信方式。为内置两套陀螺和加速度计MEMS传感器,互为补充矫正,内置三轴磁场传感器并可以外接一个三轴磁场传感器,同时可外接一主一备两个GPS传感器,在故障时自动切换。

除了PX4这款自驾仪软件,还有一种飞行协议栈(或称自驾仪软件)可以被烧写到Pixhawk飞控,那就是非常流行的ArduPilot或称为APM的自驾仪软件。

请牢记,Pixhawk飞控是硬件平台,而PX4和APM都是开源的可以烧写到Pixhawk飞控中的自驾仪软件。

传感器

PX4 使用传感器来确定飞行器状态(稳定和启用自动控制所需)。 系统*最低要求 *陀螺仪,加速度计,磁力计(罗盘)和气压计。 需要 GPS 或其他定位系统来启用所有自动模式和一些辅助模式。 固定翼和 VTOL 飞行器还应包括空速传感器(强烈推荐)。

加速度计其定义为去掉重力后的整体加速度。不太好理解,简单来说重力的分解,来测算物体所受的加速度。加速度计也可以测量横滚角、俯仰角。

优点:加速度计测量角度没有积累误差,低频特性好,可以测量低速的静态加速度。

缺点:因为其低频特性,容易受高频振动的影响。

陀螺仪主要测量角速度。利用高速回转体的动量矩敏感壳体相对惯性空间绕正交于自转轴的一个或二个轴的角运动检测装置。优点就是高频特性比较好,可以测量飞机的三个角,即横滚角、俯仰角和偏航角。

磁力计也被称为指南针可以得到当前磁场的分布。容易收到外界环境的干扰,而且只可以测量到飞机的偏航角。

无线电控制(遥控)

遥控(RC)系统用于 手动 控制机体。 它由一个遥控装置组成,使用发射机来与飞行器上的接收机通信。 一些 RC 系统还可以接自动驾驶仪传回的收遥测信息。

遥控系统:由遥控器和接收器、解码器和伺服系统组成.接收器接到遥控器信号(通常为PWM信号)进行解码,分离出动作信号传输给伺服系统,伺服系统则根据信号做出相应的动作。

为了能够对您的PX4无人驾驶仪进行配置、控制及交互,需要先对其进行连接。对于Pixhawk硬件有三种类型的连接:

  遥控连接 – 通过无线电实现遥控器对飞控的连接。

  数据连接 – 使用数传、WiFi或者USB线对QGroundControl地面站和无人机进行的连接。

  机外连接 – PX4和外部能够控制PX4的微机之间的数据连接。

动力系统及其他硬件设备

基本动力套装包括单片机、电机、电调、螺旋桨等套装。其余硬件设备还包括机架、电池、GPS、蜂鸣器等等,

输出:电机,舵机,执行器

PX4使用输出来控制:电机速度(例如通过ESC),飞行平面如副翼和襟翼,相机触发器,降落伞,抓手,和许多其他类型的有效载荷。

例如,下面的图像显示 Pixhawk 4 和 Pixhawk 4 mini 的 PWM 输出端口。

电调 & 电机

许多 PX4 无人机使用无刷电机,其由飞行控制器通过电子调速器(ESC)驱动(ESC将来自飞行控制器的信号转换为合适的功率水平,传递给电机)。

电池/电源

PX4 无人机通常由锂聚合物(LiPo)电池供电。 电池通常使用*电源模块 电源管理板 *连接到系统,它为飞行控制器和 ESC(用于电动机)提供单独的动力。

安全开关

机体通常必须有一个 安全开关,然后才能使用 解锁(解锁后,电机会供电,螺旋桨开始旋转)。 通常,安全开关被整合到GPS设备中,但也可能是一个单独的物理组件。

数传电台

数传电台 可以在诸如 QGC 地面站 与运行 PX4 的机体之间提供无线 MAVLink 连接。 这使得飞机飞行中调试参数、实时检查遥测信息、更改任务等等成为了可能。

机载计算机

PX4 可以通过串行接线或 WiFi 由独立的机载伴飞计算机进行控制。 机载计算机通常使用 MAVLink API(如 MAVSDK 或 MAVROS)进行通信。

SD卡(可移除储存器)

PX4 使用 SD 储存卡存储 飞行日志,而且还需要内存卡才能使用 UAVCAN 外围设备,运行 飞行任务。

默认情况下,如果没有 SD 卡,PX4 将在启动时播放 格式化失败(2-声短响) 两次(且上述需要储存卡的功能都不可用)。

无人机硬件连接如下

开发指南

PX4开发指南Mac OS

PX4代码可以在 Mac OS, Linux 或者 Windows上进行开发,建议在Mac OS和Linux上进行开发,因为图像处理和高级导航在windows上不容易开发。

这里看看在Mac OS上进行安装(之前博客《ROS实验笔记之——基于Prometheus自主无人机开源项目的学习与仿真》已经在linux上配置了~)

第一步就是从Mac应用商店中安装Xcode。打开一个新的终端并安装命令行工具:

xcode-select --install

然后安装Homebrew 。Homebrew 是最简单和灵活的方式,用来在 Mac OS X 安装 Linux 工具包(https://blog.csdn.net/jdsjlzx/article/details/108081327)。

安装过程很简单:

https://gitee.com/cunkai/HomebrewCN

/bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)"

HomeBrew是ruby脚本,但是mac下不需要安装ruby解释环境,系统自带了。

安装好后,可以运行下面命令,通过检查homebrew版本确认是否安装成功。

brew –v

安装好Homebrew以后,拷贝以下命令到终端命令行:

brew tap PX4/px4
brew tap PX4/simulation(安装不了)
brew update
brew install git bash-completion genromfs kconfig-frontends gcc-arm-none-eabi
brew install astyle cmake ninja
# simulation tools
brew install ant graphviz sdformat3 eigen protobuf
brew install opencv

再安装以下:

brew tap PX4/px4
brew install px4-dev
# 可选,但建议安装额外的仿真模拟用工具
brew install px4-sim

遇到安装不成功,可以看看https://www.cnblogs.com/my-blogs-for-everone/articles/14256182.html

然后安装python包:

sudo easy_install pip
sudo pip install pyserial empy pandas jinja2
Java for jMAVSim
brew install xquartz java

Gazebo仿真

sudo easy_install pip
sudo -H pip install pyserial empy toml numpy pandas jinja2 pyyaml
# install required packages using pip3
python3 -m pip install --user pyserial empy toml numpy pandas jinja2 pyyaml pyros-genmsg packaging
# if this fails with a permissions error, your Python install is in a system path - use this command instead:
sudo -H python3 -m pip install --user pyserial empy toml numpy pandas jinja2 pyyaml pyros-genmsg packaging

jMAVSim 仿真模拟

brew install --cask xquartz
brew install px4-sim-gazebo

gazebo安装出错:http://gazebosim.org/tutorials?tut=install_on_mac

其他额外工具

brew tap AdoptOpenJDK/openjdk
brew install --cask adoptopenjdk15
brew install px4-sim-jmavsim

安装完毕

安装IDE vscode

下载px4的源代码

git clone https://github.com/PX4/PX4-Autopilot.git

通过vscode打开并编译(Select the PX4-Autopilot directory and then press OK.)

将推荐的都安装,然后cmake(依次点击小红框,选择px4_sitl)

调试成功后会显示:

然后点击build(其中可能会报错,需要安装一些依赖,安报错的要求安装即可)

You can then kick off a build from the config bar (select either Build or Debug).

After building at least once you can now use [code completion](#code completion) and other VSCode features.

下载 PX4 源代码

git clone --recursive https://github.com/google/bloaty.git /tmp/bloaty \&& cd /tmp/bloaty && cmake -GNinja . && ninja bloaty && cp bloaty /usr/local/bin/ \&& rm -rf /tmp/*

初次编译(使用 jMAVSim 模拟器)

导航到 Firmware 目录,并使用以下命令启动 jMAVSim:

make px4_sitl jmavsim

如下图所示

报错了,估计就是JDK版本不一致

参考链接:https://docs.px4.io/master/en/simulation/jmavsim.html#troubleshooting

里面要安装版本15好像没错~但是细细一看,应该是16才对,所以重新运行

brew install --cask adoptopenjdk16

再试试~终于ok了~

打开地面站

然后运行

pxh> commander takeoff

搭建第一个PX4应用

源代码在/src/examples/px4_simple_app中

启动/构建 SITL 模拟

# 启动固定翼机型的 Gazebo
make px4_sitl gazebo_plane# 启动有光流的Iris机型的 Gazebo
make px4_sitl gazebo_iris_opt_flow# 启动Iris(默认机型)的 JMavSim
make px4_sitl jmavsim

编译

编写完应用后需要编译。

  • PX4 SITL (Simulator): PX4-Autopilot/boards/px4/sitl/default.cmake(opens new window)
  • Pixhawk v1/2: PX4-Autopilot/boards/px4/fmu-v2/default.cmake(opens new window)
  • Pixracer (px4/fmu-v4): PX4-Autopilot/boards/px4/fmu-v4/default.cmake(opens new window)
  • cmake files for other boards can be found in PX4-Autopilot/boards/

To enable the compilation of the application into the firmware create a new line for your application somewhere in the cmake file:

examples/px4_simple_app

Build the example using the board-specific command:

  • jMAVSim Simulator: make px4_sitl_default jmavsim
  • Pixhawk v1/2: make px4_fmu-v2_default (or just make px4_fmu-v2)
  • Pixhawk v3: make px4_fmu-v4_default
  • Other boards: Building the Code

代码测试

Enter px4_simple_app to run the minimal app.

pxh> px4_hello_app
INFO  [px4_simple_app] Hello Sky!

The application can now be extended to actually perform useful tasks

源代码如下:

#include <px4_platform_common/log.h>//The main function must be named <module_name>_main and exported from the module as shown.
__EXPORT int px4_hello_app_main(int argc, char *argv[]);
int px4_hello_app_main(int argc, char *argv[])
{PX4_INFO("Hello Sky! 666666");//打印输出(included from px4_platform_common/log.h)//有几种不同的形式:PX4_INFO, PX4_WARN, PX4_ERR, PX4_DEBUGreturn OK;
}

订阅传感器的信息

#include <px4_platform_common/log.h>//include用于PX4_INFO
#include <uORB/topics/sensor_combined.h> //订阅传感器用
#include <px4_platform_common/px4_config.h>
#include <px4_platform_common/tasks.h>
#include <px4_platform_common/posix.h>
#include <unistd.h>
#include <stdio.h>
#include <poll.h>
#include <string.h>#include <uORB/uORB.h>
#include <uORB/topics/sensor_combined.h>
#include <uORB/topics/vehicle_attitude.h>//The main function must be named <module_name>_main and exported from the module as shown.
__EXPORT int px4_hello_app_main(int argc, char *argv[]);
int px4_hello_app_main(int argc, char *argv[])
{PX4_INFO("Hello Sky! 666666");//打印输出(included from px4_platform_common/log.h)//有几种不同的形式:PX4_INFO, PX4_WARN, PX4_ERR, PX4_DEBUG//订阅传感器的信息int sensor_sub_fd = orb_subscribe(ORB_ID(sensor_combined));//有点类似ros中创建订阅者//“sensor_sub_fd”是一个消息句柄,能够十分有效处理新数据的到来之前的延迟等待。//当前线程会休眠,直到新的传感器数据到来时,被调度器唤醒,并且在等待时不需要占用任何的CPU时间。/* one could wait for multiple topics with this technique, just using one here */px4_pollfd_struct_t fds[] = {{ .fd = sensor_sub_fd,   .events = POLLIN },/* there could be more file descriptors here, in the form like:* { .fd = other_sub_fd,   .events = POLLIN },*/};int error_counter = 0;for (int i = 0; i < 5; i++) {/* wait for sensor update of 1 file descriptor for 1000 ms (1 second) */int poll_ret = px4_poll(fds, 1, 1000);/* handle the poll result */if (poll_ret == 0) {/* this means none of our providers is giving us data */PX4_ERR("[px4_simple_app] Got no data within a second");} else if (poll_ret < 0) {/* this is seriously bad - should be an emergency */if (error_counter < 10 || error_counter % 50 == 0) {/* use a counter to prevent flooding (and slowing us down) */PX4_ERR("[px4_simple_app] ERROR return value from poll(): %d", poll_ret);}error_counter++;} else {if (fds[0].revents & POLLIN) {/* obtained data for the first file descriptor */struct sensor_combined_s raw;/* copy sensors raw data into local buffer */orb_copy(ORB_ID(sensor_combined), sensor_sub_fd, &raw);PX4_WARN("[px4_simple_app] Accelerometer:\t%8.4f\t%8.4f\t%8.4f",(double)raw.accelerometer_m_s2[0],(double)raw.accelerometer_m_s2[1],(double)raw.accelerometer_m_s2[2]);}}}PX4_INFO("exiting");return OK;
}

PX4 系统架构概述

PX4 由两个主要部分组成:

  • 一是 飞行控制栈(flight stack) ,该部分主要包括状态估计和飞行控制系统;
  • 另一个是 中间件 ,该部分是一个通用的机器人应用层,可支持任意类型的自主机器人,主要负责机器人的内部/外部通讯和硬件整合。

所有的 PX4 支持的无人机机型(包括其他诸如无人船、无人车、无人水下航行器等平台)均共用同一个代码库。 整个系统采用了响应式(reactive)设计,这意味着:

  • 所有的功能都可以被分割成若干可替换、可重复使用的部件。
  • 通过异步消息传递进行通信。
  • 系统可以应对不同的工作负载。

顶层软件架构

下面的架构图对 PX4 的各个积木模块以及各模块之间的联系进行了一个详细的概述。 图的上半部分包括了中间件模块,而下半部分展示的则是飞行控制栈的组件。

上图中的箭头表示的是各个模块之间 最重要的 信息流连接。 实际运行时各模块之间信息流的连接数目比图中展示出来的要多很多,且部分数据(比如:配置参数)会被大部分模块访问。

PX4 系统通过一个名为 uORB 的 发布-订阅 消息总线实现模块之间的相互通讯。 使用 发布-订阅 消息总线这个方案意味着:

  • 系统是 “响应式” 的 — 系统异步运行,新数据抵达时系统立即进行更新。
  • 系统所有的活动和通信都是完全并行的。
  • 系统组件在任何地方都可以在保证线程安全的情况下使用数据。

飞行控制栈

飞行控制栈是针对自主无人机设计的导航、制导和控制算法的集合。 它包括了为固定翼、旋翼和 VTOL 无人机设计的控制器,以及相应的姿态、位置估计器。下图展示了飞行控制栈的整体架构, 它包含了从传感器数据、 RC 控制量输入 到自主飞行控制(制导控制器,Navigator ),再到电机、舵机控制(执行器,Actuators)的全套通路。

估计器 (estimator) 取一个或者多个传感器数据作为输入量,并进行数据融合进而计算出无人机的状态(例如:从 IMU 传感器数据计算得到无人机的姿态角)。

控制器 (controller) 组件以一个期望设定值和一个测量值或状态估计量(过程变量)作为输入, 它的目标是将过程变量的实际值调整到与期望设定值相一致, 得到的输出量实现对状态变量的矫正以使其最终抵达期望的设定值。 以位置控制器为例,该控制器以期望位置作为输入,过程变量是当前位置的估计值,控制器最终输出的是将引导无人机前往期望位置的姿态、油门指令。

混合器 (mixer) 响应力的指令(例如右转),并将其转换为单独的电机指令并保证产生的指令不超限。 每一类飞机都有特定的指令转换方式且受许多因素的影响,例如:电机关于重心的安装位置,飞机的惯性矩参数等。

中间件

中间件 主要包由载嵌入式传感器驱动、与外界的通讯(配套计算机, GCS 等)以及 uORB 发布-订阅 消息总线三部分组成。

此外,中间件还包括一个 仿真应用层 以实现在桌面操作系统运行 PX4 飞行代码并在计算机的模拟“世界”中控制由计算机建模得到的无人机。

参考资料

  • PX4 Github主页:PX4 Github (代码有分支,请查看v1.10.0分支)
  • PX4开发者手册:PX4手册 v1.11 (手册有分支,请查看v1.11.0分支)
  • PX4官方仿真教程 : PX4手册 - gazebo simulation
  • PX4环境配置可参考PX4手册 - getting_started,请选择1.11分支。

  • 创客的教程:https://www.ncnynl.com/archives/201709/2003.html

  • https://mp.weixin.qq.com/s/CTBrfBv8M-NOrtoEaOhpuQ

  • https://dev.px4.io/v1.11_noredirect/zh/

  • https://dev.px4.io/v1.11_noredirect/zh/concept/architecture.html

  • https://mp.weixin.qq.com/s/UT4ZI-hqzu2JswBSGcfj9g

ROS学习笔记之——PX4开发初入门相关推荐

  1. ROS学习笔记(八): ROS通信架构

    ROS学习笔记(八): ROS通信架构 文章目录 01 Node & Master 1.1 Node 1.2 Master 1.3 启动master和node 1.4 rosrun和rosno ...

  2. 【ROS学习笔记】(三)发布者Publisher的实现

    一.目标功能 ROS Master内有两个节点,一个是Subscriber(turtlesim),一个是Publisher,发布者通过程序实现发布Message,Message的内容包括线速度.角度, ...

  3. ROS学习笔记之——robot_localization包

    之前博客已经介绍过robot_pose_ekf功能包以及(extended)kalman滤波的原理< ROS学习笔记之--EKF (Extended Kalman Filter) node 扩展 ...

  4. Python学习笔记--10.Django框架快速入门之后台管理admin(书籍管理系统)

    Python学习笔记--10.Django框架快速入门之后台管理 一.Django框架介绍 二.创建第一个Django项目 三.应用的创建和使用 四.项目的数据库模型 ORM对象关系映射 sqlite ...

  5. ros学习笔记12——python实现发布和接收ros topic

    ros学习笔记12--python实现发布和接收ros topic 一.简单demo 1.工作空间是存放工程开发的相关文件的文件夹 2.创作工作空间指令 3 .创建功能包 4. 创建Topic的订阅发 ...

  6. Redis学习笔记①基础篇_Redis快速入门

    若文章内容或图片失效,请留言反馈.部分素材来自网络,若不小心影响到您的利益,请联系博主删除. 资料链接:https://pan.baidu.com/s/1189u6u4icQYHg_9_7ovWmA( ...

  7. Java 学习笔记:第一章 Java入门

    Java 学习笔记:第一章 Java入门 1.1 计算机语言发展史以及未来方向 1.2 常见编程语言介绍 C语言 C++ 语言 Java语言 PHP 语言 Object-C和Swift 语言 Java ...

  8. ROS学习笔记-ROS订阅和发布节点

    一个简单的ROS包,一个发布者,一个订阅者 刚开始学习ROS,参考网上的资料完成了测试节点的编写,记录一下. 个人习惯在home/Develop目录中做开发,于是在Develop目录下面创建了一个RO ...

  9. Python学习笔记:Day1-2 开发环境搭建

    前言 最近在学习深度学习,已经跑出了几个模型,但Pyhton的基础不够扎实,因此,开始补习Python了,大家都推荐廖雪峰的课程,因此,开始了学习,但光学有没有用,还要和大家讨论一下,因此,写下这些帖 ...

  10. Python学习笔记:web开发3

    前言 最近在学习深度学习,已经跑出了几个模型,但Pyhton的基础不够扎实,因此,开始补习Python了,大家都推荐廖雪峰的课程,因此,开始了学习,但光学有没有用,还要和大家讨论一下,因此,写下这些帖 ...

最新文章

  1. git ssh key创建和github使用
  2. bat文件注册为Windows服务与依赖关系设置
  3. 大数据领域可以应聘的岗位
  4. python笔记之 inputprintformat函数
  5. canal —— 阿里巴巴mysql数据库binlog的增量订阅消费组件
  6. MySQL进阶篇(03):合理的使用索引结构和查询
  7. Python创建list
  8. 【信息系统项目管理师】知识框架
  9. unigui发布_unigui+fastReport实现web打印方案
  10. 不确定性管理,更需要领导力
  11. C语言分支/顺序作业总结
  12. access有效性规则不为空值_在设置access有效性规则中,大于0并且小于100怎么写?...
  13. matplotlib使用笔记
  14. cropper(裁剪图片)插件使用(案例)
  15. 如何使用python的openpyxl进行强大的图表处理
  16. Unity 网格画图形
  17. jspdf添加宋体_JSPDF支持中文(思源黑体)采坑之旅,JSPDF中文字体乱码解决方案...
  18. Android | 音乐播放器(版本4)
  19. fmm3d在windows环境中的编译使用过程
  20. 为什么我们从 Python 切换到 Go

热门文章

  1. FTP 权限的修改 之CuteFTP问题
  2. java实现筑业软件官网下载,筑业资料软件2020旗舰版|筑业资料软件免费官方下载-系统族...
  3. 视频教程-网络工程师实战系列视频课程【VLAN专题】-网络技术
  4. 张宇:概率论与数理统计公式总结
  5. Struts 学习笔记之ActionForm
  6. 【✈躺平了,三分钟学bat脚本✈】adb shell 执行命令 + bat脚本延时操作
  7. java垃圾回收文件分析
  8. 计算机电子表格相关简答题,2017年计算机一级excel操作试题及答案
  9. CPCL简易打印模板设计
  10. PIN码-使用与解决办法