Skip to content

胶条拐点高度及平面度检测

项目简介

项目背景

随着汽车厂商对轮胎质量愈来愈严格的要求,轮胎制造厂家迫切需要速度快、操作简单、精度高的测量装置,可以在线使用,减少停机时间停机时间,可以最大程度地避免错误不良品的发生。

本地图片

相机选型

LMI激光线扫相机 Gocator2350

检测要求

测量精度 ≤ 0.03mm
测量重复性 ≤ 0.02mm
测量周期 ≤ 3s

解决方案

AI-Vision同时可以处理轮廓与点云,通过点云图找到拐点位置从而计算体积,测量高度;提取截面轮廓进行截面积测量。

设计思路

本地图片

执行效果展示

  • 工程结果展示:

    本地图片

    本地图片

  • HMI结果展示:

    本地图片

项目流程

一、初始化

[00] 选择Lua脚本语言工具,全局变量初始化,创建待接收数据的csv文件。

lua
--初始化全局变量
SetVariable("pinCount" , 0)
SetVariable("pinCount1" , 0)
SetVariable("HeightSave" , "")
SetVariable("PlaneSave" , "")

--生成用于拼接的字符串
write = ""

--如果该文件不存在,生成该文件
if FileSize("./Height.csv") <= 0 then  
    
    --生成表头
    write = write .. "Time,"  
    for i = 1,30,1 do    
        write = write .. "h" .. i
        write = write .. ","
    end
    write = write .. "OK/NG" .. "\n"   
end

--将时间拼接入表头中
write = write .. os.date("%Y_%m_%d %H:%M;%S") .. ","  
--将表头写入文件中
fprint("./Height.csv",write)

--生成用于拼接的字符串
write = ""

--如果该文件不存在,生成该文件
if FileSize("./Plane.csv") <= 0 then  
    --生成表头
    write = write .. "Time," 
    for i = 1,30,1 do    
        write = write .. "Plane" .. i
        write = write .. ","
    end
    write = write .. "OK/NG" .. "\n"   
end
--将时间拼接入表头中
write = write .. os.date("%Y_%m_%d %H:%M;%S") .. ","   
--将表头写入文件中
fprint("./Plane.csv",write)

[01] 选择加载点云工具,获取点云。

二、预处理

  • 图像初定位

    [02-03] 选择3D方形探针工具和3D位置调整工具,通过选取底面上边坐标进行x,y方向位置的调整。

  • 拟合平面

    [04-12] 选择3D区域工具,选取底面19块不同的区域进行拟合平面。

    本地图片

    [13] 选择3D平面工具,通过存入寄存器中的区域信息来拟合平面,并将拟合出来的平面作为0平面。

    本地图片

三、高度测量

  • 图像预处理

    [14] 选择3D裁切工具,将图像复制到IM1上便于后续操作。

  • 循环测量

    [15]选择切换配方工具,将配方切换至Height。

    本地图片

    [16]选择标记工具,设置循环起点。

    [17]选择lua脚本语言工具,找到当前待测点的坐标并写入寄存器中。

    lua
    --读取当前循环数
    count = GetVariable("pinCount")
    --根据当前循环数读取配方中指定序号的数据
    Result = GetRecipeSet(count)
    
    --将配方中的数据赋值给x,y,z
    x = Result.PinPositionX
    y = Result.PinPositionY
    z = Result.PinHight
    
    --计算得出待测区域范围
    sx = x-0.5 
    sy = y-0.5
    sz = z-0.5
    
    ex = x+0.5 
    ey = y+0.5
    ez = z+0.5
    
    --将待测区域输出到寄存器中用于后续调用
    PushBox(sx,sy,sz,ex,ey,ez)
    
    --将待测区域的Box显示在IM1上
    DrawBox(1,sx,sy,sz,ex,ey,ez)

    [18]选择3D高度工具,从寄存器读取坐标测量高度。

    本地图片

    [19]选择lua脚本语言工具,保存测量内容,并设定循环次数。

    lua
    
    --获取当前循环数赋值给count(因为已经测量过一次高度,所以当前循环数需要+1)
    count = GetVariable("pinCount")+1
    
    --获取高度值
    height = GetMeasure(0)
    
    --获取之前存储的高度
    write = GetVariable("HeightSave")
    
    --将此次测量的高度拼接入write字符串中
    write = write ..  string.format("%.3f", height) .. ","
    
    --保存当前已测量高度至全局变量中
    SetVariable("HeightSave" , write)
    
    --保存当前测量的高度至全局变量中
    SetVariable("Height" .. tointeger(count) , tointeger(1000*height)/1000 )
    
    --保存当前循环数至全局变量中
    SetVariable("pinCount",count)
    
    
    --判断循环
    if count < 30 then
      Jump("Start")
    elseif count == 30 then
      Jump("End")
    end

    [20]选择标记工具,设置循环终点。

    [21]选择lua脚本语言工具,将结果写入csv文件中。

    lua
    -- 高度判断
    Judge = true
    for i = 0,29,1 do
        -- 获取指定序号的配方值
        currentPin = GetRecipeSet(i)
        -- 对测量结果进行判断
        if currentPin.PinHight -0.3 > GetVariable("Height" .. i+1) or GetVariable("Height" .. i+1) > currentPin.PinHight +0.1 then
          Judge = false
          println(currentPin.PinHight -0.3)
          println(GetVariable("Height" .. i+1) )
          println(currentPin.PinHight +0.1)
          print(i)
          break
        end
    end
    
    -- 对结果进行判断,根据判断的结果拼接数据至字符串中
    if Judge == true then
        write = GetVariable("HeightSave") .. "OK" .. "\n"
        DrawOverlay(1,30,-13,35,20,"green","检测结果:" .. "OK")
    elseif Judge == false then
        write = GetVariable("HeightSave") .. "NG" .. "\n"
        DrawOverlay(1,30,-13,35,20,"red","检测结果:" .. "NG")
    end
    
    -- 保存csv文件
    fprint("./Height.csv",write)

