Custom Job Processor Logic using the Scripting Interface

158 views
Skip to first unread message

Simon K.

unread,
Mar 20, 2025, 9:38:14 PMMar 20
to OpenPnP
Hi everyone,
I am currently trying to figure out whether the following is possible.
We have a set up of two JEDEC trays on a machine and we would like to implement the following logic:

1. Pick a part from left tray (e.g. as TrayFeeder)
2. Align the Part on the bottom camera
3. Put the part into a test socket and run a test script (e.g. Python)
4a. If the test passed, place the part into the right tray (place locations from a pick and place file) mark part as placed
4b. If the test failed, put the part back where it came from ("takeBackPart") and mark part as don't place, so we can have another try
5. Feed to next part and go to 1.

I have interviewed the "Le Chat" GPT AI about it, and it always seems to suggest you could somehow add your own Python class implementation as Processor to OpenPNP, however looking at the Java code, I don't think that's possible.

class CustomReferenceProcessor(JobProcessor):
....

def runCustomProcessor(job): # Register the custom processor custom_processor = CustomReferenceProcessor() Configuration.get().addJobProcessor(custom_processor)

Before I try to go one way or the other, what do you think would be the best way to implement the desired behaviour? Is it possible at all?

Thanks a lot in advance and Best Regards

Jan

unread,
Mar 21, 2025, 6:59:10 PMMar 21
to ope...@googlegroups.com
Hi Simon!
I'd say no for a simple reason: scripts do not return anything and the
JobProcessor does not branch depending on a script result.
Picking, aligning and placing parts into a test socket is no problem.
Could be defined as a job with a lot of parts that are to be placed all
at the same location. Everything else would have to be done insight the
script, incl. testing and storing the parts somewhere based on the test
result. I don't think that the feeder logic itself could be used for
that because the take back feature will consider the part as good and
pick it on next round. So, it might actually be doable...

Jan

PS: If you feel, you'd need a new JobProcessor, I'd suggest to modify
the existing one. Adding new steps is not that difficult...
> --
> You received this message because you are subscribed to the Google
> Groups "OpenPnP" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to openpnp+u...@googlegroups.com
> <mailto:openpnp+u...@googlegroups.com>.
> To view this discussion visit https://groups.google.com/d/msgid/
> openpnp/79888f4b-b6df-4ffb-a704-146dc2403dbfn%40googlegroups.com
> <https://groups.google.com/d/msgid/openpnp/79888f4b-b6df-4ffb-
> a704-146dc2403dbfn%40googlegroups.com?utm_medium=email&utm_source=footer>.

Toby Dickenson

unread,
Mar 21, 2025, 7:50:06 PMMar 21
to ope...@googlegroups.com
On Fri, 21 Mar 2025 at 01:38, Simon K. <sk.ku...@gmail.com> wrote:
Hi everyone,
I am currently trying to figure out whether the following is possible.
We have a set up of two JEDEC trays on a machine and we would like to implement the following logic:

1. Pick a part from left tray (e.g. as TrayFeeder)
2. Align the Part on the bottom camera

So far this is sounding like a normal pick and place job....
 
3. Put the part into a test socket and run a test script (e.g. Python)

Vision.PartAlignment.After is a script that is run after alignment is complete. I dont see any problem in having that script take control of the machine movement to put the part into a test socket, then run a test. Note that openpnp scripts run in the same JVM as openpnp. If your script is python, this is running in Jython, and therefore there are limitations compared to a regular python script. Depending on the nature of your test it might make sense for your openpnp script to trigger something out of process. There are other script events that trigger during the cycle, but Vision.PartAlignment.After looks ok to me.
 
4a. If the test passed, place the part into the right tray (place locations from a pick and place file) mark part as placed

This is the normal place action
 
4b. If the test failed, put the part back where it came from ("takeBackPart") and mark part as don't place, so we can have another try
5. Feed to next part and go to 1.

I think this is a requirements bug. If take-back happened, it would return the failed part back to the original feeder. The part is pushed on the top of the stack, and the same part would be re-picked on the next cycle. 

If your Vision.PartAlignment.After script raises an exception and the placements have a "deferred" error handling policy then I expect openpnp would drop the part at your discard location then proceed to pick the next part.

Having failed parts returned to a tray feeder I think should be possible too, but you need the pick and take-back to occur on different feeders. The take-back feeder needs to be disabled, to ensure that the pick cycle doesnt pick parts from here. I think the take-back can work using lower-level APIs; your script needs to find the feeder object and call its takeBack method directly.

