G4P/grafica multiwindow plot crash

Hello everyone,

I’m having a stability issue when using G4P and grafica libraries. I want to create a program which reads a serial string sent by arduino. It is a two-channel pressure measurements - an E and an F channel. I built a GUI that shows in two windows the real-time plots of pressure against time measurements.

While the code compiles and runs, after a while (20/30 seconds circa) it starts giving some Errors - without crashing:

ERROR 1:

################ EXCEPTION IN EVENT HANDLER ################
An error occured during execution of the eventhandler:
CLASS: Lilliput_GUI_2 METHOD: win_drawE
Caused by java.lang.IndexOutOfBoundsException: Index: 522, Size: 676
java.util.ArrayList.rangeCheck(ArrayList.java:657)
java.util.ArrayList.get(ArrayList.java:433)
grafica.GLayer.drawPoints(Unknown Source)
grafica.GPlot.drawPoints(Unknown Source)
Lilliput_GUI_2.win_drawE(Lilliput_GUI_2.java:272)
sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:498)
g4p_controls.GWindow.draw(Unknown Source)
g4p_controls.GWindowAWT.draw(Unknown Source)
sun.reflect.GeneratedMethodAccessor3.invoke(Unknown Source)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:498)
processing.core.PApplet$RegisteredMethods.handle(PApplet.java:1411)
processing.core.PApplet$RegisteredMethods.handle(PApplet.java:1404)
processing.core.PApplet.handleMethods(PApplet.java:1603)
processing.core.PApplet.handleDraw(PApplet.java:2442)
processing.awt.PSurfaceAWT$12.callDraw(PSurfaceAWT.java:1557)
processing.core.PSurfaceNone$AnimationThread.run(PSurfaceNone.java:313)
##############################################################

After a relatively long period (700 seconds circa, a totally insufficient period for my purposes), the program stops plotting on the windows (not at the same time) without crashing, giving the errors

################ EXCEPTION IN EVENT HANDLER ################
An error occured during execution of the eventhandler:
CLASS: Lilliput_GUI_2 METHOD: win_drawE
Caused by java.lang.IndexOutOfBoundsException: Index: 558, Size: 698
java.util.ArrayList.rangeCheck(ArrayList.java:657)
java.util.ArrayList.get(ArrayList.java:433)
grafica.GLayer.drawPoints(Unknown Source)
grafica.GPlot.drawPoints(Unknown Source)
Lilliput_GUI_2.win_drawE(Lilliput_GUI_2.java:272)
sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:498)
g4p_controls.GWindow.draw(Unknown Source)
g4p_controls.GWindowAWT.draw(Unknown Source)
processing.core.PApplet.handleDraw(PApplet.java:2429)
processing.awt.PSurfaceAWT$12.callDraw(PSurfaceAWT.java:1557)
processing.core.PSurfaceNone$AnimationThread.run(PSurfaceNone.java:313)
##############################################################

################ EXCEPTION IN EVENT HANDLER ################
An error occured during execution of the eventhandler:
CLASS: Lilliput_GUI_2 METHOD: win_drawE
Caused by java.lang.RuntimeException: pushMatrix() cannot use push more than 32 times
processing.awt.PGraphicsJava2D.pushMatrix(PGraphicsJava2D.java:2144)
processing.core.PApplet.pushMatrix(PApplet.java:13193)
grafica.GAxis.drawAsYAxis(Unknown Source)
grafica.GAxis.draw(Unknown Source)
grafica.GPlot.drawYAxis(Unknown Source)
Lilliput_GUI_2.win_drawE(Lilliput_GUI_2.java:270)
sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:498)
g4p_controls.GWindow.draw(Unknown Source)
g4p_controls.GWindowAWT.draw(Unknown Source)
processing.core.PApplet.handleDraw(PApplet.java:2429)
processing.awt.PSurfaceAWT$12.callDraw(PSurfaceAWT.java:1557)
processing.core.PSurfaceNone$AnimationThread.run(PSurfaceNone.java:313)
##############################################################

repeatedly.

I still have to figure out what’s going wrong, but I think it is related on how G4P handles the plot creation. Also because I haven’t used pushMatrix() method anywhere in the code.

Link to code;
Link to GUI;

1 Like

All these errors are occurring inside the draw method for the second window win_drawE so is not necessarily as a result of G4P. The trick here is to read and understand the stack trace.

So we will start with the first one and what we are looking for is not where the exception is thrown but the cause of the exception and if we look at the trace we can see this in line 4.

  1. ################ EXCEPTION IN EVENT HANDLER ################
  2. An error occured during execution of the eventhandler:
  3. CLASS: Lilliput_GUI_2 METHOD: win_drawE
  4. Caused by java.lang.IndexOutOfBoundsException: Index: 522, Size: 676
  5. java.util.ArrayList.rangeCheck(ArrayList.java:657)
  6. java.util.ArrayList.get(ArrayList.java:433)
  7. grafica.GLayer.drawPoints(Unknown Source)
  8. grafica.GPlot.drawPoints(Unknown Source)
  9. Lilliput_GUI_2.win_drawE(Lilliput_GUI_2.java:272)
  10. sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)