四、高度测量

  • 图像预处理

    [22]选择3D裁切工具,将图像复制到IM2上便于后续操作。

  • 循环测量

    [23]选择切换配方工具,将配方切换至Plane。

    本地图片

    [24]选择标记工具,设置循环起点。

    [25]选择lua脚本语言工具,找到当前待测点的坐标并写入寄存器中。

    lua
    --获取当前循环数
    count = GetVariable("pinCount1")
    
    --获取指定序号的配方值
    Result = GetRecipeSet(count)
    
    --将配方值赋值给x,y,z
    x = Result.PinPositionX
    y = Result.PinPositionY
    z = Result.PinHight
    
    --计算得出待测区域范围
    sx = x-0.5 
    sy = y-0.5
    sz = z-1
    
    ex = x+0.5 
    ey = y+0.5
    ez = z+1
    
    --将待测区域输出到寄存器中用于后续调用
    PushBox(sx,sy,sz,ex,ey,ez)
    
    --将待测区域的Box显示在IM2上
    DrawBox(2,sx,sy,sz,ex,ey,ez)

    [26]选择3D平面度工具,从寄存器读取坐标测量平面度。

    [27]选择lua脚本语言工具,保存测量内容,并设定循环次数。

    lua
    --获取当前循环数赋值给count(因为已经测量过一次平面度,所以当前循环数需要+1)
    count = GetVariable("pinCount1")+1
    
    --获取之前存储的高度值
    write = GetVariable("PlaneSave")
    --获取当前测量的平面度
    plane = GetMeasure(0)
    --将当前测量的平面度结果拼接入存储已经测量的平面度的字符串中
    write = write ..  string.format("%.3f", plane) .. ","
    
    --更新已经测量的平面度至全局变量中
    SetVariable("PlaneSave" , write)
    --存储当前测量的平面度至全局变量中
    SetVariable("Plane" .. tointeger(count) ,  tointeger(1000*plane)/1000 )
    --更新当前循环数至全局变量中
    SetVariable("pinCount1",count)
    
    --判断循环
    if count < 30 then
        Jump("Start1")
    else
        Jump("End1")
    end

    [28]选择标记工具,设置循环终点。

    [29]选择lua脚本语言工具,将结果写入csv文件中。

    lua
    -- 平面度判断
    Judge = true
    for i = 1,30,1 do
        if 0.08 < GetVariable("Plane" .. i) or GetVariable("Plane" .. i) < 0 then
          Judge = false
          break
        end
    end
    
    -- 对结果进行判断,根据判断的结果拼接数据至字符串中
    if Judge == true then
        write = GetVariable("PlaneSave") .. "OK" .. "\n"
        DrawOverlay(2,30,-13,35,20,"green","检测结果:" .. "OK")
    elseif Judge == false then
        write = GetVariable("PlaneSave") .. "NG" .. "\n"
        DrawOverlay(2,30,-13,35,20,"red","检测结果:" .. "NG")
    end
    
    -- 保存csv文件
    fprint("./Plane.csv",write)

AI-Vision,让3D测量更简单