+86-13951940532
contact@oakchina.cn

使用myCobot 280机械臂校准OAK智能深度相机

使用myCobot 280机械臂校准OAK智能深度相机

本次使用的机械臂来自我们的朋友@大象机器人,测试模拟工厂在OAK相机出厂前的校准工作。大家如果没有机械臂,也可以手动校准(教程),效果差别不会特别大。本次校准使用的OAK相机是OAK-D-Lite,其他型号的双目OAK相机也可参考此教程校准。

机械臂环境

  • arduino mega 2560 *1
  • USB串口调试器 *1

参考文档烧写机械臂的驱动、设置arduino开发环境、以及设备的连接,ATOM驱动烧写4.1版本。

设备连接

机械臂与arduino的连接参考上一步的文档。

USB串口调试器是用来触发每一张图片的动作,需要rx和tx交叉接,接到rx0和tx0上,还有一个GND也要接。

OAK连接到电脑,固定到机械臂末端。

arduino烧写

烧写时检查rx0和tx0不要被占用(即烧写时不要接USB串口调试器),烧写以下代码:

#include <MyCobotBasic.h>
#include <ParameterList.h>
#include <SoftwareSerial.h>
MyCobotBasic myCobot;

void setup()
{  

    Serial.begin(4800);
    myCobot.setup();
    delay(100);
    myCobot.powerOn();
    delay(100);
}

void loop()
{
  if (Serial.available()) {
    int read1;
    read1 = Serial.read();
//    Serial.println("read1");
//    Serial.println(read1);
    if (read1 == 1){
        myCobot.writeAngle(1, 17.40, 50);
        delay(1000);
        myCobot.writeAngle(2, -121.64, 50);
        delay(1000);
        myCobot.writeAngle(3, 42.27, 50);
        delay(1000);
        myCobot.writeAngle(4, 73.21, 50);
        delay(1000);
        myCobot.writeAngle(5, -11.51, 50);
        delay(1000);
        myCobot.writeAngle(6, 21.79, 50);
        delay(4000);
        Serial.write(1);
    } else if (read1 == 2){
        //2
        myCobot.writeAngle(1, 43.41, 50);
        delay(1000);
        myCobot.writeAngle(2, -118.03, 50);
        delay(1000);
        myCobot.writeAngle(3, 44.73, 50);
        delay(1000);
        myCobot.writeAngle(4, 58.62, 50);
        delay(1000);
        myCobot.writeAngle(5, -60.20, 50);
        delay(1000);
        myCobot.writeAngle(6, 32.08, 50);
        delay(4000);
        Serial.write(2);
    } else if (read1 == 3){
        //3
        myCobot.writeAngle(1, 43.24, 50);
        delay(1000);
        myCobot.writeAngle(2, -121.81, 50);
        delay(1000);
        myCobot.writeAngle(3, 45.08, 50);
        delay(1000);
        myCobot.writeAngle(4, 63.89, 50);
        delay(1000);
        myCobot.writeAngle(5, -55.98, 50);
        delay(1000);
        myCobot.writeAngle(6, 31.72, 50);
        delay(4000);
        Serial.write(3);
    } else if (read1 == 4){
        //4
        myCobot.writeAngle(1, 47.02, 50);
        delay(1000);
        myCobot.writeAngle(2, -116.36, 50);
        delay(1000);
        myCobot.writeAngle(3, 45.61, 50);
        delay(1000);
        myCobot.writeAngle(4, 58.09, 50);
        delay(1000);
        myCobot.writeAngle(5, -52.29, 50);
        delay(1000);
        myCobot.writeAngle(6, 31.81, 50);
        delay(4000);
        Serial.write(4);
    } else if (read1 == 5){
        //5
        myCobot.writeAngle(1, -15.55, 50);
        delay(1000);
        myCobot.writeAngle(2, -121.28, 50);
        delay(1000);
        myCobot.writeAngle(3, 74.35, 50);
        delay(1000);
        myCobot.writeAngle(4, 28.56, 50);
        delay(1000);
        myCobot.writeAngle(5, 35.59, 50);
        delay(1000);
        myCobot.writeAngle(6, 8.70, 50);
        delay(4000);
        Serial.write(5);
    } else if (read1 == 6){
        //6
        myCobot.writeAngle(1, -17.22, 50);
        delay(1000);
        myCobot.writeAngle(2, -114.08, 50);
        delay(1000);
        myCobot.writeAngle(3, 49.83, 50);
        delay(1000);
        myCobot.writeAngle(4, 54.84, 50);
        delay(1000);
        myCobot.writeAngle(5, 32.69, 50);
        delay(1000);
        myCobot.writeAngle(6, 12.65, 50);
        delay(4000);
        Serial.write(6);
    } else if (read1 == 7){
        //7
        myCobot.writeAngle(1, -14.32, 50);
        delay(1000);
        myCobot.writeAngle(2, -105.90, 50);
        delay(1000);
        myCobot.writeAngle(3, 31.90, 50);
        delay(1000);
        myCobot.writeAngle(4, 64.51, 50);
        delay(1000);
        myCobot.writeAngle(5, 25.31, 50);
        delay(1000);
        myCobot.writeAngle(6, 12.65, 50);
        delay(4000);
        Serial.write(7);
    } else if (read1 == 8){
        //8
        myCobot.writeAngle(1, 2.10, 50);
        delay(1000);
        myCobot.writeAngle(2, -47.19, 50);
        delay(1000);
        myCobot.writeAngle(3, 33.39, 50);
        delay(1000);
        myCobot.writeAngle(4, -22.23, 50);
        delay(1000);
        myCobot.writeAngle(5, 4.83, 50);
        delay(1000);
        myCobot.writeAngle(6, 17.84, 50);
        delay(4000);
        Serial.write(8);
    } else if (read1 == 9){
        //9
        myCobot.writeAngle(1, 0.61, 50);
        delay(1000);
        myCobot.writeAngle(2, -47.81, 50);
        delay(1000);
        myCobot.writeAngle(3, 32.95, 50);
        delay(1000);
        myCobot.writeAngle(4, -19.51, 50);
        delay(1000);
        myCobot.writeAngle(5, 2.72, 50);
        delay(1000);
        myCobot.writeAngle(6, 15.11, 50);
        delay(4000);
        Serial.write(9);
    } else if (read1 == 10){
        // A
        myCobot.writeAngle(1, 9.84, 50);
        delay(1000);
        myCobot.writeAngle(2, -69.87, 50);
        delay(1000);
        myCobot.writeAngle(3, 33.31, 50);
        delay(1000);
        myCobot.writeAngle(4, 11.16, 50);
        delay(1000);
        myCobot.writeAngle(5, -5.0, 50);
        delay(1000);
        myCobot.writeAngle(6, 22.58, 50);
        delay(4000);
        Serial.write(10);
    } else if (read1 == 11){
        // B
        myCobot.writeAngle(1, 3.51, 50);
        delay(1000);
        myCobot.writeAngle(2, -140.36, 50);
        delay(1000);
        myCobot.writeAngle(3, 33.66, 50);
        delay(1000);
        myCobot.writeAngle(4, 113.64, 50);
        delay(1000);
        myCobot.writeAngle(5, 2.37, 50);
        delay(1000);
        myCobot.writeAngle(6, 18.45, 50);
        delay(4000);
        Serial.write(11);
    } else if (read1 == 12){
        // C
        myCobot.writeAngle(1, 4.04, 50);
        delay(1000);
        myCobot.writeAngle(2, -140.18, 50);
        delay(1000);
        myCobot.writeAngle(3, 33.31, 50);
        delay(1000);
        myCobot.writeAngle(4, 116.45, 50);
        delay(1000);
        myCobot.writeAngle(5, 2.37, 50);
        delay(1000);
        myCobot.writeAngle(6, 17.40, 50);
        delay(4000);
        Serial.write(12);
    } else if (read1 == 13){
        // D
        myCobot.writeAngle(1, 3.51, 50);
        delay(1000);
        myCobot.writeAngle(2, -140.27, 50);
        delay(1000);
        myCobot.writeAngle(3, 33.31, 50);
        delay(1000);
        myCobot.writeAngle(4, 107.31, 50);
        delay(1000);
        myCobot.writeAngle(5, 2.37, 50);
        delay(1000);
        myCobot.writeAngle(6, 14.50, 50);
        delay(4000);
        Serial.write(13);
    } else if (read1 == 14){
      // E
      myCobot.setFreeMove();
    } else if (read1 == 15){
      // F
      Angles  angles = myCobot.getAngles();
      delay(200);
      
      for (int i = 0; i < 6; i++) {
          Serial.println(angles[i]);
      }
    }
 }

}

