Python wrapper and orekit.initVM()

Hi Orekit experts!

I am just starting out with orekit, using it from python using the python wrapper here:

I cannot use anaconda so I built the egg myself following instructions here:

I will be calling Orekit in a python service on a background thread. Most of the samples I see have this code at the top of each module where orekit is used:

import orekit
orekit.initVM()

this works fine if the code is used from the main thread. but if orekit is called from a background thread I get this:

“RuntimeError: attachCurrentThread() must be called first”

What is the best practice for calling Orekit from a background thread? Should initVM() should only be called once per thread? Or once per process? Is there a function or method I can call to discover if initVM() needs to be called?

I did some experiments and got a segfault after calling Orekit a second time. first time works, second time segfaults:

# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x00007f0eac15da84, pid=29843, tid=0x00007f0e7affd700
#
# JRE version: OpenJDK Runtime Environment (8.0_151-b12) (build 1.8.0_151-8u151-b12-0ubuntu0.17.04.2-b12)
# Java VM: OpenJDK 64-Bit Server VM (25.151-b12 mixed mode linux-amd64 compressed oops)
# Problematic frame:
# C  [_orekit.cpython-36m-x86_64-linux-gnu.so+0x80ca84]  JCCEnv::setClassPath(char const*)+0x24

Thanks,
Jesse

Hi Jesse,

And welcome to the orekit community :slight_smile:

I played a bit with the attachCurrentThread but can’t seem to find the code. Orekit is based on the JCC tool, which describes the method shortly at:

Before PyLucene APIs can be used from a thread other than the main thread that was not created by the Java Runtime, the attachCurrentThread() method must be called on the JCCEnv object returned by the initVM() or getVMEnv() functions.

Basically you get an object returned from the vm=orekit.initVM() call, which you then pass to the new thread and call the vm.attachCurrentThread() on, or get it via orekit.getVMEnv() in the new thread. You can use the orekit.getVMEnv() to see if there is a java engine has been started as well.

Regards
/Petrus

Old thread, but I came across this and it helped me - here is what happened in my case and how I solved it:

  • I was running an orekit based propagator from a python UI. The UI script and propagation script were separate and stand-alone.
  • Was trying to implement threading into the UI to stop it from hanging while the propagation went in the background. Using threading for this then broke the ability to re-run the simulator, the second attempt would crash everything (without threading from the UI, this re-run always worked).
  • I have orekit only implemented in the background script, and just had to add/run the attachCurrentThread() method every time i spawned a thread (and IN the thread, of course).

What I ended up doing was always call orekit from a separate process using ProcessPoolExecutor(). That way the answer to “should orekit.initVM() be called?” is always “yes”.

In my used case it’s not called too much so this works fine. If it was called in a tight loop it would be another story.

Hi,

I am trying to install the spacetech-kubesat project from the following link: https://github.com/IBM/spacetech-kubesat. Here, there is a python script test_orekit.py https://github.com/IBM/spacetech-kubesat/blob/master/tests/test_orekit.py. While executing the script in a conda environment, I am encountering the following error
Exception in thread “main” java.lang.NoSuchMethodError: getTypeName
Traceback (most recent call last):
File “test_orekit.py”, line 38, in
import kubesat.orekit as orekit_utils
File “/home/swagata/anaconda3/envs/kubesat/lib/python3.8/site-packages/kubesat/orekit.py”, line 86, in
orekit.initVM()
orekit.JavaError: <exception str() failed>

Can you please suggest any solution to resolve the above issue?

Just wanted to say that I encountered this SIGSEGV fault error while calling orekit from a web app I am creating in Python Dash. I solved this by performing two steps:

  1. Moving the initial call of the orekit VM to the main python module app.py
  2. Making the first line of any subfunction that calls on the orekit code: orekit.getVMEnv().attachCurrentThread()

Example directory structure:

  • callbacks/main.py
  • layouts/main.py
  • app.py (contains our main)

app.py code:

import dash
from dash import Dash, dcc, html, dash_table, Input, Output, State, callback
import dash_bootstrap_components as dbc

import orekit
vm = orekit.initVM()

from orekit.pyhelpers import setup_orekit_curdir
setup_orekit_curdir()

from layouts.main import main_layout
app = Dash(__name__)
app = dash.Dash(external_stylesheets=[dbc.themes.BOOTSTRAP])

# Include layout
app.layout = main_layout

# Include callbacks (Needs to be assigned after setting layout up)
from callbacks.main import *

if __name__ == '__main__':
    app.run(debug=True)

callbacks/main.py code

import orekit 

# Import Orekit packages
from org.orekit.bodies import GeodeticPoint
// Import other modules

def function(input1, input2):
    orekit.getVMEnv().attachCurrentThread()   
    // code
    return X

Hi,

Yes, if multi threads are used one need to connect them to the JVM.

What one can do is to use a decorator for this also:

def attach_thread(func):
    def wrapper_do_attach(*args, **kwargs):
        orekit.getVMEnv().attachCurrentThread()
        return func(*args, **kwargs)
    return wrapper_do_attach

and then for the actual functions they can be decorated with:

@attach_thread
def my_orekit_calc(parameter):
    ....

maybe we should include this in the wrapper…