找回密码
 马上注册

QQ登录

只需一步,快速开始

查看: 5909|回复: 7

关于NXC编写的迷宫机器人问题

[复制链接]
发表于 2011-11-9 22:18:34 | 显示全部楼层 |阅读模式
恩~是这样的,第二个程序咯这个是我接触乐高以来的,因为学校里有德国交换生来了,所以学校布置下任务要求我想一个乐高项目来进行演示,于是我选择了迷宫机器人。迷宫是一系列泡沫板拼接起来的,就是最普通的迷宫,里面没有任何记号。我选用的是一个超声传感器用于判断距离,然后每走30cm或者遇到障壁时停下进行一次左右方向的探测,然后根据“十”字岔路先直走然后若不通则退回来时左转(相当于进入十字路时右转)不通则退回直走(此时相当于左转)还不通则退回左转(相当于原路退出这个十字路)丁字路则先左后右然后返回,其他路总是先直走不通时再退回探测。可是当实际行走的时候出现以下问题:

1、机器人的判断频率似乎很难调整好,30cm有些地方可能超声探头刚好伸到岔路(车身还在直路里)而由于超声此时判断有岔路,若选择转弯则会卡在迷宫墙上,或者是直走转弯时可能由于左/右距离不够导致转弯时卡住
2、机器人选用2个伺服电机(B、C)加同样电压(设置为30)同时开关,但是行走时发现总是向左偏离直线,若设置为B=30、C=28,则会向右偏离直线,若选择B=30、C=29则向左偏,如此导致经常卡住或者卡在墙角(L形墙角前左右都认为被挡住了原地180度转弯会卡住,然后就一直在哪里转探头)
3、通过游标卡尺测得的两轮间距D(即车宽)与车轮直径d,计算转弯角度a及每个轮子所需转动角度b间关系的算式:b= (D*a)/d时实际转动的角度总是会多出那么4~5度(是指整辆车,如果是每个轮子的话肯定不止这么几度)

由以上这么多问题导致机器人总是无法正常通过迷宫(有时候需要用手去调整它的位置比如转弯角度太大的时候)能通过也是滑着墙过去的,有时甚至在不该回溯的地方回溯(由于转弯问题和走歪问题)
天朝说要河蟹不可以歪的!
附上程序各部件,希望各位大牛帮忙找找问题(程序上的),由于今天时间仓促,明天我会附上机器人的照片(配尺)希望大家能帮我找找错误,谢谢吖!因为后天下午就要演示了!><学校催的紧吖><

maze_stack.h:


  1. #define max_depth 100 //the max depth of the cross roads in the maze(no more than 100)
  2. int maze[max_depth];
  3. int head,top;
  4. bool push(int record)
  5. {
  6.   if (top >= max_depth)
  7.     {
  8.       return false;
  9.     }else{
  10.     if (top < head)
  11.       {
  12. top = 0;
  13.       }
  14.     maze[top] = record;
  15.     top++;
  16.     return true;
  17.   }
  18. }
  19. int pop()
  20. {
  21.   int record;
  22.   if (top < head)
  23.     {
  24.       return -1;
  25.     }else{
  26.     record = maze[top];
  27.     top--;
  28.     return record;
  29.   }
  30. }
复制代码

