魔方还原算法学习笔记

定义任意打乱的魔方称为随机状态或者初始状态,处于特殊水域的那些状态称为目标状态,目的地为还原状态

初始状态可以看作是由 U,R,F,D,L,B 这 6 个基本转动复合而成的,由这 6 个转动生成的群记为 G = 〈 U , R , F , D , L , B 〉 G=\langle U,R,F,D,L,B \rangleG=〈U,R,F,D,L,B〉
目标状态是只由 U,D,L2,R2,F2,B2 这 6 种转动复合生成的,同样的记为 G 1 = 〈 U , D , L 2 , R 2 , F 2 , B 2 〉 

目标状态的性质

棱边有 2 种状态,未翻转(flip)用 0 表示,翻转用 1 表示, 只有 F,B 层的转动能够改变方向

角块有 3 种状态,未扭转(twist)用 0 表示,顺时针扭转用 1 表示,逆时针扭转用 2 表示,只有 U,D 层转动不改变角块方向

目标状态由 U,D,L2,R2,F2,B2 这 6 种转动生成,而这 6 种转动不会引起角块和棱块方向的变化。因为不论怎么转动,角块拥有的 U 层面或 D 层面始终处于 U 层或者 D 层,所以方向不变。也不会引起棱块方向变化,因为只有 F,B 的转动会引起棱块方向的变化,而像 F2 这样的连续转动两次,翻转再反转棱块相当于未翻转,所以棱块的方向也是不会变化的。这 6 种转动也不会将中层块带到 U 层或者 D 层,所以处于中层的块只能处于中层
棱块角块方向不变,即各自的方向值总和都为 0

还原状态下的中层块处于中层

科先巴的二阶段算法使用的搜索算法是 IDA* 算法,也就是迭代加深搜索算法,而且两个阶段使用的都是 IDA* 算法

#最优化方案:
#在旋转每个面以后,不再进行F层位置还原!在完成本层任务后,函数返回值 1.当前机械位置 2.手爪状态(一般都是闭合)3.魔方当前位姿
#每个面函数,接受 1.机械位置 2.手爪状态 3.魔方当前位姿  并通过判断以上参数,在当前魔方位姿与机械位置条件下进行运动规划
#******考虑 正面的情况 #(魔方位姿相对机械本体) 6*4=24种情况

#******考虑 手腕位置  手腕 现在规定,各手腕有 (1)-270(2)-180(3)-90(4)0 (5)90(6)180(7)270 这样可以提供270延时,但决策复杂
    #取代方案:只判断水平或者竖直 问题所在:不能为270度提供精确延时  解决方法:判断完水平还是竖直之后,再预判断转角是否超过软件限位,如果超出,则进行延时补偿

#******考虑 手指状态  现在规定,各手指有 (1)开(2)闭

#******考虑 列表迭代完毕,执行到最后不再复位,直接执行AandBopen()

#当前思路:程序输入为一个大的list,函数中更新list
#真正学习面向对象

机械绝对位置:

#机械绝对位置
A_angle = 0    #A手腕初始化 0度
A_finger = 0    #A手指初始化 关闭 1 open

B_angle = 0     #B手腕初始化 0度
B_finger = 0    #B手指初始化 关闭 1 open

定义其他部分:

#水平 L  竖直 V  #bool
A_L = (A_angle == 0 or A_angle == 180 or A_angle == -180 )
A_V = (A_angle == 90 or A_angle == -90 or A_angle == 270 or A_angle == -270)

B_L = (B_angle == 0 or B_angle == 180 or B_angle == -180 )
B_V = (B_angle == 90 or B_angle == -90 or B_angle == 270 or B_angle == -270)

Aopen = (A_finger == 1 )
Aclose = (A_finger == 0 )
Bopen = (B_finger == 1 )
Bclose = (A_finger == 0 )

相对位置:

#魔方相对位置
F_direction = 0 #初始化 F面朝向
U_direction = 3 #初始化 U面朝向

#machine_pos = [A_L, A_finger, B_L, B_finger]  #定义机械绝对位置 内容为 A 手腕绝对角度  A 手指开闭 B 手腕绝对角度  B 手指开闭

相对位姿:

cube_pos = [F_direction, U_direction]  #定义魔方相对位姿 内容为 魔方正面朝向 元素1:F面 元素2:U面

穷举限位:

def B180():   #有点意思  穷举限位
    print('B180...')
    global B_angle
    B_angle = B_angle + 180   #预判
    
    #if(B_angle != 450 or B_angle != 360)
    #    time.sleep(0.001)
    #    ser.write("\x40".encode('utf-8'))     #B 180
    #    time.sleep(time180)
    
    if(B_angle == 450):
        #B_angle = 90
        time.sleep(0.001)
        ser.write("\x40".encode('utf-8'))     #B 180
        time.sleep(time180)
        return
    
    if(B_angle == 360):
        #B_angle = 0
        time.sleep(0.001)
        ser.write("\x40".encode('utf-8'))     #B 180
        time.sleep(time180)
        return
    
    else:
        time.sleep(0.001)
        ser.write("\x40".encode('utf-8'))     #B 180
        time.sleep(time180)
        return

初代机防止缠绕气管,记录每一次旋转方向,并记录旋转了多少;

上一篇:python点到向量的距离,夹角


下一篇:计算两点与正北方向夹角