@@ -159,6 +159,9 @@ def __init__(self):
159159 except :
160160 pass # Icon not critical
161161
162+ # Initialize configuration with reasonable defaults first
163+ self ._initialize_simple_config ()
164+
162165 # Create central widget and layout
163166 central_widget = QWidget ()
164167 self .setCentralWidget (central_widget )
@@ -204,6 +207,13 @@ def _setup_ui(self, central_widget):
204207 main_layout .setColumnStretch (0 , 1 ) # Status/Emotion column
205208 main_layout .setColumnStretch (1 , 2 ) # Conversation/Tools column (wider)
206209 main_layout .setColumnStretch (2 , 1 ) # Analytics/Controls column
210+
211+ # Initialize conversation widget with default configuration
212+ if hasattr (self , 'last_config_update' ):
213+ self .conversation_widget .update_configuration (
214+ self .last_config_update ['config_data' ],
215+ "disconnected" # Start as disconnected
216+ )
207217
208218 def _init_ros (self ):
209219 """Initialize ROS2 node and connections"""
@@ -232,14 +242,6 @@ def _init_ros(self):
232242 self .ros_executor .add_node (self .ros_node )
233243 self .ros_thread = threading .Thread (target = self .ros_executor .spin , daemon = True )
234244 self .ros_thread .start ()
235-
236- # Query and distribute initial configuration (with delay for bridge startup)
237- QTimer .singleShot (2000 , self ._query_and_distribute_config ) # Wait 2 seconds for bridge to initialize
238-
239- # Set up periodic config refresh in case bridge connects later
240- self .config_refresh_timer = QTimer ()
241- self .config_refresh_timer .timeout .connect (self ._retry_config_if_fallback )
242- self .config_refresh_timer .start (10000 ) # Check every 10 seconds
243245
244246 def _setup_timers (self ):
245247 """Set up update timers for the UI"""
@@ -253,86 +255,16 @@ def _setup_timers(self):
253255 self .analytics_timer .timeout .connect (self ._update_analytics )
254256 self .analytics_timer .start (1000 ) # 1 FPS for analytics
255257
256- def _query_and_distribute_config (self ):
257- """Query configuration parameters from bridge and distribute to widgets"""
258- try :
259- # Query parameters from the voice agent bridge
260- config_data = {}
261- config_source = "fallback"
262-
263- # Try to get parameters from bridge using parameter client
264- try :
265- from rclpy .parameter_client import AsyncParameterClient
266-
267- # Create parameter client to query bridge node
268- param_client = AsyncParameterClient (self .ros_node , 'voice_agent_bridge' )
269-
270- # Wait for bridge node to be available (timeout after 5 seconds)
271- if param_client .wait_for_services (timeout_sec = 5.0 ):
272- # Query timeout parameters from bridge
273- parameter_names = ['user_response_timeout' , 'max_conversation_time' , 'config_received' ]
274-
275- # Use async parameter client - get future and wait for result
276- future = param_client .get_parameters (parameter_names )
277-
278- # Spin until the future is complete (with timeout)
279- import time
280- start_time = time .time ()
281- timeout = 5.0
282-
283- while not future .done () and (time .time () - start_time ) < timeout :
284- rclpy .spin_once (self .ros_node , timeout_sec = 0.1 )
285-
286- if future .done ():
287- parameters = future .result ().values
288-
289- config_data = {
290- 'user_response_timeout' : parameters [0 ].double_value if parameters [0 ].type == 3 else 15.0 , # PARAMETER_DOUBLE = 3
291- 'max_conversation_time' : parameters [1 ].double_value if parameters [1 ].type == 3 else 180.0
292- }
293-
294- # Check if we got real configuration from agent using config_received flag
295- config_received = parameters [2 ].bool_value if parameters [2 ].type == 1 else False # PARAMETER_BOOL = 1
296- if config_received :
297- config_source = "agent" # Bridge has received agent configuration
298- else :
299- config_source = "fallback" # Bridge still using defaults
300-
301- self .ros_node .get_logger ().info (f"Retrieved configuration from bridge: { config_data } (source: { config_source } )" )
302- else :
303- raise Exception ("Parameter query timed out" )
304- else :
305- raise Exception ("Bridge node not available" )
306-
307- except Exception as e :
308- # Parameters not available, use fallback values
309- self .ros_node .get_logger ().warn (f"Could not query bridge parameters: { e } , using fallback configuration" )
310- config_data = {
311- 'user_response_timeout' : 15.0 ,
312- 'max_conversation_time' : 180.0
313- }
314- config_source = "fallback"
315-
316- # Distribute configuration to widgets
317- if hasattr (self , 'conversation_widget' ):
318- self .conversation_widget .update_configuration (config_data , config_source )
319- self .ros_node .get_logger ().info ("Updated conversation widget configuration" )
320-
321- # Add configuration info to analytics data
322- self .last_config_update = {
323- 'config_data' : config_data ,
324- 'config_source' : config_source ,
325- 'timestamp' : datetime .now ()
326- }
327-
328- except Exception as e :
329- self .ros_node .get_logger ().error (f"Error in configuration query and distribution: { e } " )
330-
331- def _retry_config_if_fallback (self ):
332- """Retry configuration query if still using fallback values"""
333- if (hasattr (self , 'last_config_update' ) and
334- self .last_config_update .get ('config_source' ) == 'fallback' ):
335- self ._query_and_distribute_config ()
258+ def _initialize_simple_config (self ):
259+ """Initialize configuration with reasonable defaults"""
260+ self .last_config_update = {
261+ 'config_data' : {
262+ 'user_response_timeout' : 15.0 ,
263+ 'max_conversation_time' : 180.0
264+ },
265+ 'config_source' : "fallback" ,
266+ 'timestamp' : datetime .now ()
267+ }
336268
337269 @pyqtSlot (AgentStatus )
338270 def _update_agent_status (self , status ):
@@ -356,6 +288,12 @@ def _update_user_speech(self, speech):
356288 def _update_connection_status (self , connected ):
357289 """Update UI with connection status"""
358290 self .agent_status_widget .update_connection (connected )
291+
292+ # Update conversation widget configuration status based on connection
293+ if hasattr (self , 'conversation_widget' ) and hasattr (self , 'last_config_update' ):
294+ config_data = self .last_config_update ['config_data' ]
295+ source = "connected" if connected else "disconnected"
296+ self .conversation_widget .update_configuration (config_data , source )
359297
360298 @pyqtSlot (str )
361299 def _send_virtual_request (self , request_json ):
@@ -402,8 +340,6 @@ def closeEvent(self, event):
402340 self .update_timer .stop ()
403341 if hasattr (self , 'analytics_timer' ):
404342 self .analytics_timer .stop ()
405- if hasattr (self , 'config_refresh_timer' ):
406- self .config_refresh_timer .stop ()
407343
408344 # Clean up ROS
409345 if hasattr (self , 'ros_executor' ):
0 commit comments