(续)标靶识别与自动炮击

上篇说了基本题的实现过程,现在继续讨论一波发挥部分,实际上,发挥部分是在基本部分上的进一步拓展,基本部分做不出来,发挥部分也基本无从入手,做电赛不能有的心态是,基本部分不搞,直接搞发挥题,因为不现实,基本分拿满,国赛而言,基本省二应该是稳得,发挥部分一般是角逐国一的

在基本题的第三题的基础上,进行改进,可以完成发挥部分的第一题,其实读一读题目,这题基本是基础第三题增加一个标靶识别功能,或者说只要找到了标靶,即获取d和α就可以套用基础三的后续射击过程了,关键不就是如何定位么?

仔细想一想,既然只有三天四夜,不可能让你去深入的搞一波什么摄像头识别,OpenCv之类,即使有,也必有成品模块,但是这题不可能用的摄像头,最起码我的方案不需要,我只需要一个激光测距模块足够了,对!就一个模块也足以搞定定位,不光是测距,但是我只要一个拥有测距功能的激光模块就行,而且是模块!意味着只要有TTL数据输出口,我连这个模块的底层驱动代码都不用写,因为直接支持数据输出嘛!你可能回想,有这样的好事?嗯哼,好事还真有!

相位单点激光测距传感器,高精度模块(链接)

嗯哼?,没想到吧!万能的某宝啥都有,其实嘛,我咋找到的,因为我经常逛淘宝,额,我可不像女孩子一样去买衣服化妆品啥的,我主要是看看有没有啥好玩的电子Diy之类,所以很熟!

额,现在看看,我如何实现用一个激光测距传感器完成标靶的定位和测距了,根据-30°<=α<=30°,可以确定靶心的角度范围是60°转动以内,以逆时针30°为基准点0,每隔3°测一次距离,存储距离,一共测到21个

void Distance_get_21()
{
  int i;
  for(i=0;i<21;i++)
  {
    Server_ctrl(30-(i*3),0);
    Dis_[i] = Dis_sample();
    Delay_500ms();
  }
}
extern int Dis_[21] = {0};

全局变量是为了方便使用,测距驱动函数在总的采样函数里调用即可,一次测满21个数据,存储,下面就是利用测得的数据进行分析了!哦对了,注意保证测距传感器模块与引导标识中心正对!在引导靶子的中心垂线上标定一下即可!

void Analysis_Dis()
{
  int j;
  int record = 0;
  int Small_ = Dis_[0];
  for(j=0;j<21;j++)
  {
    if(Small_>=Dis_[j])
    {
      Small_ = Dis_[j];
      record = j;
    }
  }
  α = 30 - record*3;
  d = Small_ - 30;
}

经过上述分析,即可得到需要的两个参数,α和d,调入电磁炮转向与射击函数,进行射击即可,注意测距延时500ms一次,总延时不超过30000ms即可,实际上,划分更小的测距角可以提高测得的数据准确性,在满足时限的情况下可以进一步改进,发挥题一得分!

实际上,为啥我会想到利用测距分析发挥题一呢?因为我看了发挥题二,顺便联想了一下AD采集

往复运动不能停顿,那就是说第一题可以停顿了,正好我的想法是按角测距,存储距离,再分析,应该说是碰上了!这就是为啥我是这样做发挥部分第一题的原因

实际上第二题都不需要距离d,额,这并不是说不需要测距,因为靶心距离给定了!250cm,额,就是电磁炮的仰角确定了,详细参考前篇如何确定仰角的,剩下的就是测定α,或者说是,实时检测标靶,射击

α起始角度-30°,然后转到30°再到-30°,往复,发现标靶射击,一次完成命中即可,额,听起来很简单,实际上动脑子想一想,不能停!这就意味着,炮弹有水平速度,对准靶心射击貌似不太靠谱,这题没尝试,但有个想法可以安利一波!

开启Stm32定时器,间隔20ms测距一次,即将原先的角度测距改为定时测距,按照舵机响应大概在1s左右估计,其间可以测得50次左右,额,当然不是记录并使用!而是寻找引导靶边缘,按照程序来说,测距会在进入靶子的一定角度内会有距离跳变,在这个跳变点发射即可!

int Transfer_point()
{
  static int last_dis = 0;
  static int now_dis = 0;
  
  if((timer++)%20==0)
  {
    now_dis  = Dis_sample();
    if(now_dis<=300)
    {
      if(Abs(now_dis-last_dis)>=100)
      {
        return true;
      }
    }
    else
    {
      last_dis = now_dis;
    }
  }
  return false;
}
void Timer_Interrupt_period_us()
{
  if(!Terminate_)
  {
    if(!Transfer_point())
    {
      /*维系转动*/
    }
    else
    {
      /*开炮*/
      ...

      ...
      Terminate_ = 1;
    }
  }
}

结果嘛,除了最后一题,基本完美,但是我估计,最后一题按照这样的思路的话,至少不会出现脱靶的现象,但是得分的话,由于水平速度不确定性,嗯,暂时没想到好的办法,但是按照这样的情况,进入国赛应该是没问题,可惜,没这个机会参加,有兴趣的话欢迎一起交流!

唯我超电磁炮永世长存:https://www.bilibili.com/medialist/play/ml216593946

发表评论

电子邮件地址不会被公开。 必填项已用*标注