big_uncle

Results 105 issues of big_uncle

源码地址:https://github.com/RoboMaster/RoboRTS/tree/ros/roborts_costmap --- ## 1.文件结构 ```bash roborts_costmap ├── CMakeLists.txt ├── cmake_module │ ├── FindEigen3.cmake │ └── FindProtoBuf.cmake ├── config # 配置文件 │ ├── costmap_parameter_config_for_decision.prototxt │ ├── costmap_parameter_config_for_global_plan.prototxt │ ├── costmap_parameter_config_for_local_plan.prototxt │...

RM

这是19年12月初的小项目,当时是为了给人培训PnP算法而写的一个小示例。 这一个半月都没写博客,但我几乎每天都在写代码学东西,一直没时间总结,终于明天就要离开学校回家了,今天便有了时间稍微写写过去这一个半月的所做所学。 OpenCV实现AR本质上是将一系列世界坐标投影到图像坐标的过程,属于最基础的3D知识。这里面的东西不多,首先从相机标定开始说。 # 相机标定 目前被大家普遍使用的是张正友标定法,这里就不给出具体的算法推导了,推荐几篇将算法原理的文章: * [相机标定——张正友棋盘格标定法](https://blog.csdn.net/JennyBi/article/details/85764988) * [SLAM入门之视觉里程计(6):相机标定 张正友经典标定法详解](https://www.cnblogs.com/wangguchangqing/p/8335131.html) * [【计算机视觉】1. 张正友平面标定法](https://zhuanlan.zhihu.com/p/36371959) * [从零开始学习「张氏相机标定法」(一) 7](http://www.sohu.com/a/220313594_100007727) 总之,从不同角度拍几张棋盘图,就可以使用张正友标定法计算出相机的内参矩阵。相机最重要的坐标变换关系如下(为简单起见,这里省略了畸变矩阵): ![image](https://user-images.githubusercontent.com/35989223/72493552-6d4b0080-385c-11ea-8081-a508eec71bb1.png) 其中矩阵K就是相机的内参矩阵。在内参矩阵已知的情况下,对于一个点来说,其在世界坐标系下的坐标、在图像坐标系中的坐标、相机的外参矩阵,这三个量只要知道其中任意两个就可以求得第三个。 # 程序思路分析 我们要实现的是AR功能,举个例子,我们想将一个指定长宽高的方块放置在图像中的一个平面上,也就是说,我们给定了世界坐标,需要求解图像坐标,拿到方块八个顶点的图像坐标后,就可以相互连线绘制出方块。 根据上面的等式,我们还差相机的外参矩阵。这里就用到了PnP算法。 PnP算法的功能是根据一个平面的四个点的图像和真实世界坐标计算相机相对于该平面的姿态,即相机的外参矩阵。算法很简单,关于它的算法推导可以看这篇:[3D-2D:PnP算法原理](https://blog.csdn.net/u014709760/article/details/88029841) 所以我们的程序思路是,首先标定相机,获取相机的内参(这一步只需要拿到相机后标定一下就行,相机不变内参就不变),然后寻找我们目标平面的四个不共线的特征点,根据这四个点的世界坐标和图像坐标求解出相机的外参,然后给定要显示图像的各个点的坐标,使用上述矩阵等式求出对应的图像坐标,最后画线即可。 # 具体程序实现 ```cpp int...

RM
CV

