ensenso / ros_driver

Official ROS driver for Ensenso stereo cameras.
http://wiki.ros.org/ensenso_driver
BSD 3-Clause "New" or "Revised" License
28 stars 25 forks source link

load remote lib fails on ubuntu 20.04 #97

Closed ttyusb007 closed 1 year ago

ttyusb007 commented 1 year ago

This is regarding the python interface of ensenso nxlib, which seems to have been archived now, but the problem should be quite related to the ros driver too.

I used to be able to start a remote process by

    ensenso_nxlib.api.open_tcp_port(24000)

    api.initialize()
    # You can open your camera here or remotely from the other process.
    camera_serial = '123456'

    # Opens the camera with the serial stored in camera_serial variable
    cmd = NxLibCommand(CMD_OPEN)
    cmd.parameters()[ITM_CAMERAS] = camera_serial
    cmd.execute()
    print("camera {} ready".format(camera_serial))
    print("Close the camera with Ctrl+c")
    signal.signal(signal.SIGINT, handle_sigint)
    signal.pause()`**

and open it via

api.load_remote_lib()
api.connect("localhost", port)
# Captures with the previous openend camera
capture = NxLibCommand(CMD_CAPTURE)
capture.parameters()[ITM_CAMERAS] = '123456'
capture.execute()

However, the process no longer works when I switch to a new Ubuntu 20.04 desktop, when I try to capture an image it gives me an the error ErrorText": "The specified serial number '123456' does not match any open camera.", while the serial number is right. I have also tried the ITM_BY_SERIAL_NO with no success, it just seems that no cameras are available when creating the localhost from the port.

I have been trying to debug this for two days, could you suggest what could be wrong here? Thanks

saierd commented 1 year ago

There were no recent changes related to this and at first glance the code looks like it should work.

ttyusb007 commented 1 year ago

Hi thank you for your prompt response! For those questions: Do you use the same version of the NxLib and the Python interface as before, when it worked? --The station that works has nxlib 3.1.X and python version 3.6, ubuntu 18, and the newer station has nxlib 3.3.x and python version 3.8, ubuntu 20. Could that cause the problem? Does the capture command work if you do it directly in the other process after opening the camera? -- Capture works if I open the camera and capture in the same process (without the TCP session and load_remote_lib) Could you print the tree of the NxLib from both sides and verify that your camera shows up and is opened in both? -- I am fairly sure it doesn't show up on the receiving end, but could you show me how to print the tree with the python interface?

benthie commented 1 year ago

With SDK Version 3.3.x we made the NxLib Python interface part of our Ensenso SDK in order to reduce version compatibility problems.

On your Ubuntu 20.04 machine, did you install the Python interface together with the Ensenso SDK (or via pip) or do you use the source code from our GitHub repository?

In case your installed Python interface version matches the installed NxLib version, you should be able to print the tree with the following snippet:

from nxlib import NxLib, NxLibItem

with NxLib():
    tree = NxLibItem()
    print(tree.as_json())
ttyusb007 commented 1 year ago

Hi we made sure to update the SDK to the newest version and have the same NxLib python interface, however the problem still exists.

I tried to print out the tree on the server and client side, those are the messages we got: Server side: "SerialNumber": "123456", "Status": { "Available": false, "Calibrated": true, "DynamicCalibrationLimitReached": false, "FirmwareSupportsModel": true, "IsSuppliedFirmwareVersion": true, "LocalEepromFile": false, "LowBandwidth": false, "Open": true, "Overtemperature": false, "Paired": true, "ValidCameraFirmware": true, "ValidFirmware": true, "ValidIpAddress": true, "ValidProjectorFirmware": true },

and on the client side: "SerialNumber": "123456", "Status": { "Available": false, "Calibrated": true, "FirmwareSupportsModel": true, "IsSuppliedFirmwareVersion": true, "LocalEepromFile": false, "LowBandwidth": false, "Open": false, "Overtemperature": false, "Paired": true, "ValidCameraFirmware": true, "ValidFirmware": true, "ValidIpAddress": true, "ValidProjectorFirmware": true },

We have three ensenso N35s connected and in this case we only established on tcp session for camera "123456". It does seem like camera "123456" is opened somehow, but when I load the romote API on the client side I get the specified serial number '123456' does not match any open camera." error.

benthie commented 1 year ago

I tried to reproduce the problem on my Ubuntu 20.04 machine, but without any success. The following three files led to the desired behavior. In one terminal I ran python3 local.py and in a second python3 remote.py, which then captured with the open camera.

Please copy the contents into the three files with the given filenames into the same directory. In common.py you have to adapt the value of camera_serial to the one of your camera. I used the TCP port 24001 because in case an NxView is opened in parallel, it will by default open the TCP port 24000.


# common.py
camera_serial = "160606"
hostname = "localhost"
port = 24001

print_tree = False
# local.py
import signal
import sys

import common

from nxlib.constants import *

from nxlib import api
from nxlib import NxLibCommand
from nxlib import NxLibItem

def handle_sigint(sigint, stack_frame):
    print("\n\nClosing NxLib ... ", end ="")
    api.finalize()
    print("done")
    sys.exit(0)

def main():
    print(f"Initializing NxLib ... ", end="", flush=True)
    api.initialize()
    print("done")

    print(f"Opening TCP port {common.port} ... ", end="", flush=True)
    api.open_tcp_port(common.port)
    print("done")

    print(f"Opening camera {common.camera_serial} ... ", end="", flush=True)
    cmd = NxLibCommand(CMD_OPEN)
    cmd.parameters()[ITM_CAMERAS] = common.camera_serial
    cmd.execute()
    print("done")

    if common.print_tree:
        print(NxLibItem().as_json())

    print("\nClose the camera with Ctrl+c ... ", end="")

    signal.signal(signal.SIGINT, handle_sigint)
    signal.pause()

if __name__ == "__main__":
    main()
# remote.py
import common

from nxlib.constants import *

from nxlib import api
from nxlib import NxLibCommand
from nxlib import NxLibItem

def main():
    print(f"Loading remote NxLib ... ", end="", flush=True)
    api.load_remote_lib()
    print("done")

    print(f"Connecting remote lib to local lib on {common.hostname}:{common.port} ... ", end="", flush=True)
    api.connect(common.hostname, common.port)
    print("done")

    if common.print_tree:
        print(NxLibItem().as_json())

    # Captures with the previous openend camera
    capture = NxLibCommand(CMD_CAPTURE)
    capture.parameters()[ITM_CAMERAS] = common.camera_serial

    print(f"Capturing images ... ", end="")
    capture.execute()
    print("done")

if __name__ == "__main__":
    main()
ttyusb007 commented 1 year ago

Thank you! From the your code, I realized the problem has been importing ensenso_nxlib instead of nxlib, importing nxlib solves the problem!

benthie commented 1 year ago

Importing ensenso_nxlib should also work, I just verified that on my machine, although you have to install it manually via pip. We provide the package under the old name for backwards compatibility. See our manual for more information on the installation and a detailed documentation of the complete interface.

ttyusb007 commented 1 year ago

Hi this may be unrelated, but I have a Basler camera connected alongside ensensos. I notice that ever since I switch to nxlib from ensenso-nxlib, when I have ensenso TCP ports open (run local.py), while the ensensos work perfectly, the Basler failed to be captured with the pypylon packages most of the time (although it does work sometimes) with the following error:

return _pylon.InstantCamera_Open(self) _genicam.RuntimeException: Failed to open 'Basler a….’ The device is controlled by another application. Err: An attempt was made to access an address location which is currently/momentary not accessible. (0xE1018006) : RuntimeException thrown (file 'GigEDevice.cpp', line 288)

This seems to only occur after updating the ensenso SDK and importing nxlib, I am commanding the Basler camera to open and capture locally, not through a tcp port.

I wonder if you happen to have insights on what may cause this error. Thank you very much!

saierd commented 1 year ago

The NxLib can also use Basler GigE Vision cameras. When they are detected, it opens them in the background to read the EEPROM and check if they are calibrated, need a firmware update etc.

If you try to open the camera while this happens it is already in use. Usually this should not take long until the NxLib releases the camera again, but you seem to have unfortunate timing at the start of your program, so that it happens most of the time. If you just retry opening in this case it will probably work fine.

ttyusb007 commented 1 year ago

Thank you for the explanation! Since I always have the nxlib tcp open in the background the Basler keeps failing to load after the first time it fails(I do close the Basler camera each time I attempt to open it), seems like this failure occur regardless of the timing, and when I turn off the local TCP connection the Basler opens again. Again, this didn't happen with the old ensenso-nxlib. I wonder if the checking EEPROM and calibration is new in the Nxlib? And also could an outdated firmware or no calibration cause the issue?

saierd commented 1 year ago

This functionality in the NxLib is not new, it always did this. When the Basler camera is not calibrated through the NxLib, then the NxLib should read it once, see that there is nothing in the EEPROM that it can use and close it again.

When you open NxView while your Python program doesn't run, do you see the Basler camera and is it flagged as in use permanently there?

ttyusb007 commented 1 year ago

I see, thanks! Well if I open the nxView and check the status of the Basler when it doesn't run, it usually shows in-use and then switch to available even if I am not doing anything. Is there a way to capture Basler image with nxlib? I would try any alternative

saierd commented 1 year ago

Could you please open some camera in NxView and stop capturing. Then use Tools -> Profiling... to create a Trace log for ~30s and upload it here: https://download.optonic.com/s/gnkGk2gXoeRDFp2

I can check if the NxLib is what opens the camera all the time.

Is there a way to capture Basler image with nxlib? I would try any alternative

The NxLib can use Basler cameras like any other mono camera it supports, although this is not tested a lot. You can try to open it in NxView. But I don't expect this to help with your problem when NxView also shows your camera as permanently in use.