Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Camera calibration segfault when displaying images from thread #85

Closed
pieleric opened this issue Jun 29, 2014 · 8 comments
Closed

Camera calibration segfault when displaying images from thread #85

pieleric opened this issue Jun 29, 2014 · 8 comments

Comments

@pieleric
Copy link

Running the camera calibration (mono or stereo) with git head (indigo) fails with this errors:

QObject::moveToThread: Widgets cannot be moved to a new thread
QObject::setParent: Cannot set parent, new parent is in a different thread
Segmentation fault (core dumped)

That's on a Ubuntu 14.04 64-bits (x86).

My understanding is that it's due to the move to OpenCV2, which uses QT, which doesn't allow to draw on the window from a different thread than the original thread that created the window.

I'm not sure what's the right way to fix it. As a workaround, I've moved the window init code to its own function, and add a call to that function from the init of the ConsumerThread (passed as a 3rd argument).
But I had to disable the stereo thread.

It looks more or less like that:

class ConsumerThread(threading.Thread):
    def __init__(self, queue, function, init):
        threading.Thread.__init__(self)
        self.queue = queue
        self.function = function
        init()
:
class CalibrationNode:
    :
    mth = ConsumerThread(self.q_mono, self.handle_monocular, self.initWindow)
:
class OpenCVCalibrationNode(CalibrationNode):
    :
    def __init__(self, *args):
        CalibrationNode.__init__(self, *args)

    def initWindow(self):
        cv2.namedWindow("display", cv2.WINDOW_NORMAL)
        cv2.setMouseCallback("display", self.on_mouse)
        cv2.createTrackbar("scale", "display", 0, 100, self.on_scale)

@vrabaud
Copy link
Contributor

vrabaud commented Jun 29, 2014

I have Indigo on the same configuration and I do not have that problem (other persons are using this code without errors too).
Do you get that error every time ? With my Kinect, I just run:

rosrun camera_calibration cameracalibrator.py image:=/camera/rgb/image_raw

Anything else you are running ?
Can you also please try that branch at https://github.com/vrabaud/image_pipeline/tree/indigo . I created it to solve another problem but it might work for you.

@pieleric
Copy link
Author

Strange... anyway, I've tried with your branch but it gave the same result.

Actually, from time to time, instead of segfaulting, it gives this output, and blocks there:

OK
init done 
opengl support available 
QMetaMethod::invoke: Unable to invoke methods with return values in queued connections

I don't know whether it's helpful, or more confusing ;-)

I run camera calibration with a simple webcam, like that:

roslaunch ar_pose ar_pose_single.launch  # part of ar_tools, to start a camera node
rosrun camera_calibration cameracalibrator.py --size 9x6 --square 0.25 image:=/camera/image_raw  camera:=/camera

Let's try to be more precise on the libraries:

libopencv-core2.4:amd64       2.4.8+dfsg1-2ubuntu
libqtgui4:amd64 4:4.8.5+git192-g085f851+dfsg-2ubuntu4

@vrabaud
Copy link
Contributor

vrabaud commented Jun 29, 2014

I have both kubuntu and ubuntu installed ... I guess I need a pure Ubuntu. I'll try to get a big enough USB key to get that going.
My OpenCV is slightly newer: 2.4.8+dfsg1-2ubuntu1

@delmic
Copy link

delmic commented Jun 30, 2014

I think the OpenCV version is the same, it's just the last character that got dropped in my copy/pasting ;-)

@vrabaud vrabaud modified the milestone: indigo Jul 14, 2014
vrabaud added a commit that referenced this issue Jul 20, 2014
that could be a fix for #85
@vrabaud
Copy link
Contributor

vrabaud commented Jul 20, 2014

please, try this out and tell me if it works for you. Thx

@pieleric
Copy link
Author

Almost :-)

The __init__() of the Thread object is done in the original thread, so you have to move the window init to the run() function:

    def __init__(self, queue, opencv_calibration_node):
        threading.Thread.__init__(self)
        self.queue = queue
        self.opencv_calibration_node = opencv_calibration_node

    def run(self):
        cv2.namedWindow("display", cv2.WINDOW_NORMAL)
        cv2.setMouseCallback("display", self.opencv_calibration_node.on_mouse)
        cv2.createTrackbar("scale", "display", 0, 100, self.opencv_calibration_node.on_scale)
        while True:
   :

Also, there is a typo in redraw_stereo():

self.queue.display.put(display) --> self.queue_display.put(display)

@vrabaud
Copy link
Contributor

vrabaud commented Jul 21, 2014

I had fixed the typo, I guess I did not push at the right moment. And does that work for you with those 2 changes ?

@pieleric
Copy link
Author

With these 2 small fixes, yes it works fine :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants