【毕业设计】基于STM32的解魔方机器人

news2024/11/24 1:44:00


4ff5afc23dd4dfd6fa5db49786bd54fb.jpeg

1、方案设计

1.采用舵机作为魔方机器人的驱动电机,从舵机的驱动原理可知:舵机运行的速度和控制器的主频没有关系,所以采用单片机和采用更高主频的嵌入式处理器相比在控制效果上没有什么差别。单片机编程过程简单,非常容易上手,而且不需要进行操作系统的移植,非常适合对魔方机器人的舵机进行控制。

2.复原时间是魔方机器人的一个非常重要,可以说是最为重要的一个参数,本文的软件设计中涉及到了大量的算法,如 Kocemba 复原算法和 KNN 分类算法等,而控制器主频对于算法运行时间的长短起着决定性的作用。

所以在本文的方案设计中,我们把核心算法全部交给 Allwinner A20 运行的 APP。


2、设计原理

1、Kociemba算法
Kociemba算法,又称为二阶段算法,是一个使用较短时间和较少次数还原魔方的算法。按照以前网上的说法,详细的原理可以在网页http://kociemba.org/cube上面找到。然而现在这一个网页也是已经不存在了,其他网站所介绍的也是非常的简略。幸好,在我的努力之下,还是找到一些零星的资料,主要是一些外文的论文和一些github项目。通过几天的加班阅读,我总算是理解了大部分的内容。我把自己所理解的只是写在这篇论文上面,希望能给和我一样的魔方爱好者一些启发,同时也算是一个抛砖引玉,希望能够获得读者们更好的建议。
2、从魔方的状态数说起

这篇文章讨论的对象是三阶魔方,原则上Kociemba算法可以变形为四阶魔方的,但是这并不是本文要讨论的内容。首先我们先对魔方的元素进行命名上面的约定,魔方由26个方块组成,每个方块由1到3个面是露在外面的,有1个面的我们称为中心方块,两个面为边,三个面的为角。通过旋转,每个角有8中位置、3个方向,每个边有12种位置、2个方向。我们假定魔方的中心方块是不会移动的,也就是说,只有非中间层的面可以旋转,以后也是不考虑中间面的旋转。所以会产生变化的只有边和角的位置和方向,不考虑组合的合法性,魔方的总组合为: 8!12!(38)*(212)种

但是魔方会包括非法的情况,这里要考虑到魔方的状态集的问题。我们约定魔方的所有边和角的位置和方向为魔方的一个状态。魔方从一个状态通过若干次的旋转后,魔方的新状态一定和原状态在一个状态集里面。可以证明,魔方的状态集分成12个,每一个的总数是一样的,所以,实际上魔方的状态数为: 8!12!(38)*(212)/12种

这个数大概是4.3万亿亿,具体大小不必细究,反正非常大。如果使用最暴力的算法,例如DFS、BFS等,绝对会耗尽计算机的资源,更高阶的魔方就不用说了。所以,我们要对这些状态进行裁剪,Kociemba使用的就是因式分解的算法。打个比方,如果m=a*b,且a、b>2,那么令n=a+b,必有n<m。同理,将上面的式子分解为:8!、12!、(38)、(212),至少可以将空间缩小为一亿分之一。当然,实际上算法对其做出了更多的工作。

同理,将上面的式子分解为:8!、12!、(38)、(212),至少可以将空间缩小为一亿分之一。当然,实际上算法对其做出了更多的工作。<> 最后,我们将将魔方的面分为6个:T(上)、D(下)、F(前)、B(后)、L(左)、R(右)。面向X面,顺时针旋转X面90度表示为X、旋转半周为X2、逆时针旋转90度为X’。

3、魔方的特殊性质

人们发现,魔方具有一些优良的性质,这些性质可以帮助将状态数分解:
1.指定角的方向后,对于所有的面,旋转两次并不会改变角的方向,会有相对的两个面(例如前和后),旋转一次不会改变角的方向。其他面旋转一次,会按照特定的规律变换方向,如果我们把方向编码为0、1、

2,假如某一个面的四个角原始方向按照顺时针是co0、co1、co2、co3,那么如果这个面的一次旋转会改变四个角的方向的话,对角的两个角会变成co0+1、co2+1另外两个对角会变成co1-1、co3-1。 2.指定边的方向后,只有两个相对的面的旋转会改变边的方向,其余面的旋转不会改变。

下面,我们假定一次旋转上下面不会改变魔方的角的方向,一次旋转左右面会改变魔方边的方向。至于具体如何编码,我会在下下面详细阐述。

