Two Robots One Part
Program Example 3.1
Example Type:
Robots & 1 Physical Part Type - Motion in PF_Robot callback - Picking in a specific order
Configuration
- Number of Robots: 2
- Number of Feeders: 1
- Number of Parts Types on the Feeder: 1
- Number of Placement Positions: 2
- Camera Orientation: Fixed Downward Camera
Description
There are two robots and one feeder. There is only 1 physical part type. Because each robot has its own camera calibration, there are two logical Parts - Part 1 for Robot 1 and Part 2 for Robot 2.
The robots will take turns picking from the feeder. The pick order matters for this application. The alternating pick order is accomplished with "PF_ActivePart".
Robot motion is performed inside the PF_Robot callback.
This example does not have parallel processing of the feeder and robot motion. The code is simple but not efficient. Each robot has a point labeled "park" and a point labeled "place". The key concept of this example is the PF_Robot callback return value "PF_CALLBACKRESTARTACTIVEPART".
This return value allows multiple robots to use the same feeder without the potential of the part coordinates in both Part’s queues. The return value forces a new image to be acquired for only the PF_ActivePart and only the PF_ActivePart queue is loaded.
Sample Code
Main.prg
Function Main
Robot 1
Motor On
Power High
Speed 50
Accel 50, 50
Jump Park
Robot 2
Motor On
Power High
Speed 50
Accel 50, 50
Jump Park
PF_Start 1, 2
Fend
PartFeeding.prg
Function PF_Robot(PartID As Integer) As Integer
If PF_QueLen(PartID) > 0 Then
Select PartID
Case 1
Robot 1
P0 = PF_QueGet(1)
PF_QueRemove (1)
Jump P0 /R
On rbt1Gripper
Wait 0.25
Jump Place
Off rbt1Gripper
Wait 0.25
PF_ActivePart 2
Case 2
Robot 2
P0 = PF_QueGet(2)
PF_QueRemove (2)
Jump P0 /L
On rbt2Gripper
Wait 0.25
Jump Place
Off rbt2Gripper
Wait 0.25
PF_ActivePart 1
Send
EndIf
PF_Robot = PF_CALLBACK_RESTART_ACTIVEPART
Fend
Program Example 3.2
Example Type:
2 Robots & 1 Physical Part Type - motion in separate tasks - pick order does not matter - Picking in a specific order
Configuration
- Number of Robots: 2
- Number of Feeders: 1
- Number of Parts Types on the Feeder: 1
- Number of Placement Positions: 2
- Camera Orientation: Fixed Downward Camera
Description
There are two robots and one feeder. There is only 1 physical part type. Because each robot has its own camera calibration, there are two logical Parts - Part 1 for Robot 1 and Part 2 for Robot 2. Pick order does not matter - first come, first served.
What makes this example different is that vision is acquired for each part every cycle. This may be helpful if you are concerned that surrounding parts may be disturbed during pick up.
The PF_Robot callback return value "PF_CALLBACK_RESTART" will force vision to re-run for all parts and all part queues will be reloaded.
This method is not efficient but "PF_CALLBACKRESTART" can be useful in certain circumstances.
Sample Code
Main.prg
Function Main
Robot 1
Motor On
Power High
Speed 50
Accel 50, 50
Jump Park
Robot 2
Motor On
Power High
Speed 50
Accel 50, 50
Jump Park
MemOff PartsToPick
PF_Start 1, 2
Xqt Robot1PickPlace
Xqt Robot2PickPlace
Fend
Function Robot1PickPlace
Robot 1
Do
PF_AccessFeeder (1)
Wait MemSw(PartsToPick) = On
If PF_QueLen(1) > 0 Then
P0 = PF_QueGet(1)
PF_QueRemove (1)
Jump P0 /R
On 5
Wait 0.5
Jump Place ! D30; MemOff PartsToPick; PF_ReleaseFeeder 1 !
Off 5
Wait 0.25
Else
MemOff PartsToPick; PF_ReleaseFeeder 1
EndIf
Loop
Fend
Function Robot2PickPlace
Robot 2
Do
PF_AccessFeeder (1)
Wait MemSw(PartsToPick) = On
If PF_QueLen(2) > 0 Then
P0 = PF_QueGet(2)
PF_QueRemove (2)
Jump P0 /L
On 2
Wait 0.5
Jump Place ! D30; MemOff PartsToPick; PF_ReleaseFeeder 1 !
Off 2
Wait 0.25
Else
MemOff PartsToPick; PF_ReleaseFeeder 1
EndIf
Loop
Fend
PartFeeding.prg
Function PF_Robot(PartID As Integer) As Integer
MemOn PartsToPick
Wait MemSw(PartsToPick) = Off
PF_Robot = PF_CALLBACK_RESTART 'Force vision and vibration to refresh
Fend
Program Example 3.3
Example Type:
2 Robots & 1 Physical Part Type - motion in separate tasks - First Come, First Served - Simulated process delay
Configuration
- Number of Robots: 2
- Number of Feeders: 1
- Number of Parts Types on the Feeder: 1
- Number of Placement Positions: 2
- Camera Orientation: Fixed Downward Camera
Description
There are two robots and one feeder. There is only 1 physical part type. Because each robot has its own camera calibration, there are two logical Parts - Part 1 for Robot 1 and Part 2 for Robot 2. For this example, each robot has a variable process time (simulated by a random wait time).
Each robot is busy performing some other operation after picking up a part from the feeder.
Memory bits "Rbt1Complete" and "Rbt2Complete" are used to signal when the robot has finished picking a part from the feeder and is ready to pick up another part from the feeder. The PF_Robot callback will return the value "PF_CALLBACK_RESTART_ACTIVEPART" if the desired part (PF_ActivePart) is not the same as the current part (i.e., the other robot wants to pick up a part). This will prevent duplication of points in the robot queues.
A new image will be acquired for the PF_ActivePart and only the PF_ActivePart’s queue will be loaded. However, if the next part is the same as the current part (i.e., the same robot is going to pick from the feeder) then the PF_Robot callback return value will be "PF_CALLBACK_SUCCESS". PF_AccessFeeder and PF_ReleaseFeeder ensure that the robots will not collide when accessing the feeder.
Sample Code
Main.prg
Function Main
Robot 1
Motor On
Power High
Speed 50
Accel 50, 50
Jump Place
Robot 2
Motor On
Power High
Speed 50
Accel 50, 50
Jump Place
MemOff PartsToPick1
MemOff PartsToPick2
PF_Start 1, 2
Xqt Robot1PickPlace
Xqt Robot2PickPlace
Fend
Function Robot1PickPlace
Integer randomTime
Robot 1
MemOn Rbt1Complete
Do
Wait MemSw(PartsToPick1) = On
PF_AccessFeeder (1)
MemOff Rbt1Complete
P0 = PF_QueGet(1)
PF_QueRemove (1)
Jump P0 /R
On rbt1Gripper
Wait 0.25
Jump Place ! D30; MemOff PartsToPick1; PF_ReleaseFeeder 1 !
Off rbt1Gripper
Wait 0.25
'Test long process time - robot is doing something else
Randomize
randomTime = Int(Rnd(9)) + 1
Wait randomTime
MemOn Rbt1Complete
Loop
Fend
Function Robot2PickPlace
Integer randomTime
Robot 2
MemOn Rbt2Complete
Do
Wait MemSw(PartsToPick2) = On
PF_AccessFeeder (1)
MemOff Rbt2Complete
P0 = PF_QueGet(2)
PF_QueRemove (2)
Jump P0 /L
On rbt2Gripper
Wait 0.25
Jump Place ! D30; MemOff PartsToPick2; PF_ReleaseFeeder 1 !
Off rbt2Gripper
Wait 0.25
'Test long process time - robot is doing something else
Randomize
randomTime = Int(Rnd(9)) + 1
Wait randomTime
MemOn Rbt2Complete
Loop
Fend
PartFeeding.prg
Function PF_Robot(PartID As Integer) As Integer
Integer nextPart
Select PartID
Case 1
MemOn PartsToPick1
Wait MemSw(PartsToPick1) = Off
Case 2
MemOn PartsToPick2
Wait MemSw(PartsToPick2) = Off
Send
Wait MemSw(Rbt1Complete) = On Or MemSw(Rbt2Complete) = On
If MemSw(Rbt1Complete) = On Then
nextPart = 1
ElseIf MemSw(Rbt2Complete) = On Then
nextPart = 2
EndIf
PF_ActivePart nextPart
If nextPart = PartID Then
'Same part so no need to re-acquire an image and reload the queue
PF_Robot = PF_CALLBACK_SUCCESS
Else
'Restart from vision-
'Acquire image and load queue for only the Active Part
PF_Robot = PF_CALLBACK_RESTART_ACTIVEPART
EndIf
Fend