<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>沐沐小站</title><description>漂泊者的休憩之地，守岸人的灯塔。用文字抵抗遗忘，用开源连接彼此。</description><link>https://undf.cn/</link><language>zh_CN</language><item><title>毕业，工作，赚钱，然后爱自己</title><link>https://undf.cn/posts/post/life/%E6%AF%95%E4%B8%9A%E5%B7%A5%E4%BD%9C%E8%B5%9A%E9%92%B1%E7%84%B6%E5%90%8E%E7%88%B1%E8%87%AA%E5%B7%B1/</link><guid isPermaLink="true">https://undf.cn/posts/post/life/%E6%AF%95%E4%B8%9A%E5%B7%A5%E4%BD%9C%E8%B5%9A%E9%92%B1%E7%84%B6%E5%90%8E%E7%88%B1%E8%87%AA%E5%B7%B1/</guid><pubDate>Sat, 17 Jan 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;2025 年 6 月&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;毕业了&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;工作了&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;赚钱了&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;走过这一路，才发现最重要的事情其实很简单：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;那就是，好好爱自己。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;无论生活带给我们什么，都要记得给自己留一份温柔。&lt;/p&gt;
&lt;p&gt;加油，未来的路还长，先从爱自己开始。&lt;/p&gt;
</content:encoded></item><item><title>CMSIS-DAP 烧录器分享（STM32）</title><link>https://undf.cn/posts/post/code/embedded/arm-%E7%83%A7%E5%BD%95%E5%99%A8%E5%88%86%E4%BA%ABstm32/</link><guid isPermaLink="true">https://undf.cn/posts/post/code/embedded/arm-%E7%83%A7%E5%BD%95%E5%99%A8%E5%88%86%E4%BA%ABstm32/</guid><pubDate>Sat, 20 Jul 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;在嵌入式系统开发领域，要将程序代码成功烧录到STM32芯片中，选择合适的烧录器是至关重要的本文分享几种流行的ARM烧录器，特别是针对STM32系列，从而加快项目开发进度。&lt;/p&gt;
&lt;h2&gt;有线烧录器&lt;/h2&gt;
&lt;h3&gt;STLINK&lt;/h3&gt;
&lt;h4&gt;官方原版&lt;/h4&gt;
&lt;p&gt;相信这是大多数人使用的第一个烧录器，支持SWD（Serial Wire Debug）接口或JTAG接口与目标MCU通信，不过体积和线束都略大，没有多久我就换掉了。但是，后来在尝试ST自家的软件工具（如STM32CubeProgrammer, STM32CubeIDE）的时候它非常顺手，这里再贴一张引脚图，方便以后自己查找。&lt;/p&gt;
&lt;p&gt;价格 80+&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://img.undf.top/ob/81e0fc9899fed998c44d9a9f77e7b54f.png&quot; alt=&quot;image|525&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://img.undf.top/ob/d9dae04c02631140b2cac5d50bd19a3b.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://img.undf.top/ob/15a183d986ca6fcdcb7a919c31d1d6b6.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;h4&gt;带有串口的STLINK V2.1&lt;/h4&gt;
&lt;p&gt;&lt;img src=&quot;https://img.undf.top/ob/c6d4acc47ef5ac6bea4afd9236b3671b.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;没用过，但看着不错 体积还是大了点，单面贴片工艺&lt;/p&gt;
&lt;p&gt;价格20+&lt;/p&gt;
&lt;h3&gt;CMSIS-DAP&lt;/h3&gt;
&lt;p&gt;这个品类是我用的最多的，所以比较多。&lt;/p&gt;
&lt;h4&gt;MUSE LAB&lt;/h4&gt;
&lt;p&gt;比&lt;a href=&quot;####%20%E5%B8%A6%E6%9C%89%E4%B8%B2%E5%8F%A3%E7%9A%84STLINK%20V2.1&quot;&gt;这个&lt;/a&gt;是不是精致了很多，这里要提一嘴，它支持Keil和openocd，在Linux上也能用，非常不错。他家也有高速款（进口芯片的发烫，据说国产不会），但一般用不上。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://img.undf.top/ob/07c240407f26db86aafa7ad6062fd0c5.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;价格 20+&lt;/p&gt;
&lt;h4&gt;合宙&lt;/h4&gt;
&lt;p&gt;刚开始奔9.9买的，后来涨价。迷你是真的迷你，但是要自己焊排针，没有热缩管，最重要的是没有5V电平，不太能供电，而且openocd不支持，9.9可以冲，但涨价后就没什么必要了&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://img.undf.top/ob/aee553aea3e5fe633c23ce34f4a15230.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;无线烧录器&lt;/h2&gt;
&lt;h3&gt;CMSIS-DAP （WCHLINK）&lt;/h3&gt;
&lt;p&gt;之前也用过几款&lt;a href=&quot;https://www.wch.cn/products/WCH-Link.html&quot;&gt;WCHLINK&lt;/a&gt;，但都很大，网上有很多自己制作的教程，但是感觉没必要。
最近逛到了这一款
&lt;img src=&quot;https://img.undf.top/ob/ef69dfc0281303d5138cfd7e44e30d5a.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;支持有线+无线，速度也很棒，买来记得更新固件（找老板要教程）连接也很稳定。
主要是连接方便，不用配对，可以自动连上，很棒。
价格20&lt;/p&gt;
&lt;h2&gt;不太建议的两款&lt;/h2&gt;
&lt;h3&gt;有线DAP&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://img.undf.top/ob/531379d99792b38a841ccf684969bebf.png&quot; alt=&quot;image&quot; /&gt;
功能确实多，但是做的不咋地，最重要的功能烧录都没做好，不支持烧录后复位，问客服说后续更新，实际画饼不更新，逻辑分析仪据说也要装他定制的软件，不支持原版软件，很离谱。
&lt;img src=&quot;https://img.undf.top/ob/419d508116af6e81f0991e155668708b.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;无线DAP&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://img.undf.top/ob/c03a805cd9e03bf5946489f906d111a6.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;看这个图就知道有多麻烦了，体验过一次设置后就再也没碰过。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://img.undf.top/ob/acda7e5fef865b1211bcbbb4d44d3c92.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
</content:encoded></item><item><title>我的博客</title><link>https://undf.cn/posts/post/hexo/%E6%88%91%E7%9A%84%E5%8D%9A%E5%AE%A2/</link><guid isPermaLink="true">https://undf.cn/posts/post/hexo/%E6%88%91%E7%9A%84%E5%8D%9A%E5%AE%A2/</guid><pubDate>Fri, 15 Mar 2024 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;背景&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://img.undf.top/ob/5a6e68e7ea68562b2499934f9f0402f4.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;博客建立到现在已经近三年了，期间各种写作方式，各种主题，都折腾了不少，简单聊聊，分享一下。详细的操作方式这里就不啰嗦了，相信胆大心细的你肯定能解决。&lt;/p&gt;
&lt;h2&gt;关于主题&lt;/h2&gt;
&lt;p&gt;主题从最初的 &lt;a href=&quot;https://github.com/XPoet/hexo-theme-keep?tab=readme-ov-file&quot;&gt;keep&lt;/a&gt;到有名的 &lt;a href=&quot;https://github.com/jerryc127/hexo-theme-butterfly&quot;&gt;butterfly&lt;/a&gt; 被我折腾的花里胡哨，再然后折腾的尽头是极简，所以主题换成 &lt;a href=&quot;https://github.com/ChrAlpha/hexo-theme-cards&quot;&gt;cards&lt;/a&gt; 非常简约，但是时间久了看腻了，就换成了现在的 &lt;a href=&quot;https://github.com/xaoxuu/hexo-theme-stellar&quot;&gt;stellar&lt;/a&gt; 简约而又不简单。&lt;/p&gt;
&lt;h2&gt;关于发布流程&lt;/h2&gt;
&lt;p&gt;说到博客的写作流程，最初当然是最基础的 &lt;code&gt;hexo g&lt;/code&gt; &lt;code&gt;hexo d&lt;/code&gt; 发布到 Github 当然非常麻烦，后来学会了通过 Github Action 实现&lt;a href=&quot;https://juejin.cn/post/6943895271751286821&quot;&gt;自动部署&lt;/a&gt;这之后就方便了一些，开始尝试在线的编辑器，最初用过 &lt;a href=&quot;https://github.com/HexoPlusPlus/HexoPlusPlus&quot;&gt;HexoPlusPlus&lt;/a&gt; 类似于现在的 &lt;a href=&quot;https://github.com/Qexo/Qexo&quot;&gt;QEXO&lt;/a&gt; 都是在浏览器编辑文件，然后上传到 github 触发自动部署，但因为编辑器不太好使，而且不太方便，还是用 VScode 最舒服，就这样大概用了一年多。&lt;/p&gt;
&lt;p&gt;不过，去年我开始用 Obsidian 记笔记，规划项目等等，所以就想把博客编辑放到这里，通过 &lt;a href=&quot;https://github.com/ObsidianPublisher/obsidian-github-publisher&quot;&gt;github-publisher&lt;/a&gt; 插件上传到 Github 触发 Action 实现部署&lt;/p&gt;
&lt;h2&gt;关于域名和备案&lt;/h2&gt;
&lt;p&gt;域名最初当然是 github 生成的&lt;a href=&quot;https://wxydejoy.github.io&quot;&gt;默认域名&lt;/a&gt; (现在这里是很久之前的 butterfly 主题博客)后来买了 &lt;code&gt;wxydejoy.top&lt;/code&gt; 并通过阿里云进行备案（备案才能使用国内 CDN）后来觉得域名太长换了 &lt;code&gt;undf.top&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;备案的话，需要三个月以上的服务器才行，当时是 27 块通过新人优惠在阿里云买了三个月，然后就是填资料等电话等等等等，繁琐但不复杂。不过服务器到期后阿里云会发邮件警告：域名未指向服务（解决方案是建个 OSS 将域名指向它然后开启访问鉴权，通过 github Action 每周访问一次，这样就可以 0 成本实现）&lt;/p&gt;
&lt;h2&gt;关于网站加速与防御&lt;/h2&gt;
&lt;p&gt;刚开始，博客当然是使用 github page 部署，国内基本无法访问，后来使用 &lt;a href=&quot;https://vercel.com/&quot;&gt;Vercel&lt;/a&gt; 进行部署，速度也是一般般，类似的还有 &lt;a href=&quot;https://pages.cloudflare.com/&quot;&gt;Cloudflare Page&lt;/a&gt; 国内访问速度都很感人。&lt;/p&gt;
&lt;p&gt;现在，使用的是&lt;a href=&quot;https://www.upyun.com&quot;&gt;又拍云 CDN&lt;/a&gt; 通过加入 &lt;a href=&quot;https://www.upyun.com/league&quot;&gt;又拍云联盟&lt;/a&gt; 实现，当然你也可以使用腾讯阿里等等，但是一定要开启各种防护，防止被攻击欠费（前段时间我就被刷了一点点流量，莫名其妙）。&lt;/p&gt;
&lt;p&gt;防御第一条：禁止国外 IP 访问 CDN，通过 DNS 将其指向源站（Github），然后就是限制各种访问频率，一般小站访问量也不会太多，每分钟能有几百次差不多了。&lt;/p&gt;
</content:encoded></item><item><title>Python 爬虫之 DrissionPage</title><link>https://undf.cn/posts/post/code/py/python-%E7%88%AC%E8%99%AB%E4%B9%8B-drissionpage/</link><guid isPermaLink="true">https://undf.cn/posts/post/code/py/python-%E7%88%AC%E8%99%AB%E4%B9%8B-drissionpage/</guid><pubDate>Fri, 15 Mar 2024 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;DrissionPage 是什么&lt;/h2&gt;
&lt;p&gt;DrissionPage 是一个基于 python 的网页自动化工具。
它既能控制浏览器，也能收发数据包，还能把两者合而为一。
可兼顾浏览器自动化的便利性和 requests 的高效率。
它功能强大，内置无数人性化设计和便捷功能。
它的语法简洁而优雅，代码量少，对新手友好。&lt;/p&gt;
&lt;p&gt;用 requests 做数据采集面对要登录的网站时，要分析数据包、JS 源码，构造复杂的请求，往往还要应付验证码、JS 混淆、签名参数等反爬手段，门槛较高，开发效率不高。使用浏览器，可以很大程度上绕过这些坑，但浏览器运行效率不高。&lt;/p&gt;
&lt;p&gt;因此，这个库设计初衷，是将它们合而为一，同时实现“写得快”和“跑得快”。能够在不同需要时切换相应模式，并提供一种人性化的使用方法，提高开发和运行效率。&lt;br /&gt;
除了合并两者，本库还以网页为单位封装了常用功能，提供非常简便的操作和语句，使用户可减少考虑细节，专注功能实现。 以简单的方式实现强大的功能，使代码更优雅。&lt;/p&gt;
&lt;p&gt;以前的版本是对 selenium 进行重新封装实现的。从 3.0 开始，作者另起炉灶，对底层进行了重新开发，摆脱对 selenium 的依赖，增强了功能，提升了运行效率。&lt;/p&gt;
&lt;h2&gt;示例代码&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;from DrissionPage import ChromiumPage

