joint_state_publisher on OSX
When running joint_state_publisher on OSX Lion, I encounter the following error
[INFO] [WallTime: 1335373686.654959] Centering
2012-04-25 10:08:06.886 Python[41356:450b] *** Assertion failure in +[NSUndoManager _endTopLevelGroupings], /SourceCache/Foundation/Foundation-833.24/Misc.subproj/NSUndoManager.m:324
2012-04-25 10:08:06.888 Python[41356:450b] +[NSUndoManager(NSInternal) _endTopLevelGroupings] is only safe to invoke on the main thread.
2012-04-25 10:08:06.901 Python[41356:450b] (
0 CoreFoundation 0x00007fff8c261fc6 __exceptionPreprocess + 198
1 libobjc.A.dylib 0x00007fff9040dd5e objc_exception_throw + 43
2 CoreFoundation 0x00007fff8c261dfa +[NSException raise:format:arguments:] + 106
3 Foundation 0x00007fff93a7c743 -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 169
4 Foundation 0x00007fff939eb983 +[NSUndoManager(NSPrivate) _endTopLevelGroupings] + 144
5 AppKit 0x00007fff8df2721b -[NSApplication run] + 596
6 libwx_osx_cocoau_core-2.9.dylib 0x000000010d637e20 _ZN14wxGUIEventLoop5DoRunEv + 44
7 libwx_baseu-2.9.dylib 0x000000010dbebf79 _ZN13wxCFEventLoop3RunEv + 63
8 libwx_baseu-2.9.dylib 0x000000010db3cd97 _ZN16wxAppConsoleBase8MainLoopEv + 81
9 _core_.so 0x000000010cfa5619 _ZN7wxPyApp8MainLoopEv + 81
10 _core_.so 0x000000010cfc1c2b _wrap_PyApp_MainLoop + 235
11 Python 0x000000010c5315d8 PyEval_EvalFrameEx + 16006
12 Python 0x000000010c533cd8 PyEval_EvalCodeEx + 1996
13 Python 0x000000010c4d1abf PyClassMethod_New + 1378
14 Python 0x000000010c4b0d32 PyObject_Call + 97
15 Python 0x000000010c4bf6e9 PyInstance_New + 13169
16 Python 0x000000010c4b0d32 PyObject_Call + 97
17 Python 0x000000010c530f63 PyEval_EvalFrameEx + 14353
18 Python 0x000000010c533cd8 PyEval_EvalCodeEx + 1996
19 Python 0x000000010c4d1abf PyClassMethod_New + 1378
20 Python 0x000000010c4b0d32 PyObject_Call + 97
21 Python 0x000000010c5315ec PyEval_EvalFrameEx + 16026
22 Python 0x000000010c533df7 PyEval_EvalCode + 224
23 Python 0x000000010c530e0a PyEval_EvalFrameEx + 14008
24 Python 0x000000010c533df7 PyEval_EvalCode + 224
25 Python 0x000000010c530e0a PyEval_EvalFrameEx + 14008
26 Python 0x000000010c533cd8 PyEval_EvalCodeEx + 1996
27 Python 0x000000010c4d1abf PyClassMethod_New + 1378
28 Python 0x000000010c4b0d32 PyObject_Call + 97
29 Python 0x000000010c4bf6e9 PyInstance_New + 13169
30 Python 0x000000010c4b0d32 PyObject_Call + 97
31 Python 0x000000010c52cc40 PyEval_CallObjectWithKeywords + 180
32 Python 0x000000010c55e40d initthread + 2629
33 libsystem_c.dylib 0x00007fff9074b8bf _pthread_start + 335
34 libsystem_c.dylib 0x00007fff9074eb75 thread_start + 13
)
After some google search, it appears the issue that in newer Cocoa/Lion, it requires the "App.MainLoop" run in the same thread as the thread who initialize the wx. In joint state publisher, the App.MainLoop is run by a newly created thread while the main thread is used to send out joint_state messages..
Here I provide an workaround that swap these two threads,
diff -r 655f14965dbc joint_state_publisher/joint_state_publisher
--- a/joint_state_publisher/joint_state_publisher Wed Jun 01 14:37:58 2011 -0700
+++ b/joint_state_publisher/joint_state_publisher Wed Apr 25 10:00:03 2012 -0700
@@ -58,10 +58,10 @@
use_gui = get_param("use_gui", False)
if use_gui:
- app = wx.App()
+ self.app = wx.App()
self.gui = JointStatePublisherGui("Joint State Publisher", self)
self.gui.Show()
- Thread(target=app.MainLoop).start()
else:
self.gui = None
@@ -200,7 +203,8 @@
try:
rospy.init_node('joint_state_publisher')
jsp = JointStatePublisher()
- jsp.loop()
+ Thread(target=jsp.loop).start()
+ jsp.app.MainLoop()
except rospy.ROSInterruptException: pass
Here's a minimum set of code to generate the same crash
def gui():
import wx
app = wx.App()
frame = wx.Frame(None)
frame.Show()
app.MainLoop()
import threading
threading.Thread(target=gui).start()
(re-post as edit)