This sounds like an interesting example of openpnp scripting. Please let us know how it works out.
 
I have interviewed the "Le Chat" GPT AI about it, and it always seems to suggest you could somehow add your own Python class implementation as Processor to OpenPNP, however looking at the Java code, I don't think that's possible.

Nonsense as expected.

Simon K.

unread,
Mar 22, 2025, 3:40:04 AMMar 22
to OpenPnP
Thanks for the reply Jan!
Is it maybe possible to run takeBackPart and then immediately issue a "feed" command, so that the part that was taken back is not considered for future placement anymore?

Modifying the existing JobProcessor would also be okay, but I assume you are talking about modifying the Java code, correct? It is doable but for now I want to avoid creating my own fork of the software and have diverging branches in the future.

I guess in the end, it sounds doable one way or another, but I need to find "the best" way to achieve this with the given API and function hooks.

Simon K.

unread,
Mar 22, 2025, 3:57:45 AMMar 22
to OpenPnP
Thanks for the message!
From my limited experience, it looks like I have the following options to try:
a) Left Tray as Feeder, (Right Tray maybe also as a feeder), Tester as Board. Have a Job picking parts from left tray to tester and then intercepting the Post-Assembly hook to start the test and move the part to the correct location (back to left tray for failed or right tray for pass)

b) Left Tray as Feeder, Right Tray as board. Have a job picking parts from left tray to the right tray and intercepting the Vision.PartAlignment.After hook for running the script and determine if the placement continues or the part is taken back.

With option b) I am not sure if you can really "stop" the Job Processor from placing the part in the right tray if the test fails. I think raising an Exception might stop the Job, but I am not sure. So even in a fail situation (and taking the part back to the left tray), it would like to continue to want to place the part to the right tray after my script runs. I could just change the target location on the fly (I assume) but then the processor considers the part as placed (although its not present in the right tray).

I am currently evaluating what might be the way that least "abuses" the OpenPNP pick process and is likely to work well (e.g. Job pausing and other OpenPNP features still work). At some point I will have to just start trying something, when I have my setup completely ready.

Optionally I would like to not modify the entire OpenPNP instance, like I would by adding the hook scripts. So in case I use the machine for something else, I would need to remove the scripts from the directory so it doesn't want to stuff parts into a non-existing tester unit. I maybe thought it was possible to install hooks by running a script from the menu within OpenPNP, but not sure. Howver that is an optional goal that could maybe be solved with a custom configuration directory selected upon launch or something. (via System.getProperty("configDir"))

Jan

unread,
Mar 27, 2025, 6:41:24 AMMar 27
to ope...@googlegroups.com
Hi Simon!
I'd like to add some more points to the discussion (in arbitrary order):
- take back assumes, that the part is still "as bad" aligned as it was
picked. That's very likely not the case when you place the part in the
test adapter and pick it up from there.
- you might setup a job with two (or more) placements. The first picks a
part from the tray feeder and places it in the test adapter. The second
picks the part from the test adapter and places it somewhere. Both could
use vision alignment.
- In an after-placement-script you could toggle between pick for testing
and pick for post-test-processing by (re)enabling the respective placement.
- the post-test-processing could be a hand coded take back (IIRC the
JobProcessor does not support automatic take back) into any feeder (even
to the original feeder with the extra feed you suggested) or a place to
any location depending on the test result.
As Toby explained, you can modify the job on the fly because the
JobProcessor always processes the entire list of placements. (This might
require to switch Job order to Unsorted and manually prepare a job file.)
I'd love to hear on your progress. If this requirement is interesting
for others too (to have a dedicated test/program step as part of the
placement process) it might be worth adding the required UI and
JobProcessor step for it.

Jan
> <https://groups.google.com/d/msgid/>
> > openpnp/79888f4b-b6df-4ffb-a704-146dc2403dbfn%40googlegroups.com
> <http://40googlegroups.com>
> > <https://groups.google.com/d/msgid/openpnp/79888f4b-b6df-4ffb-
> <https://groups.google.com/d/msgid/openpnp/79888f4b-b6df-4ffb->
> > a704-146dc2403dbfn%40googlegroups.com?
> utm_medium=email&utm_source=footer <http://40googlegroups.com?
> utm_medium=email&utm_source=footer>>.
>
> --
> You received this message because you are subscribed to the Google
> Groups "OpenPnP" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to openpnp+u...@googlegroups.com
> <mailto:openpnp+u...@googlegroups.com>.
> To view this discussion visit https://groups.google.com/d/msgid/
> openpnp/3fc6ffd7-0d98-44bc-a618-9bae34231ca5n%40googlegroups.com
> <https://groups.google.com/d/msgid/openpnp/3fc6ffd7-0d98-44bc-
> a618-9bae34231ca5n%40googlegroups.com?utm_medium=email&utm_source=footer>.

apaydi...@gmail.com

unread,
Apr 24, 2025, 11:06:03 AMApr 24
to OpenPnP
Hi Simon,
I am currently working on the same concept.
OpenPnP has great vision and calibration capabilities.
I completed all items in Issues&Solutions and currently writing scripts to control all the movement via Python on top of the OpenPnp infrastructure.
It is in very early phase of proof of concept and my current test subject is 7mm*7mm QFN package and a socket.
The current flow as below.
1.) Make fiducial check on board to update the board and socket position.
2.) Pick a part from "Untested Part" tray and prerotate it according to board&socket orientation.
3.) Bottom vision checks the part offset&resudial rotation and then center&align the part.
4.) Place part into the socket.
5.) Move top camera over the part. I have not implemented yet but I am planning to check (somehow?) whether part is placed into socket properly via top vision before appling force on top of the part.
6.) Apply force on top of the part to get proper electrical contact. Still not implemented but I have an intention to design a second 3d printable head with presure sensor to control and apply similiar force for all parts.
7.) Do testing.(I have not done any real electrical test here yet).
8.) Based on the test results either discard part on discard location or placed it to "Good Part" tray.
9.) Increase part index by 1 and repeat all steps beginning Step 2.

I uploaded a video recording on youtube for your reference.
https://youtu.be/5RsHm_O6pFY

Best regards,
Emre

21 Mart 2025 Cuma tarihinde saat 04:38:14 UTC+3 itibarıyla sk.ku...@gmail.com şunları yazdı:

Simon K.

unread,
Apr 24, 2025, 12:46:28 PMApr 24
to OpenPnP
That is really impressive, well done!

Does the job run purely in the python script or are you using the regular job controls of openpnp and you just added some python script hooks to the sequence?

I am curious how you want to solve the top camera part. Not sure if there are any facilities that one can use for this in openpnp?

Best regards
Simon

Simon K.

unread,
Apr 24, 2025, 1:16:42 PMApr 24
to OpenPnP
Thanks for the reply Jan! Much appreciated
What do you consider to be "two placements"? I am still quite fresh to openpnp, but would you suggest having two boards, one of them is the target tray and the other one the testing unit?

I have done some first testing without any scripting by defining the source tray as a tray feeder and the target tray as a board. 
With some alignment jigs I have aligned the target tray using fiducials and now I can very well pick parts from source to target. 
Next will be entering the scripting part of this. Thanks for hinting useful hooks that I could use!

I will get back to you when I have some results (good or bad) ;-)

Best Regards
Simon

apaydi...@gmail.com

unread,
Apr 24, 2025, 2:05:19 PMApr 24
to OpenPnP
Hi Simon,
It's pure ~200 lines python script, which uses OpenPnP classes & methods, runs in OpenPnP.
I am not sure if it is ok for OpenPnP community and it is in very early stage but I can create a github repo which includes python code(s) if you would like to collaborate for further development or just try it without any guarantee .

Kind regards,
Emre

24 Nisan 2025 Perşembe tarihinde saat 19:46:28 UTC+3 itibarıyla sk.ku...@gmail.com şunları yazdı:

Jan

unread,
Apr 25, 2025, 5:08:48 PMApr 25
to ope...@googlegroups.com


On 24.04.2025 19:16, Simon K. wrote:
[...]
> What do you consider to be "two placements"? I am still quite fresh to
> openpnp, but would you suggest having two boards, one of them is the
> target tray and the other one the testing unit?
>
I was suggesting to setup a job with two placements in. The first picks
from the tray of new parts and places in the test adapter. The second
placements picks from the test adapter and places the (good) part where
ever you like. With some scripting logging you could configure the first
placement as not-placed to pick a new part for testing and/or you could
define a third placement you enable/set as not-placed to place a bad
part somewhere else. (You'd need to disable the sorting in the job
processor to make sure the ordering of placements is exactly as you
specified. Only then the JobProcessor will process the first placement
that is enabled and not marked as placed next.)

