Skip to content

Commit 19d3499

Browse files
committed
Add subscription callback to update state of camera_node
1 parent 2870503 commit 19d3499

File tree

1 file changed

+134
-2
lines changed

1 file changed

+134
-2
lines changed

coffee_ws/src/coffee_vision/coffee_vision/camera_node.py

Lines changed: 134 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
from python_qt_binding.QtWidgets import QApplication, QMainWindow, QWidget, QVBoxLayout, QLabel, QPushButton, QComboBox, QHBoxLayout, QCheckBox, QMessageBox
1515
from python_qt_binding.QtGui import QImage, QPixmap
1616
from python_qt_binding.QtCore import Qt, QTimer, pyqtSignal, QObject
17-
from std_msgs.msg import Float32MultiArray, String
17+
from std_msgs.msg import Float32MultiArray, String, Bool, Int32
1818
from sensor_msgs.msg import Image
1919
from geometry_msgs.msg import Point
2020
from cv_bridge import CvBridge
@@ -108,7 +108,7 @@ def __init__(self, node=None):
108108
self.face_pub = node.create_publisher(String, 'face_detection_data', 10)
109109
self.face_position_pub = node.create_publisher(Point, '/vision/face_position', 10)
110110
self.face_position_pub_v2 = node.create_publisher(String, '/vision/face_position_v2', 10)
111-
self.frame_pub = node.create_publisher(Image, 'camera_frame', 10)
111+
self.frame_pub = node.create_publisher(Image, '/coffee_bot/camera/image_raw', 10)
112112
self.face_image_pub = node.create_publisher(Image, 'face_images', 10)
113113
self.bridge = CvBridge()
114114

@@ -1157,6 +1157,9 @@ def __init__(self, executor):
11571157
self.ui = CameraViewer(self)
11581158
self.ui.show()
11591159

1160+
# Set up ROS control interface for separated UI communication
1161+
self._setup_ros_control_interface()
1162+
11601163
# Start a background thread for ROS spinning
11611164
self.spinning = True
11621165
self.ros_thread = threading.Thread(target=self.spin_thread)
@@ -1185,6 +1188,135 @@ def __init__(self, executor):
11851188
self.spinning = False
11861189
self.destroy_node()
11871190