通过这两种性质,我们将魔方的状态分成两个状态集G1、G2。其中G1状态为魔方的原始状态经过若干步规定以内的旋转所组成的状态集,这规定的旋转包括:T、T’、D、D’、T2、D2、F2、B2、L2、R2。根据上面的假定,这些旋转不会改变魔方8个角的方向,也不会改变12条边的方向,而且原始状态下中间的四条边,在这个集合里面依然在中间层内。根据这一个结论,我们可以将魔方的总数减少为: 4!*8!*8!/12

第一个4!表示中间四条边的位置排列,第二个8!表示上下四条边的位置排列,第三个8!表示8个角的位置排列。在使用因式分解,总数就变为:4!+8!+8!,这个数少于10万,并且在下面会看到,使用这一种裁剪方法会获得较高的精度。

G2表示以G1的所有状态为原始状态,经过若干次任意旋转后的状态集,在这个状态集里面内有什么优良的的性质可以利用,所以实际上使用了单纯的裁剪手段。也是分成三组,第一组为编号为0到3的所有边的方向和位置,第二组为编号为4到11的所有边位置上面边的方向,第三组为所有角的方向,所以总数为A(12,4)*(26)+28+3^8种。

4、搜索算法

Kociemba算法使用了搜索算法还原魔方。具体来说,就是先使用搜索算法转换为G1状态,在使用另一种搜索方式转换为原始状态。使用何种搜索算法对于还原魔方至关重要,搜索算法选得不好,例如使用BFS解决问题,会耗尽计算机的资源。经过前辈的不断探索,最终改良出IDA*。所谓IDA*,就是A*算法加上迭代加深的升级版。迭代加深就是可以保证搜索树上面的任一个节点都可以获得精确的启发函数值,要实现迭代加深就必须先对搜索树上的各个节点进行预先的计算,也就是初始化。

具体到这里,就是在A*的启发函数初始化的时候,制作一个映射表,然后通过魔方从原始状态为起点进行若干次操作,组成一个根节点为魔方的原始状态的、具有一定深度的操作树。遍历操作树上面的所有节点,也就是每一个状态,从表上可以映射为一个启发函数值,其值的的大小就为节点的深度。因为此时的魔方的状态就是魔方在原始状态通过等于其深度的次数的操作结果,经过相反的操作当然可以还原魔方。同时,可以知道,操作数上面必然会有状态相同的不同节点,因为启发函数的值应该为最小值才可以保证精度,因此,我们在遍历操作树的时候,使用广度优先搜索,保证浅层的节点先被记录,而深层的同状态节点因为映射已经存在就会被忽略。

有了映射表,在调用启发函数的时候,根据当前的魔方状态,经过查表可以获得启发函数的值,使用A*算法判断魔方的下一个判断即可,同时因为迭代加深的缘故,节点的判断函数都是准确的,不需要记录对未搜索的可达节点。

那么,问题推到了映射表上面,如何设计高效的映射表?

5、映射表的设计

映射表只是一个概念,它代表从魔方的特定状态向最小还原步数的映射。具体需要选择什么实现,还需要看实际情况。实际需求可以总结为一下几点:
1.映射表初始化后不会发生改动,也就是说不需要动态的改动映射的内容和规模。
2.映射需要一个比较高的效率。
3.映射的规模是已知的。
4.映射表应该覆盖所有的状态编码组合。

第2条决定了不应该使用像std::map之类的树型映射表,最佳方案应该是数组。因为数组查询速度快,规模是固定的。只要我们找到一个哈希函数,将当前魔方的状态转换为一个整数,就可以完成映射表了。

6、方块编码

我认为,这一部分是算法的核心之一,之前的各种设计各种规律都是建立在这种编码方案之上的。这说明一个好的建模方案可以大大地减少问题的难度。

首先,我要介绍角的编码,容易知道,魔方有八个角,分别编码为0至7,编码与位置的对应关系与问题的解决没有关系。同理,魔方的12条边编码为0值11。

真正的问题在于边和方块的方向问题。我们知道,边和角的方向没有固定的参照物,因此,我们在编码的时候,通过规定某一些方向的方法规定方块的方向。对于边的方向,这比较简单,只要是0或者1即可。

对于角,情况就有点复杂,我在这里举个例子,说明一下编码的过程:

我们将T、F、R面交界处的角方块,暂称为方块1,方块1的原始位置为位置1。我们要求在位置1上面的各种角方块面,都要按照T、F、R方向的顺序表示,如果1号方块在1号位置的顺序刚好就是T、F、R,那么我们认为此时1号方块的方向就是0,除此之外,还有的可能的顺序就是F、R、T和R、T、F,我们分别标号为1和2。

