touilleMan / godot-python

Python support for Godot 🐍🐍🐍
Other
1.83k stars 136 forks source link

Weird bug when using pip lib that connects to the external camera. #373

Open TheBricktop opened 1 year ago

TheBricktop commented 1 year ago

Hey another issue ive ran into and this one is particulary weird : im using depthai from pypi to connect to the stereocamera and get some frames. While it can use the python interpreter provided by the godot-python module and it runs ok, the moment godot editor links to it it stops recognizing the device. I know this is very soecific problem and I can't possibly expect anyone to have this particular sensor but im rather asking about what might block a working device out of godot-python when they are connected. Another weird thing was when one of my scripts in python had def main (): and then main() construction because it started automatically when editor started and was running in the background. Both problems might be connected, and i think that the reslution could be to start the "daemon" that operates the device and after that another script would read the incoming data but thats a wild guess.

Edit:

The possible culprit might be that godot language server runs through all of the init and main functions in provided *.py files and then it effectively blocks the device from being used again as it is already engaged.

touilleMan commented 1 year ago

Hi @TheBricktop

You are talking about Godot editor, so you know there is multiple way Godot run a project:

So I advice you to make sure you are not by mistake running multiple instance of the python code that would then fight over connecting to your camera...

The possible culprit might be that godot language server runs through all of the init and main functions in provided

there is no main function in godot-python (this is because it's godot that decides which class should be loaded, then ask godot-python load the corresponding python file). So everything in you class's file will be executed and if you have a if __name__ == "__main__": .... it will be skipped

TheBricktop commented 1 year ago

there is no main function in godot-python (this is because it's godot that decides which class should be loaded, then ask godot-python load the corresponding python file). So everything in you class's file will be executed and if you have a if name == "main": .... it will be skipped

but the question remains : how to stop godot python from autoexecuting every python script on start of the editor because its locking some of the features and hardware before the actual game can start. I can put the aforementioned code behind if name == main but that stops it from being executed when the game starts. Is there a way to do like if is_godot_engine == false : to lock some parts of code behind ?

My problem stems from need to block the execution of functions that im holding in a helper classes, so i dont know if i should to stuff all the class into the "if name" block.

also there is a weird bug that does not allow exporting the variables in the script to the editor, i cant put my finger on why.

let me post my script here to examine what is wrong with it :

from godot import exposed, export, ResourceLoader
from godot import *
import ctypes 
import subprocess
import sys
import cv2
import depthai as dai
from depthaiHelpers import dai_pipeline as pipeline
from depthaiHelpers import dai_getCalibration as calib
from depthaiHelpers import cv2_tracking as tracking

    import numpy as np

    @exposed
    class Main(Spatial):
    # member variables here, example:
texture = ImageTexture()

material = export(SpatialMaterial)

pool_array = PoolByteArray()
sensor = pipeline.Oakd_pipeline(True,True,True,True)
sensor.setupPipeline()
print("main is being run")

frame, height, width, channels, size = None,None,None,None,None

def frame_to_godot_image(self, frame, height, width, channels, size):
    print(width, height, channels)
    image = Image()

    with self.pool_array.raw_access() as ptr:
        numpy_array = np.ctypeslib.as_array(ctypes.cast(ptr.get_address(), ctypes.POINTER(ctypes.c_uint8)), (size,))
        numpy_array[:] = np.frombuffer(frame, dtype=np.uint8).reshape((height,width)[::-1]+(channels,)).flatten()

    image.create_from_data( width, height, False, Image.FORMAT_RGB8, self.pool_array)
    return image

def _ready(self):
    print("YEllo")

    frame = self.sensor.getColorFrames()
    self.height, self.width, self.channels = frame.shape
    self.size = self.width * self.height * self.channels
    self.pool_array.resize(self.size)
    #if self.material is not None:
    #   self.material.albedo_texture = self.texture

def _process(self,delta):
    frame = self.sensor.getColorFrames()
    image = self.frame_to_godot_image(frame,self.height, self.width, self.channels, self.size)
    self.texture.create_from_image(image) 
    self.material.emission_texture = self.texture

EDIT: After some tinkering ive managed to understand what You've meant and moved all the functional code to the def _ready: and def _process: to avoid premature actions.