1818
1919
2020import logging
21+ import threading
2122import traceback
2223from contextlib import nullcontext
2324from copy import copy
@@ -131,6 +132,8 @@ def init_keyboard_listener():
131132 # Allow to exit early while recording an episode or resetting the environment,
132133 # by tapping the right arrow key '->'. This might require a sudo permission
133134 # to allow your terminal to monitor keyboard events.
135+ # Initialize simple text-based keyboard listener to avoid sudo permission issues.
136+ # Uses input() in a background thread - no special permissions required.
134137 events = {}
135138 events ["exit_early" ] = False
136139 events ["rerecord_episode" ] = False
@@ -143,27 +146,42 @@ def init_keyboard_listener():
143146 listener = None
144147 return listener , events
145148
146- # Only import pynput if not in a headless environment
147- from pynput import keyboard
149+ print ("Text-based keyboard controls enabled:" )
150+ print (" 'n' + Enter: Next/forward command (simulate right arrow) - Exit current loop" )
151+ print (" 'b' + Enter: Back command (simulate left arrow) - Re-record episode" )
152+ print (" 's' + Enter: Stop recording completely" )
148153
149- def on_press ( key ):
154+ def input_listener ( ):
150155 try :
151- if key == keyboard .Key .right :
152- print ("Right arrow key pressed. Exiting loop..." )
153- events ["exit_early" ] = True
154- elif key == keyboard .Key .left :
155- print ("Left arrow key pressed. Exiting loop and rerecord the last episode..." )
156- events ["rerecord_episode" ] = True
157- events ["exit_early" ] = True
158- elif key == keyboard .Key .esc :
159- print ("Escape key pressed. Stopping data recording..." )
160- events ["stop_recording" ] = True
161- events ["exit_early" ] = True
156+ while not events ["stop_recording" ]:
157+ try :
158+ user_input = input ().strip ().lower ()
159+ if user_input == 'n' :
160+ print ("Next/forward command received. Exiting loop..." )
161+ events ["exit_early" ] = True
162+ elif user_input == 'b' :
163+ print ("Back command received. Exiting loop and re-record episode..." )
164+ events ["rerecord_episode" ] = True
165+ events ["exit_early" ] = True
166+ elif user_input == 's' :
167+ print ("Stop command received. Stopping data recording..." )
168+ events ["stop_recording" ] = True
169+ events ["exit_early" ] = True
170+ except EOFError :
171+ # Handle case where input is not available (e.g., piped input)
172+ break
162173 except Exception as e :
163- print (f"Error handling key press : { e } " )
174+ logging . debug (f"Input listener error : { e } " )
164175
165- listener = keyboard .Listener (on_press = on_press )
166- listener .start ()
176+ input_thread = threading .Thread (target = input_listener , daemon = True )
177+ input_thread .start ()
178+
179+ # Return a simple object to maintain compatibility
180+ class SimpleListener :
181+ def stop (self ):
182+ events ["stop_recording" ] = True
183+
184+ listener = SimpleListener ()
167185
168186 return listener , events
169187
0 commit comments