由于T和D旋转是不会改变方块的方向,所以我们可以来一个T’旋转,是的T、F、L面交界处的角方块,我们暂称为方块2,到达位置1。此时从T、F、R面上面读取方块2,可以读到T、L、F。也就是所,方块2在顺序为T、L、F的时候是0号方向,我们模仿1号方块,认为顺序L、F、T为1号方向,F、T、L为2号。同理可以知道T面的其他角。

由于F2旋转是不活改变角的方向,所以我们进行F2旋转,此时方块2旋转至F、D、R的交接面处,暂称为位置3。此时T、L、F面的方向为D、R、F,所以我们认为方块3的0号方向顺序为D、R、F。同理可以知道D面的其他角。


通过这种建模方式,可以模仿上面说道的魔方的这些优良性质,保证搜索算法和映射表的成立。

3、硬件设计框图


a332f01c740432110e8c3ff6df226e32.jpeg


4、软件设计框架


a2255795d2320ef154aa7646f00d5080.jpeg

5、原理图


e76dbd6039d563b269838e354ddd3064.jpeg

42924ccb1af937122432b11b4f66d01d.jpeg

6、工程设计图纸

42db926ec1df57b548481bd9387d1357.jpeg

7、 源代码
1bb15bb48d62248876fa93b95f17ea7e.jpeg

8、全部资料


7523d9708aa339be756429e2d0e8b707.jpeg

9、资料获取

关注我后,在后台回复关键字。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1306170.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

c#_sqlserver_三层架构winform学生信息管理及选课系统

基本功能包括管理员登录、注册学生账号、删除学生信息、查找学生信息、发布课程、修改课程、删除课程等。 教师端 登录&#xff1a;管理员登陆&#xff0c;拥有相应账号即可登录&#xff08;后台注册&#xff09;。注册学生账号&#xff1a;管理员可给学生分配学号&#xff0…

Linux Mint编译安装Qemu

文章目录 前言1. 准备Qemu源码包2. 编译安装2.1 首次尝试编译2.2 安装python3-venv2.3 安装sphinx2.4 安装sphinx-rtd-theme2.4 安装ninja2.6 安装编译器 3. 重新编译并安装4. 进行固件仿真4.1 准备固件4.2 Binwalk解析文件4.3 看一下文件结构4.4 安装sasquatch4.5 重新解析文件…

OkHttp: 拦截器和事件监听器

文章目录 1. 拦截器1. 拦截器链2. 实际案例1. 注册为应用拦截器2. 注册为网络拦截器 3. 如何选择用哪种拦截器1. 应用拦截器2. 网络层拦截器3. 重写请求4. 重写响应 4. 可用性 2. 事件监听器1. 请求的生命周期2. EventListener使用案例3. EventListener.Factory4. 调用失败的请…

一、Oracle学习笔记

1.1.1实例的概念实例是一组内存结构和后台进程的集合。oracle适用于大型的应用系统1.1.2实例的构成1.实例中的这部分内存结构叫做系统全局区&#xff08;SGA&#xff09;:存储数据库中的数据、存储数据字典的信息、重做日志、经过解析的SQL代码等一个实例只有一个SGA&#xff1…

QT作业4

实现一个闹钟&#xff0c;当输入时间后&#xff0c;点击启动到达时间后循环播报三遍&#xff0c;便签内容 头文件&#xff1a; #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QTextToSpeech> //文本转语言类 #include <QTimerEvent> //定…

EasyV易知微助力智慧城市未来趋势发展——数字孪生城市

“智慧城市的未来趋势就是数字孪生”——《基于数字孪生的智慧城市》 城市数字化管理、智慧城市和数字孪生城市的发展是相互促进、逐步深化的过程。 城市数字化管理作为起点&#xff0c;奠定了信息化、数据化的基础&#xff1b;而智慧城市则将数字城市管理进一步升级&#xff…

什么是防抖与节流?应用场景举例

防抖节流如何处理防抖与节流 防抖节流防抖例子节流例子Vue Axios全局接口防抖、节流封装实现 小结 防抖 防抖&#xff1a;触发高频事件后n秒内函数只会执行一次&#xff0c;如果n秒内高频事件再次被触发&#xff0c;则重新计算时间 应用场景&#xff1a; 提交按钮、用户注册…

时间序列预测 — CNN-LSTM实现多变量多步光伏预测(Tensorflow)

目录 1 数据处理 1.1 导入库文件 1.2 导入数据集 1.3 缺失值分析 2 构造训练数据 ​3 模型训练 3.1 CNN-LSTM网络 3.2 模型训练 4 模型预测 专栏链接&#xff1a;https://blog.csdn.net/qq_41921826/category_12495091.html 1 数据处理 1.1 导入库文件 import scip…

数据库系统相关概念