So the error is caused by an IndexOutOfBoundsException thrown by the java.util.ArrayList.rangeCheck method.

If we look at the next line (6) we can see that the program attempted to use the ArrayList get(int) method. So the problem is that the index value passed to the get method is < 0 or >= arraylist size. So when did this happen? Look at the next line (7) the error occurred in the Grafica library library, specifically in the drawPoints() method of the GLayer class.

If we look at the other traces all the problems appear to be in the graphica library rather than G4P.

One final point, each GWindow has its own event-handling thread so you need to be careful when using shared data e…g. the plot[] array it might be part of the problem.

1 Like

Thank you very much for your reply.

So what do you think is the problem?
The fact is that I have to add points to plot[i] dynamically any time the serial arduino port is available and fetches data; hence I use plot[i] - which is an array of GPlot - and add to them the datapoints, via the plot[i].add method.

Now, I want the plot to be shown in the two windows “pressioneE” and “pressioneF” and this is why I call the plot[i].beginDraw() (etc) method inside the win_drawE function;

There is a more suitable way to real-time plot a function-scoped variable that reads the datapoints from the global-scoped plot[i] GPlot object?

Also, the plot stop working when the pushMatrix() error kicks in. Is that problem related to this one (let us say, a consequence)?

Do you suggest to modify (or re-post) this thread to a “Grafica multiwindow plot crash”?

1 Like

I would rename this thread Graphica / G4P mult window crash do not re-post.

I have not looked at the Graphica library for a very long time so there will be changes that I am not familiar with. If you seriously want my help then I would need to experiment with the sketch code so you would need to send the sketch to me.

I will send you a PM with my email address, and if you want me to look at it then archive the sketch (Tools >> Archive Sketch menu option) and send the zip file to me by email.

Before you do that make sure you are using the latest versions Processing, G4P and Graphica.

1 Like
  • There’s no GPlot method exactly named add() but 1s that start w/ “add”.
  • Much probably you’re using method addLayer().
  • When you do so, you’re increasing the size() of the GPlot’s internal ArrayList.
  • The library grafica, as the majority of Processing’s 3rd-party libraries, is single-threaded only.
  • That is, it lacks mechanisms to deal w/ multithreading access.
  • So you should never invoke GPlot::addLayer() outside the PApplet’s Thread it is bound to!
  • Actually, most of grafica’s API is dangerous to access from other threads.
  • As a workaround you can collect the Arduino’s received data to some global container.
  • Then once inside the GPlot’s Thread code, invoke GPlot::addLayer() there, passing the container’s items as its argument.
1 Like

OK I have had a look at your sketch and the problem is caused by having multiple windows sharing data.

The solution is too use a Java concurrent collection. The other problem was your code is not extensible and the code logic was difficult to understand. Although you have programming experience it is very limited with Java so it would be very time consuming to try and take you through the process of creating a fully extensible solution so I have done it for you.

The link below will download an archived sketch (zip file) simply unzip it and put it inside your sketch folder.

The sketch has 2 java tabs for the top level classes PressureMonitor and Serial. The Serial class simply simulates the connection to an Arduino device and in the finished product simply delete or better still comment out all the code in this class and import Processing’s Serial class instead. Inside the serial class the serialProcess() method produces dummy data for each channel.

The PressureMonitor encapsulates everything needed to graph a single channel

  • a window
  • a LinkedBlockingQueue (thread safe) to cache pressure data
  • a table for the data
  • a graphic plot
  • a checkbox to ignore data for plotting
  • a button to save the data as a csv file.

To add another channel simply add an identifier to this list in main pde tab

// ===========================================================
// To create more monitors simply add their unique ID here and
// modify the method 'serialProcess' in the Serial class
String[] channel_ids = new String[] { "E", "F" };
// ===========================================================

and modify the serialProcess() method to produce data for the new channel.

I have had the sketch running for 30 minutes now without any problems.

I think the time needed to produce an initial version for yourselves would be better spent studying and modifying this sketch to meet your needs.

Download the sketch

If you have any questions about using it just ask.

Thank you A LOT for the suggestions and for the code.
I’ve been running it for 2 hours now, and no error has appeared yet.
I am very sorry for the messy code, but you are right, we have a very basic Java experience.

Unfortunately I cannot try the code at work, since we are in the “red zone” due to the coronavirus, but I will let you know if everything is ok when I will be able to test it at work again.

Thank you again!!