public static Matrix4x4 GetRelativeTransform(MRecipe recipe, MRecipeBaseNode recipeNode) { if (recipeNode is MRecipePlate plate) { return(GetRelativeTransform(plate)); } else if (recipeNode is MRecipeDevice device) { return(GetRelativeTransform(recipe, device)); } else if (recipeNode is MRecipeDeviceLayer layer) { return(GetRelativeTransform(recipe, layer)); } return(GeometricArithmeticModule.GetDefaultTransformationMatrix()); }
public virtual void AddRecipeNode(MRecipe recipe, MRecipeBaseNode recipeNode) { if (recipe == null || recipeNode == null) { return; } var extents = GeometryExtents <double> .CreateDefaultDouble(); MRecipe.BeginGetAllLayers_Parallel(recipeNode, (layer) => { extents = GeometryExtents <double> .Combine( extents, AddLayer(recipe, layer) ); }); // calculate size of fiducial relative to the node var fiducialSize = 0.025 * extents.Hypotenuse; // generate fiducial pattern GenerateFiducialPattern(fiducialSize); // get node's transform var parentsTransform = (recipeNode.Parent as MRecipeBaseNode)?.TransformInfo.ToMatrix4x4() ?? GeometricArithmeticModule.GetDefaultTransformationMatrix(); // render fiducials in parent's reference frame foreach (var fiducial in recipeNode.Fiducials) { var transform = GeometricArithmeticModule.CombineTransformations( GeometricArithmeticModule.GetTranslationTransformationMatrix( fiducial.X, fiducial.Y, fiducial.Z ), parentsTransform ); foreach (var geometry in _fiducialPattern) { var clone = (IMarkGeometry)geometry.Clone(); clone.Transform(transform); AddDefault(clone, FiducialColor); } } }
public async Task <Matrix4x4> GetAbsoluteTransform(MRecipeBaseNode node, Matrix4x4 parentTransform, CancellationToken ctIn) { if (parentTransform == null) { parentTransform = GeometricArithmeticModule.GetDefaultTransformationMatrix(); } // node has no fiducials, hences it's position // is relative to its parent if (node.Fiducials.Count <= 0) { return(GeometricArithmeticModule.CombineTransformations( parentTransform, node.TransformInfo.ToMatrix4x4() )); } // attempt to retrieve tasksHandler; handles process specific stage motion // camera, find n centre, etc. IProcessConfigurationTasksHandler tasksHandler = GetClosestConfigurationTasksHandler(node); if (tasksHandler == null) { throw new Exception("Failed to retrieve a Task Handler for the closest process mode"); } // buffer to store estimated and measured fiducials var estimatedPoints = new List <MarkGeometryPoint>(); var measuredPoints = new List <MarkGeometryPoint>(); for (int i = 0; i < node.Fiducials.Count; i++) { var estimatedPosition = new MarkGeometryPoint( node.Fiducials[i].X, node.Fiducials[i].Y ); // transform to parents space estimatedPosition.Transform(parentTransform); estimatedPoints.Add(estimatedPosition); // move camera to position await tasksHandler.FocusCameraAtXY( estimatedPosition.X, estimatedPosition.Y, ctIn ); // get measured position var results = await tasksHandler.TakeMeasurement(); // handle results not found if (!results.Found) { throw new Exception("Failed to find fiducial"); } // store measured point measuredPoints.Add( new MarkGeometryPoint( results.Position.X, results.Position.Y ) ); } return(GeometricArithmeticModule.CombineTransformations( parentTransform, MAlignmentCalculator.GetAlignmentTransform( node.AlignmentType, estimatedPoints, measuredPoints ) )); }