数据&#xff1a;描述事务的符号记录。 数据库(DB)&#xff1a;按一定的数据模型组织&#xff0c;描述和存储在计算机内的&#xff0c;有组织的&#xff0c;可共享的数据集合。 数据库管理系统(DBMS)&#xff1a;位于用户和操作系统之间的一层数据管理软件。主要功能包括&#…

(C++)最大连续1的个数--滑动窗口

个人主页&#xff1a;Lei宝啊 愿所有美好如期而遇 力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台备战技术面试&#xff1f;力扣提供海量技术面试资源&#xff0c;帮助你高效提升编程技能&#xff0c;轻松拿下世界 IT 名企 Dream Offer。https://le…

【LeetCode题目拓展】第207题 课程表 拓展(拓扑排序、Tarjan算法、Kosaraju算法)

文章目录 一、拓扑排序题目二、题目拓展1. 思路分析2. tarjan算法3. kosaraju算法 一、拓扑排序题目 最近在看一个算法课程的时候看到了一个比较好玩的题目的扩展&#xff0c;它的原题如下&#xff1a; 对应的LeetCode题目为 207. 课程表 这个题目本身来说比较简单&#xff…

C# WPF上位机开发(增强版绘图软件)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 前面我们写过一个绘图软件&#xff0c;不过那个比较简单&#xff0c;主要就是用鼠标模拟pen进行绘图。实际应用中&#xff0c;另外一种使用比较多的…

【flutter对抗】blutter使用+ACTF习题

最新的能很好反编译flutter程序的项目 1、安装 git clone https://github.com/worawit/blutter --depth1​ 然后我直接将对应的两个压缩包下载下来&#xff08;通过浏览器手动下载&#xff09; 不再通过python的代码来下载&#xff0c;之前一直卡在这个地方。 如果读者可以…

C++11 【初识】

C11简介 1.在2003年C标准委员会曾经提交了一份技术勘误表(简称TC1)&#xff0c;使得C03这个名字已经取代了C98称为C11之前的最新C标准名称。 2.不过由于C03(TC1)主要是对C98标准中的漏洞进行修复&#xff0c;语言的核心部分则没有改动&#xff0c;因此人们习惯性的把两个标准合…

【vtkWidgetRepresentation】第十期 vtkAngleRepresentation标注角度

很高兴在雪易的CSDN遇见你 前言 本文分享VTK中的角度标注,希望对各位小伙伴有所帮助! 感谢各位小伙伴的点赞+关注,小易会继续努力分享,一起进步! 你的点赞就是我的动力(^U^)ノ~YO AngleRepresentation 目录 前言 1. vtkAngleRepresentatio

Windows使用selenium操作浏览器爬虫

以前的大部分程序都是操作Chrome&#xff0c;很少有操作Edge&#xff0c;现在以Edge为例。 Selenium本身是无法直接控制浏览器的&#xff0c;不同的浏览器需要不同的驱动程序&#xff0c;Google Chrome需要安装ChromeDriver、Edge需要安装Microsoft Edge WebDriver&#xff0c…

直面双碳目标,优维科技携手奥意建筑打造绿色低碳建筑数智云平台

优维“双碳”战略合作建筑 为落实创新驱动发展战略&#xff0c;增强深圳工程建设领域科技创新能力&#xff0c;促进技术进步、科技成果转化和推广应用&#xff0c;根据《深圳市工程建设领域科技计划项目管理办法》《深圳市住房和建设局关于组织申报2022年深圳市工程建设领域科…

二叉搜索树基本概念与实现

目录 基本概念 模拟实现 完整代码 基本概念 根的左节点比根小 根的右节点比根大 左右子树都满足 搜索二叉树的中序遍历是升序 模拟实现 完整代码 #pragma oncetemplate<class K> struct BSNode {BSNode<K>* _left;BSNode<K>* _right;K _val;BSNode(c…

【C语言程序设计】循环结构程序设计

目录 前言 一、程序设计第一题 二、程序设计第二题 三、程序设计第三题 总结 &#x1f308;嗨&#xff01;我是Filotimo__&#x1f308;。很高兴与大家相识&#xff0c;希望我的博客能对你有所帮助。 &#x1f4a1;本文由Filotimo__✍️原创&#xff0c;首发于CSDN&#x1f4da…

1.函数递归起(复习)

1.debug版本可以调试,realse版本不能调试 2.在realse版本中,代码已经得到了优化(编译器可能会自作主张地对代码进行优化),在大小和速度上都是最优的 3.ctrl F5 是开始执行不调试 4.设置好断点后,用F5到达该断点,相当于是到达了该断点的那个位置程序就先停止运行了 5.设立断…