Há muito tempo, eu queria resolver os projetos que fiz nos últimos anos. Agora só há tempo suficiente para me encorajar, vamos lá! YapethsDY
Deixe-
me apresentar brevemente a situação geral do projeto : use o robô colaborativo multi-joint desenvolvido pela Siasun + câmera Bumblebee XB3 (resolução 1024 * 768) + ambiente de desenvolvimento VS2010 + Halcon 18.05. Modificar: 2020/7/13 adicionar sistema de coordenadas de câmera
A primeira etapa é esclarecer os sistemas de coordenadas BBX2 e BBX3
Método: segure o pino da câmera em sua mão e olhe para o conector 1394A da câmera. O lado direito é a câmera do olho direito, o lado esquerdo é a câmera do olho esquerdo, a frente da câmera é a direção Z positiva e o centro do olho direito afastado da câmera do olho esquerdo é a direção X positiva. Então, de acordo com a regra da mão direita, a direção Y da câmera pode ser determinada.
- Sistema de coordenadas envolvido
- Sistema de coordenadas da peça
- Sistema de coordenadas da ferramenta
- Sistema de coordenadas da câmera
Existe um sistema de coordenadas de imagem e um sistema de coordenadas de pixel no sistema de coordenadas da câmera
A câmera BumblebeeXB3 usada neste projeto tem a origem das coordenadas no centro do olho direito.
A segunda etapa do formulário de calibração mão-olho
Dependendo se a câmera é fixa em relação à origem da coordenada do robô, podemos dividi-la nos dois modos a seguir:
- Câmera fixa (olho na mão)
- A câmera não está fixa (olho na mão)
O resultado final que precisamos é obter a relação de posição espacial entre a câmera e a ferramenta, que é uma matriz 4 * 4 NOAP. Isso pode ser feito fixando a placa de calibração e mudando a pose do robô para fazer a câmera disparar a placa de calibração várias vezes em diferentes posições e ângulos. Calcular. (Não consigo desenhar, as imagens são trechos)
- A posição relativa da câmera e da ferramenta permanece inalterada e a matriz de alteração é definida como .
- A relação de transformação do sistema de coordenadas da ferramenta para o sistema padrão de base também é certa, deixe estar a matriz de transformação .
- Depois que o robô é colocado em uma posição de posicionamento, o sistema de coordenadas da peça também é constante em relação ao sistema de coordenadas de base e uma matriz de transformação é definida .
Depois que a relação de conversão entre a câmera e o sistema de coordenadas do robô é calculada, as operações subsequentes podem ser realizadas.
A terceira etapa da calibração mão-olho
- Obtenha os parâmetros internos da câmera
Existem 8 parâmetros relacionados à calibração da câmera: Foco, Kappa, Sy, Sx, Cx, Cy, ImageWidth, ImageHeight.
/// <summary>
/// 相机内参
/// 确定摄像机从三维空间到二维图像的投影关系
/// </summary>
/// <param name="fFocal">镜头焦距 单位m</param>
/// <version BBX3-13S2C-60指的是焦距为0.006m>
/// <version BBX3-13S2G-38指的是焦距为0.0038m>
/// <前者为彩色相机,后者为灰度相机>
/// <param name="fCenterRow">图像中心坐标行</param>
/// <param name="fCenterCol">图像中心坐标列</param>
/// <param name="fKappa">径向畸变量级<0则为桶型,>0则为枕型,在标定的时候设置为0</param>
/// <缩放比例因子,对相机来讲,表示图像传感器上水平和垂直方向上相邻像素之间的距离>
/// <像素在世界坐标系中的尺寸>
/// <param name="fSx"></param>
/// <param name="fSy"></param>
/// <param name="nImageHeight">图像分辨率高</param>
/// <param name="nImageWidth">图像分辨率宽</param>
/// <returns>执行结果</returns>
bool CFastRecognizeAndLocattedVisionDoc::GetCameraParam(CString strFilePath)
{
if (m_bCameraConnectted)
{
HTuple hv_CamParam;
float fFocalLength = 0.0f;
//镜头焦距 单位m
float fFocal = 0.0038f;
float fCenterRow = 0.0f;
float fCenterCol = 0.0f;
float fKappa = 0.0f;
float fSx = 0.0f;
float fSy = 0.0f;
int nImageWidth = 0;
int nImageHeight = 0;
CString strCamParamFileName;
triclopsGetImageCenter(m_triclopsContext,&fCenterRow,&fCenterCol);
//归一化焦距
triclopsGetFocalLength(m_triclopsContext,&fFocalLength);
triclopsGetResolution(m_triclopsContext,&nImageHeight,&nImageWidth);
fSx = fFocal / fFocalLength;
fSy = fFocal / fFocalLength;
strCamParamFileName = strFilePath + CAM_PARAM_FILE_NAME;
WriteCameraParamIntoFile("area_scan_division",fFocal,fKappa,fSx,fSy,fCenterCol,fCenterRow,nImageWidth,nImageHeight,strCamParamFileName);
CString strText;
strText.Format(_T("相机内参文件写入成功,路径为%s"),strCamParamFileName);
m_LogUtl.AddMsgInLogFile(strText);
return true;
}
else
{
m_LogUtl.AddMsgInLogFile(_T("相机未连接,无法获取相机内参"));
return false;
}
}
-
Após obter os parâmetros internos da câmera, comece a mover a extremidade do robô (acompanhamento da câmera), pegue a imagem de correção do olho direito da câmera de disparo (placa de calibração fixa no campo de disparo), preste atenção ao ambiente ao redor durante a fotografia, observe o efeito de imagem da imagem e preste atenção especial para garantir que cada A amplitude do segundo robô móvel deve ser grande (a mudança do ângulo multieixo é mais do que 5 graus) e 10-15 grupos de imagens são necessários. O sistema de coordenadas da ferramenta pode ser selecionado ao armazenar a pose final do robô, e o formato F2 é seguido ao salvar a pose final. O código de calibração é o seguinte:
bool CFastRecognizeAndLocattedVisionDoc::CalculateCalibrationTransform(CString strFileName, int nDataNum, TRANSFORMPOSE& transRobotCalibration)
{
m_LogUtl.AddMsgInLogFile(_T("系统开始执行标定矩阵计算"));
// Local iconic variables
HObject ho_Image, ho_Caltab;
// Local control variables
HTuple hv_ImageNameStart, hv_DataNameStart, hv_NumImages;
HTuple hv_Width, hv_Height, hv_WindowHandle, hv_ParamName;
HTuple hv_ParamValue, hv_Labels, hv_Instructions, hv_ArrowThickness;
HTuple hv_ArrowLength, hv_OM3DToolOrigin, hv_OM3DBase;
HTuple hv_CalTabFile, hv_StartCamParam, hv_CalibDataID;
HTuple hv_WindowHandleR, hv_I, hv_RCoord, hv_CCoord, hv_Index;
HTuple hv_PoseForCalibrationPlate, hv_ToolInBasePose, hv_PoseIn;
HTuple hv_PoseOut, hv_OM3DTool, hv_Warnings, hv_Errors;
HTuple hv_CamCalibError, hv_CamParam, hv_ToolInCamPose;
HTuple hv_CalObjInBasePose, hv_PlaneInBasePose, hv_Exception;
HTuple hv_CalibObjIdx, hv_PoseIds, hv_CameraSize, hv_CameraConeLength;
HTuple hv_PX, hv_PY, hv_PZ, hv_OM3DObjectOrig, hv_OM3DObject;
HTuple hv_CalObjInCamPose, hv_Message, hv_OM3DCamera, hv_ObjInCamPose;
HTuple hv_CamInToolPose, hv_CamInBasePose, hv_ObjInBasePose;
hv_ImageNameStart = (LPCTSTR)(strFileName + m_strCalibrationImage);
hv_DataNameStart = (LPCTSTR)(strFileName + m_strCalibrationRobotPose);
hv_NumImages = nDataNum;
hv_CalTabFile = (LPCTSTR)(strFileName + CALTAB_FILE_NAME);
//读取相机内参
ReadCamPar((LPCTSTR)(strFileName + CAM_PARAM_FILE_NAME), &hv_StartCamParam);
//创建Halcon标定数据模型返回输出数据模型句柄
CreateCalibData("hand_eye_moving_cam", 1, 1, &hv_CalibDataID);
//设置在相机校准模型的类型和初始参数
SetCalibDataCamParam(hv_CalibDataID, 0, HTuple(), hv_StartCamParam);
//在标定模型中设定标定对象 设定标定对象句柄索引 标定板坐标点储存地址
SetCalibDataCalibObject(hv_CalibDataID, 0, hv_CalTabFile);
//设定标定数据模型最优化的方式
SetCalibData(hv_CalibDataID, "model", "general", "optimization_method", "nonlinear");
{
HTuple end_val72 = hv_NumImages-1;
HTuple step_val72 = 1;
//遍历处理每个标定位姿的标定图像
for (hv_I=0; hv_I.Continue(end_val72, step_val72); hv_I += step_val72)
{
ReadImage(&ho_Image, hv_ImageNameStart+(hv_I.TupleString("02d")));
//搜索标定区域并识别标定轮廓和标定点信息
//获取标定板轮廓信息
//获取标定板标定点信息
//若图像太亮会出现一点问题 可以可使用HALCON进行验证
FindCalibObject(ho_Image, hv_CalibDataID, 0, 0, hv_I, HTuple(), HTuple());
GetCalibDataObservContours(&ho_Caltab, hv_CalibDataID, "caltab", 0, 0, hv_I);
GetCalibDataObservPoints(hv_CalibDataID, 0, 0, hv_I, &hv_RCoord, &hv_CCoord, &hv_Index, &hv_PoseForCalibrationPlate);
//hv_ToolInBasePose指机器人末端p点位姿
ReadPose((hv_DataNameStart+(hv_I.TupleString("02d")))+".dat", &hv_ToolInBasePose);
if (0 != (hv_I==0))
{
hv_PoseIn.Clear();
hv_PoseIn[0] = -0.006;
hv_PoseIn[1] = -0.296;
hv_PoseIn[2] = 12;
hv_PoseIn[3] = 178;
hv_PoseIn[4] = 2;
hv_PoseIn[5] = 270;
hv_PoseIn[6] = 0;
}
else
{
hv_PoseIn = hv_PoseOut;
}
//将工具初始坐标OM3DToolOrigin值通过ToolInBasePose即工具坐标在机器人基坐标中的位姿转换矩阵转换为工具在基坐标下的表示形式 OM3DTool
RigidTransObjectModel3d(hv_OM3DToolOrigin, hv_ToolInBasePose, &hv_OM3DTool);
SetCalibData(hv_CalibDataID, "tool", hv_I, "tool_in_base_pose", hv_ToolInBasePose);
}
}
//开始进行手眼标定
//从手眼标定结果中获取所需的参数具体数值
CalibrateHandEye(hv_CalibDataID, &hv_Errors);
GetCalibData(hv_CalibDataID, "model", "general", "camera_calib_error", &hv_CamCalibError);
GetCalibData(hv_CalibDataID, "camera", 0, "params", &hv_CamParam);
GetCalibData(hv_CalibDataID, "camera", 0, "tool_in_cam_pose", &hv_ToolInCamPose);
GetCalibData(hv_CalibDataID, "calib_obj", 0, "obj_in_base_pose", &hv_CalObjInBasePose);
//考虑标定板的厚度 延z向做一个0.005m的平移
SetOriginPose(hv_CalObjInBasePose, 0, 0, 0.005, &hv_PlaneInBasePose);
ClearCalibData(hv_CalibDataID);
//获取相机坐标系在机器人坐标系下的坐标
PoseInvert(hv_ToolInCamPose, &hv_CamInToolPose);
transRobotCalibration.PointX = float(hv_CamInToolPose[0].D() * 1000);
transRobotCalibration.PointY = float(hv_CamInToolPose[1].D() * 1000);
transRobotCalibration.PointZ = float(hv_CamInToolPose[2].D() * 1000);
transRobotCalibration.RollAngle = float(hv_CamInToolPose[3].D());
transRobotCalibration.PitchingAngle = float(hv_CamInToolPose[4].D());
transRobotCalibration.YawAngle = float(hv_CamInToolPose[5].D());
CString str;
str.Format(_T("机器人和视觉标定完成,标定结果为:横滚%5.2f,俯仰%5.2f,偏航%5.2f,X%5.2f,Y%5.2f,Z%5.2f")
,transRobotCalibration.RollAngle,transRobotCalibration.PitchingAngle,transRobotCalibration.YawAngle
,transRobotCalibration.PointX,transRobotCalibration.PointY,transRobotCalibration.PointZ);
m_LogUtl.AddMsgInLogFile(str);
return true;
}
Durante a calibração:
- Equações de cinemática direta e inversa envolvendo atitude
- Isso envolverá o ângulo de rotação, ângulo de inclinação, ângulo de guinada (Roll, Pitch, Yaw, RPY)
- Euler Point
O ângulo de rotação, ângulo de inclinação e ângulo de guinada são girados respectivamente em torno dos eixos a, o e n em três sequências, o que pode ajustar o robô para a postura desejada.
/// Em torno do eixo a (o eixo z do sistema de coordenadas de movimento) é chamado de rolamento;
/// Em torno do eixo o (o eixo y do sistema de coordenadas de movimento) é chamado de inclinação;
/// Em torno do eixo n (o eixo x do sistema de coordenadas de movimento) Chamado yaw
Isso envolverá a conversão direta e inversa entre a posição final e atitude e a matriz NOAP.O processo de implementação específico fará o upload do código de engenharia posteriormente.
Final feliz! Sejam todos bem-vindos para me corrigir! Dingyi 2020/08/24