前几天春节期间花了点时间把个人网站改造了一下,在这里做个总结Mark一下。 改造的念头来源于一次无意间翻到的一个在issue页面建立的博客(相当于只有后台的博客),我就有了要将网站与issue挂钩的想法。 之前我的网站是基于[Editor.md](https://pandao.github.io/editor.md/examples/)的,以在本地写好相应的.md文件后push到GitHub上的方式来发表文章,也不是太麻烦,唯有一个遗憾,就是没有评论功能。去年的时候我接触过[Gitment](https://github.com/imsun/gitment),但当时还不太了解GitHub,更别说issue了,而且Gitment需要手动为每个文章初始化一次,显得比较麻烦。现在作者网站的安全证书过期了,导致Gitment访问不是很稳定。 于是我决定自己来试着把GitHub的issues和comments都集成到我的网站里。 首先是注册一个GitHub的OAuth App,点[这里](https://github.com/settings/applications/new)可以注册。注册后可以拿到对应的`client_id`和`client_secret`。 最开始我一直想通过纯JavaScript实现此功能,但总是遇到各种各样的问题,最后遇到了一个实在无解的问题,详情可以点[这里](?id=21),然后我发邮件询问GitHub,结果直接来了个官方劝退: > Exchanging a code for a token is not possible from a browser via JavaScript -- it's not something that our OAuth flow...

web

刚接触惯性导航传感器的时候,被求解姿态角的一系列操作秀了一脸,虽然研究了一两天,但最后还是浅尝辄止,只了解了个大概,当时把MPU9250的算法逻辑捋了个大概思路,原文见:[MPU9250姿态解析](https://imuncle.github.io/content.html?id=39)、[MPU9250六轴算法](https://imuncle.github.io/content.html?id=44)。这其中最不理解的就是四元数的那一部分,为什么四元数可以这样求解出来?为什么四元数与欧拉角之间的转换关系式这样的?四元数到底有什么几何或者物理意义? 可惜的是普遍的讲解姿态解析的文章都是直接给出了最后的公式,并没有讲解为什么。最近又因为想做四足机器人,需要实现惯导的室内定位功能,正好趁此机会好好研究一下四元数。 以下内容绝大部分参考自《惯性导航》(作者 秦永元)一书。 # 什么是四元数 ## 四元数的定义 顾名思义,四元数是由四个元构成的数,它是一个超复数,具有一个实部和三个虚部,也可以看成是一个四维空间中的一个向量。 ![image](https://user-images.githubusercontent.com/35989223/59964075-62322b00-952e-11e9-9937-a5b6b8eedd39.png) ## 四元数的运算法则 四元数的运算也有加减乘除四种,加减就很简单了,这里看看乘法和除法。 不过既然四元数是一个四维向量,那么它的运算法则就完全符合向量的运算法则,换句话说,符合矩阵的运算法则。 ### 四元数的乘法 乘法分为一个四元数和一个常数相乘以及两个四元数相乘两种情况,第一种情况太简单了,就看第二种乘法运算: ![image](https://user-images.githubusercontent.com/35989223/59964133-1df35a80-952f-11e9-8225-ee408d309334.png) ![image](https://user-images.githubusercontent.com/35989223/59964140-3bc0bf80-952f-11e9-9eca-cf0bb79c9efc.png) ![image](https://user-images.githubusercontent.com/35989223/59964149-4c713580-952f-11e9-80ba-5fdd57ad75aa.png) ![image](https://user-images.githubusercontent.com/35989223/59964151-57c46100-952f-11e9-94ae-803113bbbf79.png) ### 四元数的除法 矩阵的除法可以转换成逆矩阵相乘,所以除法的关键是四元数的逆的求解。 ![image](https://user-images.githubusercontent.com/35989223/59964160-83474b80-952f-11e9-8830-05c9af374fb6.png) 四元数就了解到这里,接下来就研究四元数与欧拉角之间的关系。 # 四元数与姿态阵间的关系 首先看下图模型: ![image](https://user-images.githubusercontent.com/35989223/59964182-d91bf380-952f-11e9-9823-be9fd48ed3fe.png)...

RM

昨天刚搞定STM32模拟CH340,今天就实现了ROS的串口通信,果然还是硬件让人头秃,软件开发的资料太丰富了,随便百度就能找到答案。 下面进入正题。 ROS要和STM32通信首先要确定通信协议。我的协议很简单,单片机上有两个LED,如果接收到命令'0x01',就改变1号LED的亮灭状态,如果收到`0x02`,就改变2号LED的亮灭状态。另外STM32会返回本次接受到的数据第一位和数据长度。 我的思路是ROS读取键盘输入,然后将键盘的输入以键盘码(不是字符串ASCII码)的形式发送给STM32,同时监听STM32的消息。 # 实现串口通信 这里参考的是这篇博客:[ROS使用官方包进行串口通信](https://blog.csdn.net/qq_25254777/article/details/81364716) 我的代码如下: ```cpp int main(int argc, char **argv) { ros::init(argc, argv, "serial_read_node"); ros::NodeHandle n; ros::Subscriber write_sub = n.subscribe("keyboard", 1000, write_callback); try { //设置串口属性,并打开串口 ser.setPort("/dev/ttyUSB0");...

RM
ROS

不经意间刷到了一篇知乎问答:[没有磁强计的陀螺仪能算出偏航角(Yaw)吗?](https://www.zhihu.com/question/68156189/answer/900276549),赞同数最高的答案中提到了两种姿态解算算法,`MadgwickAHRS`和`MahonyAHRS`,其中`MohonyAHRS`算法就是我之前一直在使用的姿态解析算法,可以参考这几篇: * [MPU9250姿态解析](https://imuncle.github.io/content.html?id=39) * [MPU9250六轴算法](https://imuncle.github.io/content.html?id=44) `MadgwickAHRS`算法还没看太懂,等之后搞懂了再补充。下面的链接里有这两种算法的**C代码**、**C#代码**、**MATLAB代码**以及相关论文等: [Open source IMU and AHRS algorithms](https://x-io.co.uk/open-source-imu-and-ahrs-algorithms/) 我这里把两种算法的C语言版本贴出来,方便以后直接复制使用。 ## MadgwickAHRS ```c //===================================================================================================== // MadgwickAHRS.c //===================================================================================================== // // Implementation of Madgwick's IMU and AHRS algorithms. //...

RM
STM32

# CMakeLists配置 ```cmake cmake_minimum_required (VERSION 2.8) include_directories(${OpenCV_INCLUDE_DIRS}) #OpenCV的include文件夹 set(OpenCV_DIR /usr/local/lib) #OpenCV的lib文件夹 find_package(OpenCV REQUIRED) add_executable(程序名 主函数所在cpp) target_link_libraries(程序名 ${OpenCV_LIBS}) ``` # 显示图像 ```cpp #include using namespace cv; void main() { Mat src...

RM

之前有一篇写如何制作CMSIS-DAP下载器的文章:[自制CMSIS-DAP下载器](https://imuncle.github.io/content.html?id=83),就在昨晚,我搞定了它的无线版本,也就是可以实现无线下载程序和调试程序。 # 代码修改 就直接在上一篇文章建立的工程上修改。其实可以看出来,这份代码可以分为两部分,一部分是用于和PC端通信的USB HID,另一部分是和单片机调试内核通信的DAP,要实现无线通信,意味着要制作一个发射端和一个接收端,发射端主要实现USB HID,接收端主要实现DAP,两者之间的信息交互通过无线模块实现。 整份CMSIS-DAP代码最关键的部分就是在`DAP_Thread()`函数中的 ```c DAP_ExecuteCommand(USB_Request[USB_RequestIndexO], USB_Response[USB_ResponseIndexI]); ``` 从函数名就可以看出来,这个函数是将USB HID的命令`USB_Request[USB_RequestIndexO]`传给DAP处理函数`DAP_ExecuteCommand`,同时返回一个单片机的响应`USB_Response[USB_ResponseIndexI])`,那么对于发射端,我就直接把DAP的那五个核心代码都删除,只留下USB HID的代码,然后把上面这行代码修改如下: ```c HAL_UART_Transmit(&huart1, USB_Request[USB_RequestIndexO], 64, 500); HAL_UART_Receive_DMA(&huart1, USB_Response[USB_ResponseIndexI], 64); while(__HAL_DMA_GET_COUNTER(huart1.hdmarx) > 0){} ``` 因为我选用的无线串口模块,所以这里使用的是串口发送和接收。 对应的从机部分则只保留DAP部分,删除USB HID部分,代码执行靠串口接收中断推动,关键性代码如下: ```c...

RM
other
STM32

之前有提到一个想使用Windows批处理脚本模拟CMake的想法,具体见[gcc编译带资源的Win32程序](https://imuncle.github.io/content.html?id=91),正当我还在纠结怎么使用batch比较文件修改时间的时候,VBScript进入了我的视野,只因一句话,我就震惊了: ```vb Msgbox "Hello World" ``` 将它保存为`hello.vbs`,然后双击运行: ![image](https://user-images.githubusercontent.com/35989223/68651050-791afd80-0561-11ea-96ae-9a6aa3da175d.png) 一个Message Box就这样产生了!这也太简洁了吧。而且VB是深度嵌入进Windows系统的,也就是说这是真正的随便一个Windows都可以运行的代码,并且因为是脚本文件,运行时是一行一行解析运行的,所以这还省去了编译的步骤,这也太帅了吧。 后续进一步了解发现,原来VBScript曾经是和JavaScript一争高下的脚本语言,可惜VBScript只支持IE,而后者则是所有浏览器都支持,自然被搞下台。现在基本上网页开发里已经看不到它的身影了。 鉴于VBScript的API接口多很多,所以我打算使用它来模拟CMake,以实现我的“自动化编译”。 我的工程文件如下: ![image](https://user-images.githubusercontent.com/35989223/68651377-3279d300-0562-11ea-9fc6-8e38f4cc9cac.png) VBScript代码如下: ```vb Set objFSO = CreateObject("Scripting.FileSystemObject") Set obj = createobject("wscript.shell") Const targetFile = "poppad" '判断是否存在build文件夹,若不存在则创建 if...

other
Win32

两天前我突然回想自己当初是为什么想学编程的。 大约是高三毕业的那个暑假,我第一次尝试学习编程,当时也就听说过C语言,就上网百度,结果因为对编程一点概念都没有,直接点进了一个图形化编程的教学网站,最后也没学到啥东西,这网站现在好像已经找不到了。 后来大一的时候又决定学一次C语言,这次学乖了,下载了网上的C语言入门书籍的PDF(说实话那是我第一次知道还有PDF这种格式,之前我的脑子里就只有txt,excel,word和ppt),算是正式入门C语言了吧,在学习线性代数的时候因为不想手算矩阵,还用C语言写了一个矩阵计算器,但依旧是停留在命令行的交互阶段。 我其实一直想写出像Windows其他应用程序一样的东西,拥有窗口界面,用户鼠标点点点就行,人机交互良好,尤其喜欢那种单独一个exe执行文件,无需安装,无需解压,随表找台装有Windows系统的电脑,双击就能运行,体积也不大,可能也就2~3MB,特别喜欢这种小软件,比如我日常开发就用到一款类似的小软件`XCOM.exe`,是正点原子开发的。 再后来我接触了Qt,开发起来确实很方便,但是使用过后发现,我只是实现一个很简单的功能,但是打包出来的工程还需要带很多dll库文件,给其他人使用非常不方便,最最关键的是那些dll库体积真的很大,工程本身只有一百多KB,dll库文件加起来有几百MB,这谁顶得住啊,Debug版本和Release版本都是差不多的样子。 于是两天前我想,自己已经写代码两年有余了,如果连最初的目标都实现不了的话,还算什么程序员。 所以我把手伸向了Win32开发,使用最原生的Windows API,追求简洁小巧高效率,写自己的小工具,做一个自由软件开发者。另外我还要拜托IDE的束缚,直接使用文本编辑器写代码,这会让我对程序有更深入的认识,也带来更多的成就感。 直接贴上我的第一份代码吧: ```c #include int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { MessageBox(NULL, TEXT("Hello World!"), TEXT("大叔的第一个窗口程序"), MB_OK); return 0...

other
Win32