maze_motor.h:


  1. /*=================================================/
  2. /                                                                                                                                         /
  3. /                The Header of maze.c                                                                                      /
  4. /  Here includes some definations and functions                                                              /
  5. /                       Made by CAKURA                                                                                      /
  6. /=================================================*/
  7. #define NEAR 10
  8. #define Can_pass 30
  9. #define h_WheelBase 12.5
  10. #define d_Wheel 5.5
  11. #define Turn_Angle(alpha) ((h_WheelBase*alpha)/d_Wheel)
  12. #define Angle 90
  13. #define left  2 //2 = 0b10 shows the left way hasn't been explored
  14. #define right 1 //1 = 0b01 shows the right way hasn't been explored
  15. #define step_len 30 //this parameter sets how often the robot stop to check the way(20 means stop per 20cm)
  16. #define tire_len (d_Wheel*PI) //this parameter shows the circumference of the tire
  17. #define turn_left  8 //8 = 0b1000 tells that we are now exploring the left cross
  18. #define turn_right 4 //4 = 0b100  tells that we are now exploring the right cross
  19. #define power_motor_run 30
  20. #define power_turning_sensor power_motor_run
  21. #define power_backing_sensor power_motor_run
  22. #define unexplored 3 // 3  = 0b11 the low 2 digs records the ways that hasn't been explored
  23. #define turning 12 //   turning = 0b1100 the records the turnning direction we need to turn
  24. #define T_road 16 //   16 = 0b10000 sets if it is the T cross road
  25. bool left_ok,right_ok;
  26. int angle;
  27. task run_B()
  28. {
  29.   RotateMotorEx(OUT_B,power_motor_run,-Turn_Angle(angle),0,false,true);
  30.   left_ok = true;
  31. }
  32. task run_C()
  33. {
  34.   RotateMotorEx(OUT_C,power_motor_run,Turn_Angle(angle),0,false,true);
  35.   right_ok = true;
  36. }

  37. bool explore_left()
  38. {
  39.   if (!(MotorRotationCount(OUT_A) == 0))
  40.     {
  41.       RotateMotorEx(OUT_A,power_backing_sensor,-(MotorRotationCount(OUT_A)),0,false,true);
  42.     }
  43.   ResetRotationCount(OUT_A);
  44.   RotateMotorEx(OUT_A,power_turning_sensor,Angle,0,false,true);
  45.   if (SensorUS(IN_4) > Can_pass)
  46.   {
  47.    RotateMotorEx(OUT_A,power_backing_sensor,-(MotorRotationCount(OUT_A)),0,false,true);
  48.    return true;
  49.   }else
  50.   {
  51.    RotateMotorEx(OUT_A,power_backing_sensor,-(MotorRotationCount(OUT_A)),0,false,true);
  52.    return false;
  53.   }
  54. }
  55. bool explore_right()
  56. {
  57.   if (!(MotorRotationCount(OUT_A) == 0))
  58.     {
  59.       RotateMotorEx(OUT_A,power_backing_sensor,-(MotorRotationCount(OUT_A)),0,false,true);
  60.     }
  61.   ResetRotationCount(OUT_A);
  62.   RotateMotorEx(OUT_A,power_turning_sensor,-Angle,0,false,true);
  63.   if (SensorUS(IN_4) > Can_pass)
  64.   {
  65.    RotateMotorEx(OUT_A,power_backing_sensor,-(MotorRotationCount(OUT_A)),0,false,true);
  66.    return true;
  67.   }else
  68.   {
  69.    RotateMotorEx(OUT_A,power_backing_sensor,-(MotorRotationCount(OUT_A)),0,false,true);
  70.    return false;
  71.   }
  72. }
  73. int turn_the_way(int ways)
  74. {
  75.   int new_way;
  76.   switch (ways)
  77.     {
  78.     case  1:
  79.       new_way = 2;
  80.       break;
  81.     case  2:
  82.       new_way = 1;
  83.       break;
  84.     default:
  85.       new_way = ways;
  86.       break;
  87.     }
  88.   return new_way;
  89. }
  90. void wait_motor(bool is_back,bool is_left)
  91. {
  92.   left_ok = false;
  93.   right_ok = false;
  94.   if (is_back)
  95.   {
  96.      angle = 180;
  97.   }else
  98.   {
  99.    if (is_left)
  100.    {
  101.     angle = Angle;
  102.    }else
  103.    {
  104.     angle = -Angle;
  105.    }
  106.   }
  107.   if (is_left)
  108.     {
  109.       start run_C;
  110.       start run_B;
  111.     }else
  112.     {
  113.       start run_B;
  114.       start run_C;
  115.     }
  116.   while (!(left_ok && right_ok));
  117.   stop run_B;
  118.   stop run_C;
  119. }
  120. void run_step()
  121. {
  122.   int distance;
  123.   ResetRotationCount(OUT_BC);
  124.   distance = SensorUS(IN_4);
  125.   OnFwd(OUT_BC,power_motor_run);
  126.   while (((distance - SensorUS(IN_4)) < step_len) && (SensorUS(IN_4) > NEAR)) ;
  127.   Off(OUT_BC);
  128. }
  129. int check_ways()
  130. {
  131.   int ways;
  132.   ways = 0;
  133.   if (explore_left())
  134.     {
  135.       ways = ways | left;
  136.     }
  137.   if (explore_right())
  138.     {
  139.       ways = ways | right;
  140.     }
  141.   return ways;
  142. }
