Skip to content

Copper Coil Position Detection and Dimension Measurement

Project Introduction

Project Background

Using pan-tilt sensors to capture images, detect the front, back, left, right and height position of copper foil rolls that need to be packaged into boxes on iron pallets, providing guidance for robotic arm gripping, while reading the QR code information on the product to match the wooden box specifications for copper foil; Secondly, detect wooden box specifications and their left and right positions on the trolley to verify the box specifications, while providing position guidance information for robotic arm to grip copper foil into boxes.

Local Image

Camera Selection

SICK Pan-tilt Line Scan

Detection Requirements

X-axis accuracy ≤ 0.025mm
Y-axis accuracy ≤ 0.03mm
Measurement cycle ≤ 2s

Solution

AI-Vision software processes 3D point clouds, first using Blob tool for copper coil positioning, outputting copper coil position information, then using cylinder tool to fit cylinders for volume calculation.

Design Concept

Local Image

Execution Result Display

  • Project result display:

    Local Image

  • HMI result display:

    Local Image

Project Process

I. Initialization

  1. Select Lua Script Language tool, initialize global variables, create CSV files to receive data.
  • Concatenate header strings, save initialization CSV files

Experience

.. Used for string concatenation

part1 = "Hello, "
part2 = "world!"
result = part1 .. part2
print(result) # Output: Hello, world!

, as separator, split each data item

lua
-- Initialize global variables
SetIntVariable('CurrentTime',0)


write = ''

-- Check file, if current file does not exist, generate file
if FileExists("./H.csv") == false then  
    write = write .. 'Time,'  
    for i = 1,15,1 do     
        write = write .. 'h' .. i .. ","
    end
    write = write .. '\n'
    -- "\n" indicates line break
end
-- Write current time to first column of each row
write = write .. os.date("%Y_%m_%d %H:%M;%S") .. ","  
-- Write the content to CSV file
WriteToFile("./H.csv",write)     
  
-- Generate string for concatenation 
write = ''
if FileExists("./Position.csv") == false then  
    write = write .. 'Time,'  
    for i = 1,15,1 do     
        write = write .. 'x' .. i .. ","
        write = write .. 'y' .. i .. ","
        write = write .. 'z' .. i .. ","
        write = write .. ','
    end
    write = write .. '\n'
end
-- Write current time to first column of each row
write = write .. os.date("%Y_%m_%d %H:%M;%S") .. ","    
-- Write the content to CSV file
WriteToFile("./Position.csv",write)
  1. Select Load Point Cloud tool to obtain point cloud.

II. Preprocessing

Local Image

  1. Select 3D Transform tool, rotate image 90 degrees in reverse direction around x-axis.

  2. Select 3D Crop tool, cut the cylinder and output to IM1.

Local Image

  1. Select 3D Downsample tool, reduce number of points in point cloud for easier subsequent operations.

  2. Select 3D Outlier Filter tool, filter out noise points.

Local Image

III. Cylinder Height and Position Measurement

  1. Select 3D Blob tool, segment 15 cylinders.

Local Image

  1. Select Lua Script, bind blob position variables in operator variables from previous step, write Lua script to save cylinder positions to file.

  2. Select 3D Cylinder tool, fit copper coils into cylinders

Local Image

IV. Data Saving

Select Lua Script, bind operator variables output from previous step (two top coordinates of cylinder), calculate dimension information and save to file.

  • Concatenate fitted cylinder dimension information to string and save string to global variable

  • Save individual cylinder dimension information to global variable

Experience

string.format is used for formatting strings %.nf formats floating-point numbers to n decimal places.

pi = 3.14159 str = string.format("Pi is approximately %.3f", pi) print(str) -- Output: Pi is approximately 3.141

lua
write = ""

write = write .. string.format("%.3f, %.3f, %.3f, %.3f, %.3f, %.3f, %.3f, %.3f, %.3f, %.3f, %.3f, %.3f, %.3f, %.3f, %.3f,"
    ,math.abs(Circle1.Bottom.X - Circle1.Top.X),math.abs(Circle2.Bottom.X - Circle2.Top.X),
    math.abs(Circle3.Bottom.X - Circle3.Top.X),math.abs(Circle4.Bottom.X - Circle3.Top.X),
    math.abs(Circle3.Bottom.X - Circle5.Top.X),math.abs(Circle6.Bottom.X - Circle3.Top.X),
    math.abs(Circle3.Bottom.X - Circle7.Top.X),math.abs(Circle8.Bottom.X - Circle3.Top.X),
    math.abs(Circle3.Bottom.X - Circle9.Top.X),math.abs(Circle10.Bottom.X - Circle3.Top.X),
    math.abs(Circle3.Bottom.X - Circle11.Top.X),math.abs(Circle12.Bottom.X - Circle3.Top.X),
    math.abs(Circle3.Bottom.X - Circle13.Top.X),math.abs(Circle14.Bottom.X - Circle3.Top.X),
    math.abs(Circle3.Bottom.X - Circle15.Top.X))


SetFloatVariable("h" .. "1" ,math.floor(1000*math.abs(Circle1.Bottom.X - Circle1.Top.X))/1000)
SetFloatVariable("h" .. "2" ,math.floor(1000*math.abs(Circle2.Bottom.X - Circle2.Top.X))/1000)
SetFloatVariable("h" .. "3" ,math.floor(1000*math.abs(Circle3.Bottom.X - Circle3.Top.X))/1000)
SetFloatVariable("h" .. "4" ,math.floor(1000*math.abs(Circle4.Bottom.X - Circle4.Top.X))/1000)
SetFloatVariable("h" .. "5" ,math.floor(1000*math.abs(Circle5.Bottom.X - Circle5.Top.X))/1000)
SetFloatVariable("h" .. "6" ,math.floor(1000*math.abs(Circle6.Bottom.X - Circle6.Top.X))/1000)
SetFloatVariable("h" .. "7" ,math.floor(1000*math.abs(Circle7.Bottom.X - Circle7.Top.X))/1000)
SetFloatVariable("h" .. "8" ,math.floor(1000*math.abs(Circle8.Bottom.X - Circle8.Top.X))/1000)
SetFloatVariable("h" .. "9" ,math.floor(1000*math.abs(Circle9.Bottom.X - Circle9.Top.X))/1000)
SetFloatVariable("h" .. "10" ,math.floor(1000*math.abs(Circle10.Bottom.X - Circle10.Top.X))/1000)
SetFloatVariable("h" .. "11" ,math.floor(1000*math.abs(Circle11.Bottom.X - Circle11.Top.X))/1000)
SetFloatVariable("h" .. "12" ,math.floor(1000*math.abs(Circle12.Bottom.X - Circle12.Top.X))/1000)
SetFloatVariable("h" .. "13" ,math.floor(1000*math.abs(Circle13.Bottom.X - Circle13.Top.X))/1000)
SetFloatVariable("h" .. "14" ,math.floor(1000*math.abs(Circle14.Bottom.X - Circle14.Top.X))/1000)
SetFloatVariable("h" .. "15" ,math.floor(1000*math.abs(Circle15.Bottom.X - Circle15.Top.X))/1000)

write = write .. "\n"
-- Write data to table
WriteToFile("./H.csv",write)

AI-Vision, Making 3D Measurement Easier