RPlidar学习(三)——RPlidar源代码库
1.头文件简介
rplidar.h//一般情况下开发的项目中仅需要引入该头文件即可使用 RPLIDAR SDK 的所有功能。
rptypes.h//平台无关的结构和常量定义
rplidar_protocol.h//定义了 RPLIDAR 通讯协议文档中描述的底层相关数据结构和常量定义。
rplidar_cmd.h//定义了 RPLIDAR 通讯协议文档中描述的各类请求/应答相关的数据结构和常量定义。
rplidar_driver.h//定义了 SDK 核心驱动接口: RPlidarDriver 的类声明。
2.头文件解析(代码理解加部分英文单词翻译)
(1)rplidar_protocol.h
#pragma once(避免同一个文件被include多次)
// RP-Lidar Input Packets(输入数据包)
#define RPLIDAR_CMD_SYNC_BYTE 0xA5(十六进制0x开头)//请求报文开始字节
#define RPLIDAR_CMDFLAG_HAS_PAYLOAD 0x80 //请求报文负载
#define RPLIDAR_ANS_SYNC_BYTE1 0xA5 //应答报文起始标志1
#define RPLIDAR_ANS_SYNC_BYTE2 0x5A //应答报文起始标志2
#define RPLIDAR_ANS_PKTFLAG_LOOP 0x1 //多次应答模式
#define RPLIDAR_ANS_HEADER_SIZE_MASK 0x3FFFFFFF
#define RPLIDAR_ANS_HEADER_SUBTYPE_SHIFT (30)
#if defined(_WIN32)
#pragma pack(1)//每个结构成员都必须限制在1个字节之内 ,也就是说储存在内存中是连续的
#endif
//请求报文格式
typedef struct _rplidar_cmd_packet_t {
_u8 syncByte; //must be RPLIDAR_CMD_SYNC_BYTE //起始标志
_u8 cmd_flag; //请求命令
_u8 size; //负载长度
_u8 data[0]; //请求负载数据
} __attribute__((packed)) rplidar_cmd_packet_t;//__attribute__ ((packed)) 的作用就是告诉编译器取消结构在编译过程中的优化对齐,按照实际占用字节数进行对齐
//使用之后才会是几字节就是几字节,否则就每个变量的字节长度都跟结构体中变量字节长度最长相同
//应答报文格式
typedef struct _rplidar_ans_header_t {
_u8 syncByte1; // must be RPLIDAR_ANS_SYNC_BYTE1(起始标志1)
_u8 syncByte2; // must be RPLIDAR_ANS_SYNC_BYTE2(起始标志2)
_u32 size_q30_subtype; // see _u32 size:30; _u32 subType:2;(应答报文长度)
_u8 type; //应答模式
} __attribute__((packed)) rplidar_ans_header_t;
#if defined(_WIN32)
#pragma pack()
#endif
//按照实际占用字节数进行对齐
(2)rplidar_cmd.h
#pragma once
#include "rplidar_protocol.h"
// Commands
//-----------------------------------------
// Commands without payload(负载) and response(响应)
#define RPLIDAR_CMD_STOP 0x25 //离开扫描模式,进入空闲状态
#define RPLIDAR_CMD_SCAN 0x20 //请求进入扫描采样状态
#define RPLIDAR_CMD_FORCE_SCAN 0x21 //请求进入扫描采样状态,强制数据输出
#define RPLIDAR_CMD_RESET 0x40 //测距核心软重启
// Commands without payload but have response
#define RPLIDAR_CMD_GET_DEVICE_INFO 0x50 //获取设备序列号等信息
#define RPLIDAR_CMD_GET_DEVICE_HEALTH 0x52 //获取设备健康状态
#define RPLIDAR_CMD_GET_SAMPLERATE 0x59 //added in fw 1.17获取单次激光测距的用时
// Commands with payload and have response
#define RPLIDAR_CMD_EXPRESS_SCAN 0x82 //added in fw 1.17请求进入扫描状态,幷工作在最高采样频率下
//add for A2 to set RPLIDAR motor pwm(脉宽调变) when using accessory board(开发系统)
#define RPLIDAR_CMD_SET_MOTOR_PWM 0xF0// 设置PWM
#define RPLIDAR_CMD_GET_ACC_BOARD_FLAG 0xFF//系统标志
#if defined(_WIN32)
#pragma pack(1)
#endif
// Payloads
// ------------------------------------------
#define RPLIDAR_EXPRESS_SCAN_MODE_NORMAL (正常模式) 0
#define RPLIDAR_EXPRESS_SCAN_MODE_FIXANGLE(固定角度) 1
typedef struct _rplidar_payload_express_scan_t { //带有负载的数据包
_u8 working_mode;
_u32 reserved;
} __attribute__((packed)) rplidar_payload_express_scan_t;
#define MAX_MOTOR_PWM 1023//电机脉宽最大值
#define DEFAULT_MOTOR_PWM 660//电机脉宽默认值
//电机PWM结构
typedef struct _rplidar_payload_motor_pwm_t {
_u16 pwm_value;
} __attribute__((packed)) rplidar_payload_motor_pwm_t;
//开发系统标志
typedef struct _rplidar_payload_acc_board_flag_t {
_u32 reserved;
} __attribute__((packed)) rplidar_payload_acc_board_flag_t;
// Response
// ------------------------------------------
#define RPLIDAR_ANS_TYPE_DEVINFO 0x4//设备信心获取 起始应答结尾
#define RPLIDAR_ANS_TYPE_DEVHEALTH 0x6//设备健康状态获取 起始应答结尾
#define RPLIDAR_ANS_TYPE_MEASUREMENT 0x81//普通采集
// Added in FW ver 1.17
#define RPLIDAR_ANS_TYPE_MEASUREMENT_CAPSULED 0x82//高速采集
// Added in FW ver 1.17
#define RPLIDAR_ANS_TYPE_SAMPLE_RATE 0x15
#define RPLIDAR_ANS_TYPE_ACC_BOARD_FLAG 0xFF
#define RPLIDAR_RESP_ACC_BOARD_FLAG_MOTOR_CTRL_SUPPORT_MASK (0x1)
typedef struct _rplidar_response_acc_board_flag_t {
_u32 support_flag;
} __attribute__((packed)) rplidar_response_acc_board_flag_t;
//设备状态
#define RPLIDAR_STATUS_OK 0x0
#define RPLIDAR_STATUS_WARNING 0x1
#define RPLIDAR_STATUS_ERROR 0x2
#define RPLIDAR_RESP_MEASUREMENT_SYNCBIT (0x1<<0)
#define RPLIDAR_RESP_MEASUREMENT_QUALITY_SHIFT 2
#define RPLIDAR_RESP_MEASUREMENT_CHECKBIT (0x1<<0)
#define RPLIDAR_RESP_MEASUREMENT_ANGLE_SHIFT 1
//激光测距用时获取数据包
typedef struct _rplidar_response_sample_rate_t {
_u16 std_sample_duration_us; //在标准扫描模式下,设备测距核心进行单次激光测距的耗时 单位:微秒
_u16 express_sample_duration_us;//在高速采样模式下,设备测距核心进行单次激光测距的耗时 单位:微妙
} __attribute__((packed)) rplidar_response_sample_rate_t;
//激光测距测量节点数据包
typedef struct _rplidar_response_measurement_node_t {
_u8 sync_quality; // syncbit:1;syncbit_inverse:1;quality:6;//信号质量
_u16 angle_q6_checkbit; // check_bit:1;angle_q6:15;//测距点相对于RPLIDAR朝向夹角 实际角度 = angle_q6 / 64.0 Deg
_u16 distance_q2;//测距点相对于RPLIDAR的距离 实际距离 = distance_q2 / 4.0 mm
} __attribute__((packed)) rplidar_response_measurement_node_t;
//[distance_sync flags]
#define RPLIDAR_RESP_MEASUREMENT_EXP_ANGLE_MASK (0x3)
#define RPLIDAR_RESP_MEASUREMENT_EXP_DISTANCE_MASK (0xFC)
// 激光测距小屋测量节点数据包
typedef struct _rplidar_response_cabin_nodes_t {
_u16 distance_angle_1; // see [distance_sync flags]
_u16 distance_angle_2; // see [distance_sync flags]
_u8 offset_angles_q3;
} __attribute__((packed)) rplidar_response_cabin_nodes_t;
#define RPLIDAR_RESP_MEASUREMENT_EXP_SYNC_1 0xA
#define RPLIDAR_RESP_MEASUREMENT_EXP_SYNC_2 0x5
#define RPLIDAR_RESP_MEASUREMENT_EXP_SYNCBIT (0x1<<15)
// 激光测距容器测量节点数据包
typedef struct _rplidar_response_capsule_measurement_nodes_t {
_u8 s_checksum_1; // see [s_checksum_1]
_u8 s_checksum_2; // see [s_checksum_1]
_u16 start_angle_sync_q6;
rplidar_response_cabin_nodes_t cabins[16];
} __attribute__((packed)) rplidar_response_capsule_measurement_nodes_t;
//设备信息数据报文
typedef struct _rplidar_response_device_info_t {
_u8 model;
_u16 firmware_version;
_u8 hardware_version;
_u8 serialnum[16];
} __attribute__((packed)) rplidar_response_device_info_t;
//设备健康信息数据报文
typedef struct _rplidar_response_device_health_t {
_u8 status;
_u16 error_code;
} __attribute__((packed)) rplidar_response_device_health_t;
#if defined(_WIN32)
#pragma pack()
#endif
(3)rplidar_driver.h
#pragma once
#ifndef __cplusplus
#error "The RPlidar SDK requires a C++ compiler to be built"
#endif
namespace rp { namespace standalone{ namespace rplidar {
class RPlidarDriver {
public:
enum {
DEFAULT_TIMEOUT = 2000, //枚举量默认超时时间2000 ms
};
enum {
DRIVER_TYPE_SERIALPORT = 0x0,//枚举量驱动程序类型串口为0x0(linux被驱动使用的连接类型)
};
public:
/// Create an RPLIDAR Driver Instance(实例)
/// This interface(接口) should be invoked(调用) first before any other operations(操作)
///
/// \param(参数) drivertype(驱动类型)( the connection type used by the driver.
static RPlidarDriver * CreateDriver(_u32 drivertype = DRIVER_TYPE_SERIALPORT);//静态创建对象接口
/// Dispose the RPLIDAR Driver Instance specified by the drv parameter
/// Applications should invoke this interface when the driver instance is no longer used in order to free memory
static void DisposeDriver(RPlidarDriver * drv);//处理驱动程序//静态接口函数析构RPlidar实例
public:
/// Open the specified serial port and connect to a target RPLIDAR device
///
/// \param port_path the device path of the serial port
/// e.g. on Windows, it may be com3 or \\.\com10
/// on Unix-Like OS, it may be /dev/ttyS1, /dev/ttyUSB2, etc
///
/// \param baudrate(波特率) the baudrate used
/// For most RPLIDAR models, the baudrate should be set to 115200
///
/// \param flag(标志) other flags
/// Reserved for future use, always set to Zero
virtual u_result connect(const char * port_path, _u32 baudrate, _u32 flag = 0) = 0;//设备连接函数,调用时会默认停止电机旋转,测试时需要使用startMotor启动电机旋转
/// Disconnect with the RPLIDAR and close the serial port(断开连接并关上串口端)
virtual void disconnect() = 0;//断开连接
/// Returns TRUE when the connection has been established(连接已建立)
virtual bool isConnected() = 0;
/// Ask the RPLIDAR core system to reset it self
/// The host system can use the Reset operation to help RPLIDAR escape the self-protection mode.
///
// \param timeout The operation timeout value (in millisecond) for the serial port communication
virtual u_result reset(_u32 timeout = DEFAULT_TIMEOUT) = 0;//超时重置
/// Retrieve(恢复) the health status of the RPLIDAR
/// The host system can use this operation to check whether RPLIDAR is in the self-protection mode.
///
/// \param health The health status info returned from the RPLIDAR
///
/// \param timeout The operation timeout value (in millisecond) for the serial port communication
virtual u_result getHealth(rplidar_response_device_health_t & health, _u32 timeout = DEFAULT_TIMEOUT) = 0;//获取 RPLIDAR 设备的健康状态
///
/// Get the device information of the RPLIDAR include the serial number, firmware version, device model etc.
///
/// \param info The device information returned from the RPLIDAR
///
/// \param timeout The operation timeout value (in millisecond) for the serial port communication
virtual u_result getDeviceInfo(rplidar_response_device_info_t & info, _u32 timeout = DEFAULT_TIMEOUT) = 0;//获取 RPLIDAR 设备序列号、固件版本等信息
/// Get the sample(样本) duration(持续时间) information of the RPLIDAR.
///
/// \param rateInfo The sample duration information returned from the RPLIDAR
///
/// \param timeout The operation timeout value (in millisecond) for the serial port communication
virtual u_result getSampleDuration_uS(rplidar_response_sample_rate_t & rateInfo, _u32 timeout = DEFAULT_TIMEOUT) = 0;//获取 RPLIDAR 分别在标准 Scan 以及 ExpressScan 模式下单次激光采样的用时。 单位为微秒(uS)
/// Set the RPLIDAR's motor pwm when using accessory board, currently valid for A2 only.
///
/// \param pwm(脉宽) The motor(电机) pwm value would like to set
virtual u_result setMotorPWM(_u16 pwm) = 0;//向开发套件的 USB 附件板发送特定的 PWM 占空比,控制RPLIDAR 扫描电机转速
/// Start RPLIDAR's motor when using accessory(附件) board
virtual u_result startMotor() = 0;//启动电机
/// Stop RPLIDAR's motor when using accessory board
virtual u_result stopMotor() = 0;//停止电机
/// Check whether the device support motor control.
/// Note: this API will disable grab.
///
/// \param support Return the result.
/// \param timeout The operation timeout value (in millisecond) for the serial port communication.
virtual u_result checkMotorCtrlSupport(bool & support, _u32 timeout = DEFAULT_TIMEOUT) = 0;//检测附件板是否支持电机 PWM 控制。
/// Calcuate(计算) RPLIDAR's current scanning frequency from the given scan data
/// Please refer to the application note doc for details
/// Remark: the calcuation will be incorrect if the specified scan data doesn't contains enough data
///
/// \param inExpressMode Indicate whether the RPLIDAR is in express mode(表达模式)
///
/// \param count The number of sample nodes inside the given buffer(缓冲区)
///
/// \param frequency The scanning frequency (in HZ) calcuated by the interface.
///
/// \param is4kmode Return whether the RPLIDAR is working on 4k sample rate mode.
virtual u_result getFrequency(bool inExpressMode, size_t count, float & frequency, bool & is4kmode) = 0;//从实现抓取的一圈扫描数据序列计算 RPLIDAR 的转速
/// Ask the RPLIDAR core system to enter the scan mode(Normal/Express, Express mode is 4k mode)
/// A background thread(后台线程) will be created by the RPLIDAR driver to fetch(获取) the scan data continuously.
/// User Application(应用) can use the grabScanData() interface to retrieved(恢复) the scan data cached(隐藏) previous by this background thread.
///
/// \param force Force the core system to output scan data regardless whether the scanning motor is rotating or not.(旋转与否)
///
/// \param autoExpressMode Force the core system to trying express mode first, if the system does not support express mode, it will use normal mode.
///
/// \param timeout The operation timeout value (in millisecond) for the serial port communication.
virtual u_result startScan(bool force = false, bool autoExpressMode = true) = 0;
virtual u_result startScanNormal(bool force, _u32 timeout = DEFAULT_TIMEOUT) = 0;
virtual u_result startScanExpress(bool fixedAngle, _u32 timeout = DEFAULT_TIMEOUT) = 0;
/// Check whether the device support express mode.
///
/// \param support Return the result.
///
/// \param timeout The operation timeout value (in millisecond) for the serial port communication.
virtual u_result checkExpressScanSupported(bool & support, _u32 timeout = DEFAULT_TIMEOUT) = 0;
/// Ask the RPLIDAR core system to stop the current scan operation and enter idle state(空闲状态). The background thread will be terminated(终止)
///
/// \param timeout The operation timeout value (in millisecond) for the serial port communication
virtual u_result stop(_u32 timeout = DEFAULT_TIMEOUT) = 0;
/// Wait and grab a complete 0-360 degree scan data previously received.
/// The grabbed scan data returned by this interface always has the following charactistics:
///
/// 1) The first node of the grabbed data array (nodebuffer[0]) must be the first sample of a scan, i.e. the start_bit == 1
/// 2) All data nodes are belong to exactly ONE complete 360-degrees's scan
/// 3) Note, the angle data in one scan may not be ascending(上升). You can use API(应用程序界面) ascendScanData to reorder the nodebuffer.
///
/// \param nodebuffer(存储扫描数据的缓冲区 ) Buffer provided by the caller application to store the scan data
///
/// \param count The caller must initialize this parameter to set the max data count of the provided buffer (in unit of rplidar_response_measurement_node_t).
/// Once the interface returns, this parameter will store the actual received data count.
///
/// \param timeout Max duration allowed to wait for a complete scan data, nothing will be stored to the nodebuffer if a complete 360-degrees' scan data cannot to be ready timely.
///
/// The interface will return RESULT_OPERATION_TIMEOUT to indicate that no complete 360-degrees' scan can be retrieved withing the given timeout duration(持续时间).
///
/// \The caller application can set the timeout value to Zero(0) to make this interface always returns immediately to achieve non-block operation.
virtual u_result grabScanData(rplidar_response_measurement_node_t * nodebuffer, size_t & count, _u32 timeout = DEFAULT_TIMEOUT) = 0;
/// Ascending the scan data according to the angle value in the scan.
///
/// \param nodebuffer Buffer provided by the caller application to do the reorder. Should be retrived(索取) from the grabScanData
///
/// \param count The caller must initialize this parameter to set the max data count of the provided buffer (in unit of rplidar_response_measurement_node_t).
/// Once the interface returns, this parameter will store the actual received data count.
/// The interface will return RESULT_OPERATION_FAIL when all the scan data is invalid.
virtual u_result ascendScanData(rplidar_response_measurement_node_t * nodebuffer, size_t count) = 0;
protected:
RPlidarDriver() {}
virtual ~RPlidarDriver() {}//此函数将在源文件中使用但不在此类中使用
};
}}}
(4)rptypes.h
#pragma once
#ifdef _WIN32
//fake stdint.h for VC only
typedef signed char int8_t;
typedef unsigned char uint8_t;
typedef __int16 int16_t;
typedef unsigned __int16 uint16_t;
typedef __int32 int32_t;
typedef unsigned __int32 uint32_t;
typedef __int64 int64_t;
typedef unsigned __int64 uint64_t;
#else
#include <stdint.h>//定义int8 uint8等类型
#endif
//based on stdint.h
typedef int8_t _s8;
typedef uint8_t _u8;
typedef int16_t _s16;
typedef uint16_t _u16;
typedef int32_t _s32;
typedef uint32_t _u32;
typedef int64_t _s64;
typedef uint64_t _u64;
#define __small_endian
#ifndef __GNUC__
#define __attribute__(x)
#endif
// The _word_size_t uses actual data bus width of the current CPU
#ifdef _AVR_
typedef _u8 _word_size_t;
#define THREAD_PROC
#elif defined (WIN64)
typedef _u64 _word_size_t;
#define THREAD_PROC __stdcall
#elif defined (WIN32)
typedef _u32 _word_size_t;
#define THREAD_PROC __stdcall
#elif defined (__GNUC__)
typedef unsigned long _word_size_t;
#define THREAD_PROC
#elif defined (__ICCARM__)
typedef _u32 _word_size_t;
#define THREAD_PROC
#endif
typedef uint32_t u_result;
#define RESULT_OK 0
#define RESULT_FAIL_BIT 0x80000000
#define RESULT_ALREADY_DONE 0x20
#define RESULT_INVALID_DATA (0x8000 | RESULT_FAIL_BIT)
#define RESULT_OPERATION_FAIL (0x8001 | RESULT_FAIL_BIT)
#define RESULT_OPERATION_TIMEOUT (0x8002 | RESULT_FAIL_BIT)
#define RESULT_OPERATION_STOP (0x8003 | RESULT_FAIL_BIT)
#define RESULT_OPERATION_NOT_SUPPORT (0x8004 | RESULT_FAIL_BIT)
#define RESULT_FORMAT_NOT_SUPPORT (0x8005 | RESULT_FAIL_BIT)
#define RESULT_INSUFFICIENT_MEMORY (0x8006 | RESULT_FAIL_BIT)
#define IS_OK(x) ( ((x) & RESULT_FAIL_BIT) == 0 )
#define IS_FAIL(x) ( ((x) & RESULT_FAIL_BIT) )
typedef _word_size_t (THREAD_PROC * thread_proc_t ) ( void * );
(5)rplidar.h
#pragma once
#include "rptypes.h"
#include "rplidar_protocol.h"
#include "rplidar_cmd.h"
#include "rplidar_driver.h"
#define RPLIDAR_SDK_VERSION "1.5.7"
由此可见,在编程rplidar的相关代码时只需调用rplidar.h即可,但必须清楚其中所包含的其他头文件所含参数的意义,不然无法看懂相关C++代码文件。。。
RPlidar学习(三)——RPlidar源代码库相关推荐
- SQLite学习(三) - SQLite源代码文件结构
SQLite Version3.3.6源代码文件结构 文件名称 大小byte 备注 API main.c 35414 SQLite Library的大部分接口 legacy.c 3734 sq ...
- 强化学习(三) - Gym库介绍和使用,Markov决策程序实例,动态规划决策实例
强化学习(三) - Gym库介绍和使用,Markov决策程序实例,动态规划决策实例 1. 引言 在这个部分补充之前马尔科夫决策和动态规划部分的代码.在以后的内容我会把相关代码都附到相关内容的后面.本部 ...
- 微软企业库4.1学习笔记(三)企业库迁移和并行使用,以及企业库的扩展
一.迁移和并行使用 通常来说,企业库是建立在.NET 2.0 的基础上,使用后续版本的企业库也不需要改变任何代码.不需要将引用更新到新的程序集,也不需要在配置文件中指明程序集的正确版本. 这个版本4. ...
- 多线程编程学习笔记——任务并行库(三)
接上文 多线程编程学习笔记--任务并行库(一) 接上文 多线程编程学习笔记--任务并行库(二) 六. 实现取消选项 本示例学习如何实现基于Task的异步操作进行取消流程,以及在任务真正运行前如何知 ...
- 【开源】Caffe、TensorFlow、MXnet三个开源库对比
from:http://www.wtoutiao.com/p/1cbxddO.html 最近Google开源了他们内部使用的深度学习框架TensorFlow[1],结合之前开源的MXNet[2]和Ca ...
- 3D视觉学习计划之PCL库的基础知识
3D视觉学习计划之PCL库的基础知识 一.PCL库的概述 PCL是一个大型跨平台开源C++编程库,它在吸收了前人点云相关研究基础上建立起来,实现了大量点云相关的通用算法和高效数据结构,涉及到点云获取. ...
- 深度学习Deep Learning 相关库简介
本文将从deep learning 相关工具库的使用者角度来介绍下github上stars数排在前面的几个库(tensorflow, keras, torch, theano, skflow, las ...
- 【技术综述】图像与CNN发家简史,集齐深度学习三巨头
文章首发于微信公众号<有三AI> [技术综述]图像与CNN发家简史,集齐深度学习三巨头 没有一个经典的发现会是突然之间横空出世,它总是需要一些积淀. 提起卷积神经网络,我们总会从LeNet ...
- 多线程编程学习笔记——任务并行库(二)
接上文 多线程编程学习笔记--任务并行库(一) 三. 组合任务 本示例是学习如何设置相互依赖的任务.我们学习如何创建一个任务的子任务,这个子任务必须在父任务执行结束之后,再执行. 1,示例代码如下 ...
- IOS学习:常用第三方库(GDataXMLNode:xml解析库)
IOS学习:常用第三方库(GDataXMLNode:xml解析库) 解析 XML 通常有两种方式,DOM 和 SAX: DOM解析XML时,读入整个XML文档并构建一个驻留内存的树结构(节点树),通过 ...
最新文章
- Android微信智能心跳方案 Android微信智能心跳方案
- 关于软件工程课程的期望
- Webix 1.5发布:一个强大的JavaScript UI组件库
- String类及其构造器和常用方法
- cesium面板动态显示并跟随移动
- 限流算法(漏桶算法、令牌桶算法)对比
- 【报告分享】2021新青年国货消费研究报告:文化觉醒时代,宝藏国货迎复兴机遇.pdf(附下载链接)...
- 蓝桥杯 ALGO-42 算法训练 送分啦
- 1128. 等价多米诺骨牌对的数量
- Docker 容器的数据管理
- [Android动画] 补间动画-动画工具类( AnimationUtils)七
- .NET使用存储过程实现对数据库的增删改查
- 随机森林模型解释_随机森林解释
- 年终工作总结汇报和述职报告ppt模板,内含范文可参考,精选20套可下载
- JDK1.8 下载及安装步骤
- 怎么关闭vivo系统自检_MIUI11系统已发布,你怎么能不会这个一键关闭广告的功能呢!...
- c语言电话簿管理系统的,C语言 电话簿管理系统VC++6.0运行通过
- OpenStack | Placement组件
- 基于STM32之控制步进电机,学到即赚到!(含主代码)
- C++实现二叉树 前、中、后序遍历(递归与非递归)非递归实现过程最简洁版本
热门文章
- 修改django后台管理员密码
- 百度计算机视觉算法工程师面试题(秋招)
- 需求调研第二篇--调研准备阶段避免哪些错误
- MindMaster Pro 8.0.0 — 亿图思维导图
- 天正坐标标注怎么不显示_cad中坐标标注怎么显示不了xy的
- Unsupervised Deep Homography - Pytorch实现
- win7系统修复工具_win7系统如何修复
- 程序员的自我修养(收藏)
- 台式计算机网卡型号怎么查找,怎么确定台式机无线网卡驱动版本 台式机无线网卡驱动版本查看方法...
- w7计算机应用放大按键,设置Win7放大功能 老年人用电脑更方便