• 粽子产线的速度提升


    今天公司组织发福利,端午的福利,粽子、、、 也不是直接的发粽子。而是给你礼品卷,自己选择相应的礼品进行兑换。

    fd94494f22f999b2222a23fc6aab3e8.jpg

    931a278bdecf7d6c57723e460837438.jpg

    就是这么个东西,由于我们公司一直致力于做工业智能化,我就查了一下粽子的生产流程:
    我的个乖乖,从来没有关注过粽子的生产,今天以卡,基本上属于人工生产的方式,这怎么能忍。一个做智能制造的,怎么能忍受人工生产呢。所以,我就农了这篇文章,表达一下我的看法,当然了,实现全自动的可能性应该没有,应为预算太高,粽子一年就买几天,回本太慢了。

    image.png

    image.png
    基本上都属于人工,那么我们就来对粽子生产的的某些功能进行升级吧!

    粽子的分类以及抓取放到包装盒

    由于我这里没有粽子的产线,智能放一个大体上相同的

    image.png
    我们通过前端的视觉拍照,得到粽子的大小以及在传送带上的位置,把他发送给机器人,机器人根据得到的数据在后方将粽子抓取到相应的包装盒。

    前期标定

    我们通过手眼标定的方式将机器人和相机标定到同一个坐标系下面,具体操作不走如下:

    image.png

    1.我们首先在视觉相机下方找到九个点,平且求出9个点在相机坐标下的像素坐标值P(i);

    image.png
    2.传送带万千移动,我们记录一下传送带往前走了的编码的脉冲量M;

    3.将九个点的位置以机器人为坐标,记录下9个点的机器人坐标数据q(i);

    image.png

    我们通过机器人端的开发包建立随动坐标,将我们的数据传入到随动坐标中;

    视觉这块,我们将的到的机械的坐标和视觉的坐标合二为一,通过halcon9点标定的方式来进行一个标定;

    
    *图像坐标
    area_center(SortedRegions,Area,Row,Column) %
    Column_robot := [275,225,170,280,230,180,295,240,190]
    
    *机器人9点的列坐标
    Row_robot := [55,50,45,5,0,-5,-50,-50,-50]
    *机器人9点的行坐标
    vector_to_hom_mat2d(Row,Column,Row_robot,Column_robot,HomMat2D)
    *求解变换矩阵,HomMat2D是图像坐标和机械手坐标之间的关系
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    `affine_trans_point_2d(HomMat2D,Row2,Column2,Qx,Qy)’

    '*由像素坐标和标定方式求出机器人基础坐标系中的坐标 `

    视觉程序

    我们首先以粽子的原图作为模型,通过模型识别定位

    示例如下:

    image.png

    * ------------------------------------------------------------------------------------------------
    * This example program uses shape-based matching to align ROIs for the measure
    * tool, which then inspects individual razor blades.
    * The program can be run in two modes: (1) with the full affine transformation
    *                                                                (2) using translate_measure
    * Modify the next line to switch between the modes.
    USING_TRANSLATE_MEASURE := 0
    * ------------------------------------------------------------------------------------------------
    * general configuration of HDevelop
    dev_update_window ('off')
    * image acquisition and window size
    read_image (ModelImage, 'razors1')
    get_image_pointer1 (ModelImage, Pointer, Type, Width, Height)
    dev_close_window ()
    dev_open_window (0, 0, Width, Height, 'white', WindowHandle)
    dev_set_part (0, 0, Height - 1, Width - 1)
    dev_display (ModelImage)
    * colors and other settings for the visualization
    dev_set_color ('cyan')
    dev_set_draw ('margin')
    dev_set_line_width (2)
    stop ()
    * -------------------  start of the application  ----------------
    * -> select the model object
    Row1 := 46
    Column1 := 57
    Row2 := 79
    Column2 := 94
    gen_rectangle1 (ROIPart1, Row1, Column1, Row2, Column2)
    gen_rectangle1 (ROIPart2, Row1 + 364, Column1 + 13, Row2 + 364, Column2 + 13)
    union2 (ROIPart1, ROIPart2, ModelROI)
    area_center (ModelROI, Area, CenterROIRow, CenterROIColumn)
    dev_display (ModelImage)
    dev_display (ModelROI)
    stop ()
    * -> create the model
    reduce_domain (ModelImage, ModelROI, ImageROI)
    create_shape_model (ImageROI, 4, 0, 0, 'auto', 'none', 'use_polarity', 30, 10, ModelID)
    inspect_shape_model (ImageROI, ShapeModelImage, ShapeModelRegion, 1, 30)
    get_shape_model_contours (ShapeModel, ModelID, 1)
    dev_clear_window ()
    dev_set_color ('blue')
    dev_display (ShapeModelRegion)
    stop ()
    * step 1: create variables describing  the measurement ROIs and display them
    Rect1Row := 244
    Rect1Col := 73
    DistColRect1Rect2 := 17
    Rect2Row := Rect1Row
    Rect2Col := Rect1Col + DistColRect1Rect2
    RectPhi := rad(90)
    RectLength1 := 122
    RectLength2 := 2
    gen_rectangle2 (MeasureROI1, Rect1Row, Rect1Col, RectPhi, RectLength1, RectLength2)
    gen_rectangle2 (MeasureROI2, Rect2Row, Rect2Col, RectPhi, RectLength1, RectLength2)
    dev_display (ModelImage)
    dev_set_color ('yellow')
    dev_display (MeasureROI1)
    dev_display (MeasureROI2)
    * translate measurement ROIs to lie on XLD model (without clipping!)
    get_system ('clip_region', OriginalClipRegion)
    set_system ('clip_region', 'false')
    move_region (MeasureROI1, MeasureROI1Ref, -CenterROIRow, -CenterROIColumn)
    move_region (MeasureROI2, MeasureROI2Ref, -CenterROIRow, -CenterROIColumn)
    set_system ('clip_region', OriginalClipRegion)
    DistRect1CenterRow := Rect1Row - CenterROIRow
    DistRect1CenterCol := Rect1Col - CenterROIColumn
    DistRect2CenterRow := Rect2Row - CenterROIRow
    DistRect2CenterCol := Rect2Col - CenterROIColumn
    if (USING_TRANSLATE_MEASURE != 0)
        * -> measure objects are created only once in advance and then translated later
        gen_measure_rectangle2 (Rect1Row, Rect1Col, RectPhi, RectLength1, RectLength2, Width, Height, 'bilinear', MeasureHandle1)
        gen_measure_rectangle2 (Rect2Row, Rect2Col, RectPhi, RectLength1, RectLength2, Width, Height, 'bilinear', MeasureHandle2)
    endif
    stop ()
    * step 2: find the objects in another image
    read_image (SearchImage, 'razors2')
    dev_display (SearchImage)
    find_shape_model (SearchImage, ModelID, 0, 0, 0.8, 0, 0.5, 'least_squares', 0, 0.7, RowCheck, ColumnCheck, AngleCheck, Score)
    if (|Score| > 0)
        for i := 0 to |Score| - 1 by 1
            * step 3: determine the affine transformation
            vector_angle_to_rigid (0, 0, 0, RowCheck[i], ColumnCheck[i], AngleCheck[i], MovementOfObject)
            affine_trans_contour_xld (ShapeModel, ModelAtNewPosition, MovementOfObject)
            dev_display (ModelAtNewPosition)
            * step 4: measure width and distance of the teeth
            * -> display the moved ROIs
            affine_trans_region (MeasureROI1Ref, MeasureROI1AtNewPosition, MovementOfObject, 'constant')
            affine_trans_region (MeasureROI2Ref, MeasureROI2AtNewPosition, MovementOfObject, 'constant')
            dev_display (MeasureROI1AtNewPosition)
            dev_display (MeasureROI2AtNewPosition)
            affine_trans_pixel (MovementOfObject, DistRect1CenterRow, DistRect1CenterCol, Rect1RowCheck, Rect1ColCheck)
            affine_trans_pixel (MovementOfObject, DistRect2CenterRow, DistRect2CenterCol, Rect2RowCheck, Rect2ColCheck)
            if (USING_TRANSLATE_MEASURE != 0)
                * -> translate the already created measure objects
                translate_measure (MeasureHandle1, Rect1RowCheck, Rect1ColCheck)
                translate_measure (MeasureHandle2, Rect2RowCheck, Rect2ColCheck)
                measure_pairs (SearchImage, MeasureHandle1, 2, 25, 'negative', 'all', RowEdge11, ColEdge11, Amp11, RowEdge21, ColEdge21, Amp21, Width1, Distance1)
                measure_pairs (SearchImage, MeasureHandle2, 2, 25, 'negative', 'all', RowEdge12, ColEdge12, Amp12, RowEdge22, ColEdge22, Amp22, Width2, Distance2)
            else
                * -> create new measure objects and destroy them after the measurement
                RectPhiCheck := RectPhi + AngleCheck[i]
                gen_measure_rectangle2 (Rect1RowCheck, Rect1ColCheck, RectPhiCheck, RectLength1, RectLength2, Width, Height, 'bilinear', MeasureHandle1)
                gen_measure_rectangle2 (Rect2RowCheck, Rect2ColCheck, RectPhiCheck, RectLength1, RectLength2, Width, Height, 'bilinear', MeasureHandle2)
                * step 5: perform the measurement
                measure_pairs (SearchImage, MeasureHandle1, 2, 25, 'negative', 'all', RowEdge11, ColEdge11, Amp11, RowEdge21, ColEdge21, Amp21, Width1, Distance1)
                measure_pairs (SearchImage, MeasureHandle2, 2, 25, 'negative', 'all', RowEdge12, ColEdge12, Amp12, RowEdge22, ColEdge22, Amp22, Width2, Distance2)
                close_measure (MeasureHandle1)
                close_measure (MeasureHandle2)
            endif
            * step 6: check for too short or missing teeth
            NumberTeeth1 := |Width1|
            NumberTeeth2 := |Width2|
            dev_set_color ('red')
            if (NumberTeeth1 < 37)
                for j := 0 to NumberTeeth1 - 2 by 1
                    if (Distance1[j] > 4.0)
                        RowFault := round(0.5 * (RowEdge11[j + 1] + RowEdge21[j]))
                        ColFault := round(0.5 * (ColEdge11[j + 1] + ColEdge21[j]))
                        disp_rectangle2 (WindowHandle, RowFault, ColFault, 0, 4, 4)
                        dev_open_window (0, Width + 20, 80, 80, 'black', WindowHandleZoom)
                        dev_set_part (RowFault - 10, ColFault - 10, RowFault + 10, ColFault + 10)
                        dev_display (SearchImage)
                        disp_rectangle2 (WindowHandleZoom, RowFault, ColFault, 0, 4, 4)
                        stop ()
                        dev_close_window ()
                        dev_set_part (0, 0, Height - 1, Width - 1)
                    endif
                endfor
            endif
            if (NumberTeeth2 < 37)
                for j := 0 to NumberTeeth2 - 2 by 1
                    if (Distance2[j] > 4.0)
                        RowFault := round(0.5 * (RowEdge12[j + 1] + RowEdge22[j]))
                        ColFault := round(0.5 * (ColEdge12[j + 1] + ColEdge22[j]))
                        disp_rectangle2 (WindowHandle, RowFault, ColFault, 0, 4, 4)
                        dev_open_window (0, Width + 20, 80, 80, 'black', WindowHandleZoom)
                        dev_set_part (RowFault - 10, ColFault - 10, RowFault + 10, ColFault + 10)
                        dev_display (SearchImage)
                        disp_rectangle2 (WindowHandleZoom, RowFault, ColFault, 0, 4, 4)
                        stop ()
                        dev_close_window ()
                        dev_set_part (0, 0, Height - 1, Width - 1)
                    endif
                endfor
            endif
            dev_set_color ('yellow')
            stop ()
        endfor
    endif
    * -------------------  end of the application  -----------------
    * clean up
    if (USING_TRANSLATE_MEASURE != 0)
        close_measure (MeasureHandle1)
        close_measure (MeasureHandle2)
    endif
    dev_update_window ('on')
    clear_shape_model (ModelID)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158

    机器人配合

    在我们做完酒店标定以后,机器人只需要将视觉传过来的坐标带入到随动坐标系中,这样就能够得到准确的随动坐标。

    结束语

    本次我们提升了包装的速率,后续我们将对整个产线都实行自动化的功能升级;

  • 相关阅读:
    【Vue】vuex 求和案例
    【arduino】I/O端口操作
    线性回归模型
    云计算到底什么,十个问答告诉您
    (最新版2022版)剑指offer之队列 & 栈题解
    cmakelist中查找boost和eigen3
    初步认识 Web Components 并实现一个按钮
    PE文件解析(5):重定位表详解
    C/C++ 使用 define 实现运行时函数是在哪个文件哪个函数被调用
    同一份数据全域共享,HashData UnionStore实时性背后的故事
  • 原文地址:https://blog.csdn.net/ashjc/article/details/124942962