1191+
def _setup_ros_control_interface(self):
1192+
"""Set up ROS subscribers and publishers for separated UI control"""
1193+
self.get_logger().info('Setting up ROS control interface for separated UI communication')
1194+
1195+
# Publishers for status updates to separated UI
1196+
self.camera_status_pub = self.create_publisher(String, '/coffee_bot/camera/status/info', 10)
1197+
self.available_cameras_pub = self.create_publisher(String, '/coffee_bot/camera/status/available', 10)
1198+
self.diagnostics_pub = self.create_publisher(String, '/coffee_bot/camera/status/diagnostics', 10)
1199+
1200+
# Subscribers for commands from separated UI
1201+
self.camera_select_sub = self.create_subscription(
1202+
Int32, '/coffee_bot/camera/cmd/select', self._on_camera_select_command, 10)
1203+
self.quality_control_sub = self.create_subscription(
1204+
Bool, '/coffee_bot/camera/cmd/quality', self._on_quality_change_command, 10)
1205+
self.face_detection_sub = self.create_subscription(
1206+
Bool, '/coffee_bot/camera/cmd/face_detection', self._on_face_detection_command, 10)
1207+
self.camera_refresh_sub = self.create_subscription(
1208+
String, '/coffee_bot/camera/cmd/refresh', self._on_camera_refresh_command, 10)
1209+
1210+
# Subscriber for state queries from separated UI
1211+
self.state_query_sub = self.create_subscription(
1212+
String, '/coffee_bot/camera/query/state', self._on_state_query, 10)
1213+
1214+
self.get_logger().info('ROS control interface setup complete')
1215+
1216+
def _on_camera_select_command(self, msg):
1217+
"""Handle camera selection command from separated UI"""
1218+
camera_index = msg.data
1219+
self.get_logger().info(f'Received camera selection command: {camera_index}')
1220+
1221+
# Forward command to the integrated UI if it exists
1222+
if hasattr(self, 'ui') and hasattr(self.ui, 'change_camera'):
1223+
# Find the combo box index for this camera index
1224+
for i in range(self.ui.camera_combo.count()):
1225+
if self.ui.camera_combo.itemData(i) == camera_index:
1226+
self.ui.camera_combo.setCurrentIndex(i)
1227+
break
1228+
1229+
# Publish status update
1230+
status_msg = String()
1231+
status_msg.data = f"Camera selection changed to index {camera_index}"
1232+
self.camera_status_pub.publish(status_msg)
1233+
1234+
def _on_quality_change_command(self, msg):
1235+
"""Handle quality change command from separated UI"""
1236+
high_quality = msg.data
1237+
self.get_logger().info(f'Received quality change command: {"high" if high_quality else "standard"}')
1238+
1239+
# Forward command to the integrated UI if it exists
1240+
if hasattr(self, 'ui') and hasattr(self.ui, 'quality_checkbox'):
1241+
self.ui.quality_checkbox.setChecked(high_quality)
1242+
1243+
# Publish status update
1244+
status_msg = String()
1245+
status_msg.data = f"Quality changed to {'high (1080p)' if high_quality else 'standard (480p)'}"
1246+
self.camera_status_pub.publish(status_msg)
1247+
1248+
def _on_face_detection_command(self, msg):
1249+
"""Handle face detection toggle command from separated UI"""
1250+
enabled = msg.data
1251+
self.get_logger().info(f'Received face detection command: {"enabled" if enabled else "disabled"}')
1252+
1253+
# Forward command to the integrated UI if it exists
1254+
if hasattr(self, 'ui') and hasattr(self.ui, 'face_detection_checkbox'):
1255+
self.ui.face_detection_checkbox.setChecked(enabled)
1256+
1257+
# Publish status update
1258+
status_msg = String()
1259+
status_msg.data = f"Face detection {'enabled' if enabled else 'disabled'}"
1260+
self.camera_status_pub.publish(status_msg)
1261+
1262+
def _on_camera_refresh_command(self, msg):
1263+
"""Handle camera refresh command from separated UI"""
1264+
self.get_logger().info('Received camera refresh command')
1265+
1266+
# Forward command to the integrated UI if it exists
1267+
if hasattr(self, 'ui') and hasattr(self.ui, 'scan_cameras'):
1268+
self.ui.scan_cameras()
1269+
1270+
# Publish status update
1271+
status_msg = String()
1272+
status_msg.data = "Camera scan completed"
1273+
self.camera_status_pub.publish(status_msg)
1274+
1275+
def _on_state_query(self, msg):
1276+
"""Handle state query from separated UI and respond with current camera state"""
1277+
self.get_logger().info('Received state query from separated UI')
1278+
1279+
# Gather current state from integrated UI
1280+
current_state = {}
1281+
1282+
if hasattr(self, 'ui'):
1283+
# Get current camera index
1284+
current_camera_index = -1
1285+
if hasattr(self.ui, 'camera_combo') and self.ui.camera_combo.count() > 0:
1286+
current_camera_index = self.ui.camera_combo.itemData(self.ui.camera_combo.currentIndex())
1287+
current_state['camera_index'] = current_camera_index
1288+
1289+
# Get quality setting
1290+
high_quality = False
1291+
if hasattr(self.ui, 'quality_checkbox'):
1292+
high_quality = self.ui.quality_checkbox.isChecked()
1293+
current_state['high_quality'] = high_quality
1294+
1295+
# Get face detection setting
1296+
face_detection = True
1297+
if hasattr(self.ui, 'face_detection_checkbox'):
1298+
face_detection = self.ui.face_detection_checkbox.isChecked()
1299+
current_state['face_detection_enabled'] = face_detection
1300+
1301+
# Get available cameras
1302+
available_cameras = []
1303+
if hasattr(self.ui, 'available_cameras'):
1304+
available_cameras = [
1305+
{"index": idx, "name": name}
1306+
for idx, name in self.ui.available_cameras
1307+
]
1308+
current_state['available_cameras'] = available_cameras
1309+
1310+
# Publish current state as JSON
1311+
import json
1312+
state_msg = String()
1313+
state_msg.data = json.dumps(current_state)
1314+
self.available_cameras_pub.publish(state_msg) # Reuse existing publisher
1315+
1316+
self.get_logger().info(f'Published current state: camera_index={current_state.get("camera_index", -1)}, '
1317+
f'high_quality={current_state.get("high_quality", False)}, '
1318+
f'face_detection={current_state.get("face_detection_enabled", True)}')
1319+
11881320
def spin_thread(self):
11891321
"""Background thread for ROS spinning"""
11901322
while self.spinning:

0 commit comments

Comments
 (0)