复制代码

maze.nxc:


  1. #include "NXCDefs.h"
  2. #include "maze_stack.h"
  3. #include "maze_motor.h"
  4. //There's something you must know before reading the Program
  5. //the formation of data used in the stack is set to like this
  6. //sample data : 10 ;10 = 0b01010 and the low two digs 10 means there's 2 directions still not be explored
  7. //and the higher two digs 10 means when backing to this cross,we will choose to turn left(left = 0b10,right = 0b01)
  8. //and the highest dig 0 means it is not a "T" corss (1 means Yes)
  9. void init()
  10. {
  11.   head = 0;
  12.   top = 0;
  13.   maze[top] = 0;
  14.   
  15.   //Setup the UltraSonicSensor installed in Socked_4,and start it to work
  16.   SetSensorLowspeed(IN_4);
  17.   
  18.   //Reset the Rotation Count of Motor_A and sets it to fornt
  19.   RotateMotorEx(OUT_A,power_backing_sensor,-(MotorRotationCount(OUT_A)),0,false,true);
  20.   ResetRotationCount(OUT_A);
  21. }
  22. task main()
  23. {
  24.   int ways,temp;
  25.   bool backing;
  26.   init();
  27.   backing = false;
  28.   while (1)
  29.     {
  30.       //we run steply to make sure we won't miss any possible crosses
  31.       run_step();
  32.       ways = check_ways();
  33.       
  34.       if (!(backing))
  35. {
  36.      //if we are not going back
  37.           if (SensorUS(IN_4) > Can_pass)
  38.      {
  39.         // if there's a way in front,we check the ways found by UltraSonic Sensor
  40.        switch (ways)
  41.   {
  42.   case   (left | right) :{      // if left & right is both accessible,we identify it as a "+" cross
  43.     push(ways-1);
  44.     run_step();
  45.     break;
  46.   }
  47.   case   (left) :{
  48.     push((ways-1) | turn_right);
  49.     run_step();
  50.     break;
  51.   }
  52.   case   (right) :{
  53.     push((ways) | turn_left);
  54.     run_step();
  55.     break;
  56.   }
  57.   default  :break;
  58.   }
  59.      }else
  60.      {
  61.        switch (ways)
  62.   {
  63.   case  (left | right) :{
  64.     push(1 | turn_left | T_road);
  65.     wait_motor(false,true);
  66.     run_step();
  67.     break;
  68.   }
  69.   case  (left) :{
  70.     wait_motor(false,true);
  71.     break;
  72.   }
  73.   case  (right) :{
  74.     wait_motor(false,false);
  75.     break;
  76.   }
  77.   default :{
  78.     wait_motor(true,true);
  79.     backing = true;
  80.     break;
  81.   }
  82.   }
  83.      }
  84. }else
  85. {
  86.    temp = pop();
  87.    if (SensorUS(IN_4) > Can_pass)
  88.      {
  89.        switch (ways)
  90.   {
  91.   case    (left | right) :{
  92.     switch(temp)
  93.       {
  94.       case   (left):{
  95.         wait_motor(false,true);
  96.         run_step();
  97.         push(temp-1);
  98.         backing = false;
  99.         break;
  100.       }
  101.       case   (right):{
  102.         run_step();
  103.         backing = false;
  104.         push(temp-1);
  105.         break;
  106.       }
  107.       case   0:{
  108.         wait_motor(false,false);
  109.         run_step();
  110.         break;
  111.       }
  112.       default :break;
  113.       }
  114.     break;
  115.   }
  116.   case     (left) :{
  117.     wait_motor(false,((temp & turning) == turn_left));
  118.     run_step();
  119.     if (!((temp & unexplored) == 0)) push(temp-1);
  120.     backing = ((temp & unexplored) == 0);
  121.     break;
  122.   }
  123.   case     (right) :{
  124.     if ((temp & T_road) != T_road)
  125.       {
  126.         wait_motor(false,((temp & turning) == turn_left));
  127.       }else{
  128.       temp = (temp & unexplored) | turn_left;
  129.     }
  130.     run_step();
  131.     if (!((temp & unexplored) == 0)) push(temp-1);
  132.     backing = ((temp & unexplored) == 0);
  133.     break;
  134.   }
  135.   default    : break;
  136.   }
  137.      }else
  138.      {
  139.        switch(ways)
  140.   {
  141.   case    (left | right):{
  142.     wait_motor(false,((temp & turning) == turn_left));
  143.     run_step();
  144.     break;
  145.   }
  146.   case    (left):{
  147.     wait_motor(false,true);
  148.     break;
  149.   }
  150.   case    (right):{
  151.     wait_motor(false,false);
  152.     break;
  153.   }
  154.   case    0: StopTask(main);
  155.   }
  156.      }
  157. }
  158.     }
  159. }
