- 博客(51)
- 收藏
- 关注
原创 FastPlanner的一些技术细节(有图有真相)
作为一种经典且热门的无人机路径规划算法,FastPlanner在许多文章中已经被重点介绍。本人研读FastPlanner的论文和代码后给出了一些补充。
2025-02-06 22:36:46
849
原创 从角速度向量的角度理解姿态角速度和机体角速度的转换公式
这是一篇半copy半原创的文章,讲述了如何理解姿态角速度到机体角速度的转换公式。文章中资料的来源是北航全权老师著的《多旋翼飞行器设计与控制》(第一版第91页)原文中并没有给公式推导以足够的解释,让我难以理解。我在实验室苦苦思考了两天,终于想明白了一点,遂写为文章。
2024-09-24 22:40:44
1287
原创 如何使用yolov5-master进行训练
主要记录配置完成的yolov5-master如何进行自定义数据集训练。本人使用的设备是jetson-orin AGX,系统是英伟达官方魔改过的ubuntu18.04.。
2024-08-12 19:58:57
1425
1
原创 pytorch中的面向对象编程方法
我们可以经常在python代码片段中看到类的定义,其中第一个被定义的方法往往是__init__,如下所示:我们知道__init__显然是类的构造函数,但为什么要在前后都加上双下划线呢?原来这是python设计的一种特殊方法,它别称为魔法方法,它可以被运算符隐式调用,下面给出示例:可以发现,所谓魔法方法,实质上实现的就是c++中运算符重载的功能。 它让test.__getitem__(2)和test[2]这两种语法都能调用该方法!对于更多的python的魔法方法,可以看看下面这一篇文章:Pytho
2024-07-23 20:52:45
1283
1
原创 关于CMakeLists的基础知识
介绍了ros2中的CMakeLists,着重介绍了基础知识。由浅入深地介绍了什么是cmake,为什么要用cmake
2024-06-25 22:51:38
1181
原创 模拟电路PN结:为什么自由电子由N区移动至P区,就有空穴由P区移动至N区?
简单而并不严谨地解释了“自由电子由N区移动至P区,就有空穴由P区移动至N区”
2024-03-04 15:21:04
2475
2
原创 C/C++函数指针以及如何解决C++泛型编程中的多样化参数问题
笔者最近需要在ubuntu平台上写一个类似于TimeSetEvent的计时器,实现按一定频率重复执行回调函数的功能。这就需要运用C/C++函数指针的性质。由于笔者希望计时器预留给回调函数的接口可以适配任何函数,所以需要使用C++泛型编程的性质并解决回调函数参数多样化的问题。这篇文章是笔者解决问题的学习笔记和记录,欢迎交流和指正。
2024-01-22 16:30:33
1122
原创 Cpp多线程(一)
对于thread构造函数,其第一个参数为所执行函数的名称(可能是引用),后面的参数则为所执行函数的参数。对于线程,C++用类来描述,创建了一个Thread类的对象,即是新增了一个线程。上面这个例子,我们可以说吗,托thread1的福,thread2也得以运行完毕,但是如果thread2运行得慢一点,那么thread2依旧无法执行完毕。可以看出,位于join之前的one和two还是可以被打印的,而three要等到thread1和thread2执行完毕,才被打印。上面这张图就解释了线程和多线程的意义。
2024-01-17 23:00:00
1342
1
原创 一元线性回归计算·Cpp实现
闲来无事地时候写了一个一元线性回归的类,我上传了源代码和具体的使用方法。显然,这个程序的功能是很弱鸡的,有兴趣的同学可以看一看,玩一玩!
2023-09-08 22:52:56
314
原创 手搓cpp数据结构库·记录1
由于array指针往往被分配了内存空间,而使用值传参调用的默认复制构造函数只会进行浅复制,所以传入参数中的array指针所指空间和原有的array指针所指空间是一致的。而在传参完毕后,这个参数——一个临时构造的myStackNode类对象实例将会按照该类型析构函数释放空间(你肯定规定了析构函数要主动释放array指针所指空间,不然会造成内存泄漏),那么,原有类对象实例的空间会被提前释放。通常多文件编程时,会把类的定义放到头文件中,把类方法的定义放到cpp文件中,只在头文件中留下类方法的声明。
2023-08-30 13:27:37
189
原创 Python迭代器
需要注意的是,除了这两个方法,迭代器还可以实现其他方法,例如__iter__()方法用于初始化迭代器对象。但是,无论迭代器实现了哪些其他方法,只要它实现了__iter__()方法和__next__()方法,并且方法名正确,就可以被认为是迭代器。迭代器必须包含__iter__()方法和__next__()方法,这在下面会详细介绍。根据迭代器协议,一旦类中定义了__iter__()方法和__next__()方法,并且方法名正确,python就会把这个类视为迭代器类。可迭代对象不一定是一个迭代器。
2023-08-19 09:34:03
123
原创 Python修饰器和修饰函数
可以这样理解,@fun_d1修饰的是@fun_d2和fun函数组成的整体,先运行fun_d1中的wrap,直至发现func(),然后开始运行@fun_d2修饰函数。此般操作,相当于不直接执行sort_test函数,而是把sort_test函数作为一个参数传入修饰函数runtime_of_sorttest,然后由修饰函数及其嵌套函数决定其是否执行,何时执行。也就是说,fun_d1中的func参数,代表是@fun_d2和fun函数组成的整体,而fun_d2中的fun参数,代表的是fun啊哈纳树本身!
2023-08-13 18:40:12
703
1
原创 从C到Cpp——十七、抽象基类
如果把Student设置为抽象基类,那么就不允许创建Student对象,只能派生出各种各样的Student子类,比如CS_Student、EE_Student、ME_Student等等,然后创建派生类的对象。尽管set_age函数被声明为虚,而a是Student类型的指针,a->set_age(20)应该调用纯虚函数中的方法,但由于派生类中set_age没有被定义,最终函数还是调用了基类的方法。C++中还有一种基类,它不允许自己被创建具体的对象,但它的派生类可以被创建对象。4--纯虚函数也可以有定义。
2023-07-15 09:33:31
190
原创 从C到Cpp——十六、类继承(二)虚方法和protected访问控制
在正常情况下(也就是类方法不添加任何限定词),派生类类型的指针和引用可以调用基类和派生类的方法(所以它只能指向派生类对象),但基类类型的指针和引用只能调用基类的方法,不管它具体指向的是派生类对象还是基类对象。如果用基类指针指向一个派生类对象,那么本来是只能调用基类方法的,但如果加上virtual,由于现在调用方法的依据是指针或引用真正指向的对象了,所以这个基类指针会调用派生类的方法了!第一个set调用的是基类的方法,第二个set调用的是派生类的方法。派生类类型的指针和引用调用了基类的方法。
2023-07-13 13:33:30
151
原创 从C到Cpp——十五、类继承(一)
试想,如果类A不是你写的,或者是你很久以前写的,你需要为之添加功能,你就需要完整地细读这个类的代码,然后才能做出改动。然而,不能把基类的对象和地址赋给派生类的引用和指针。这个规则是有道理的,如果允许把基类对象赋给派生类的引用,那么就可以给基类对象调用派生类方法了,这显然就不合适了!是C++中的重要概念,类继承的实质是为一个已有类添加成员和方法,使之成为一个更复杂的新类。在定义继承类的时候,利用列表初始化的方法调用基类的普通构造函数,实现基类的构造,然后再把补充部分初始化完毕!你只要关心你增加的功能就行了。
2023-07-11 16:44:44
202
原创 从C到Cpp——十四、类的默认函数以及它们的隐患
对于第二种和第三种,编译器可能调用直接调用复制构造函数,也可能是先利用复制构造函数创建一个名称隐藏的临时对象,然后利用利用默认重载的赋值运算符把值赋予目标对象!由于函数传参是按照值传递的,编译器会先利用复制构造函数创建一个作用域和持续时间仅在这个自定义函数种的临时对象,然后再利用析构函数清除这个临时变量。复制构造函数用于将一个已有的对象复制到新创建的对象中,也就是说,它被用于初始化的过程中,而不是常规的赋值过程中。有趣的是,自定义复制构造函数会覆盖默认构造函数,如果定义了复制构造函数,请自定义构造函数!
2023-07-10 17:33:05
141
原创 从C到Cpp——十三、运算符重载、友元函数和转换函数
由于非成员函数是在类定义外部定义的,且不带作用域解析运算符,那么编译器是能够识别并把运算符按照非成员函数的方式重载的,而不是按照成员函数的方式。由于能重载的运算符只有一元运算符和二元运算符,所以对于二元函数,成员函数最多只有一个参数,非成员函数最多两个参数;由于C++中的结构体可以被当作默认成员属性为public的类(有一定差别,但操作上可以姑且这么认为),所以同样可以进行运算符重载。这里+为被重载的运算符,a为参数。自定义的运算符函数重载实质上是对自定义函数的调用,不过调用的方式是使用已有的普通运算符。
2023-07-07 23:27:38
189
原创 从C到Cpp——十二、类和引用、对象数组和类作用域
类对象和类成员函数(类方法)的作用域都为类,这意味着,在类声明和成员函数定义中,可以直接使用未用作用域限限定符::修饰的变量。也就是说,使用方法的对象,实质上是通过隐式的方法访问的。前面的Student& 说明函数的返回类型是关于Student类的引用,后面的Student param说明传入了一个Student类型的对象作为实参,形参是param!使用类作为函数参数时,通常采用引用的方法。这里,Student是类的名称,name_of_array是对象数组名称,NUM_OF_ARRAY是定义的元素数量。
2023-07-07 16:58:04
221
原创 从C到Cpp——十一、名称空间
如果namespace代码块的前面已经使用using namespace std,则不用加std::前缀,因为using的作用域包括namespace定义;前者就好像在相应的代码块中声明了相应的名称一样,而后者保留了名称空间的层次独立性。对于声明在代码块内的变量,其名称空间为所在的代码块。之所以说是有条件的,是因为函数块/代码块中定义的局部变量会覆盖student::age。3--名称空间可以是全局的,可以在别的名称空间中,但不能在代码块中。4--没有定义名称的名称空间等价于链接性为内部的静态变量!
2023-07-06 10:50:36
133
1
原创 从C到Cpp——十、内存模型
1--自定义函数默认是具有外部链接性的,即源文件a中定义的函数可以在源文件b中使用,函数声明(原型)和函数定义中同时使用关键字static可以使函数只有内部链接性,即只能在某一个源文件中使用。2--和变量一样,静态函数(也就是上面用static定义的函数)也满足覆盖的规则,如果源文件b中定义了某个函数,即使同一项目下的源文件a中已经定义了同名的函数,也不会被源文件b使用!为什么要这么设计呢?如果像下面这样使用,则变量a的链接性为内部,虽然程序运行时该变量始终存在,但仅在该源文件中可以使用变量a。
2023-07-05 11:49:21
223
4
原创 从C到Cpp——九、Cpp的强大函数特性(二)
对于上面这个片段,在定义myswap模板时并没有生成用于int的交换函数,在main函数中,编译器发现程序确确实实需要交换m和n这两个int型变量时,才生成了相应的函数。在函数声明和定义前加上template <>这一段,并在参数列表前加上<具体化的类型>,就可以实现具体化函数。具体化函数给予编译器一个优先于函数模板的选择,如果存在具体化定义,就不再使用函数模板,转而按照具体化函数来生成函数定义!读者可以自己去运行一下,发现任何类型——整型,小数到结构甚至是类对象,都是可以由模板生成出堪用的交换函数的!
2023-07-03 17:55:11
375
2
原创 从C到Cpp——八、Cpp的强大函数特性(一)
(有趣的是,这并不意味着a和b这两个函数参数不可以与m和n重名,说明函数变量的独立性还是有的!如果以普通变量作为函数参数,函数在运行时事实上没有访问这些普通变量,而是创建临时变量,将普通变量的值传递给临时变量,然后对临时变量进行访问。然后,笔者尝试后,发现是可以实现的。只能说,这样的写法是不严谨的,最好别这么做,而且在现代的编译器中,这种做法无法通过编译!想不到吧,引用变量可以作为函数的返回值,返回指向某个类型某个变量的引用。,如果引用变量b是引用变量a的别名,那么对b进行的操作和对a进行的操作是等价的!
2023-07-02 20:33:14
200
2
原创 从C到Cpp——七、this指针
所有的类成员函数都包括一个隐含参数,this指针,这是一个指向这个类型的指针;虽然在函数声明和函数定义中并没有显示这个参数,但这个参数是的的确确存在的,编写函数的时候可以直接调用!注意到,this指针后使用了->运算符,因为this->name可以被理解为(*this).name,这和结构体中的定义是一模一样的!事实上,name在函数定义中是this->name的缩写,类方法是依靠this指针访问成员对象的!这一语句即是->运算符号的实例,说明 指向对象的指针->成员函数 的方式是可以被使用的。
2023-06-28 09:35:23
282
1
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人