| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899 |
- #!/usr/bin/env python3
- # -*- coding: utf-8 -*-
- import rospy
- import cv2
- import json
- import requests
- import sys
- from pyzbar.pyzbar import decode
- from sensor_msgs.msg import Image
- from cv_bridge import CvBridge
- from qr_vision.srv import ScanQRCodes, ScanQRCodesResponse
- sys.path.append('/home/ucar/ucar_ws/src/SparkTalk')
- from SparkMain import build_prompt, ask_xinghuo, clean_json_response, validate_result_structure
- class QRVisionNode:
- def __init__(self):
- self.bridge = CvBridge()
- self.product_names = []
- self.scanned_urls = set()
- rospy.init_node('qr_vision_node', anonymous=True)
- rospy.Subscriber('/ucar_camera/image_raw', Image, self.image_callback)
- rospy.Service('/scan_qrcodes', ScanQRCodes, self.handle_scan_request)
- rospy.loginfo("二维码视觉节点已启动")
- def image_callback(self, img_msg):
- if len(self.product_names) >= 3:
- return
- frame = self.bridge.imgmsg_to_cv2(img_msg, "rgb8")
- frame_bgr = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)
- for obj in decode(frame_bgr):
- url = obj.data.decode('utf-8')
- if url in self.scanned_urls:
- continue
- rospy.loginfo("识别到二维码URL: %s", url)
- try:
- resp = requests.get(url, timeout=5)
- data = resp.json()
- if data.get("code") == 200:
- product = data["result"]
- self.product_names.append(product)
- self.scanned_urls.add(url)
- rospy.loginfo("货品: %s (%d/3)", product, len(self.product_names))
- except Exception as e:
- rospy.logwarn("请求URL失败: %s", str(e))
- def handle_scan_request(self, req):
- real_cat = req.real_category
- sim_cat = req.simulation_category
- timeout = rospy.Time.now() + rospy.Duration(15)
- while len(self.product_names) < 3 and rospy.Time.now() < timeout:
- rospy.sleep(0.5)
- if len(self.product_names) < 3:
- rospy.logwarn("只识别到%d个二维码", len(self.product_names))
- rospy.loginfo("识别到的货品: %s", str(self.product_names))
- prompt = build_prompt(real_cat, sim_cat, self.product_names)
- raw_response = ask_xinghuo(prompt)
- real_product = ""
- sim_product = ""
- try:
- cleaned = clean_json_response(raw_response)
- result = json.loads(cleaned)
- is_valid, errors = validate_result_structure(
- result, real_cat, sim_cat, self.product_names)
- if is_valid:
- real_product = result["real_task"]["matched_product"]
- sim_product = result["simulation_task"]["matched_product"]
- rospy.loginfo("决策成功: 真实=%s 仿真=%s", real_product, sim_product)
- else:
- rospy.logwarn("校验失败: %s", str(errors))
- except Exception as e:
- rospy.logerr("JSON解析失败: %s", str(e))
- saved_products = list(self.product_names)
- self.product_names = []
- self.scanned_urls = set()
- return ScanQRCodesResponse(
- product_names=saved_products,
- real_product=real_product,
- simulation_product=sim_product
- )
- if __name__ == '__main__':
- try:
- QRVisionNode()
- rospy.spin()
- except rospy.ROSInterruptException:
- pass
|