Jan
> > <https://groups.google.com/d/msgid/ <https://groups.google.com/d/
> msgid/>>
> > > openpnp/79888f4b-b6df-4ffb-
> a704-146dc2403dbfn%40googlegroups.com <http://40googlegroups.com>
> > <http://40googlegroups.com <http://40googlegroups.com>>
> > > <https://groups.google.com/d/msgid/openpnp/79888f4b-b6df-4ffb-
> <https://groups.google.com/d/msgid/openpnp/79888f4b-b6df-4ffb->
> > <https://groups.google.com/d/msgid/openpnp/79888f4b-b6df-4ffb-
> <https://groups.google.com/d/msgid/openpnp/79888f4b-b6df-4ffb->>
> > > a704-146dc2403dbfn%40googlegroups.com <http://40googlegroups.com>?
> > utm_medium=email&utm_source=footer <http://40googlegroups.com
> <http://40googlegroups.com>?
> > utm_medium=email&utm_source=footer>>.
> >
> > --
> > You received this message because you are subscribed to the Google
> > Groups "OpenPnP" group.
> > To unsubscribe from this group and stop receiving emails from it,
> send
> > an email to openpnp+u...@googlegroups.com
> > <mailto:openpnp+u...@googlegroups.com>.
> > To view this discussion visit https://groups.google.com/d/msgid/
> <https://groups.google.com/d/msgid/>
> > openpnp/3fc6ffd7-0d98-44bc-a618-9bae34231ca5n%40googlegroups.com
> <http://40googlegroups.com>
> > <https://groups.google.com/d/msgid/openpnp/3fc6ffd7-0d98-44bc-
> <https://groups.google.com/d/msgid/openpnp/3fc6ffd7-0d98-44bc->
> > a618-9bae34231ca5n%40googlegroups.com?
> utm_medium=email&utm_source=footer <http://40googlegroups.com?
> utm_medium=email&utm_source=footer>>.
>
> --
> You received this message because you are subscribed to the Google
> Groups "OpenPnP" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to openpnp+u...@googlegroups.com
> <mailto:openpnp+u...@googlegroups.com>.
> To view this discussion visit https://groups.google.com/d/msgid/
> openpnp/381d1cf4-ac7e-4f8b-b1c7-300318796510n%40googlegroups.com
> <https://groups.google.com/d/msgid/openpnp/381d1cf4-ac7e-4f8b-
> b1c7-300318796510n%40googlegroups.com?utm_medium=email&utm_source=footer>.

Simon K.

unread,
Nov 22, 2025, 6:16:32 AM (7 days ago) Nov 22
to OpenPnP
Just a heads up, this topic is still relevant on my side but I have not yet found time to work on this. Things have delayed a bit in time as well.

However I quite pleasantly found a few new interesting changes for the planned 2.5 release that might solve some issues with my endeavour.

As I understand correctly, with release 2.5 the following would be possible. Correct me if I am wrong:

- Have a Tray feeder (on the left) acting as the source
- Have a virtual PCB Tray (on the right) acting as the destination, set up with a pick-n-place file
- Set OpenPNP to deferred error processing
- Use a script that triggers after Pick+Alignment of the part that
  1. moves the head over the tester unit, opens the tester, inserts part and raises head again
  2. run the actual testing software script and wait for response
  3. open tester unit, pick up part from tester, close tester unit and then
      - if PASS: continue the remaining placement as if nothing happened (shouldn't be too hard?)*
      - if FAIL: raise an Exception, that will cause the Job Processor to abort the placement and discard the part
- Use a script that triggers before discarding:
  1. Change the discard destination dynamically to the last pick location on the source tray feeder, so that the FAIL part is put back where it came from in this placement (Not sure if that is as easy as I think it is)
- (New in 2.5) The Job Processor will try to repeat the placement (and not skip or pause like it did before?) with the next part in the feeder, doing above all over again until all output cells are filled

If that would work with "just" some scripting, I would be very delighted. If I have time again I might need to check out the test-branch on GitHub

* For extra bonus credit: Swap to the other toolhead, because the destination (on the right) might not always be reachable by the left toolhead due to machine limits.

Best Regards
Simon
Reply all
Reply to author
Forward
0 new messages