复制代码


万分感谢吖!

如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
 楼主| 发表于 2011-11-9 22:28:10 | 显示全部楼层
程序用的思想是“深度优先搜索”即回溯法,即不断尝试各条路,只要发现可能便深入发现不对便退回重新选择(将原递归思路改成while循环配上栈的方法)进行探测。

PS:NXT(或者说NXC)允许递归吗~?最大深度是多少~?谁用过NXC来递归~?
如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

发表于 2011-11-10 00:02:40 | 显示全部楼层
我觉得不用这么复杂,不需要用递归。
先测右边
右边有墙:测前面:前面有墙左转,前面没有墙,往前走。
右边没有墙,测右转。

如此循环就可以了
如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

发表于 2011-11-10 00:08:08 | 显示全部楼层
本帖最后由 wangxj 于 2011-11-10 00:09 编辑

如果不用递归来写,
程序相对简单。
用nxt——g就能完成任务了,因为nxt-g电机的控制比较好,直线性比较好。
转弯由于惯性是会有差错的,而且每块地方的摩擦力不同,水平程度不同,有误差很正常。
如果时间急,是没有方法精确调整这么多的角度的。
建议直接后退靠墙,调整机器位置,有效而且稳定,就是整个过程时间比较长。
如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

发表于 2011-11-10 08:42:38 | 显示全部楼层
nxc不支持递归的,至少以前是不知道,不知道后面更新后怎么样
如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

发表于 2011-11-10 09:01:55 | 显示全部楼层
楼主,我也刚接触乐高机器人是个新手,说一下我的一些想法,也没有验证过,仅供参考。
如果用右转法则解迷宫,我的想法如下:
1、超声波距离传感器面向右侧,探测与墙面的距离,和是否有岔路。
2、触碰传感器面向前方判断路是不是通。
程序可以这样设计:
1、保持距离传感器与右墙面的距离使小车直线行走。
2、如果右侧探测到岔路(距离突然变大),则右转。
3、如果前方的触碰传感器被压下,说明此路不通,则180度掉头。
不知道用以上方法能不能做出迷宫机器人,只是本人的设想而已。
如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

 楼主| 发表于 2011-11-10 22:01:38 | 显示全部楼层
回复6楼,理论上可行,不过想想走出迷宫以后机器人的行为·。·绕着迷宫外墙走·。·不过理论上来说除了回形岔路以外基本这样右行规则确实可以走啦~。
4楼的童鞋,有个问题,靠墙以后我怎么转弯·。·~?还有~要么就是按6楼的X行规则,不然没有数据结构的支持NXT-G做不出来吧~?
大家一起讨论啊!这个问题似乎跟电机和尾轮有关,走不了直线啊!!!

突然想到,大家说,我在run_step()过程那里while循环里面监视BC2个电机转过的角度发现某电机转过角度比另一个大就把转的慢的那个电压加高等相同了再调回来是否可行~?
如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

发表于 2011-11-10 22:10:30 | 显示全部楼层
……是转弯后靠墙~~~
不是靠墙后转弯……
如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 马上注册

本版积分规则

手机版|中文乐高 ( 桂ICP备13001575号-7 )

GMT+8, 2024-11-23 12:06 , Processed in 0.135128 second(s), 23 queries .

Powered by Discuz! X3.5

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表