启动OAK

https://github.com/Marco-ardu/depthai/tree/lite_calibration

定格角度commit: e6a0c9f43e2e18f2c31d70a1cb248a867d3e5ede

自动校准commit: 52f8e08887738ce8ab348a586cacc64bec0881dd

依赖(建议创建虚拟环境安装)

python -m pip install -r requirements.txt

启动

python calibrate.py -s 2 -brd oak-d-lite -db -rd

找定格角度

XCOM V2.6.exe下载

启动OAK相机之后,可以看到三个相机的画面,以及画面上黑色的框,先调整棋盘格到机械臂的距离,能够保证棋盘格在三个画面里就可以了,不能太远,大概距离是50cm-60cm,具体根据真实环境调整。

确认USB串口调试器已经连接好

打开XCOM软件,配置如下,波特率根据上面的arduino代码设置的填写


串口输出E让机械臂自由移动,然后移动机械臂将棋盘格移动到框内(在大致大概即可),然后串口输出F,获取定格角度;点击相机画面,然后键盘输入空格,进入下一张,如果失败,说明当前位置不正确,重新调整位置,一共13张。

自动校准

在获得13张图片的定格角度之后,填写到上面的arduino代码中,重新烧写代码。

OAK关闭后,切换到自动校准的commit。

启动相机,点击相机画面,键盘输入s,即可开始自动校准。

结果

出现以下图像即表示校准成功!

大部分的测试校准都能成功,但偶尔会出现以下错误。



校准会出现以上错误,网上查了校准的原理,这个错误原因是rgb画面在检测的那一帧模糊导致检测的角点过少,无法构建对应的方程去解出校准参数。

索引