using Cognex.VisionPro;
using Cognex.VisionPro.ToolBlock;
using MaterialDesignThemes.Wpf;
using MathNet.Numerics;
using MathNet.Numerics.LinearAlgebra;
using NPOI.SS.Formula.Functions;
using OpenCvSharp;
using Prism.Commands;
using Prism.Events;
using Prism.Ioc;
using Prism.Mvvm;
using Prism.Regions;
using Prism.Services.Dialogs;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Reflection.Metadata;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media.Media3D;
using Team.FFFeederService.Interfaces;
using TeamAAS_VP.Controls;
using TeamAAS_VP.Core;
using TeamAAS_VP.Events;
using TeamAAS_VP.Interfaces;
using TeamAAS_VP.Models;
using TeamAAS_VP;
using static OpenCvSharp.LineIterator;
using TeamAAS_VP.Resources.Languages;
namespace TeamAAS_VP.ViewModels.Calibration
{
public class CalibToolViewModel : BindableBase, IDialogAware
{
IRegionManager _regionManager;
IRegionNavigationService _regionNavigationService;
IContainerProvider _container;
IDialogService _dialogService;
IEventAggregator _eventAggregator;
#region 属性
private ICogImage _Image;
public ICogImage Image
{
get { return _Image; }
set { SetProperty(ref _Image, value); }
}
private Cognex.VisionPro.CogGraphicCollection _Graphic;
public Cognex.VisionPro.CogGraphicCollection Graphic
{
get { return _Graphic; }
set { SetProperty(ref _Graphic, value); }
}
private CalibrationInfo _SelectCalibration;
public CalibrationInfo SelectCalibration
{
get { return _SelectCalibration; }
set { SetProperty(ref _SelectCalibration, value); }
}
public string Title=> "校准工具坐标";
private double _Angle = 180;
///
/// 机器人移动的范围U
///
public double Angle
{
get { return _Angle; }
set { SetProperty(ref _Angle, value); }
}
public RobotTool Tool { get; set; }
///
/// 机器人与相机之间的旋转矩阵
///
public Matrix RobotCameraRotationMatrix { get; set; }
public Management management { get; set; }
public RobotService robotService { get; set; }
public IRobot Robot { get; set; }
public IVoiceCoilMotorFeeder Feeder { get; set; }
private bool _IsRunning=true;
public bool IsRunning
{
get { return _IsRunning; }
set { SetProperty(ref _IsRunning,value); }
}
private ICamera _Camera;
public ICamera Camera
{
get { return _Camera; }
set { SetProperty(ref _Camera, value); }
}
#endregion
#region 命令
private DelegateCommand _ConfirmCommand;
public DelegateCommand ConfirmCommand =>
_ConfirmCommand ?? (_ConfirmCommand = new DelegateCommand(ExecuteConfirmCommand).ObservesCanExecute(() => IsRunning));
private DelegateCommand _CancelCommand;
public DelegateCommand CancelCommand =>
_CancelCommand ?? (_CancelCommand = new DelegateCommand(ExecuteCancelCommand).ObservesCanExecute(() => IsRunning));
private DelegateCommand _StartCalibCommand;
public DelegateCommand StartCalibCommand =>
_StartCalibCommand ?? (_StartCalibCommand = new DelegateCommand(ExecuteStartCalibCommand).ObservesCanExecute(()=> IsRunning));
#endregion
#region 事件
public event Action RequestClose;
#endregion
public CalibToolViewModel(IRegionManager regionManager, IEventAggregator ea, IRegionNavigationService regionNavigationService, IContainerProvider container, IDialogService dialogService)
{
_regionManager = regionManager;
_regionNavigationService = regionNavigationService;
_container = container;
_dialogService = dialogService;
_eventAggregator = ea;
}
#region 方法
///
/// 确定
///
void ExecuteConfirmCommand()
{
if (Tool==null)
{
return;
}
IDialogParameters parameters = new DialogParameters();
parameters.Add("Tool", Tool);
parameters.Add("RobotCameraRotationMatrix", RobotCameraRotationMatrix);
parameters.Add("Angle", Angle);
RequestClose?.Invoke(new DialogResult(ButtonResult.OK, parameters));
}
///
/// 取消
///
void ExecuteCancelCommand()
{
IDialogParameters parameters = new DialogParameters();
parameters.Add("Tool", Tool);
RequestClose?.Invoke(new DialogResult(ButtonResult.Cancel, parameters));
}
///
/// 开始校准
///
async void ExecuteStartCalibCommand()
{
if (SelectCalibration == null) return;
if (Robot == null || !Robot.IsConnected) return;
Robot.Timeout = 600000;
try
{
if (Angle == 0)
Angle = 10;
var view = new ShowMessage(Lang.Tool校准, Lang.是否开始自动校准工具坐标);
//show the dialog
var result = await DialogHost.Show(view, "CalibToolDialog", null, null, null);
if (!((bool)result)) return;
IsRunning = false;
//发送校准的参数
await Robot.CalibParameAsync(SelectCalibration.Pick, SelectCalibration.Speed, SelectCalibration.Accel, SelectCalibration.Power, SelectCalibration.WaitSuction, SelectCalibration.WaitBlow);
Tuple, double, double> calibresult=new Tuple, double, double>(false,null,0,0);
if (SelectCalibration.CameraMount == Enums.CameraMount.FixedDown)
{
calibresult = await CalibToolForFixedDown();
}
else if (SelectCalibration.CameraMount == Enums.CameraMount.FixedUp)
{
calibresult = await CalibToolForFixedUp();
}
else if (SelectCalibration.CameraMount == Enums.CameraMount.MobileJ4)
{
calibresult = await CalibToolForMobileJ4();
}
else
{
view = new ShowMessage(Lang.Tool校准, Lang.暂不支持此安装方式的相机, false);
result = await DialogHost.Show(view, "CalibToolDialog", null, null, null);
return;
}
if (calibresult.Item1)
{
if (Tool==null)
{
Tool = new RobotTool();
}
Tool.X = calibresult.Item3;
Tool.Y = calibresult.Item4;
RobotCameraRotationMatrix = calibresult.Item2;
//MessageBox.Show("校准完成");
view = new ShowMessage(Lang.Tool校准, Lang.校准完成, false);
await DialogHost.Show(view, "CalibToolDialog", null, null, null);
IDialogParameters parameters = new DialogParameters();
parameters.Add("Tool", Tool);
parameters.Add("RobotCameraRotationMatrix", RobotCameraRotationMatrix);
RequestClose?.Invoke(new DialogResult(ButtonResult.OK, parameters));
}
else
{
view = new ShowMessage(Lang.Tool校准, Lang.校准失败, false);
//show the dialog
await DialogHost.Show(view, "CalibToolDialog", null, null, null);
}
IsRunning = true;
}
catch (Exception ex)
{
IsRunning = true;
LogHelper.WriteLogError("相机校准-校准验证界面示加载时出错!", ex);
//MessageBox.Show(ex.Message);
var view = new ShowMessage(Lang.Tool校准, $"{ex.Message}", false);
//show the dialog
var result = await DialogHost.Show(view, "CalibToolDialog", null, null, null);
}
}
public bool CanCloseDialog()
{
return true;
}
public void OnDialogClosed()
{
}
public void OnDialogOpened(IDialogParameters parameters)
{
SelectCalibration = _container.Resolve().SelectCalibration;
management = _container.Resolve();
robotService = management.RobotService;
if (SelectCalibration != null)
{
Camera = management.CameraService.GetCamera(SelectCalibration.CameraID);
Robot = robotService.GetRobot(SelectCalibration.RobotId);
if (SelectCalibration.FeederId!=Guid.Empty)
{
Feeder = management.FeederService.GetFeeder(SelectCalibration.FeederId);
}
Angle = SelectCalibration.Angle;
}
}
///
/// 移动机器人3个点计算旋转矩阵
///
/// (旋转矩阵,PixelScaleX,PixelScaleY)
private async Task,double,double>> MoveRobotThreePointComputCroodTrans(RPoint rPoint, float distance)
{
//-------------------------------------------P0-----------------------------------
//移动机器人至中心点
if (SelectCalibration.CameraMount == Enums.CameraMount.FixedDown)
{
await Robot.CalibMotionAsync(rPoint, 0);
//关闭吸气
await Robot.CalibOutIOAsync(false);
}
else
{
await Robot.CalibMotionAsync(rPoint, rPoint.Z);
}
RPoint RobotP0= await Robot.GetRobotPosAsync();
RPoint RobotP1 = RobotP0.Clone();
RPoint RobotP2 = RobotP0.Clone();
RobotP1.X += distance;
RobotP2.Y += distance;
if (SelectCalibration.CameraMount == Enums.CameraMount.FixedDown)
{
//移动机器人至待机位置
await Robot.CalibMotionAsync(SelectCalibration.HomePoint, 0);
}
var P0=Photo();
//-------------------------------------------P1-----------------------------------
if (SelectCalibration.CameraMount == Enums.CameraMount.FixedDown)
{
//移动机器人至P0
await Robot.CalibMotionAsync(RobotP0, 0);
//打开吸气
await Robot.CalibOutIOAsync(true);
//移动机器人至P1
await Robot.CalibMotionAsync(RobotP1, 0);
//关闭吸气
await Robot.CalibOutIOAsync(false);
//移动机器人至待机位置
await Robot.CalibMotionAsync(SelectCalibration.HomePoint, 0);
}
else
{
//移动机器人至P1
await Robot.CalibMotionAsync(RobotP1, RobotP1.Z);
}
var P1 = Photo();
//-------------------------------------------P2-----------------------------------
if (SelectCalibration.CameraMount == Enums.CameraMount.FixedDown)
{
//移动机器人至P1
await Robot.CalibMotionAsync(RobotP1, 0);
//打开吸气
await Robot.CalibOutIOAsync(true);
//移动机器人至P2
await Robot.CalibMotionAsync(RobotP2, 0);
//关闭吸气
await Robot.CalibOutIOAsync(false);
//移动机器人至待机位置
await Robot.CalibMotionAsync(SelectCalibration.HomePoint, 0);
}
else
{
//移动机器人至P2
await Robot.CalibMotionAsync(RobotP2, RobotP2.Z);
}
var P2 = Photo();
//-------------------------------------------P0--------------------------------------
if (SelectCalibration.CameraMount == Enums.CameraMount.FixedDown)
{
//移动机器人至P2
await Robot.CalibMotionAsync(RobotP2, 0);
//打开吸气
await Robot.CalibOutIOAsync(true);
//移动机器人至P0
await Robot.CalibMotionAsync(RobotP0, 0);
//关闭吸气
await Robot.CalibOutIOAsync(false);
//移动机器人至待机位置
await Robot.CalibMotionAsync(SelectCalibration.HomePoint, 0);
}
else
{
//移动机器人至P0
await Robot.CalibMotionAsync(RobotP0, RobotP0.Z);
}
//-----------------------------------------计算旋转矩阵------------------------------
Matrix M= ComputRotationMatrix(P0, P1, P2);
//Theta = Acos(M11)
//相机与机器人坐标系角度:Theta * 180 / PI
//-----------------------------------------计算像素和毫米比例-----------------------
Vector P11= Vector.Build.Dense(new double[] { distance, 0 });
Vector P21 = Vector.Build.Dense(new double[] { P1.X, P1.Y }) - Vector.Build.Dense(new double[] { P0.X, P0.Y });
double PixelScaleX = Math.Abs((M * P11)[0] / P21[0]); //mm/pixel
double PixelScaleY = Math.Abs((M * P11)[1] / P21[1]); //mm/pixel
return new Tuple, double, double>(M, PixelScaleX, PixelScaleY);
}
///
/// 计算旋转矩阵
///
///
///
///
///
private Matrix ComputRotationMatrix(PointF P0, PointF P1, PointF P2)
{
Vector Point0 = Vector.Build.Dense(new double[] { (double)P0.X, (double)P0.Y });
Vector Point1 = Vector.Build.Dense(new double[] { (double)P1.X, (double)P1.Y });
Vector Point2 = Vector.Build.Dense(new double[] { (double)P2.X, (double)P2.Y });
//2.计算坐标系的基向量:
Vector E1 = (Point1 - Point0) / (Point1 - Point0).L2Norm();
Vector E2 = (Point2 - Point0 - E1.DotProduct(Point2 - Point0) * E1) / (Point2 - Point0 - E1.DotProduct(Point2 - Point0) * E1).L2Norm();
//3.计算旋转矩阵:我们可以使用基向量组成的矩阵作为旋转矩阵。具体地,我们可以将基向量 e1 和 e2 分别作为新坐标系下的 $x$ 和 $y$ 轴,然后组成一个矩阵,再对这个矩阵求逆即可得到旋转矩阵。代码实现:
// Compute rotation matrix
Matrix R = Matrix.Build.DenseOfColumnVectors(E1, E2);
return R;
}
///
/// 相机拍照
///
///
///
private PointF Photo()
{
if (Feeder != null)
{
Feeder.OpenLight();
Feeder.SetLightTimeOut((ushort)SelectCalibration.Brightness);
}
Task.Delay(200).Wait();
//采集图像
if (Camera != null)
{
SelectCalibration.ToolBlock.Inputs["InputImage"].Value = Camera.Grab();
Image = (ICogImage)SelectCalibration.ToolBlock.Inputs["InputImage"].Value;
}
Graphic = null;
SelectCalibration.ToolBlock.Run();
CogToolBlockTerminalCollection outputCollection = SelectCalibration.ToolBlock.Outputs;
Graphic = outputCollection["Graphic"].Value as CogGraphicCollection;
bool Found = (bool)(outputCollection["Found"].Value);
if (Found)
{
var strpoints = outputCollection["Point"].Value.ToString();
string[] items = strpoints.Split(',');
return new PointF(float.Parse(items[0]), float.Parse(items[1]));
}
else
{
throw new Exception(Lang.拍照失败);
}
}
///
/// 固定向下相机校准工具坐标
///
/// (结果,旋转矩阵,Tool.X,Tool.Y)
private async Task, double, double>> CalibToolForFixedDown()
{
//移动机器人至待机位置
await Robot.CalibMotionAsync(SelectCalibration.HomePoint, 0);
if (SelectCalibration.Pick.PickPlaceModel == Enums.PickPlaceModel.Inhal)
{
//打开吸气
await Robot.CalibOutIOAsync(true);
}
else
{
//张开夹爪
//夹爪张开为false,夹爪闭合为True
await Robot.CalibOutIOAsync(false);
}
var view = new ShowMessage(Lang.提示, Lang.请将校准块放置在吸嘴中心);
var result = await DialogHost.Show(view, "CalibToolDialog", null, null, null);
if (!((bool)result)) { IsRunning = true; return new Tuple, double, double>(false,null,0,0); }
if (SelectCalibration.Pick.PickPlaceModel == Enums.PickPlaceModel.Clamp)
{
//夹紧夹爪
await Robot.CalibOutIOAsync(true);
}
//计算相机与机器人坐标系的旋转矩阵
var rst = await MoveRobotThreePointComputCroodTrans(SelectCalibration.CenterPoint, ((float)SelectCalibration.Height) / 3);
SelectCalibration.PixelScaleX = rst.Item2;
SelectCalibration.PixelScaleY = rst.Item3;
var P0 = Photo(); //拍照获取中点像素坐标
RPoint RobotU = SelectCalibration.CenterPoint.Clone();
RobotU.U += (float)Angle;
//移动机器人中心点
await Robot.CalibMotionAsync(SelectCalibration.CenterPoint, 0);
//打开吸气
await Robot.CalibOutIOAsync(true);
//机器人U轴旋转
await Robot.CalibMotionAsync(RobotU, 0);
//关闭吸气
await Robot.CalibOutIOAsync(false);
//移动机器人至待机位置
await Robot.CalibMotionAsync(SelectCalibration.HomePoint, 0);
var curPixel = Photo();
bool IsFinish = false;
for (int i = 0; i < 10; i++)
{
//计算需要移动的偏移量,目的是逼近中心点
double offsetx = (P0.X - curPixel.X) * rst.Item2;
double offsety = (P0.Y - curPixel.Y) * rst.Item3;
var pos = rst.Item1.Inverse() * Vector.Build.Dense(new double[] { offsetx, offsety });
//移动机器人取标定块
await Robot.CalibMotionAsync(RobotU, 0);
//打开吸气
await Robot.CalibOutIOAsync(true);
RobotU.X += (float)pos[0];
RobotU.Y += (float)pos[1];
//机器人移动
await Robot.CalibMotionAsync(RobotU, 0);
//关闭吸气
await Robot.CalibOutIOAsync(false);
//移动机器人至待机位置
await Robot.CalibMotionAsync(SelectCalibration.HomePoint, 0);
curPixel = Photo();
offsetx = P0.X - curPixel.X;
offsety = P0.Y - curPixel.Y;
//await Console.Out.WriteLineAsync($"移动后的差异:{offsetx},{offsety}");
if (Math.Abs(offsetx) < 1 && Math.Abs(offsetx) < 1)
{
//移动机器人取标定块
await Robot.CalibMotionAsync(RobotU, 0);
//打开吸气
await Robot.CalibOutIOAsync(true);
//移动机器人至待机位置
await Robot.CalibMotionAsync(SelectCalibration.HomePoint, 0);
IsFinish = true;
break;
}
}
if (IsFinish)
{
Vector p0 = Vector.Build.Dense(new double[] { SelectCalibration.CenterPoint.X, SelectCalibration.CenterPoint.Y });
Vector p1 = Vector.Build.Dense(new double[] { RobotU.X, RobotU.Y });
ToolCoord toolCoord = new ToolCoord();
double u1 = SelectCalibration.CenterPoint.U;
double u2 = RobotU.U;
if (Robot.Brand == Enums.RobotBrand.Schneider)
{
u1 *= -1;
u2 *= -1;
}
toolCoord.ComputeTool(p0, p1, u1, u2);
if (Tool == null)
{
Tool = new RobotTool();
}
Tool.X = toolCoord.X;
Tool.Y = toolCoord.Y;
RobotCameraRotationMatrix = rst.Item1;
return new Tuple, double, double>(true, RobotCameraRotationMatrix, Tool.X, Tool.Y);
}
else
{
return new Tuple, double, double>(false, null,0,0);
}
}
///
/// 固定向上相机校准工具坐标
///
/// (结果,旋转矩阵,Tool.X,Tool.Y)
private async Task, double, double>> CalibToolForFixedUp()
{
//移动机器人至中心位置
await Robot.CalibMotionAsync(SelectCalibration.CenterPoint, 0);
if (SelectCalibration.Pick.PickPlaceModel == Enums.PickPlaceModel.Inhal)
{
//打开吸气
await Robot.CalibOutIOAsync(true);
}
else
{
//张开夹爪
await Robot.CalibOutIOAsync(false);
}
var view = new ShowMessage(Lang.提示, Lang.请将校准块放置在吸嘴中心);
var result = await DialogHost.Show(view, "CalibToolDialog", null, null, null);
if (!((bool)result)) { IsRunning = true; return new Tuple, double, double>(false,null,0,0); }
if (SelectCalibration.Pick.PickPlaceModel == Enums.PickPlaceModel.Clamp)
{
//夹紧夹爪
await Robot.CalibOutIOAsync(true);
}
//计算相机与机器人坐标系的旋转矩阵
var rst = await MoveRobotThreePointComputCroodTrans(SelectCalibration.CenterPoint, ((float)SelectCalibration.Height) / 3);
SelectCalibration.PixelScaleX = rst.Item2;
SelectCalibration.PixelScaleY = rst.Item3;
var imagecenter = Camera.Grab();
PointF P0 = new PointF((float)(imagecenter.Width/2), (float)(imagecenter.Height / 2)); //中心点像素坐标
//先找相机中心点,校准中心点坐标
bool IsFinish = false;
var curPixel = Photo();
var curpos = Robot.GetRobotPos();
for (int i = 0; i < 10; i++)
{
//计算需要移动的偏移量,目的是逼近中心点
double offsetx = (P0.X - curPixel.X) * rst.Item2;
double offsety = (P0.Y - curPixel.Y) * rst.Item3;
var pos = rst.Item1.Inverse() * Vector.Build.Dense(new double[] { offsetx, offsety });
curpos.X += (float)pos[0];
curpos.Y += (float)pos[1];
//机器人移动
await Robot.CalibMotionAsync(curpos, curpos.Z);
curPixel = Photo();
offsetx = P0.X - curPixel.X;
offsety = P0.Y - curPixel.Y;
//await Console.Out.WriteLineAsync($"移动后的差异:{offsetx},{offsety}");
if (Math.Abs(offsetx) < 1 && Math.Abs(offsetx) < 1)
{
IsFinish = true;
break;
}
}
if (IsFinish==true)
{
SelectCalibration.CenterPoint= Robot.GetRobotPos();
}
else
{
return new Tuple, double, double>(false, null, 0, 0);
}
RPoint RobotU = SelectCalibration.CenterPoint.Clone();
RobotU.U += (float)Angle;
//机器人U轴旋转
await Robot.CalibMotionAsync(RobotU, RobotU.Z);
curPixel = Photo();
IsFinish = false;
for (int i = 0; i < 10; i++)
{
//计算需要移动的偏移量,目的是逼近中心点
double offsetx = (P0.X - curPixel.X) * rst.Item2;
double offsety = (P0.Y - curPixel.Y) * rst.Item3;
var pos = rst.Item1.Inverse() * Vector.Build.Dense(new double[] { offsetx, offsety });
RobotU.X += (float)pos[0];
RobotU.Y += (float)pos[1];
//机器人移动
await Robot.CalibMotionAsync(RobotU, 0);
curPixel = Photo();
offsetx = P0.X - curPixel.X;
offsety = P0.Y - curPixel.Y;
//await Console.Out.WriteLineAsync($"移动后的差异:{offsetx},{offsety}");
if (Math.Abs(offsetx) < 1 && Math.Abs(offsetx) < 1)
{
IsFinish = true;
break;
}
}
if (IsFinish)
{
Vector p0 = Vector.Build.Dense(new double[] { SelectCalibration.CenterPoint.X, SelectCalibration.CenterPoint.Y });
Vector p1 = Vector.Build.Dense(new double[] { RobotU.X, RobotU.Y });
ToolCoord toolCoord = new ToolCoord();
double u1 = SelectCalibration.CenterPoint.U;
double u2 = RobotU.U;
if (Robot.Brand== Enums.RobotBrand.Schneider)
{
u1 *= -1;
u2 *= -1;
}
toolCoord.ComputeTool(p0, p1, u1, u2);
if (Tool == null)
{
Tool = new RobotTool();
}
/*double toolx= toolCoord.X;
if (Robot.Brand == Enums.RobotBrand.Schneider)
{
toolx *= -1;
}*/
Tool.X = toolCoord.X;
Tool.Y = toolCoord.Y;
RobotCameraRotationMatrix = rst.Item1;
return new Tuple, double, double>(true, RobotCameraRotationMatrix, Tool.X, Tool.Y);
}
else
{
return new Tuple, double, double>(false, null, 0, 0);
}
}
///
/// J4移动机器人校准工具坐标
///
/// (结果,旋转矩阵,Tool.X,Tool.Y)
private async Task, double, double>> CalibToolForMobileJ4()
{
//移动机器人至中心位置
await Robot.CalibMotionAsync(SelectCalibration.CenterPoint, 0);
//计算相机与机器人坐标系的旋转矩阵
var rst = await MoveRobotThreePointComputCroodTrans(SelectCalibration.CenterPoint, ((float)SelectCalibration.Height) / 3);
SelectCalibration.PixelScaleX = rst.Item2;
SelectCalibration.PixelScaleY = rst.Item3;
var imagecenter = Camera.Grab();
PointF P0 = new PointF((float)(imagecenter.Width / 2), (float)(imagecenter.Height / 2)); //中心点像素坐标
//先找相机中心点,校准中心点坐标
bool IsFinish = false;
var curPixel = Photo();
var curpos = Robot.GetRobotPos();
for (int i = 0; i < 10; i++)
{
//计算需要移动的偏移量,目的是逼近中心点
double offsetx = (P0.X - curPixel.X) * rst.Item2;
double offsety = (P0.Y - curPixel.Y) * rst.Item3;
var pos = rst.Item1.Inverse() * Vector.Build.Dense(new double[] { offsetx, offsety });
curpos.X += (float)pos[0];
curpos.Y += (float)pos[1];
//机器人移动
await Robot.CalibMotionAsync(curpos, curpos.Z);
curPixel = Photo();
offsetx = P0.X - curPixel.X;
offsety = P0.Y - curPixel.Y;
//await Console.Out.WriteLineAsync($"移动后的差异:{offsetx},{offsety}");
if (Math.Abs(offsetx) < 1 && Math.Abs(offsetx) < 1)
{
IsFinish = true;
break;
}
}
if (IsFinish == true)
{
SelectCalibration.CenterPoint = Robot.GetRobotPos();
}
else
{
return new Tuple, double, double>(false, null, 0, 0);
}
RPoint RobotU = SelectCalibration.CenterPoint.Clone();
RobotU.U += (float)Angle;
//机器人U轴旋转
await Robot.CalibMotionAsync(RobotU, RobotU.Z);
//计算相机与机器人坐标系的旋转矩阵
var rst1 = await MoveRobotThreePointComputCroodTrans(RobotU, 1);
curPixel = Photo();
IsFinish = false;
for (int i = 0; i < 10; i++)
{
//计算需要移动的偏移量,目的是逼近中心点
double offsetx = (P0.X - curPixel.X) * rst1.Item2;
double offsety = (P0.Y - curPixel.Y) * rst1.Item3;
var pos = rst1.Item1.Inverse() * Vector.Build.Dense(new double[] { offsetx, offsety });
RobotU.X += (float)pos[0];
RobotU.Y += (float)pos[1];
//机器人移动
await Robot.CalibMotionAsync(RobotU, RobotU.Z);
curPixel = Photo();
offsetx = P0.X - curPixel.X;
offsety = P0.Y - curPixel.Y;
//await Console.Out.WriteLineAsync($"移动后的差异:{offsetx},{offsety}");
if (Math.Abs(offsetx) < 1 && Math.Abs(offsetx) < 1)
{
IsFinish = true;
break;
}
}
if (IsFinish)
{
Vector p0 = Vector.Build.Dense(new double[] { SelectCalibration.CenterPoint.X, SelectCalibration.CenterPoint.Y });
Vector p1 = Vector.Build.Dense(new double[] { RobotU.X, RobotU.Y });
ToolCoord toolCoord = new ToolCoord();
double u1 = SelectCalibration.CenterPoint.U;
double u2 = RobotU.U;
if (Robot.Brand == Enums.RobotBrand.Schneider)
{
u1 *= -1;
u2 *= -1;
}
toolCoord.ComputeTool(p0, p1, u1, u2);
if (Tool == null)
{
Tool = new RobotTool();
}
Tool.X = toolCoord.X;
Tool.Y = toolCoord.Y;
RobotCameraRotationMatrix = rst.Item1;
return new Tuple, double, double>(true, RobotCameraRotationMatrix, Tool.X, Tool.Y);
}
else
{
return new Tuple, double, double>(false, null, 0, 0);
}
}
#endregion
}
}