# 创建页面对象，并启动或接管浏览器
page = ChromiumPage()
# 跳转到登录页面
page.get(&apos;https://gitee.com/login&apos;)

# 定位到账号文本框，获取文本框元素
ele = page.ele(&apos;#user_login&apos;)
# 输入对文本框输入账号
ele.input(&apos;您的账号&apos;)
# 定位到密码文本框并输入密码
page.ele(&apos;#user_password&apos;).input(&apos;您的密码&apos;)
# 点击登录按钮
page.ele(&apos;@value=登 录&apos;).click()
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;应用实例&lt;/h2&gt;
&lt;h3&gt;淘宝商品截图&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;# 部分代码
page = ChromiumPage(co)
page.get(img_url,retry=1, interval=1, timeout=1.5)
                
img = page(&apos;tag:img&apos;)
img.get_screenshot(path=&apos;./&apos;, name=&apos;temp_img.jpg&apos;)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;未来工厂订单数据爬取&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;from DrissionPage import SessionPage, SessionOptions # pip install DrissionPage
from DrissionPage import ChromiumPage
from DrissionPage import ChromiumOptions
import re
import time

co = ChromiumOptions(read_file=False)  # 不读取文件方式新建配置对象

co.set_browser_path(r&apos;C:\Program Files\Google\Chrome\Application\chrome.exe&apos;)  # 设置浏览器路径
# co.set_argument(&apos;--headless&apos;)  # 设置无头模式 隐藏浏览器界面
# 设置配置文件路径
co.set_user_data_path(r&apos;C:\Users\weiek\AppData\Local\Google\Chrome\User Data&apos;)


url_base = &quot;https://www.wenext.cn/index.php?route=account/order&amp;amp;filter_time=6&amp;amp;page=&quot;

page = ChromiumPage(co)


# cp = ChromiumPage(co)

for i in range(1, 20):
    print(i)
    url = url_base + str(i)
    page.get(url)
    # 等待页面加载完成
    page.wait.doc_loaded()
    # 从 page.html 正则匹配订单号 订单编号 86027961
    result_num = re.findall(r&apos;订单编号 (\d+)&apos;, page.html)
    # print(result_num)
    try:
        for i in result_num:
            page.get(&apos;https://www.wenext.cn/index.php?route=account/order/info&amp;amp;order_id=&apos; + i)
            page.wait.doc_loaded()
            # print(page.html)
            # 正则匹配订单金额 余额(158.00) 余额(158)
            result_money = re.findall(r&apos;余额\((.*?)\)&apos;, page.html)[0]
            print(result_money)
            # time.sleep(10)
            # 正则匹预计在2024-03-17前发货
            result_time1 = re.findall(r&apos;预计在(.*?)前发货&apos;, page.html)[0].replace(&apos;23:00:00&apos;, &apos; &apos;)
            print(result_time1)

            # 正则匹配                   &amp;lt;td class=&quot;order-body-time&quot;&amp;gt;2024-03-10&amp;lt;/td&amp;gt;
    # &amp;lt;td class=&quot;order-body-time&quot;&amp;gt;2024-03-10&amp;lt;/td&amp;gt;
    # &amp;lt;td class=&quot;order-body-time&quot;&amp;gt;已发货，待签收&amp;lt;/td&amp;gt;
            result_time2_list = re.findall(r&apos;&amp;lt;td class=&quot;order-body-time&quot;&amp;gt;(.*?)&amp;lt;/td&amp;gt;&apos;, page.html, re.S)
            result_time2 = &apos;0&apos;
            for j in result_time2_list:
                if j == &apos;已发货，待签收&apos;:
                    # 获取索引
                    index = result_time2_list.index(j)
                    # 获取发货时间
                    result_time2 = result_time2_list[index - 1]
            if result_time2 != &apos;0&apos;:
                with open(&apos;wenext.txt&apos;, &apos;a&apos;) as f: 
                    # 写入文件 订单号 订单金额 预计发货时间  实际发货时间
                    f.write(i + &apos;	&apos; + result_money + &apos;	&apos; + result_time1 + &apos;	&apos; + result_time2 + &apos;    &apos;+&apos;\n&apos;)
            print(result_time2)
            # time.sleep(1)
    except:
        with open(&apos;wenexterr.txt&apos;, &apos;a&apos;) as f: 
            f.write(i + &apos;	&apos; + &apos;error&apos; + &apos;	&apos; + &apos;error&apos; + &apos;	&apos; + &apos;error&apos; + &apos;    &apos;+&apos;\n&apos;)
&lt;/code&gt;&lt;/pre&gt;
</content:encoded></item><item><title>URDF 导出资料（ROS2）</title><link>https://undf.cn/posts/post/code/ros2/ros2_urdf/</link><guid isPermaLink="true">https://undf.cn/posts/post/code/ros2/ros2_urdf/</guid><pubDate>Mon, 21 Aug 2023 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;坐标系建立&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://img.undf.top/image/ros2_urdf/20230821145339-2023-08-21.png&quot; alt=&quot;20230821145339-2023-08-21&quot; /&gt;&lt;/p&gt;
&lt;p&gt;如图所示按照DH坐标法建立各个坐标系&lt;/p&gt;
&lt;p&gt;坐标系建立方法去复习机器人导论&lt;/p&gt;
&lt;p&gt;建立完成可能会很乱 不用担心&lt;/p&gt;
&lt;h2&gt;插件安装和使用&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/ros/solidworks_urdf_exporter&quot;&gt;插件下载地址&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;经测试 1.6.1支持 solidworks 2022 sp5（实验室当前使用的版本）&lt;/p&gt;
&lt;p&gt;warning: 插件要在装配体里面才有反应&lt;/p&gt;
&lt;h3&gt;插件使用&lt;/h3&gt;
&lt;p&gt;打开插件&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://img.undf.top/image/ros2_urdf/20230821150216-2023-08-21.png&quot; alt=&quot;20230821150216-2023-08-21&quot; /&gt;&lt;/p&gt;
&lt;p&gt;base_link&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://img.undf.top/image/ros2_urdf/20230821150418-2023-08-21.png&quot; alt=&quot;20230821150418-2023-08-21&quot; /&gt;&lt;/p&gt;
&lt;p&gt;normal_link&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://img.undf.top/image/ros2_urdf/20230821150631-2023-08-21.png&quot; alt=&quot;20230821150631-2023-08-21&quot; /&gt;&lt;/p&gt;
&lt;p&gt;其中关节类型如下&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;关节类型&lt;/th&gt;
&lt;th&gt;描述&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;continuous&lt;/td&gt;
&lt;td&gt;旋转关节，可以围绕单轴无限旋转&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;revolute&lt;/td&gt;
&lt;td&gt;旋转关节，类似于continuous,.但是有旋转的角度极限  &lt;strong&gt;一定要设置上下限不然默认为0&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;prismatic&lt;/td&gt;
&lt;td&gt;滑动关节，沿某一轴线移动的关节，带有位置极限&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;plannar&lt;/td&gt;
&lt;td&gt;平面关节，允许在平面正交方向上平移或者旋转&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;floating&lt;/td&gt;
&lt;td&gt;浮动关节，允许进行平移、旋转运动&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;fixed&lt;/td&gt;
&lt;td&gt;固定关节，不允许运动的特殊关节&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;设置完成后单击导出按钮&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://img.undf.top/image/ros2_urdf/20230821151342-2023-08-21.png&quot; alt=&quot;20230821151342-2023-08-21&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://img.undf.top/image/ros2_urdf/20230821151701-2023-08-21.png&quot; alt=&quot;20230821151701-2023-08-21&quot; /&gt;&lt;/p&gt;
&lt;p&gt;导出即可&lt;/p&gt;
&lt;p&gt;注意导出名即为ros中的包名，勿乱写&lt;/p&gt;
&lt;h2&gt;URDF 测试&lt;/h2&gt;
&lt;p&gt;CoppeliaSim Edu 导入URDF 简单拖动旋转测试一下&lt;/p&gt;
&lt;h2&gt;URDF 文件包修改&lt;/h2&gt;
&lt;h3&gt;修改CMakelist.txt&lt;/h3&gt;
&lt;p&gt;根据自己的情况修改&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;cmake_minimum_required(VERSION 3.10.2)
project(moveit_resources_fanuc_description) # 修改为自己的包名
find_package(ament_cmake REQUIRED)

ament_package()

install(DIRECTORY meshes urdf DESTINATION share/${PROJECT_NAME})
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;修改package.xml&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;?xml version=&quot;1.0&quot;?&amp;gt;
&amp;lt;package format=&quot;3&quot;&amp;gt;
  &amp;lt;!-- # 根据内容修改 --&amp;gt;
  &amp;lt;name&amp;gt;moveit_resources_panda_description&amp;lt;/name&amp;gt; 

  &amp;lt;version&amp;gt;2.0.6&amp;lt;/version&amp;gt;
  &amp;lt;description&amp;gt;panda Resources used for MoveIt testing&amp;lt;/description&amp;gt;

  &amp;lt;author email=&quot;isucan@willowgarage.edu&quot;&amp;gt;Ioan Sucan&amp;lt;/author&amp;gt;
  &amp;lt;author email=&quot;acorn@willowgarage.edu&quot;&amp;gt;Acorn Pooley&amp;lt;/author&amp;gt;

  &amp;lt;maintainer email=&quot;dave@dav.ee&quot;&amp;gt;Dave Coleman&amp;lt;/maintainer&amp;gt;

  &amp;lt;license&amp;gt;BSD&amp;lt;/license&amp;gt;

  &amp;lt;buildtool_depend&amp;gt;ament_cmake&amp;lt;/buildtool_depend&amp;gt;

  &amp;lt;export&amp;gt;
      &amp;lt;build_type&amp;gt;ament_cmake&amp;lt;/build_type&amp;gt;
  &amp;lt;/export&amp;gt;
&amp;lt;/package&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;编译包&lt;/h3&gt;
&lt;p&gt;将包放入 ros2 或者 moveit2 工作空间中&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;colcon build --packages-select moveit_resources_fanuc_description # 修改为自己的包名
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;MoveIt Setup Assistant 配置&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;# 激活ros2环境
source /opt/ros/foxy/setup.bash
# 激活moveit环境
source ~/moveit2_ws/install/setup.bash # 刚才编译包的路径
# 启动moveit  MoveIt Setup Assistant
ros2 launch moveit_setup_assistant setup_assistant.launch.py

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;剩下的就参照&lt;a href=&quot;https://moveit.picknik.ai/main/doc/examples/setup_assistant/setup_assistant_tutorial.html&quot;&gt;官网文档&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;演示&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;# 运行演示
ros2 launch panda_moveit_config demo.launch.py # 修改为自己的包名
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://img.undf.top/image/ros2_urdf/%E8%BD%A8%E8%BF%B9%E8%A7%84%E5%88%92-2023-08-21.gif&quot; alt=&quot;轨迹规划-2023-08-21&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;其他&lt;/h2&gt;
&lt;p&gt;我在导出复杂模型时遇到一些问题，可能是插件的问题，导出的模型有些问题，但是简单模型没有问题&lt;/p&gt;
&lt;p&gt;经过CoppeliaSim Edu导入再导出，可以解决这个问题（记得修改urdf内的文件路径）&lt;/p&gt;
</content:encoded></item><item><title>旭日x3PI的开发日常</title><link>https://undf.cn/posts/post/code/ros2/x3/%E6%97%AD%E6%97%A5x3pi%E7%9A%84%E5%BC%80%E5%8F%91%E6%97%A5%E5%B8%B8/</link><guid isPermaLink="true">https://undf.cn/posts/post/code/ros2/x3/%E6%97%AD%E6%97%A5x3pi%E7%9A%84%E5%BC%80%E5%8F%91%E6%97%A5%E5%B8%B8/</guid><pubDate>Wed, 05 Jul 2023 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;常用命令&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;hrut_somstatus # 用于实时查询温度传感器读数及 CPU/BPU 频率实时信息


echo performance &amp;gt; /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor  #  CPU 频率固定在最高值:

sudo apt update # 更新软件源

sudo apt full-upgrade # 更新系统


sudo nmcli device wifi rescan # 扫描wifi

sudo nmcli device wifi list # 列出wifi

sudo wifi_connect &quot;SSID&quot; &quot;PASSWD&quot; # 连接wifi  wifi支持开热点 具体看 https://developer.horizon.ai/api/v1/fileData/documents_pi/System_Configuration/System_Configuration.html#id2



&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;QT相关&lt;/h2&gt;
&lt;p&gt;QT 安装&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo apt install qt5-default
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;QT Creator 安装&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo apt install qtcreator
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;第三方包&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;串口  sudo apt install libqt5serialport5-dev&lt;/li&gt;
&lt;li&gt;蓝牙  sudo apt-get install libkf5bluezqt-dev  # 如果不行再尝试这个 sudo apt-get install libbluetooth-dev&lt;/li&gt;
&lt;li&gt;截图  sudo apt-get install xfce4-screenshooter  # 安装后键盘上面的 prtsc 按键就可以用了&lt;/li&gt;
&lt;li&gt;录屏  sudo apt-get install kazam # 找应用即可
其他包类似 可以用 apt search 搜索&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;蓝牙&lt;/h2&gt;
&lt;p&gt;蓝牙连接嵌入式设备&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# 先配对然后连接
sudo rfcomm connect hci0 (macaddress)
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;ros&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;修复ROS2使用zsh无法用tab补全 ros2 指令的相关问题&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo apt install python3-argcomplete python3-colcon-common-extensions
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后，在.zshrc里面添加如下语句，&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;source /usr/share/colcon_cd/function/colcon_cd.sh
export _colcon_cd_root=/opt/ros/foxy/
source /usr/share/colcon_argcomplete/hook/colcon-argcomplete.zsh
eval &quot;$(register-python-argcomplete3 ros2)&quot;
eval &quot;$(register-python-argcomplete3 colcon)&quot;

&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;后记&lt;/h2&gt;
&lt;p&gt;看着内容不多，但在搜索引擎里面找这些废了不少功夫，所以就写了这个，方便自己也方便别人。&lt;/p&gt;
</content:encoded></item><item><title>QtCreator 一键打包你的APP</title><link>https://undf.cn/posts/post/code/embedded/qtcreator/</link><guid isPermaLink="true">https://undf.cn/posts/post/code/embedded/qtcreator/</guid><pubDate>Mon, 03 Jul 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&amp;lt;!-- &lt;img alt=&quot;img-2023-07-03&quot; /&gt; --&amp;gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;打开这个&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;https://img.undf.top/image/QtCreator/Qtcreator%E9%85%8D%E7%BD%AE-2023-07-03.png&quot; alt=&quot;Qtcreator配置-2023-07-03&quot; /&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;添加工具&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;https://img.undf.top/image/QtCreator/Snipaste_2023-07-21_15-19-34-2023-07-21.png&quot; alt=&quot;Snipaste_2023-07-21_15-19-34-2023-07-21&quot; /&gt;&lt;/p&gt;
&lt;p&gt;添加外部程序 修改如下内容&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;执行挡： &lt;code&gt;powershell&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;参数（一行）：&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;#  qt Creator 8 以上版本  其他版本请根据最下面的提示修改
md %{ActiveProject:Path}/package/%{ActiveProject:BuildConfig:Type}/ ; copy  %{ActiveProject:RunConfig:Executable:FilePath}  %{ActiveProject:Path}/package/%{ActiveProject:BuildConfig:Type}/%{ActiveProject:RunConfig:Executable:FileName} ; %{ActiveProject:QT_HOST_BINS}/windeployqt.exe %{ActiveProject:Path}/package/%{ActiveProject:BuildConfig:Type}/%{ActiveProject:RunConfig:Executable:FileName} 
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;Base environment 改为 &lt;code&gt;Current build environment&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;双击可以重命名&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://img.undf.top/image/QtCreator/20230721152236-2023-07-21.png&quot; alt=&quot;20230721152236-2023-07-21&quot; /&gt;&lt;/p&gt;
&lt;p&gt;其他保持默认即可&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;使用&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;(可选)将编译模式改为release&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://img.undf.top/image/QtCreator/20230721152350-2023-07-21.png&quot; alt=&quot;20230721152350-2023-07-21&quot; /&gt;&lt;/p&gt;
&lt;p&gt;单击运行即可&lt;/p&gt;
&lt;p&gt;运行后可以看到下图即为成功&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://img.undf.top/image/QtCreator/20230721152840-2023-07-21.png&quot; alt=&quot;20230721152840-2023-07-21&quot; /&gt;&lt;/p&gt;
&lt;p&gt;打开项目所在目录  &lt;code&gt;package&lt;/code&gt; 文件夹即为打包后的文件夹&lt;/p&gt;
&lt;p&gt;如果使用了Git 不要忘记把package文件夹加入到忽略列表中&lt;/p&gt;
&lt;h2&gt;其他 qt Creator 版本&lt;/h2&gt;
&lt;p&gt;单击红色方框后    单击右侧环境变量按钮&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://img.undf.top/image/QtCreator/20230721153122-2023-07-21.png&quot; alt=&quot;20230721153122-2023-07-21&quot; /&gt;&lt;/p&gt;
&lt;p&gt;将 %{ActiveProject:Path} %{ActiveProject:RunConfig:Executable:FilePath} %{ActiveProject:RunConfig:Executable:FileName} 替换为对应的环境变量即可&lt;/p&gt;
&lt;p&gt;如 qt Creator 4 版本的&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#  qt Creator 4 版本
md %{CurrentProject:Path}/package/ ; copy %{CurrentRun:Executable:FilePath} %{CurrentProject:Path}/package/%{CurrentRun:Executable:FileName} ; windeployqt %{CurrentProject:Path}/package/%{CurrentRun:Executable:FileName}
&lt;/code&gt;&lt;/pre&gt;
</content:encoded></item><item><title>旭日 x3PI RealSense人体关键点识别</title><link>https://undf.cn/posts/post/code/ros2/x3/%E6%97%AD%E6%97%A5-x3pi-%E4%BA%BA%E4%BD%93%E5%85%B3%E9%94%AE%E7%82%B9%E8%AF%86%E5%88%AB/</link><guid isPermaLink="true">https://undf.cn/posts/post/code/ros2/x3/%E6%97%AD%E6%97%A5-x3pi-%E4%BA%BA%E4%BD%93%E5%85%B3%E9%94%AE%E7%82%B9%E8%AF%86%E5%88%AB/</guid><pubDate>Fri, 26 May 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&amp;lt;!--&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;@Author: weiekko weiekko@gmail.com&lt;/li&gt;
&lt;li&gt;@Date: 2023-05-26&lt;/li&gt;
&lt;li&gt;@LastEditors: weiekko weiekko@gmail.com&lt;/li&gt;
&lt;li&gt;@LastEditTime: 2023-05-26&lt;/li&gt;
&lt;li&gt;@FilePath: \blog\source_posts\code\旭日 x3PI 人体关键点识别.md&lt;/li&gt;
&lt;li&gt;@Description:&lt;/li&gt;
&lt;li&gt;&lt;/li&gt;
&lt;li&gt;Copyright (c) 2023 by weiekko weiekko@gmail.com, All Rights Reserved.
--&amp;gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;起因&lt;/h2&gt;
&lt;p&gt;简单介绍一下我的目标&lt;/p&gt;
&lt;p&gt;获取部分人体关键点的空间坐标 控制双臂机器人进行拥抱&lt;/p&gt;
&lt;h2&gt;首次尝试&lt;/h2&gt;
&lt;p&gt;2022.11 开始做识别部分的内容，开始挑选硬件
这是当时小组会的PPT
&lt;img src=&quot;https://img.undf.top/utools/1685101433236_ojwjf9ncpghqr0z3.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;X3就不用多说了 非常强大&lt;/p&gt;
&lt;h2&gt;初次接触人体关键点识别&lt;/h2&gt;
&lt;p&gt;刚开始是拿了一个普通的USB摄像头进行识别，但是摄像头的输出像素格式是YUYV，当时关键点识别还只能用mjpeg的USB摄像头或者MIPI的摄像头，于是乎买了官方的MIPI进行尝试&lt;/p&gt;
&lt;p&gt;效果确实不错，但是我不光要关键点的二维坐标，还要三维坐标，这里就需要深度相机了&lt;/p&gt;
&lt;p&gt;实验室刚好有一台Intel的深度相机435，折腾了好久，因为并不熟悉这些东西，最后也没折腾出来&lt;/p&gt;
&lt;p&gt;仔细想想，机器人头上装俩摄像头就很奇怪，想想就脑壳痛。&lt;/p&gt;
&lt;p&gt;当时问群里的开发人员，他们说这个相机暂时不支持，后面可能会支持。其实当时已经有codec模块了，但是好像没有文档，反正是没找到。&lt;/p&gt;
&lt;p&gt;所以转去了用笔记本做主控，但是因为一些结构上的原因我又回来了&lt;/p&gt;
&lt;p&gt;其实也就花了两天的时间，比我移植ALPHAPOSE快多了&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://img.undf.top/utools/1685102218857_03dwsrnjm02gsp2w.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;RealSense 人体关键点识别&lt;/h2&gt;
&lt;p&gt;先讲一下整体思路&lt;/p&gt;
&lt;p&gt;Realsense node发布的是rgb格式的图像，使用hobot_codec把rgb转成jpeg jpeg转nv12（rgb8好像不能转nv12 我也不知道为什么 程序说的）,最后nv12送给mono2d_body_detection 就可以了&lt;/p&gt;
&lt;h3&gt;安装realsense2 SDK&lt;/h3&gt;
&lt;h4&gt;设置网络环境&lt;/h4&gt;
&lt;p&gt;这里因为网络原因需要设置一下GITHUB的代理的host，不然无法访问。&lt;/p&gt;
&lt;p&gt;打开https://www.ipaddress.com/ 输入raw.githubusercontent.com 查询IP地址 找不到就一直往下滑，直到找到&lt;/p&gt;
&lt;p&gt;把找到的ip按这个格式保存好&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;140.82.112.3 github.com
185.199.108.133 raw.githubusercontent.com
185.199.109.133 raw.githubusercontent.com
185.199.110.133 raw.githubusercontent.com
185.199.111.133 raw.githubusercontent.com
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;编辑hosts文件&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo vim /etc/hosts
# 重启网络
/etc/init.d/networking restart 

# ping一下试试
ping raw.githubusercontent.com
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;添加ROS apt源&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;sudo apt update &amp;amp;&amp;amp; sudo apt install curl gnupg2 lsb-release
sudo curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key  -o /usr/share/keyrings/ros-archive-keyring.gpg
echo &quot;deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ubuntu $(source /etc/os-release &amp;amp;&amp;amp; echo $UBUNTU_CODENAME) main&quot; | sudo tee /etc/apt/sources.list.d/ros2.list &amp;gt; /dev/null


sudo apt update

&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;安装Realsense  SDK&lt;/h4&gt;
&lt;p&gt;这一步因为网络原因可能会比较漫长，耐心等待，不如起来活动活动吃个饭。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# 显示ROS当前版本，如果显示为空，请source /opt/tros/setup.bash
echo $ROS_DISTRO 
# 安装RealSense SDK
sudo apt-get install ros-$ROS_DISTRO-librealsense2* -y 
# 安装RealSense ros wrapper
sudo apt-get install ros-$ROS_DISTRO-realsense2-camera -y
sudo apt-get install ros-$ROS_DISTRO-realsense2-description -y
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;建立软连接&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;cd /opt/tros
## 使用/opt/tros目录下的create_soft_link.py创建ROS package至tros.b的软连接
sudo python3 create_soft_link.py --foxy /opt/ros/foxy/ --tros /opt/tros/
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;到这里Realsense2 SDK就安装完成了&lt;/p&gt;
&lt;h4&gt;运行测试&lt;/h4&gt;
&lt;p&gt;运行前要先：&lt;/p&gt;
&lt;p&gt;&lt;code&gt;source /opt/ros/foxy/setup.bash&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;然后：&lt;/p&gt;
&lt;p&gt;&lt;code&gt;source /opt/tros/setup.bash &lt;/code&gt;&lt;/p&gt;
&lt;p&gt;运行程序：&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ros2 launch realsense2_camera rs_launch.py depth_module.profile:=640x480x15 &lt;/code&gt;&lt;/p&gt;
&lt;p&gt;这里要感谢一下王卓大佬&lt;/p&gt;
&lt;h3&gt;运行&lt;/h3&gt;
&lt;p&gt;这里我写了个脚本，保存为.sh文件，然后运行就好了，当然你也可以一步步运行看看哪里出错了&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;echo &apos;设置ros2环境变量&apos;
source /opt/ros/foxy/setup.bash
source /opt/tros/setup.bash

sleep 5
echo &apos;启动ros2  realsense 节点&apos;

ros2 launch realsense2_camera rs_launch.py depth_module.profile:=640x480x15 &amp;amp;

sleep 5
echo &apos;启动ros2  rgb8 2 jpeg 节点&apos;
ros2 run hobot_codec hobot_codec_republish --ros-args -p channel:=0 -p in_mode:=ros -p in_format:=rgb8 -p out_mode:=ros -p out_format:=jpeg -p sub_topic:=/camera/color/image_raw -p  pub_topic:=/image_jpeg --log-level error &amp;amp;
sleep 5
echo &apos;启动ros2  jpeg 2 nv12 节点&apos;
ros2 run hobot_codec hobot_codec_republish --ros-args -p channel:=1 -p in_mode:=ros -p in_format:=jpeg -p out_mode:=shared_mem -p out_format:=nv12 -p sub_topic:=/image_jpeg -p  pub_topic:=/hbmem_img --log-level error &amp;amp;
sleep 5
echo &apos;启动ros2  websocket 节点&apos;
ros2 run websocket websocket --ros-args -p image_topic:=/image_jpeg -p image_type:=mjpeg -p smart_topic:=/hobot_mono2d_body_detection --log-level error  &amp;amp;
sleep 5
echo &apos;启动ros2  mono2d_body_detection 节点&apos;
ros2 run mono2d_body_detection mono2d_body_detection --log-level error &amp;amp;
sleep 5
echo &apos;启动ros2  websocket 节点&apos;
ros2 launch websocket hobot_websocket.launch.py &amp;amp;

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;需要注意的是  rgb8(ros) -&amp;gt; jpeg(ros) -&amp;gt; nv12(shared_mem) -&amp;gt; mono2d_body_detection&lt;/p&gt;
&lt;h3&gt;参考链接&lt;/h3&gt;
&lt;p&gt;安装realsense SDK参考：https://c-gitlab.horizon.ai/HHP/box/hobot_slam/orb_slam3&lt;/p&gt;
&lt;p&gt;软链接参考：https://developer.horizon.ai/api/v1/fileData/TogetherROS/quick_start/install_use_ros_pkg.html&lt;/p&gt;
&lt;p&gt;codec参考：https://c-gitlab.horizon.ai/HHP/box/hobot_codec&lt;/p&gt;
&lt;h2&gt;注&lt;/h2&gt;
&lt;p&gt;如果有哪里有问题，包括我的问题和你运行的问题，欢迎评论指出，我会及时修改&lt;/p&gt;
&lt;p&gt;这里还要感谢一下王卓大佬&lt;/p&gt;
&lt;p&gt;关于realsense 的文档藏的也太深了。。。&lt;/p&gt;
&lt;h2&gt;To Do&lt;/h2&gt;
&lt;p&gt;深度信息获取与计算
表情视频切换播放&lt;/p&gt;
</content:encoded></item><item><title>MoneyProgress_win</title><link>https://undf.cn/posts/post/code/cpp/moneyprogress_win/</link><guid isPermaLink="true">https://undf.cn/posts/post/code/cpp/moneyprogress_win/</guid><pubDate>Tue, 11 Apr 2023 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;起因&lt;/h2&gt;
&lt;p&gt;前段时间分享了一个MoneyProgress的Mac软件,一直有人在论坛发帖问有没有win版的,恰好最近在看Qt,于是就有了这个项目.&lt;/p&gt;
&lt;p&gt;写这个贴子的目的是为了记录一下开发过程,以及遇到的问题.&lt;/p&gt;
&lt;p&gt;以后可以拿它做参考,也可以给有需要的人提供一些帮助.&lt;/p&gt;
&lt;p&gt;MAC版的项目地址: &lt;a href=&quot;https://github.com/Lakr233/MoneyProgress&quot;&gt;MoneyProgress&lt;/a&gt;
WIN版的项目地址: &lt;a href=&quot;https://github.com/wxydejoy/MoneyProgress_win&quot;&gt;MoneyProgress_win&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;程序很大程度参考了原作者的UI设计,这里再次感谢原作者.&lt;/p&gt;
&lt;h2&gt;开发环境&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Windows 10 20H2(这个不是很重要)&lt;/li&gt;
&lt;li&gt;Qt 5.15 with Mingw(这个很重要)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;开发过程&lt;/h2&gt;
&lt;p&gt;这块看我的&lt;a href=&quot;https://github.com/wxydejoy/MoneyProgress_win/commits/main&quot;&gt;commit&lt;/a&gt;记录就行了,虽然有点乱,但是基本上都是有用的.&lt;/p&gt;
&lt;p&gt;这里只记录一些比较重要的问题,其他的问题可以参考&lt;a href=&quot;https://doc.qt.io/qt-5/index.html&quot;&gt;Qt官方文档&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;多看文档,多看文档,多看文档.&lt;/p&gt;
&lt;h3&gt;问题1: 图片过大&lt;/h3&gt;
&lt;p&gt;原作者的图片都是png格式,大小足足有3.27MB,分辨率为1024x1024,应该是自己画的吧.&lt;/p&gt;
&lt;p&gt;刚开始导入图片设置为&lt;code&gt;label&lt;/code&gt;设置样式表&lt;code&gt;background-image: url(:/img/avatar.png);&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;是这样的:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://img.undf.top/image/MoneyProgress_win/20230411122233-2023-04-11.png&quot; alt=&quot;20230411122233-2023-04-11&quot; /&gt;&lt;/p&gt;
&lt;p&gt;可以看到图片很大,很奇怪,&lt;/p&gt;
&lt;p&gt;解决办法:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;设置为&lt;code&gt;border-image: url(:/img/avatar.png);&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://img.undf.top/image/MoneyProgress_win/20230411122553-2023-04-11.png&quot; alt=&quot;20230411122553-2023-04-11&quot; /&gt;&lt;/p&gt;
&lt;p&gt;这样它就会自动缩放了.可以通过设置&lt;code&gt;label&lt;/code&gt;的&lt;code&gt;width&lt;/code&gt;和&lt;code&gt;height&lt;/code&gt;来控制图片的大小.&lt;/p&gt;
&lt;h3&gt;问题2: 无法获取到正确的屏幕分辨率&lt;/h3&gt;
&lt;p&gt;这个问题是论坛上有人提出来的,我也遇到了.&lt;/p&gt;
&lt;p&gt;原代码为:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// 这里省略了一些代码
// 获取屏幕分辨率高度
QApplication::desktop()-&amp;gt;width();


&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;实际获取的不一定就是当前屏幕的分辨率,有时候会获取到错误的值.
比如你有多块屏幕,它会获取到所有屏幕的分辨率的和.就很离谱.
这就会导致我们的程序在不同的屏幕上显示的效果不一样.
任务栏的弹窗就奇奇怪怪的.甚至看不到.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://img.undf.top/image/MoneyProgress_win/20230411123559-2023-04-11.png&quot; alt=&quot;20230411123559-2023-04-11&quot; /&gt;&lt;/p&gt;
&lt;p&gt;解决办法:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// 这里省略了一些代码
QApplication::screenAt(QCursor().pos())-&amp;gt;geometry().width()


&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;意为获取鼠标所在屏幕的分辨率宽度.非常ok.&lt;/p&gt;
&lt;h3&gt;问题3: 文本无法正常更新&lt;/h3&gt;
&lt;p&gt;问题代码:&lt;/p&gt;
&lt;p&gt;因为我想实现每次点击任务栏图标都会弹出一个弹窗,显示当前的挣钱进度,所以我在&lt;code&gt;MoneyProgress&lt;/code&gt;类中添加了一个&lt;code&gt;IconMessage&lt;/code&gt;类的对象(一个小widget),并且在&lt;code&gt;MoneyProgress&lt;/code&gt;类中添加了一个&lt;code&gt;update&lt;/code&gt;函数,用来更新弹窗中的文本.
同时&lt;code&gt;update&lt;/code&gt;还要负责更新主窗口中的文本.所以就有了如下代码&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;
void MoneyProgress::update()
{
    // 这里省略了一些代码
    // 判断两个界面是否可见
    if (this-&amp;gt;isVisible())
    {
        ui-&amp;gt;labelMoneyNow-&amp;gt;setText(&quot;您当前已经挣了&quot;+QString::number(moneyday*progress/1000,&apos;f&apos;,1)+&quot;元;&quot;);
        ui-&amp;gt;labelDay-&amp;gt;setText(&quot;您一月工作&quot; + QString::number(days) + &quot;天;&quot;);
        ui-&amp;gt;labelMoneyDay-&amp;gt;setText(&quot;您一天能挣&quot; + QString::number(moneyday, &apos;f&apos;, 1) + &quot;元;&quot;);
        ui-&amp;gt;labelHourDay-&amp;gt;setText(&quot;您一天工作&quot; + QString::number(hours, &apos;f&apos;, 1) + &quot;小时;&quot;);
        ui-&amp;gt;labelMoneySecond-&amp;gt;setText(&quot;您一秒钟能挣&quot; + QString::number(moneysecond, &apos;f&apos;, 6) + &quot;元;&quot;);
    }
    if (iconmessage.isVisible())
    {
        iconmessage.update(progress, moneyday);
        qDebug() &amp;lt;&amp;lt; progress;
    }
}

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;可以看到大致思路就是判断两个界面是否可见,如果可见就更新文本.但是任务栏那个小窗口的文本无法更新,调试发现了一个低级错误&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;
update(); //错误的写法
iconmessage.show();
// update(); 把update()放在这里就可以更新了

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;确实很低级&lt;/p&gt;
&lt;h3&gt;问题4: QSettings 无效&lt;/h3&gt;
&lt;p&gt;这个问题是在保存时间的时候遇到的,我想把设置保存到&lt;code&gt;QSettings&lt;/code&gt;里面,但是发现无论怎么设置都无效.
在网上逛了半天,发现是因为&lt;code&gt;QSettings&lt;/code&gt;只能在构造函数和析构函数中使用,不能在其他函数中使用.&lt;/p&gt;
&lt;p&gt;问题代码:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;//原本设计的是每次设置改变就保存一次,但是发现无效
void MoneyProgress::on_timeSleepdown_userTimeChanged(const QTime &amp;amp;time)
{
    // 这里省略了一些代码 settings 是一个QSettings对象,在.h文件中定义
    settings.setValue(&quot;sleepDown&quot;, sleepDown);
    
    // 保存设置

}

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;解决办法:&lt;/p&gt;
&lt;p&gt;将&lt;code&gt;QSettings&lt;/code&gt;的保存设置放到析构函数中,这样就可以正常使用了.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;

MoneyProgress::~MoneyProgress()
{
    QSettings settings(&quot;MuYin&quot;, &quot;MoneyProgress_win&quot;);
    // 保存设置
    settings.setValue(&quot;money&quot;, money);
    settings.setValue(&quot;days&quot;, days);
    settings.setValue(&quot;workUp&quot;, workUp);
    settings.setValue(&quot;workDown&quot;, workDown);
    settings.setValue(&quot;sleepUp&quot;, sleepUp);
    settings.setValue(&quot;sleepDown&quot;, sleepDown);
    // settings.setValue(&quot;geometry&quot;, this-&amp;gt;saveGeometry());
    // settings.setValue(&quot;windowState&quot;, this-&amp;gt;saveState());

    // 保存设置
    settings.sync();

    delete ui;
}


&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;问题5: QSS样式表不会用&lt;/h3&gt;
&lt;p&gt;因为我设置了标题栏隐藏&lt;/p&gt;
&lt;p&gt;&lt;code&gt;this-&amp;gt;setWindowFlags(Qt::Dialog | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint); // 隐藏标题栏&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;所以一直弄不出来&lt;code&gt;borde&lt;/code&gt;的样式,最后发现改&lt;code&gt;centralwidget&lt;/code&gt;的&lt;code&gt;border&lt;/code&gt;属性就可以了.&lt;/p&gt;
&lt;p&gt;问题代码:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;QWidget {
    background-color: rgb(255, 255, 255);
    border-width: 3px;
    border-color: rgba(255, 216, 58, 225);
    border-radius: 15px;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;解决方法&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;QWidget {
    background-color: rgb(255, 255, 255);
    border-color: rgba(255, 216, 58, 225);
    border-radius: 15px;
}
QWidget#centralwidget {
    background-color: rgb(255, 255, 255);
    border: 3px solid #ffee6f;
    /* border-color: rgba(255, 216, 58, 225); */
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;css还是不太了解,回头需要好好学习一下.&lt;/p&gt;
&lt;h3&gt;问题6: 程序整体缩放问题&lt;/h3&gt;
&lt;p&gt;引用网友的话:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Qt下高分屏的问题，几乎是一场灾难。希望未来 Qt 能有更好的解决方案。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;解决方法: 添加 &lt;code&gt;qt/etc/qt.conf&lt;/code&gt;文件,注意这是在qrc文件中的路径,它的完整路径是&lt;code&gt;qrc:/qt/etc/qt.conf&lt;/code&gt;,网上说一定不要弄错
文件内容的意思为不使用QT的缩放功能,而是使用系统的缩放功能&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[Platforms]
WindowsArguments = dpiawareness=0

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;具体看这个&lt;a href=&quot;https://github.com/wxydejoy/MoneyProgress_win/commit/76ce3656f6f45008369d1b023bd450f817b59ab3&quot;&gt;commit&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;问题7: QtCreator 无法Debug&lt;/h3&gt;
&lt;p&gt;将build模式从release改为debug就可以了..................................&lt;/p&gt;
&lt;h2&gt;总结&lt;/h2&gt;
&lt;p&gt;项目不大,时间也不算长,大概两三个晚上的样子,但是在这个过程中学到了很多东西,比如说&lt;code&gt;QSettings&lt;/code&gt;的使用,&lt;code&gt;QSS&lt;/code&gt;的使用,&lt;code&gt;QTimer&lt;/code&gt;的使用,&lt;code&gt;QApplication::screenAt(QCursor().pos())-&amp;gt;geometry().width()&lt;/code&gt;的使用,以及一些小技巧,比如说&lt;code&gt;QSettings&lt;/code&gt;只能在构造函数和析构函数中使用,&lt;code&gt;QSS&lt;/code&gt;的&lt;code&gt;border&lt;/code&gt;属性要写在&lt;code&gt;centralwidget&lt;/code&gt;上,&lt;code&gt;QTimer&lt;/code&gt;的&lt;code&gt;start&lt;/code&gt;函数可以传入一个参数,表示延迟多久开始计时,&lt;code&gt;QApplication::screenAt(QCursor().pos())-&amp;gt;geometry().width()&lt;/code&gt;可以获取鼠标所在屏幕的分辨率宽度等等.&lt;/p&gt;
&lt;p&gt;最后希望大家能够多多支持,如果有什么问题,欢迎指正,可以在评论区留言,我会尽快回复的.&lt;/p&gt;
</content:encoded></item><item><title>戴森球计划[游戏安利]</title><link>https://undf.cn/posts/post/life/%E6%88%B4%E6%A3%AE%E7%90%83%E8%AE%A1%E5%88%92/</link><guid isPermaLink="true">https://undf.cn/posts/post/life/%E6%88%B4%E6%A3%AE%E7%90%83%E8%AE%A1%E5%88%92/</guid><pubDate>Wed, 11 Jan 2023 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;游戏介绍&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;探索未知的星球，发现珍奇，让你的足迹遍布星辰大海。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;《戴森球计划》是一款融合了太空、自动化工厂、冒险、探索等元素的科幻题材沙盒建造类游戏。在未来，人类踏入高级文明的行列之时，科技的强大带来了飞速的发展，虚拟现实迭代了空间与时间。人类创造了超级计算机——“主脑”，以期待利用其强大的计算能力来进一步扩大虚拟世界的运用。&lt;/p&gt;
&lt;p&gt;作为玩家的你，加入了空间管理联盟COSMO开启的一项代号为“戴森球计划”的工程项目，建造戴森球，为“主脑”提供持续稳定的能量。
在游戏中，玩家将从上帝视角进行工厂建造及资源管理。在这一过程中，你势必会遭遇诸多困难，毕竟宇宙之大，什么都可能发生。然而，你的创造力与想象力将会助你达成这一宏大的目标，整个银河势必将在你的规划下成为人类文明前进的基石。&lt;/p&gt;
&lt;p&gt;你可以不断解锁科技，一步一步打造专属你的戴森球；
也可以探索宇宙，发现宇宙珍奇，踏遍星辰大海；
或是架设星际物流系统，串联出庞大的工业帝国；
亦或是不断优化设计，让生产流水线的效率更高。&lt;/p&gt;
&lt;p&gt;&lt;em&gt;随机生成的星图，每一局都是独一无二的宇宙。&lt;/em&gt;
&lt;em&gt;更加微观的建造戴森球，从一个零件开始构架。&lt;/em&gt;
&lt;em&gt;千变万化的宇宙生态，中子星、白矮星、红巨星，甚至黑洞。&lt;/em&gt;
&lt;em&gt;不止于地表的自动化生产流水线，跨越星系运输物资。&lt;/em&gt;
&lt;em&gt;多种可自主定制的设定，打造属于你自己的戴森球计划。&lt;/em&gt;
&lt;em&gt;球形地表，完美表现在一颗星球之上完成建设的特色。&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;将资源通过传送带串联在各个建筑之间，形成高效的流水线生产，让科技自主的前进。同时在建造过程中建筑会自动吸附网格，铺设流水线时可以利用建筑网格吸附功能自动对齐建筑，大大提高建造的效率，形成大规模的自动化流水线。&lt;/p&gt;
&lt;p&gt;跨越地表运输的限制，组建你的星际运输大队，将另一个星球的物资传递过来，集合全宇宙的力量来快速发展自己。&lt;/p&gt;
&lt;p&gt;每一次游戏的开始都会随机生成全新的星图，拥有不同的星球种类，矿物分布。每一个星球的地形也会变化。在这个千变万化的宇宙中去完全属于你自己的“戴森球计划”。&lt;/p&gt;
&lt;p&gt;同时游戏中直接展现了各式各样的星球和天象，中子星、白矮星、红巨星、气态星球、日冕、永昼永夜等，统统都可以在这里看到。&lt;/p&gt;
&lt;h2&gt;宣传视频&lt;/h2&gt;
&lt;p&gt;&amp;lt;iframe src=&quot;//player.bilibili.com/player.html?aid=713920122&amp;amp;bvid=BV1uX4y1N7RA&amp;amp;cid=289044568&amp;amp;page=1&quot; scrolling=&quot;no&quot; border=&quot;0&quot; frameborder=&quot;no&quot; framespacing=&quot;0&quot; allowfullscreen=&quot;true&quot;&amp;gt; &amp;lt;/iframe&amp;gt;&lt;/p&gt;
&lt;h2&gt;买家秀&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://img.undf.top/utools/uTools_1673411927627_Px_qcq6ltpy60u8gd2l.png&quot; alt=&quot;&quot; /&gt;
&lt;img src=&quot;https://img.undf.top/utools/uTools_1673411846852_Px_ixatoh29oz8dv61y.png&quot; alt=&quot;&quot; /&gt;
&lt;img src=&quot;https://img.undf.top/utools/uTools_1673411772808_Px(1)_ghq9uh55ib64biwb.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;一些有趣但很真实的评论&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;早上八点打开游戏，关闭游戏是已经是早上七点，这游戏能让时间倒流！！！&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;配置要求不高，但是后期PPT是无法避免的&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;戴森球计划（❌）    时间消失模拟器（✔️）&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;千人大厂十连抽，五人作坊戴森球！&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;70块钱他就能给你几十个恒星系玩哎，当你看到戴森球代替恒星升起，物流飞船遍布整个宇宙，自动化生产线源源不断生产出一些看上去非常厉害的东西的时候，那感觉，真的绝了&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;还没出的战斗序列&lt;/h2&gt;
&lt;p&gt;《戴森球计划》TGS战斗系统宣传视频：黑雾崛起&lt;/p&gt;
&lt;p&gt;&amp;lt;iframe style=&quot;height: 30rem;width: 100%;&quot; src=&quot;//player.bilibili.com/player.html?aid=645605352&amp;amp;bvid=BV1nY4y1T7vo&amp;amp;cid=832676244&amp;amp;page=1&quot; scrolling=&quot;no&quot; border=&quot;0&quot; frameborder=&quot;no&quot; framespacing=&quot;0&quot; allowfullscreen=&quot;true&quot; &amp;gt; &amp;lt;/iframe&amp;gt;&lt;/p&gt;
&lt;h2&gt;玩家文档&lt;/h2&gt;
&lt;p&gt;https://wiki.biligame.com/dsp/%E9%A6%96%E9%A1%B5&lt;/p&gt;
&lt;p&gt;最后测试一下我的随机图片壁纸&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://img.undf.top/random&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
</content:encoded></item><item><title>invoice_ocr</title><link>https://undf.cn/posts/post/code/py/invoice_ocr/</link><guid isPermaLink="true">https://undf.cn/posts/post/code/py/invoice_ocr/</guid><pubDate>Sat, 01 Oct 2022 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;因&lt;/h2&gt;
&lt;p&gt;最近实验室财务政策(报销的相关事情)有一些改变，需要自己去写入库单，然后去财务处报销，但是我不想手写Word，然后就有了这个工具。&lt;/p&gt;
&lt;p&gt;之前财务也有用过一个OCR的工具，但是我觉得不太好用，所以就干脆自己写了一个。&lt;/p&gt;
&lt;p&gt;在提高效率的同时，也可以学习一下OCR的相关知识。&lt;/p&gt;
&lt;h2&gt;用到的库&lt;/h2&gt;
&lt;p&gt;语言当然不用说了，Python。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ocr(文字识别)：百度的OCR api &lt;a href=&quot;https://ai.baidu.com/tech/ocr_receipts/vat_invoice&quot;&gt;增值税发票识别&lt;/a&gt;（封面也是这里找的）&lt;/li&gt;
&lt;li&gt;json：用来解析百度OCR的返回值&lt;/li&gt;
&lt;li&gt;python-docx：用来生成Word文档&lt;/li&gt;
&lt;li&gt;pypdf2：用来生成PDF文档&lt;/li&gt;
&lt;li&gt;datetime：用来生成时间戳&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;思路&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;从淘宝等网站获取订单发票&lt;/li&gt;
&lt;li&gt;用百度OCR识别发票信息&lt;/li&gt;
&lt;li&gt;生成Word文档&lt;/li&gt;
&lt;li&gt;将发票pdf重命名并归档&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;效果&lt;/h2&gt;
&lt;p&gt;部分效果图如下：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://img.undf.top/cundf/others/invoice_ocr.md/2022-10-01-17-16-47.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://img.undf.top/cundf/others/invoice_ocr.md/2022-10-01-17-17-30.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;代码&lt;/h2&gt;
&lt;p&gt;很长且没有注释，但是我觉得很好理解，就不贴了。&lt;/p&gt;
&lt;p&gt;其实自己也快忘了hhhh&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;
from datetime import datetime
import shutil
from time import sleep
from aip import AipOcr
import PyPDF2 as pdf
import json
import docx
import os

&quot;&quot;&quot; 你的 APPID AK SK &quot;&quot;&quot;
APP_ID = &apos;xxxx&apos;
API_KEY = &apos;xxx&apos;
SECRET_KEY = &apos;xxxx&apos;

client = AipOcr(APP_ID, API_KEY, SECRET_KEY)


&quot;&quot;&quot; 读取pdf &quot;&quot;&quot;


def get_file_content(filePath):
    with open(filePath, &apos;rb&apos;) as fp:
        return fp.read()


# 遍历文件夹下所有pdf文件
def get_pdffiles(dir_path):
    import os
    files = os.listdir(dir_path)
    pdf_files = []
    for file in files:
        if file.endswith(&apos;.pdf&apos;):
            pdf_files.append(dir_path+&apos;/&apos;+file)
    return pdf_files


# 商品类
class Commodity:
    def __init__(self):
        self.name = &apos;&apos;
        self.type = &apos;&apos;
        self.unit = &apos;&apos;
        self.price = 0
        self.tax_rate = 0
        self.tax = 0
        self.total_price = 0
        self.num = 0

    

# 入库单类


# 入库单
# Warehouse receipt

class WarehouseReceipt():
    def __init__(self, pdf_file_path=&apos;&apos;):
        self.order_num = &apos;&apos;
        self.order_date = &apos;&apos;
        self.supplier = &apos;&apos;
        self.commodity_list = []
        self.total_price = 0
        self.json = &apos;&apos;
        self.pdf_file_path = pdf_file_path
        self.company = &apos;&apos;
        self.c_price = &apos;&apos;

    def __str__(self):
        return &apos;订单号：&apos;+self.order_num+&apos;，订单日期：&apos;+self.order_date+&apos;，供应商：&apos;+self.supplier+&apos;，总价：&apos;+self.total_price

    
    def ocr(self):
        # pdf_file_path = &apos;invoice/1.pdf&apos;



        if self.get_pdf_num() &amp;gt; 1:
            #print(&apos;pdf文件页数大于1,暂不支持&apos;)
            return
        else:
            #print(&apos;pdf文件页数为1&apos;)
            #print(&apos;开始识别&apos;)
            #print(self.pdf_file_path)
            pdf_file = self.get_file_content()
            self.json = client.vatInvoicePdf(pdf_file)
            # with open(&apos;{}.json&apos;.format(self.pdf_file_path), &apos;w&apos;, encoding=&apos;utf-8&apos;) as f:
            #     json.dump(self.json, f, ensure_ascii=False, indent=4)

            #print(self.json)


    def ocr_pic(self):
        # pdf 转图片
        def pdf_to_pic(self):
            from pdf2image import convert_from_path
            pages = convert_from_path(self.pdf_file_path, 200)
            for page in pages:
                page.save(self.pdf_file_path.replace(&apos;.pdf&apos;,&apos;.jpg&apos;), &apos;JPEG&apos;)
        pdf_to_pic(self)
        # 识别图片
        image = self.get_pic_content()
        
        self.json = client.receipt(image)
        # 保存json数据
        with open(&apos;invoice/{}.json&apos;.format(self.pdf_file_path), &apos;w&apos;, encoding=&apos;utf-8&apos;) as f:
            json.dump(self.json, f, ensure_ascii=False, indent=4)
        #print(self.json)


    def handle_json(self):

        json_data = self.json
        # 商品对象列表
        self.commodity_list = []

        words_result = json_data[&apos;words_result&apos;]
        for i in range(0, len(words_result[&apos;CommodityTaxRate&apos;])):

            # 商品名称
            self.commodity_list.append(Commodity())
            if i == len(words_result[&apos;CommodityTaxRate&apos;])-1:
                for j in range(int(words_result[&apos;CommodityTaxRate&apos;][i][&apos;row&apos;])-1, len(words_result[&apos;CommodityName&apos;])):
                    #print(i, j)
                    self.commodity_list[i].name += words_result[&apos;CommodityName&apos;][j][&apos;word&apos;]
                    # self.commodity_list[i]+=(words_result[&apos;CommodityName&apos;][j][&apos;word&apos;])
            else:
                for j in range(int(words_result[&apos;CommodityTaxRate&apos;][i][&apos;row&apos;])-1, int(words_result[&apos;CommodityTaxRate&apos;][i+1][&apos;row&apos;])-1):
                    #print(i, j)
                    self.commodity_list[i].name += words_result[&apos;CommodityName&apos;][j][&apos;word&apos;]
                    # self.commodity_list[i]+=(words_result[&apos;CommodityName&apos;][j][&apos;word&apos;])

            # 商品单价(含税)
            # 判断是否含税
            if &apos;%&apos; in words_result[&apos;CommodityTaxRate&apos;][i][&apos;word&apos;]:
                #print(&apos;含税&apos;,i)
                #print(&apos;ll&apos;,self.commodity_list)
                
                #print(&apos;ll&apos;,self.commodity_list[i])

                self.commodity_list[i].price = float(
                    words_result[&apos;CommodityPrice&apos;][i][&apos;word&apos;]) + float(words_result[&apos;CommodityTax&apos;][i][&apos;word&apos;]) / int(words_result[&apos;CommodityNum&apos;][i][&apos;word&apos;])
                #print(&apos;%&apos;)
            else:
                self.commodity_list[i].price = float(
                    words_result[&apos;CommodityPrice&apos;][i][&apos;word&apos;])

            # 商品类型(只能单页)
            if words_result[&apos;CommodityType&apos;]:
                self.commodity_list[i].type = words_result[&apos;CommodityType&apos;][i][&apos;word&apos;]

            #self.commodity_list[i].price = words_result[&apos;CommodityPrice&apos;][i][&apos;word&apos;]

            # 单个商品总价
            self.commodity_list[i].total_price = self.commodity_list[i].price * \
                int(words_result[&apos;CommodityNum&apos;][i][&apos;word&apos;])

            # 处理单价和总价的小数点
            self.commodity_list[i].price = round(
                self.commodity_list[i].price, 2)
            self.commodity_list[i].total_price = round(
                self.commodity_list[i].total_price, 2)

            self.commodity_list[i].num = int(
                words_result[&apos;CommodityNum&apos;][i][&apos;word&apos;])

            # 商品单位
            self.commodity_list[i].unit = words_result[&apos;CommodityUnit&apos;][i][&apos;word&apos;]

            
        self.total_price = float(words_result[&apos;AmountInFiguers&apos;])
        self.order_date = words_result[&apos;InvoiceDate&apos;]
        self.company = words_result[&apos;SellerName&apos;]
        self.c_price = words_result[&apos;AmountInWords&apos;]
            


        

            
            

            # 商品名称

        #print(self.commodity_list)
        for i in self.commodity_list:
            #print(i.name)
            #print(i.price)
            #print(i.total_price)
            #print(i.num)
            #print(i.type)
            #print(i.unit)
            pass

    # 生成入库单word文件

    def generate_word(self):
        from docx.shared import Pt
        from docx.oxml.ns import qn
        from docx.shared import Inches
        
        from docx.enum.text import WD_ALIGN_PARAGRAPH
        import datetime
        from docx.enum.table import WD_TABLE_ALIGNMENT
        from docx.enum.table import WD_ALIGN_VERTICAL
        from docx.enum.text import WD_PARAGRAPH_ALIGNMENT


        # 生成word文件
        doc = docx.Document()
        # 设置所有字体为宋体
        doc.styles[&apos;Normal&apos;].font.name = u&apos;宋体&apos;


        doc.styles[&apos;Normal&apos;]._element.rPr.rFonts.set(qn(&apos;w:eastAsia&apos;), u&apos;宋体&apos;)
        # 设置所有段落的行距为1.5倍
        doc.styles[&apos;Normal&apos;].paragraph_format.line_spacing = 1.5
        # 设置
        title = doc.add_paragraph(&quot;浙江工业大学耗材入库单&quot;, style=&apos;Normal&apos;)
        # 设置标题字体大小
        title.runs[0].font.size = Pt(18)
        # 加粗
        title.runs[0].font.bold = True
        # 设置标题居中
        title.paragraph_format.alignment = WD_ALIGN_PARAGRAPH.CENTER

        # 添加当天时间
        today = datetime.datetime.now().strftime(&apos;%Y年%m月%d日&apos;)
        today = doc.add_paragraph(today, style=&apos;Normal&apos;)
        today.paragraph_format.alignment = WD_ALIGN_PARAGRAPH.CENTER

        # 添加部门公章
        doc.add_paragraph(&quot;部门（公章）：							单位：	元&quot;, style=&apos;Normal&apos;)




        # 设置表格
        table = doc.add_table(rows=1, cols=7, style=&apos;Table Grid&apos;)
        # 左下
        table.alignment = WD_ALIGN_VERTICAL.CENTER
        # table.alignment = 
        # table.alignment = WD_TABLE_ALIGNMENT.LEFT
        # table.alignment = WD_TABLE_ALIGNMENT.BOTTOM

        # 根据内容自动调整列宽
        # table.autofit = True
        # table.autofitcontent = True
        # 设置每一列的宽度
        table.cell(0, 1).width = Inches(4)
        table.cell(0, 2).width = Inches(3)
        

        # 设置 首行
        table.cell(0, 0).text = &apos;供货单位&apos;
        table.cell(0, 1).text = self.company
        table.cell(0, 2).text = &apos;入库日期&apos;
        table.cell(0, 3).text = self.order_date
        # 合并单元格
        table.cell(0, 3).merge(table.cell(0, 4))
        table.cell(0, 5).text = &apos;入库单号&apos;
        table.cell(0, 6).text = self.order_num
        
        # 表格 根据内容自动调整
        table.allow_autofit = True


        hdr_cells = table.add_row().cells
        hdr_cells[0].text = &apos;序号&apos;
        hdr_cells[1].text = &apos;耗材名称&apos;
        hdr_cells[2].text = &apos;规格型号&apos;
        hdr_cells[3].text = &apos;单位&apos;
        hdr_cells[4].text = &apos;数量&apos;
        hdr_cells[5].text = &apos;单价&apos;
        hdr_cells[6].text = &apos;金额&apos;
        for index,i in enumerate(self.commodity_list):
            row_cells = table.add_row().cells
            row_cells[0].text = str(index+1)
            row_cells[1].text = i.name
            row_cells[2].text = i.type
            row_cells[3].text = i.unit
            row_cells[4].text = str(i.num)
            row_cells[5].text = str(i.price)
            row_cells[6].text = str(i.total_price)
        
        # 合计行
        row_cells = table.add_row().cells
        row_cells[0].text = &apos;合计&apos;
        # 合并单元格
        
        row_cells[1].text = &apos;(大写)&apos;
        row_cells[2].merge(row_cells[3]).merge(row_cells[4]).text = self.c_price
        row_cells[5].text = &apos;(小写)&apos;
        row_cells[6].text = str(self.total_price)

        

        # 添加制表等
        doc.add_paragraph(&quot;制表（保管）：			采购：			入库验收：&quot;, style=&apos;Normal&apos;)

        last = doc.add_paragraph(
            &quot;第一联：存根联	第二联：财务	第三联：供货单位（采购）	第四联：验收人&quot;, style=&apos;Normal&apos;)
        last.runs[0].font.size = Pt(10)
        last.paragraph_format.alignment = WD_ALIGN_PARAGRAPH.CENTER
        

        # 保存文件

        doc.save(&apos;invoice/word/&apos;+str(self.total_price)+self.company+self.order_date+&apos;.docx&apos;)
    

    def get_file_content(self):
        with open(self.pdf_file_path, &apos;rb&apos;) as fp:
            return fp.read()

    def get_pic_content(self):
        with open(self.pdf_file_path.replace(&apos;.pdf&apos;,&apos;.jpg&apos;), &apos;rb&apos;) as fp:
            return fp.read()

    # 获取pdf页码

    def get_pdf_num(self):
        pdfFileObj = open(self.pdf_file_path, &apos;rb&apos;)
        pdfReader = pdf.PdfFileReader(pdfFileObj)
        num = pdfReader.numPages
        return num

    def cp(self):
        # 复制并重命名pdf文件
        shutil.copy(self.pdf_file_path, &apos;invoice/pdf/&apos;+str(self.total_price)+self.company+self.order_date+&apos;.pdf&apos;)
        # 删除原pdf文件
        os.remove(self.pdf_file_path)

    def deal(self):
        self.ocr()
        # 捕捉异常
        try:
            self.handle_json()
        except Exception as e:
            print(e, &apos;json文件处理失败&apos;)
            # 创建错误日志
            with open(&apos;invoice/log/error-{}.log&apos;.format(datetime.now().strftime(&apos;%Y年%m月%d日%H-%M&apos;)), &apos;a&apos;, encoding=&apos;utf-8&apos;) as f:
                f.write(self.pdf_file_path+&apos;  &apos;+str(e) +
                        &apos;\r\n&apos;+str(self.json)+&apos;\r\n&apos;)
            #print(e)
            #print(&apos;处理json文件出错&apos;)
        # 抛出异常
        else:
            #print(&apos;处理json文件成功&apos;)
            print(&apos;处理json文件成功&apos;,self.pdf_file_path)
            # 创建成功日志
            with open(&apos;invoice/log/success-{}.log&apos;.format(datetime.now().strftime(&apos;%Y年%m月%d日%H-%M&apos;)), &apos;a&apos;, encoding=&apos;utf-8&apos;) as f:
                f.write(self.pdf_file_path+&apos;\r\n&apos;)

        self.generate_word()
        self.cp()
        # options = {}
        # options[&apos;pdf_file_num&apos;] = get_pdf_num(pdf_file_path)
        # res_pdf = client.vatInvoicePdf(pdf_file, options)
        # # 保存json数据
        # with open(&apos;invoice/1.json&apos;, &apos;w&apos;, encoding=&apos;utf-8&apos;) as f:
        #     json.dump(res_pdf, f, ensure_ascii=False, indent=4)

    def dealdebug(self):
        self.ocr()
        # 捕捉异常
        
        self.handle_json()
        

        self.generate_word()
        # options = {}
        # options[&apos;pdf_file_num&apos;] = get_pdf_num(pdf_file_path)
        # res_pdf = client.vatInvoicePdf(pdf_file, options)
        # # 保存json数据
        # with open(&apos;invoice/1.json&apos;, &apos;w&apos;, encoding=&apos;utf-8&apos;) as f:
        #     json.dump(res_pdf, f, ensure_ascii=False, indent=4)

# read json


# def read_json(file_path):
#     with open(file_path, &apos;r&apos;, encoding=&apos;utf-8&apos;) as f:
#         json_data = json.load(f)
#         handle_json(json_data)
if __name__ == &apos;__main__&apos;:

    for i in get_pdffiles(&apos;invoice/new&apos;):
        WarehouseReceipt(i).deal()
    
    #WarehouseReceipt(&apos;invoice/new/202205171971483062.pdf&apos;).dealdebug()


    # WarehouseReceipt(&apos;invoice\new\202209102153729425.pdf&apos;).deal()












    # wh1 = WarehouseReceipt(&apos;invoice/invoice.pdf&apos;)

    # with open(&apos;invoice/invoice.json&apos;, &apos;r&apos;, encoding=&apos;utf-8&apos;) as f:
    #     wh1.json = json.load(f)
    # wh1.ocr()
    # wh1.handle_json()
    # wh1.deal()
    # wh1.handle_json()

    # wh1 = WarehouseReceipt()
    # with open(&apos;invoice/invoice.json&apos;, &apos;r&apos;, encoding=&apos;utf-8&apos;) as f:
    #     wh1.json = json.load(f)
    # wh1.handle_json()
    # wh1.generate_word()

    # read_json(&apos;invoice/invoice.json&apos;)
    # read_json(&apos;invoice/1.json&apos;)

    # pdf_file_path = &apos;invoice/1.pdf&apos;
    # pdf_file = get_file_content(pdf_file_path)
    # options = {}
    # options[&apos;pdf_file_num&apos;] = get_pdf_num(pdf_file_path)
    # res_pdf = client.vatInvoicePdf(pdf_file, options)
    # # 保存json数据
    # with open(&apos;invoice/1.json&apos;, &apos;w&apos;, encoding=&apos;utf-8&apos;) as f:
    #     json.dump(res_pdf, f, ensure_ascii=False, indent=4)


# 从文件读取json数据(测试用)


# 调用增值税发票识别
# res_image = client.vatInvoice(image)
# res_url = client.vatInvoiceUrl(url)
# res_pdf = client.vatInvoicePdf(pdf_file)
# #print(res_image)
# #print(res_url)
# #print(res_pdf)


# 如果有可选参数
# options = {}

# options[&apos;pdf_file_num&apos;] = get_invoice_num(file_path)
# res_image = client.vatInvoice(image, options)
# res_url = client.vatInvoiceUrl(url, options)
# res_pdf = client.vatInvoicePdf(pdf_file, options)
# #print(res_image)
# #print(res_url)
# #print(res_pdf)
&lt;/code&gt;&lt;/pre&gt;
</content:encoded></item><item><title>三根杆</title><link>https://undf.cn/posts/post/code/robot/%E4%B8%89%E8%87%AA%E7%94%B1%E5%BA%A6/</link><guid isPermaLink="true">https://undf.cn/posts/post/code/robot/%E4%B8%89%E8%87%AA%E7%94%B1%E5%BA%A6/</guid><pubDate>Mon, 03 Jan 2022 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;初&lt;/h2&gt;
&lt;p&gt;机械手臂（英语：robotic arm）是具有模仿人类手臂功能并可完成各种作业的自动控制设备，这种机器人系统有多关节连结并节允许在平面或三度空间进行运动或使用线性位移移动。&lt;/p&gt;
&lt;p&gt;本文的主题是平面三轴机械臂。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://img.undf.top/index/2021-12-21-17-53-30.gif&quot; alt=&quot;TU&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;启&lt;/h2&gt;
&lt;p&gt;首先来学习一下单轴的，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://img.undf.top/image/%E4%B8%89%E8%87%AA%E7%94%B1%E5%BA%A6/2022-01-03-10-38-07.png&quot; alt=&quot;2022-01-03-10-38-07&quot; /&gt;
（系统画图画的）&lt;/p&gt;
&lt;p&gt;将物理问题转化为数学问题，建立坐标系：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://img.undf.top/image/%E4%B8%89%E8%87%AA%E7%94%B1%E5%BA%A6/2022-01-03-10-41-42.png&quot; alt=&quot;2022-01-03-10-41-42&quot; /&gt;&lt;/p&gt;
&lt;p&gt;杆长取&lt;code&gt;r&lt;/code&gt;很容易就能得到端点坐标为&lt;code&gt;rcosα,rscinα&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;是不是很简单，那接下来看两个杆。&lt;/p&gt;
&lt;h2&gt;中&lt;/h2&gt;
&lt;p&gt;如图所示
&lt;img src=&quot;https://img.undf.top/image/%E4%B8%89%E8%87%AA%E7%94%B1%E5%BA%A6/2022-01-03-10-46-00.png&quot; alt=&quot;2022-01-03-10-46-00&quot; /&gt;&lt;/p&gt;
&lt;p&gt;继续将物理问题转化为数学问题，建立坐标系：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://img.undf.top/image/%E4%B8%89%E8%87%AA%E7%94%B1%E5%BA%A6/2022-01-03-10-51-13.png&quot; alt=&quot;2022-01-03-10-51-13&quot; /&gt;&lt;/p&gt;
&lt;p&gt;这里我作了两条辅助线用来辅助理解&lt;/p&gt;
&lt;p&gt;图中α，β为绝对角度（也就是相对于x轴的角度），θ1，2，是相对角度（相对于上一段的角度）他的值可能为正也可能为负值，这样我们就能得到α，β与θ的表达式&lt;code&gt;α=θ1，β=θ1+θ2&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;杆长依旧取&lt;code&gt;r&lt;/code&gt;，为了便于说明这里三根杆的长度都取&lt;code&gt;r&lt;/code&gt;这里我们很容易就能得到最右端坐标的表达式为：&lt;code&gt;rcosα+rcosβ,rscinα+rsinβ&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;同理我们可以得到三杆的表达式&lt;code&gt;α=θ1，β=θ1+θ2，γ=θ1+θ2+θ3&lt;/code&gt;和&lt;code&gt;rcosα+rcosβ+rcosγ,rscinα+rsinβ+rsinγ&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;到这里你肯定觉得这好简单，为什么要写一篇文章讲这个？&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;上述思路皆为正运动学（正运动学可以大致理解为已知三根杆的长度和角度，求端点坐标）。
既然有正运动学，就会有逆运动学（逆运动学可以理解为已知三杆长度和端点坐标，求相关角度）。
而在实际运用中，逆运动学往往更多，比如抓取物体。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;潮&lt;/h2&gt;
&lt;p&gt;咱们还是从简单的开始&lt;/p&gt;
&lt;p&gt;杆长&lt;code&gt;r&lt;/code&gt;，端点坐标为&lt;code&gt;x,y&lt;/code&gt;，很容易就能得到α角度&lt;code&gt;arccos(r/x),arcsin(r/y)&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;接下来看两杆&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://img.undf.top/image/%E4%B8%89%E8%87%AA%E7%94%B1%E5%BA%A6/2022-01-03-10-51-13.png&quot; alt=&quot;2022-01-03-10-51-13&quot; /&gt;&lt;/p&gt;
&lt;p&gt;依旧看这幅图，很容易就能想到余弦定理求角度，这没问题，但你可能会遇到一个问题，如图&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://img.undf.top/image/%E4%B8%89%E8%87%AA%E7%94%B1%E5%BA%A6/2022-01-03-12-05-57.png&quot; alt=&quot;2022-01-03-12-05-57&quot; /&gt;&lt;/p&gt;
&lt;p&gt;你得到的结果可能是两个，这个时候就需要添加条件排除掉其中一个，或者根据条件选取最合适的一个，比如说让相对角度尽可能小，这样可以减少电机转动的圈数。&lt;/p&gt;
&lt;p&gt;两杆就开始有多解，那三杆呢，肯定会有更多解，这个时候就要根据项目的具体情况去添加限制条件，下面拿具体项目来讲讲。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;题目：使用摄像头进行识别并抓取物块放到指定的位置&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;这里是三个杆，就要想办法增加条件限制解的个数，比如物体的姿态，机械爪需要从哪个角度抓取等等条件。&lt;/p&gt;
&lt;p&gt;我这里增加的就是物体姿态角，通过姿态角将三杆问题转化为两杆，再增加相对角度之和最小的条件得到最终结果。&lt;/p&gt;
&lt;p&gt;如图所示：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://img.undf.top/index/2021-12-21-17-53-30.gif&quot; alt=&quot;动图&quot; /&gt;&lt;/p&gt;
&lt;p&gt;下面详细介绍具体过程和代码实现（MFC &amp;amp; C++）&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;求解
根据坐标和姿态计算角度&lt;/li&gt;
&lt;li&gt;移动到合适的抓取姿态
依次转动三根杆到合适的角度（也可以同时转动）&lt;/li&gt;
&lt;li&gt;抓取
进行抓取&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;在这三个过程中还要通过正运动学计算并绘制爪子
另外，计算机的坐标原点和xy轴都在左上角，并不是中心点，需要进行坐标系变换，这里不再详细讲述。&lt;/p&gt;
&lt;p&gt;源码仓库&lt;a href=&quot;https://github.com/wxydejoy/DrawPath/&quot;&gt;GitHub - wxydejoy/DrawPath: 三杆 机械臂&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;这里就不对代码进行介绍了，内容很多，核心部分以及思路已经在上述内容中讲过，欢迎指正。&lt;/p&gt;
&lt;h2&gt;终&lt;/h2&gt;
&lt;p&gt;思路其实不是很难，难的是其中的细节，敲错一点或者有理解不清楚的结果就会完全不一样。&lt;/p&gt;
&lt;p&gt;平面三杆已经有点复杂了，那如果是空间三杆呢？如何计算？&lt;/p&gt;
&lt;h2&gt;引&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://zh.wikipedia.org/wiki/%E6%A9%9F%E6%A2%B0%E6%89%8B%E8%87%82&quot;&gt;機械手臂 - 维基百科，自由的百科全书&lt;/a&gt;&lt;/p&gt;
</content:encoded></item><item><title>建站的&quot;心路历程&quot;</title><link>https://undf.cn/posts/post/hexo/%E5%BB%BA%E7%AB%99/</link><guid isPermaLink="true">https://undf.cn/posts/post/hexo/%E5%BB%BA%E7%AB%99/</guid><pubDate>Thu, 10 Jun 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;在听讲座，有点无聊，所以把昨天的感想写一写&lt;/p&gt;
&lt;p&gt;太难了，踩过的坑都忘记了，这。。。。。。。&lt;/p&gt;
&lt;h2&gt;初衷&lt;/h2&gt;
&lt;p&gt;建设这个网站的目的是为了记录自己学习过程、学习笔记，以便在未来能够复习、反思、回味。&lt;/p&gt;
&lt;p&gt;另外这还是一个可以释放压力，可以倾述的平台&lt;s&gt;没人会看我叨叨的&lt;/s&gt;，甚至还可以看看自己收藏的电影&lt;/p&gt;
&lt;h2&gt;起因&lt;/h2&gt;
&lt;p&gt;这学期做了一个项目[课程设计]，是视觉识别和机械臂的综合，所以就想存到 GitHub 上面，偶遇到了 HEXO，第一个主题是 Keep，也实现了自动部署，后面换了&lt;a&gt;Butterfly&lt;/a&gt;也就是现在的主题，非常不错&lt;/p&gt;
&lt;h2&gt;搭建、域名购买、域名解析&lt;/h2&gt;
&lt;p&gt;搭建是参考的知乎找的教程，但还是踩了很多，这里不再赘述，推荐&lt;a href=&quot;https://akilar.top/&quot;&gt;店长教程&lt;/a&gt;。&lt;/p&gt;
&lt;h2&gt;主题选择&lt;/h2&gt;
&lt;p&gt;主题选择有很多，萝卜青菜各有所爱，这里就不讲了&lt;/p&gt;
&lt;h2&gt;主题魔改&lt;/h2&gt;
&lt;p&gt;魔改必须推店长，yyds，教程直接去店里翻，不会做就去加群。&lt;/p&gt;
&lt;p&gt;讲一讲我自己的魔改吧，首先我是不喜欢侧边栏的，虽然我开了，但是只是为了能有个目录，方便翻阅。魔改内容还是蛮多的，想到什么就讲什么吧！&lt;/p&gt;
&lt;p&gt;butterfly 主题内置的就不再赘述了(pwa 快把我折磨死了)&lt;/p&gt;
&lt;p&gt;先讲动效吧！&lt;/p&gt;
&lt;p&gt;加载动画是我自己魔改的，应该不会放出源码&lt;s&gt;很简单的&lt;/s&gt;&lt;/p&gt;
&lt;p&gt;动效(就是那些会动的)，置顶轮播，分类，标签外挂(文章里面比较好玩的东西)这些都是店长或者冰老师的插件&lt;a&gt;点这&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;什么时候有空把源码放上来，需要请评论，&lt;s&gt;没人会看的吧&lt;/s&gt;&lt;/p&gt;
&lt;h2&gt;服务器搭建、备案&lt;/h2&gt;
&lt;p&gt;在国内建站，肯定是要备案的，还得买服务器&lt;s&gt;一点都不合理&lt;/s&gt;，没办法，买三个月备份，肝!
教程？教程是什么？&lt;/p&gt;
&lt;p&gt;百度一下，你就知道!&lt;/p&gt;
&lt;p&gt;哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈&lt;/p&gt;
&lt;p&gt;看教程要仔细，有些教程不全，那就去百度，或者干脆换一篇教程!耐心!仔细!认真![滑稽][菜狗]&lt;/p&gt;
</content:encoded></item><item><title>气阀板使用说明</title><link>https://undf.cn/posts/post/life/%E6%B0%94%E9%98%80%E6%9D%BF%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E/</link><guid isPermaLink="true">https://undf.cn/posts/post/life/%E6%B0%94%E9%98%80%E6%9D%BF%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E/</guid><pubDate>Fri, 14 May 2021 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;物料准备&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;气阀控制板&lt;/li&gt;
&lt;li&gt;气阀（smc 比例阀,需自备）&lt;/li&gt;
&lt;li&gt;电源&lt;/li&gt;
&lt;li&gt;蓝牙模块&lt;/li&gt;
&lt;li&gt;若干接线端子&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;硬件安装&lt;/h2&gt;
&lt;h3&gt;比例阀接线（已经接好）&lt;/h3&gt;
&lt;p&gt;注意判断比例阀反馈信号是否为电压型 5V，如果不是不要接黑色线。如果不确定，请联系我!!&lt;/p&gt;
&lt;p&gt;根据线缆颜色根据图片接线，注意正反！&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://img.undf.top/ob/6c66848c9658f7655b2da990fc065602.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;蓝牙模块连接（已经接好）&lt;/h3&gt;
&lt;p&gt;这里需要接 4 跟线：&lt;code&gt;3.3V&lt;/code&gt; &lt;code&gt;GND&lt;/code&gt; 根据控制板上的标识和蓝牙模块上的标识一一对应。
&lt;code&gt;RX&lt;/code&gt; &lt;code&gt;TX&lt;/code&gt; 需要根据串口协议进行反接，只需要这四根&lt;/p&gt;
&lt;h2&gt;软件安装与使用&lt;/h2&gt;
&lt;p&gt;软件下载链接 &lt;a href=&quot;https://wekko.lanzout.com/iMIu91ucfsre&quot;&gt;https://wekko.lanzout.com/ikSh82071ila&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;连接蓝牙&lt;/h3&gt;
&lt;p&gt;系统设置 -&amp;gt; 蓝牙和其他设备 -&amp;gt; 添加设备&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://img.undf.top/ob/a49db4ec36204a6ae602c8fe2b56b778.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;单击蓝牙&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://img.undf.top/ob/30f41666105cfed4c5d2160f74d59b26.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;找到设备 &lt;code&gt;ITV&lt;/code&gt;  配对密码 &lt;code&gt;1234&lt;/code&gt; 配对成功即可&lt;/p&gt;
&lt;h3&gt;连接蓝牙&lt;/h3&gt;
&lt;p&gt;打开软件单击 &lt;code&gt;查看蓝牙对应的串口&lt;/code&gt;
&lt;img src=&quot;https://img.undf.top/ob/2746e23f202828ba2edec700aa064a67.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;找到蓝牙模块对应的串口号&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://img.undf.top/ob/6bbe7e82ff65bbfe119f4e9e9968a838.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;选择对应的串口，单击打开串口，程序按钮文字会变为关闭窗口，此时即为连接成功&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://img.undf.top/ob/36009238d7d535a673092163637a3582.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;有时会有这种弹窗点击后输入 pin 1234 即可
&lt;img src=&quot;https://img.undf.top/ob/8197a898eccb1a4ce198238ac6cf94c9.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;软件使用&lt;/h3&gt;
&lt;p&gt;若不使用蓝牙，串口配置如下：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://img.undf.top/ob/267d8627e8eb587bebd6f34c878ff34a.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;每个比例阀都由一个模块控制，这里的值只有在敲回车或者点击空白处才会生效，而进度条即时生效。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://img.undf.top/ob/68a90a422e6368ec25eeed86e1daeeda.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;右侧可以简单编程后运行&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// 命令以行分隔
D100 // 延时100ms
A00B1000 // 通道0设置为1000
A99B0000 // 读取ADC
支持读取和保存为txt文件
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;底部有一些按钮可以辅助编程&lt;/p&gt;
&lt;h2&gt;通信协议&lt;/h2&gt;
&lt;p&gt;注：// 后为注释&lt;/p&gt;
&lt;p&gt;上位机 -&amp;gt; 控制板&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;A00B0000 // 通道0气压值0
A01B1000 // 通道1气压值0.1MPa
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;控制板 -&amp;gt; 上位机&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;T: 时间戳 ch：各个通道的值，这里对应的电压值
&lt;/code&gt;&lt;/pre&gt;
</content:encoded></item></channel></rss>