如何学习开源代码?
关于如何学习开源代码?
对此我简单的以为学习开源代码就是把代码看懂,但是一旦面对工程量庞大的代码,一下子就没有任何的头绪了,而且并没有任何学长教我们,查AI似乎也不太有效果,我就去请教了下老师。经过一下午的学习,我对开源代码学习又有了一个新的认识。
如何开始?
我们用这份开源项目来做个例子(也是我正在看的)
对于一份正经的开源项目,一定会有一份完善的README文件。例如,通过这份README文档,我们可以获得以下信息
- 硬件配置
- 环境部署
- 调节参数
- 环境配置
- 文件结构
通过这些信息,我们可以大概了解整个程序所需要的配置以及它能实现的功能。如果遇到什么陌生的东西(对于我来说例如线程延时、Eigen、Cere…),这个时候我们就要自去通过各种手段去查阅相关资料去了解,这比无脑的去看还是强太多了。
Next
首先,我们需要明白什么叫做程序。程序,就是数据结构+算法+逻辑。我认为,如果我们想看懂某个项目的代码,首先就需要明确整个项目的逻辑,也就是整个代码的主程序入口(bash)。只有梳理好整个代码的逻辑,我们才能做到代码在心中杂而不乱。
接下来我们来看看代码的文件结构
文件结构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
| . ├── auto_start.sh //自启动脚本 ├── CMakeLists.txt ├── README.md └── src ├── armor_detector // 自瞄 │ ├── CMakeLists.txt │ ├── include │ │ ├── ArmorFinder.h │ │ ├── DetectAccelerator.h │ │ ├── Detector.h │ │ ├── EnemyType.h │ │ ├── LightBarFinder.h │ │ ├── NumberClassifier.h │ │ └── TargetBumper.h │ └── src │ ├── ArmorFinder.cpp // 灯条匹配装甲板 │ ├── DetectAccelerator.cpp // ROI提取 │ ├── Detector.cpp // 自瞄子线程 │ ├── LightBarFinder.cpp // 预处理 & 筛选灯条 │ ├── NumberClassifier.cpp // HOG + SVM 数字分类 │ └── TargetBumper.cpp // 优先级判断 ├── AutoAim.cpp // 主程序,生成子线程 ├── AutoAim.h ├── buff // 能量机关 │ ├── CMakeLists.txt │ ├── include │ │ ├── AdaptiveEKF.hpp │ │ ├── buffAngleKalman.h │ │ ├── buffArmorNode.h │ │ ├── buffClassifier.h │ │ ├── buffCompensation.h │ │ ├── buffCurver.h │ │ ├── buffDetector.h │ │ ├── buffEKF.h │ │ ├── buffKalman.h │ │ └── buffPredictor.h │ └── src │ ├── buffAngleKalman.cpp │ ├── buffClassifier.cpp // 能量机关SVM分类器 │ ├── buffCompensation.cpp // 能量机关补偿计算 │ ├── buffCurver.cpp // 正弦曲线拟合 │ ├── buffDetector.cpp // 能量机关识别器 │ ├── buffEKF.cpp // 能量机关EKF角度滤波,已弃用 │ ├── buffKalman.cpp // 能量机关KF角度滤波,已弃用 │ └── buffPredictor.cpp // 能量机关预测器 ├── driver │ ├── CMakeLists.txt │ ├── include │ │ ├── DxImageProc.h │ │ ├── GxCamera.h │ │ ├── GxIAPI.h │ │ ├── SerialPort.h │ │ └── VideoCapture.h │ └── src │ ├── GxCamera.cpp // 大恒相机软件驱动 │ ├── SerialPort.cpp // 串口通信线程 │ └── VideoCapture.cpp // 采集图像线程 ├── lcm // LCM通信模块,用以发送信息给自己电脑debug使用,需要配合QT小程序使用 │ ├── CMakeLists.txt │ ├── example_t.lcm │ ├── exlcm │ │ └── example_t.hpp │ ├── info.hpp │ ├── lcm_module.cpp │ └── lcm_module.h ├── pose_estimate // 位姿估计 │ ├── CMakeLists.txt │ ├── include │ │ ├── AdaptiveEKF.hpp │ │ ├── CTModel.h │ │ ├── ExtendedKalman.hpp │ │ ├── NormalEKF.h │ │ ├── NormalKalman.h │ │ ├── PitchYawFilter.h │ │ ├── PoseSolver.h │ │ ├── Predictor.h │ │ ├── SecondFilter.h │ │ └── STF.hpp //强跟踪滤波器有关文件 │ └── src │ ├── CTModel.cpp // CT运动模型估计小陀螺的旋转,已弃用 │ ├── NormalEKF.cpp // EKF滤波进行状态估计(参考上交) │ ├── NormalKalman.cpp // CV模型进行状态估计,已被EKF代替 │ ├── PitchYawFilter.cpp │ ├── PoseSolver.cpp │ ├── Predictor.cpp │ └── SecondFilter.cpp // 卡尔曼滤波进行低通滤波 └── utils ├── CMakeLists.txt ├── destroy // 部分以后可能有参考价值的弃用代码 │ ├── AdaptiveEKF.hpp │ ├── CAModel.cpp // CA运动模型 │ ├── CAModel.h │ ├── CTModel.cpp // CT旋转估计模型 │ ├── CTModel.h │ ├── README.md │ ├── SingerExtendedFilter.cpp // Singer模型(EKF) │ ├── SingerExtendedFilter.h │ ├── SingerFilter.cpp // Singer模型(KF) │ └── SingerFilter.h ├── include │ ├── Config.h │ ├── LockFreeQueue.hpp // 无锁循环队列 │ ├── Log.h │ ├── Params.h │ └── Timer.h ├── src │ ├── Config.cpp // 配置文件读取 │ ├── Log.cpp // 日志 │ ├── Params.cpp // 参数定义 │ └── Timer.cpp // 计时器,用来计算帧率; 或作为计数器,用来分频 └── tools ├── buff_model.xml // 能量机关SVM模型 ├── init.json // 配置文件 └── svm_numbers.xml // 数字分类SVM模型
|
大致分为了自瞄、能量机关、驱动、位姿估计、LCM通信等五个模块,其中我们很容易的去找到它的主程序文件AutoAim.cpp,我们直接打开。
[
]
最良心的是每个代码都有一定的注释,一定程度上为学习者提供了便利。这样以来,我们就可以正式的、愉快的开始看代码(看代码是逃不掉的,但是这样看代码一定能把逻辑捋顺)。通过VSCode的快捷功能(Ctrl+鼠标左键),遇到新定义的结构体和类时可以快速索引。我们学习的不仅仅是算法,对于我们这样的编程小白来说,代码的结构和编写方式也很重要。总的来说,我们围绕着三个方面来进行学习。(老师给我总结的,我要好好谢谢老师)
-WHAT(代码层面,对编程语言的掌握要熟练)
所编写的这个是什么,是结构体?还是类?我代码编写所用到的知识是什么?我要知道我看的是什么?如果其中有自己的知识盲点,我们就需要下去搜集相关的信息去了解学习,一步一步推进。
-HOW(算法层面)
我们这个代码某个结构体或类,是如何实现的?这一部是需要我们去研究模仿的一步,它涉及到代码的设计。
-WHY(理解层面,对数据结构的掌握熟练)
这个代码为什么要这样编写?有什么作用?