IP Camera继续前进!

JPEG编码库整合与手机监控实现
本文介绍了将JPEG编码库整合进webs的过程,虽然内存占用较大,但成功实现了手机监控功能。调试过程中解决了获取外部IP的问题,并发现了网络部分有待优化。

这两天把JPEG编码库合并到webs里面去了,效率不是很高,占用的内存有点大,大概占用3.5-4M的内存空间,

但是实现了手机监控。

url:http://coview.3322.org:8080/others/jpeg.asp

 

调试过程中发现些问题:

1.www.3322.org/dyndns/getip得到的IP地址有时候不是路由器的地址,网上又找到一个

http://www.icanhazip.com/这个暂时似乎能得到正确的IP地址

2.网络部分有些地方可以优化,正在进行中

 

(文本一(传感器): from ugot import ugot got = ugot.UGOT() got.initialize(‘192.168.8.112’) 测距 print(‘distance data:’,got.read_distance_data(11)) 陀螺仪 print(‘gyro data:’,got.read_gyro_data()) 主控姿态 print(‘attitude:’,got.get_attitude()) 文本二(小车正方形运动):from ugot import ugot import time 初始化UGOT类的实例 u = ugot.UGOT() 初始化设备 u.initialize(‘192.168.228.166’) def main(): while True: # 机器人以20的速度直行 u.mecanum_move_speed(0,20) time.sleep(2) u.mecanum_turn_speed_times(3,100,90,2) if name == “main”: main() 文本三(手势识别):#加载手势识别模型,完成手势识别 from ugot import ugot import time 初始化UGOT类的实例 u = ugot.UGOT() 初始化设备 u.initialize(‘10.10.35.42’) 手势识别 u.load_models([‘gesture’]) try: while True: print(‘------:’,u.get_gesture_result()) time.sleep(0.5) except KeyboardInterrupt: print(‘-----KeyboardInterrupt’) u.release_models() 文本四(demo-follow-line):from ugot import ugot import time camera_center_x = 320 camera_center_y = 240 max_rotate_speed = 60 base_angle2 = 90 base_angle3 = -80 u = ugot.UGOT() u.initialize(“10.10.35.25”) u.load_models([“line_recognition”]) time.sleep(2) u.set_track_recognition_line(0) #创建PID控制器。 pid_turn = u.create_pid_controller() #设置PID参数 pid_turn.set_pid(0.2, 0.001, 0) offset=0 def main(): control = MoveControl() try: #控制小车前进 control.forward() finally: control.mecanum_stop() class MoveControl: def init(self) -> None: #前进速度 self.forward_speed = 26 #索引 self.intersection_index = -1 #路口标志 self.is_cross = False u.mechanical_joint_control(0, base_angle2, base_angle3, 200) def mecanum_stop(self): u.mecanum_stop() # 计算小车原地转动的速度 def get_rotate_speed(self, check_cross=False): line_info = u.get_single_track_total_info() print(line_info) offset, line_type, x, y = line_info old_is_cross = self.is_cross self.is_cross = line_type == 2 or line_type == 3 if line_type == 2 or line_type == 3: print(line_info) if line_type == 0: return 0, line_type, 0, 0 #调用PID rotate_speed = round(pid_turn.update(offset)) print("offset=",offset) if rotate_speed > max_rotate_speed: rotate_speed = max_rotate_speed if rotate_speed < -max_rotate_speed: rotate_speed = -max_rotate_speed return rotate_speed, line_type, x, y #控制小车前进 def forward(self): while True: old_is_cross = self.is_cross #获取旋转速度 speed_info = self.get_rotate_speed() rotate_speed, line_type, x, y = speed_info new_is_cross = self.is_cross if old_is_cross and not new_is_cross: self.intersection_index = self.intersection_index + 1 print(f"------------------------路口计数增加,序号:{self.intersection_index + 1}, 坐标x:{x}, y:{y}------------------------") if self.intersection_index >= 5: u.mecanum_stop() s = f"识别到第{str(self.intersection_index+1)}个路口,没有定义控制逻辑,停止" u.play_audio_tts(s, 0, True) break print(f"已顺利通过第{str(self.intersection_index + 1)}个路口") if self.intersection_index == 5 - 1 : self.mecanum_stop() s = f"已经处理完{str(self.intersection_index+1)}个路口,终止本次巡线" u.play_audio_tts(s, 0, True) return if line_type == 0: # 没有识别到线,停止 # u.mecanum_move_xyz(0, 3, -int(rotate_speed)) u.mecanum_stop() print("没有识别到线,停止") continue # 巡线前进 u.mecanum_move_xyz(0, self.forward_speed, -int(rotate_speed)) if name == “main”: main() 文本五(demo-apriltag):from ugot import ugot import time import math camera_center_x = 320 #定义一个的类 class FaceAprilTag(): #类的构造函数(init方法),用于初始化类的实例 def init(self, ugot) -> None: self.u = ugot pass #找到标签,并且靠近它 def find_apriltag_and_face_it(self, tagid): #获取标签信息 tag = self.find_april_tag(tagid) #靠近标签 self.approach_apriltag(tagid, tag) #获取标签信息 def get_apriltag_total_info_by_id(self, tagid=0): a = self.u.get_apriltag_total_info() for info in a: id = info[0] if id == tagid: return info return None #检查并修正传入的角度值 degreey def check_degreey(self, degreey): if degreey < 90 and degreey > 0: degreey = 180 - degreey if degreey < 0 and degreey > -90: degreey = -180 - degreey if degreey < 0: degreey = -180 - degreey if degreey > 0: degreey = 180 - degreey return degreey #找到标签 def find_april_tag(self, tagid=0): while True: #获取标签信息 tag = self.get_apriltag_total_info_by_id(tagid) if tag is not None and tag[0] == tagid: id, center_x, center_y, height, width, area, distance5, distance7, distance10, x, y, z ,h,v= tag gap = camera_center_x - center_x print(f"gap to center is {gap}") if abs(gap) < 100: self.u.mecanum_stop() return tag self.u.mecanum_turn_speed(2, 16) #靠进标签 def approach_apriltag(self, tagid, info): id, center_x, center_y, height, width, area, distance5, distance7, distance10, x, y, z ,h,v= info #距离*0.6是为了让小车靠进标签时,始终保持一段距离(避免考太进),round保留整数 abs求绝对值 b=abs(round(distance5 * 100*0.6)) if b>20: fd=round(b) #*100 是为了化单位 cm self.u.mecanum_move_speed_times(0, 20, b, 1) self.u.mecanum_stop() #获取标签信息 info = self.get_apriltag_total_info_by_id(tagid) if info is None: #面对标签 info = self.find_april_tag(tagid) id, center_x, center_y, height, width, area, distance5, distance7, distance10, x, y, z,h,v = info # 弧度转角度 degreey = math.degrees(y) # 检查并修正角度值 degreey degreey = self.check_degreey(degreey) print("approach_apriltag", id, distance5, degreey) direct = 3 if degreey > 0 else 2 direct_str = "右转" if degreey >0 else "左转" #计算变量y的正弦值 siny = math.sin(y) #计算小车与标签的偏移量 dist_offset = abs(int(siny * distance5 * 100)) d = abs(int(degreey)) #左转、右转操作 if d > 0: print(f"approach_apriltag {direct_str}:{degreey}") self.u.mecanum_turn_speed_times(direct, 60, d, 2) self.u.mecanum_stop() left_right_flag = 90 if degreey < 0 else -90 left_right_flag_str = "右移" if degreey < 0 else "左移" total_offset_dist = dist_offset #平移操作 if abs(total_offset_dist) > 0: print(f"approach_apriltag {left_right_flag_str}:{total_offset_dist}") self.u.mecanum_translate_speed_times(left_right_flag, 30, total_offset_dist, 1) u = ugot.UGOT() u.initialize(“10.10.35.21”) u.load_models([“apriltag_qrcode”]) time.sleep(2) base_angle2 = 90 base_angle3 = -80 u.mechanical_joint_control(0, base_angle2, base_angle3, 200) def main(): try: apriltag_tool = FaceAprilTag(u) apriltag_tool.find_apriltag_and_face_it(0) finally: u.mecanum_stop() if name == “main”: main() 文本六(near-the-color-block):from ugot import ugot class Color: GREEN = “绿色” BLUE = “蓝色” PURPLE = “紫色” RED = “红色” UN_SET = “未设置” u = ugot.UGOT() u.initialize(“10.10.35.25”) u.load_models([“color_recognition”]) u.show_light_rgb_effect(255, 100, 100, 0) max_forward_speed = 40 #创建PID控制器 pid_forward_speed = u.create_pid_controller() #设置PID控制参数 pid_forward_speed.set_pid(0.9, 0, 0.001) 计算前进速度(负数就表示后退速度) def get_forward_speed(target_color): #获取传感器数据 distance = u.read_distance_data(21) print(“distance:”, distance) dis=8 - distance #调用PID forward_speed = round(pid_forward_speed.update(dis)) if forward_speed > max_forward_speed: forward_speed = max_forward_speed if forward_speed < -max_forward_speed: forward_speed = -max_forward_speed print(“forward_speed:”, forward_speed) return forward_speed 靠近目标 def reach_target(target_color): forward_speed = 10 falg=True while falg: color_info = u.get_color_total_info() print(color_info) [color, type, target_center_x, target_center_y, height, width, area] = color_info if ( len(color) == 0 or len(type) == 0 or target_center_x == -1 or str(target_color) != color ): u.mecanum_stop() else: falg=False while abs(forward_speed) > 1: direction = 0 if forward_speed > 0 else 1 print(“direction:”, direction) u.mecanum_move_speed(direction, abs(forward_speed)) #获取小车前进速度 forward_speed = get_forward_speed(target_color) u.mecanum_stop() if name == “main”: target_color=Color.GREEN reach_target(target_color) 文本七(rotation-test-no-pid): from ugot import ugot camera_center_x = 320 camera_center_y = 240 max_rotate_speed = 20 max_forward_speed = 60 class GrabObject(): # 开始执行靠近小球任务 def go_and_grap_object(self, target_color): start_y_speed = 0 # 调整小车朝向 self.adjust_direction(start_y_speed, target_color) # 计算小车原地转动的速度 def get_rotate_speed(self, target_color): color_info = u.get_color_total_info() [color, type, target_center_x, target_center_y, height, width, area] = color_info if ( len(color) == 0 or len(type) == 0 or target_center_x == -1 or str(target_color) != color ): target_center_x = 460 return -60 rotate_speed = target_center_x - camera_center_x if rotate_speed > max_rotate_speed: rotate_speed = max_rotate_speed if rotate_speed < -max_rotate_speed: rotate_speed = -max_rotate_speed print("rotate_speed:",rotate_speed) return rotate_speed # 调整小车朝向 def adjust_direction(self, forward_speed, target_color): #获取小车旋转速度 rotate_speed = self.get_rotate_speed(target_color) while abs(rotate_speed) > 3: u.mecanum_move_xyz(0, forward_speed, -int(rotate_speed)) #获取小车旋转速度 rotate_speed = self.get_rotate_speed(target_color) u = ugot.UGOT() u.initialize(“10.10.35.25”) u.load_models([“color_recognition”]) grab_object = GrabObject() if name == “main”: target_color=“绿色” grab_object.go_and_grap_object(target_color) 文本八(rotation-test-pid):from ugot import ugot camera_center_x = 320 camera_center_y = 240 max_rotate_speed = 60 max_forward_speed = 60 u = ugot.UGOT() u.initialize(“10.10.35.25”) u.load_models([ “color_recognition”]) class GrabObject(): def __init__(self) -> None: #创建PID控制器 self.pid_rotate_speed = u.create_pid_controller() #设置PID控制器参数 self.pid_rotate_speed.set_pid(0.3, 0, 0.01) self.pid_forward_speed = u.create_pid_controller() self.pid_forward_speed.set_pid(0.9, 0, 0.001) self.gap = 0 # def go_and_grap_object(self, target_color): start_y_speed = 0 # 调整小车朝向 self.adjust_direction(start_y_speed, target_color) # 计算小车原地转动的速度 def get_rotate_speed(self, target_color): color_info = u.get_color_total_info() [color, type, target_center_x, target_center_y, height, width, area] = color_info if ( len(color) == 0 or len(type) == 0 or target_center_x == -1 or str(target_color) != color ): target_center_x = 460 #! return -60 gap = target_center_x - camera_center_x #调用PID rotate_speed = round(self.pid_rotate_speed.update(gap)) if rotate_speed > max_rotate_speed: rotate_speed = max_rotate_speed if rotate_speed < -max_rotate_speed: rotate_speed = -max_rotate_speed return rotate_speed # 调整小车朝向 def adjust_direction(self, forward_speed, target_color): #获取小车旋速度 rotate_speed = self.get_rotate_speed(target_color) while abs(rotate_speed) > 3: u.mecanum_move_xyz(0, forward_speed, int(rotate_speed)) # 计算小车原地转动的速度 rotate_speed = self.get_rotate_speed(target_color) if name == “main”: grab_object = GrabObject() target_color=“绿色” grab_object.go_and_grap_object(target_color) 文本九(机器臂接口测试):from ugot import ugot import time got = ugot.UGOT() 初始化设备 got.initialize(‘192.168.228.166’) 打开夹手 got.mechanical_clamp_release() print(‘-----1:’,got.mechanical_get_clamp_status()) time.sleep(1) 闭合夹手 got.mechanical_clamp_close() print(‘-----2:’,got.mechanical_get_clamp_status()) time.sleep(1) 机械臂复位 got.mechanical_arms_restory() 关节角度控制 got.mechanical_joint_control(0, 0, 0, 500) 移动位置 got.mechanical_move_axis(20, 12, 0, 1000) 文本十(红外传感器):from ugot import ugot got=ugot.UGOT() camera_stopped=False got.initialize(“10.10.35.167”) dis=got.read_distance_data(21) print(“dis=”,dis) 文本十一(自然语言处理):#语音转文本 from ugot import ugot got=ugot.UGOT() camera_stopped=False got.initialize(“10.10.35.167”) ASR asr_result = got.start_audio_asr() print(“Ugot=:”,asr_result) NLP got.start_audio_nlp(asr_result, True) TTS got.play_audio_tts(‘当然可以!’, 0, True) 文本十二(颜色识别):from ugot import ugot import time got = ugot.UGOT() got.initialize(‘10.10.35.42’) got.load_models([‘color_recognition’]) while True: print(‘-------:’,got.get_color_total_info()) time.sleep(0.5) )任务一:物品运输 车形机器人根据语音指令按指定路线去取货区抓取物品运 输至指定物品存放区域。任务演示步骤如下: (1) 将车形机器人放置到启动区①中。车形机器人的垂直投 影区域应完全位于启动区①的线框范围内。 (2) 选手根据任务卡指示,根据任务卡将色块放置于取货区 中对应的位置内。 (3) 选手在启动区①给车形机器人下达指令既“请搬运 X 色 块,运输至 Y 号存储区”。(X 为选手抽取的目标色块颜色,Y 为选手抽取的目标存储区)。 (4) 车形机器人巡线行驶至取货区 按本要求调整已有代码,是它可以正确执行任务
06-07
(from ugot import ugot # 导入UGOT机器人控制库 import time # 导入时间模块,用于延时操作 import math # 导入数学模块,用于数学计算 class Color: RED = "红色" # 定义颜色常量:红色 BLUE = "蓝色" # 定义颜色常量:蓝色 GREEN = "绿色" # 定义颜色常量:绿色 YELLOW = "黄色" # 定义颜色常量:黄色 got = ugot.UGOT() # 创建UGOT机器人控制对象 camera_stopped = False # 摄像头状态标志位,初始为未停止 got.initialize("172.20.10.2") # 初始化机器人连接,指定IP地址 # 测距 print('distance data:',got.read_distance_data(11)) # 陀螺仪 print('gyro data:',got.read_gyro_data()) # 主控姿态 print('attitude:',got.get_attitude()) dis=got.read_distance_data(21) print("dis=",dis) got.load_models(["line_recognition", "color_recognition"]) # 加载线识别和颜色识别模型 class Line: def __init__(self): self.target_color = Color.GREEN # 设置目标颜色为绿色 camera_center_x = 320 # 摄像头图像中心X坐标 camera_center_y = 240 # 摄像头图像中心Y坐标 self.max_rotate_speed = 60 # 最大旋转速度 self.base_angle2 = 90 # 机械臂关节2基准角度 self.base_angle3 = -80 # 机械臂关节3基准角度 self.grab_flag = False # 抓取完成标志位 got.load_models(["line_recognition"]) # 加载线识别模型 time.sleep(2) # 等待2秒,确保模型加载完成 got.set_track_recognition_line(0) # 设置线识别模式 self.pid_turn = got.create_pid_controller() # 创建PID控制器用于转向 self.pid_turn.set_pid(0.2, 0.001, 0) # 设置PID参数:P=0.2, I=0.001, D=0 self.offset = 0 # 偏移量初始值 self.forward_speed = 15 # 前进速度 self.intersection_index = -1 # 路口索引初始值 self.is_cross = False # 是否在路口标志位 self.flag = 0 # 转弯标志位 self.current_state = "FORWARD" # 当前状态:前进 # 初始化抓取模块参数 self.focal_length = 600 # 摄像头焦距 self.image_width = 640 # 图像宽度 self.target_distance = 150 # 目标距离(mm) self.center_threshold = 30 # 中心偏差阈值(像素) def mecanum_stop(self): got.mecanum_stop() # 停止麦克纳姆轮运动 def get_rotate_speed(self, check_cross=False): line_info = got.get_single_track_total_info() # 获取单轨识别信息 # 解析线信息:偏移量、线类型、坐标X、坐标Y offset, line_type, x, y = line_info if line_info else (0, 0, 0, 0) self.is_cross = line_type == 3 # 判断是否为路口 if line_type == 2 or line_type == 3: print("识别到路口") # 打印路口识别信息 if line_type == 0: return 0, line_type, 0, 0 # 未识别到线时返回0 # 计算旋转速度并限制最大值 rotate_speed = round(self.pid_turn.update(offset)) if rotate_speed > self.max_rotate_speed: rotate_speed = self.max_rotate_speed if rotate_speed < -self.max_rotate_speed: rotate_speed = -self.max_rotate_speed return rotate_speed, line_type, x, y # 返回旋转速度和线信息 def detect_color_block(self): """平移中检测颜色物块""" try: color_info = got.get_color_total_info() # 获取颜色识别总信息 if len(color_info) >= 7: # 解析颜色信息:颜色、中心X、中心Y、宽度、高度、面积 color, _, center_x, center_y, width, height, area = color_info if color == self.target_color: # 计算物块距离 distance = self.calculate_distance(center_x, width) if distance <= self.target_distance + 50: # 50mm检测范围 print(f"检测到{color}物块,开始抓取") # 打印检测到物块信息 return center_x, center_y, distance # 返回物块中心和距离 except: return None, None, 0 # 异常时返回None return None, None, 0 # 未检测到物块时返回None def calculate_distance(self, center_x, width): """通过像素尺寸计算距离""" pixel_size = width # 物块像素宽度 return (pixel_size * self.focal_length) / 40 # 根据焦距计算实际距离(40mm为标准物块尺寸) def adjust_for_grab(self, center_x): """调整方向对准物块""" offset = center_x - self.image_width / 2 # 计算中心偏移量 rotate_speed = offset # 旋转速度等于偏移量 rotate_speed = max(-20, min(rotate_speed, 20)) # 限制旋转速度范围 got.mecanum_move_xyz(0, 0, -int(rotate_speed)) # 执行旋转动作 return abs(offset) <= self.center_threshold # 返回是否对准 def approach_and_grab(self, center_x, distance): """靠近并抓取物块""" while True: print('-------:', got.get_color_total_info()) time.sleep(0.5) self.mecanum_stop() # 停止移动 time.sleep(0.5) # 等待0.5秒 # 调整方向对准物块 while not self.adjust_for_grab(center_x): center_x, _, _ = self.detect_color_block() # 重新检测物块 if not center_x: break # 未检测到物块时退出循环 # 靠近物块 forward_speed = 10 # 前进速度 while distance > 100 and center_x: got.mecanum_move_xyz(0, forward_speed, 0) # 向前移动 center_x, _, distance = self.detect_color_block() # 更新物块信息 time.sleep(0.1) # 等待0.1秒 self.mecanum_stop() # 停止移动 time.sleep(0.5) # 等待0.5秒 # 执行抓取 self.perform_grab() # 调用抓取方法 self.grab_flag = True # 设置抓取完成标志 return True # 返回抓取成功 def perform_grab(self): """执行抓取动作""" print("执行抓取...") # 打印抓取开始信息 # 机械臂移动到抓取位置 got.mechanical_move_axis(20, 12, 0, 1000) time.sleep(1) # 等待1秒 # 闭合夹手 got.mechanical_clamp_close() time.sleep(1) # 等待1秒 print("抓取成功") # 打印抓取成功信息 def forward(self): while True: if self.grab_flag: # 已完成抓取则退出循环 break old_is_cross = self.is_cross # 保存旧的路口状态 speed_info = self.get_rotate_speed() # 获取旋转速度信息 rotate_speed, line_type, x, y = speed_info # 解析速度信息 new_is_cross = self.is_cross # 获取新的路口状态 if old_is_cross and not new_is_cross: self.intersection_index += 1 # 路口索引加1 print(f"路口计数增加,序号:{self.intersection_index + 1}") # 打印路口信息 if self.intersection_index >= 5: got.mecanum_stop() # 停止移动 break # 退出循环 if line_type == 2 or line_type == 3: print(f"右转{x}, {y}") # 打印转弯信息 time.sleep(2) # 等待2秒 if self.flag <= 1: # 执行右转动作 got.mecanum_turn_speed_times(3, 60, 80, 2) self.flag += 1 # 转弯标志加1 else: got.mecanum_stop() # 停止移动 print("到达取货区") # 打印到达取货区信息 break # 退出循环 if line_type == 0: got.mecanum_stop() # 停止移动 print("没有识别到线,停止") # 打印未识别到线信息 continue # 继续循环 # 平移中检测物块 center_x, center_y, distance = self.detect_color_block() if center_x: # 检测到物块 self.mecanum_stop() # 停止移动 if self.approach_and_grab(center_x, distance): continue # 抓取完成后继续循环 # 正常巡线平移 got.mecanum_move_xyz(0, self.forward_speed, -int(rotate_speed)) # 执行移动动作 time.sleep(0.05) # 控制循环频率 def main(self): try: self.forward() # 调用前进方法 finally: got.mecanum_stop() # 确保机器人停止 if __name__ == '__main__': line = Line() # 创建Line实例 line.main() # 调用main方法 # 以下为原代码保留部分(略作适配) class BlockApproacher: def __init__(self, target_color=Color.GREEN, target_size=40): self.u = ugot.UGOT() # 创建UGOT机器人控制对象 self.u.initialize("172.20.10.2") # 初始化机器人连接 self.u.load_models(["color_recognition"]) # 加载颜色识别模型 self.target_color = target_color # 设置目标颜色 self.target_size = target_size # 设置目标物块尺寸(mm) self.set_color_light() # 设置灯光颜色 self.max_forward_speed = 30 # 最大前进速度 self.max_turn_speed = 20 # 最大旋转速度 self.max_strafe_speed = 25 # 最大横向移动速度 self.target_distance = 150 # 目标距离(mm) self.center_threshold = 30 # 中心偏差阈值(像素) self.size_threshold = 5 # 尺寸偏差阈值(mm) self.stability_time = 1.5 # 稳定时间要求(秒) self.search_timeout = 30 # 搜索超时时间(秒) self.focal_length = 600 # 摄像头焦距(像素) self.image_width = 640 # 图像宽度(像素) self.image_height = 480 # 图像高度(像素) self.pid_forward = self.u.create_pid_controller() # 创建前进PID控制器 self.pid_strafe = self.u.create_pid_controller() # 创建横向PID控制器 self.setup_pid() # 配置PID参数 self.current_state = "SEARCHING" # 当前状态:搜索 self.stable_start_time = 0 # 稳定状态开始时间 self.last_detected_time = 0 # 最后检测到目标时间 def set_color_light(self): """根据目标颜色设置灯光""" if self.target_color == Color.RED: self.u.show_light_rgb_effect(255, 0, 0, 0) # 红色灯光 elif self.target_color == Color.BLUE: self.u.show_light_rgb_effect(0, 0, 255, 0) # 蓝色灯光 elif self.target_color == Color.GREEN: self.u.show_light_rgb_effect(0, 255, 0, 0) # 绿色灯光 elif self.target_color == Color.YELLOW: self.u.show_light_rgb_effect(255, 255, 0, 0) # 黄色灯光 else: self.u.show_light_rgb_effect(255, 255, 255, 0) # 白色灯光 def setup_pid(self): """配置PID参数""" self.pid_forward.set_pid(0.5, 0.001, 0.02) # 前进PID参数 self.pid_strafe.set_pid(0.4, 0.001, 0.02) # 横向PID参数 def calculate_real_size(self, pixel_size, distance): """根据像素尺寸和距离计算实际尺寸(mm)""" if distance <= 0: return 0 return (pixel_size * distance) / self.focal_length # 计算实际尺寸 def get_block_info(self): """获取物块信息,只关注目标颜色和尺寸""" try: color_info = self.u.get_color_total_info() # 获取颜色识别信息 if len(color_info) < 7: # 确保数据完整性 return None color, _, center_x, center_y, width, height, area = color_info # 解析颜色信息 if color != self.target_color: # 过滤非目标颜色 return None # 计算物块在图像中的平均尺寸(像素) block_size_px = (width + height) / 2 distance = self.get_distance() # 获取距离 real_size = self.calculate_real_size(block_size_px, distance) # 计算实际尺寸 # 过滤尺寸不符的物体 if abs(real_size - self.target_size) > self.size_threshold: return None print(f"检测到目标 - 中心: ({center_x}, {center_y}), 距离: {distance}mm") return { 'center_x': center_x, 'center_y': center_y, 'distance': distance, 'real_size': real_size, 'pixel_size': block_size_px } except Exception as e: print(f"获取物块信息出错: {e}") # 打印异常信息 return None def get_distance(self): """获取距离传感器数据""" try: distance = self.u.read_distance_data(21) # 读取距离传感器数据 return distance if distance is not None else 0 # 返回距离或0 except Exception as e: print(f"读取距离传感器出错: {e}") # 打印异常信息 return 0 def calculate_movement(self): """计算移动速度(前进、横向)""" block_info = self.get_block_info() # 获取物块信息 distance = self.get_distance() # 获取距离 # 如果未检测到目标物块 if block_info is None: return 0, 0, False, distance # 返回0速度和未检测标志 self.last_detected_time = time.time() # 更新最后检测时间 # 1. 计算前进速度 (基于距离误差) distance_error = block_info['distance'] - self.target_distance forward_speed = self.pid_forward.update(distance_error) # PID计算前进速度 # 2. 计算横向移动速度 (使目标位于右侧) target_x = self.image_width * 2 / 3 # 目标位置X坐标(右侧1/3处) horizontal_error = target_x - block_info['center_x'] # 横向误差 strafe_speed = self.pid_strafe.update(horizontal_error) # PID计算横向速度 # 动态调整速度限制 if block_info['distance'] > self.target_distance * 1.5: speed_factor = 1.2 # 远距离时更快 else: speed_factor = 0.8 # 中近距离更谨慎 # 限制速度范围 forward_speed = self.clamp(forward_speed * speed_factor, -self.max_forward_speed, self.max_forward_speed) strafe_speed = self.clamp(strafe_speed * speed_factor, -self.max_strafe_speed, self.max_strafe_speed) return forward_speed, strafe_speed, True, block_info['distance'] # 返回速度和检测状态 def clamp(self, value, min_val, max_val): """限制数值范围""" return max(min_val, min(value, max_val)) # 返回限制后的数值 def right_side_scan(self): """向右侧扫描寻找目标""" print("执行右侧扫描...") # 打印扫描信息 # 分三步向右移动并扫描 for i in range(3): # 向右移动 self.u.mecanum_move_xyz(15, 0, 0) time.sleep(0.8) # 等待0.8秒 self.u.mecanum_stop() # 停止移动 # 检查是否找到目标 if self.get_block_info() is not None: return True # 找到目标返回True # 小幅度前后移动 self.u.mecanum_move_xyz(0, 10, 0) time.sleep(0.5) # 等待0.5秒 self.u.mecanum_move_xyz(0, -10, 0) time.sleep(0.5) # 等待0.5秒 self.u.mecanum_stop() # 停止移动 return False # 未找到目标返回False def approach_from_right(self): """从右侧平行靠近目标物块""" print(f"开始寻找并靠近{self.target_size}mm的{self.target_color}物块...") # 打印任务开始信息 search_start_time = time.time() # 记录搜索开始时间 while True: # 检查搜索超时 if time.time() - search_start_time > self.search_timeout: print("搜索超时,未找到目标") # 打印超时信息 self.u.mecanum_stop() # 停止移动 return False # 返回失败 # 获取移动指令 forward_speed, strafe_speed, target_found, distance = self.calculate_movement() if not target_found: self.current_state = "SEARCHING" # 设置状态为搜索 self.u.mecanum_stop() # 停止移动 # 执行右侧扫描 if not self.right_side_scan(): print("未找到目标,继续搜索") # 打印未找到信息 time.sleep(0.5) # 等待0.5秒 continue else: print("找到目标!") # 打印找到目标信息 self.current_state = "APPROACHING" # 设置状态为靠近 else: self.current_state = "APPROACHING" # 设置状态为靠近 # 执行移动 (主要向右移动) self.u.mecanum_move_xyz(strafe_speed, forward_speed, 0) # 执行移动动作 # 检查是否达到稳定状态 block_info = self.get_block_info() if block_info is not None: # 检查三个条件: # 1. 目标在右侧区域 # 2. 距离合适 # 3. 尺寸匹配 is_on_right = abs(block_info['center_x'] - self.image_width*2/3) < self.center_threshold is_proper_distance = abs(block_info['distance'] - self.target_distance) < 10 # 10mm容差 is_proper_size = abs(block_info['real_size'] - self.target_size) < self.size_threshold if is_on_right and is_proper_distance and is_proper_size: if self.stable_start_time == 0: self.stable_start_time = time.time() # 记录稳定开始时间 print("进入稳定状态...") # 打印进入稳定状态信息 else: stable_duration = time.time() - self.stable_start_time # 计算稳定持续时间 print(f"稳定持续时间: {stable_duration:.2f}秒") # 打印稳定时间 if stable_duration >= self.stability_time: # 检查稳定时间 print(f"已从右侧稳定靠近目标物块!") # 打印完成信息 self.u.mecanum_stop() # 停止移动 self.indicate_success() # 执行成功指示 return True # 返回成功 else: self.stable_start_time = 0 # 重置稳定开始时间 else: self.stable_start_time = 0 # 重置稳定开始时间 time.sleep(0.05) # 控制循环频率 def indicate_success(self): """成功指示""" # 闪烁灯光表示成功 for _ in range(3): self.set_color_light() # 设置目标颜色灯光 time.sleep(0.3) # 等待0.3秒 self.u.show_light_rgb_effect(0, 0, 0, 0) # 关闭灯光 time.sleep(0.2) # 等待0.2秒 self.set_color_light() # 恢复目标颜色灯光 def main(): # 设置目标参数 target_color = Color.GREEN # 目标颜色 target_size = 40 # 目标物块棱长(mm) approacher = BlockApproacher(target_color, target_size) # 创建BlockApproacher实例 try: # 执行从右侧靠近目标的任务 success = approacher.approach_from_right() # 调用靠近方法 if success: print(f"成功完成靠近{target_size}mm{target_color}物块的任务") # 打印成功信息 else: print("任务失败") # 打印失败信息 except KeyboardInterrupt: print("用户中断,停止机器人") # 打印中断信息 finally: # 确保机器人停止 approacher.u.mecanum_stop() # 停止机器人移动 if __name__ == "__main__": main() # 调用主函数 # 机械臂控制保留部分 got.mechanical_clamp_release() # 打开夹手 print('-----1:', got.mechanical_get_clamp_status()) # 打印夹手状态 time.sleep(1) # 等待1秒 got.mechanical_clamp_close() # 闭合夹手 print('-----2:', got.mechanical_get_clamp_status()) # 打印夹手状态 time.sleep(1) # 等待1秒 got.mechanical_arms_restory() # 机械臂复位 got.mechanical_joint_control(0, 0, 0, 500) # 关节角度控制 got.mechanical_move_axis(20, 12, 0, 1000) # 移动机械臂到指定位置)微调代码,使Ugot机器可以识别颜色,并抓取
06-17
#include "ucar/ucar.hpp" #include <tf2/LinearMath/Quaternion.h> #include <ros/console.h> FileTransfer::FileTransfer(const std::string& baseDir ) : m_baseDir(baseDir), m_running(false), m_serverThread() { createDirectory(m_baseDir); } FileTransfer::~FileTransfer() { stopServer(); } // 功能1:保存字符串到本地文件 bool FileTransfer::saveToFile(const std::string& content, const std::string& filename) { std::string fullPath = m_baseDir + "/" + filename; std::ofstream file(fullPath); if (!file.is_open()) { std::cerr << "无法打开文件: " << fullPath << std::endl; return false; } file << content; file.close(); std::cout << "文件已保存到: " << fullPath << std::endl; return true; } // 功能2:发送文件到指定IP bool FileTransfer::sendTo(const std::string& serverIP, int port, const std::string& localFile, const std::string& remotePath ) { // 1. 读取文件内容 std::ifstream file(localFile, std::ios::binary | std::ios::ate); if (!file.is_open()) { std::cerr << "无法打开本地文件: " << localFile << std::endl; return false; } size_t fileSize = file.tellg(); file.seekg(0, std::ios::beg); std::vector<char> buffer(fileSize); if (!file.read(buffer.data(), fileSize)) { std::cerr << "读取文件错误: " << localFile << std::endl; return false; } file.close(); // 2. 创建Socket int sock = socket(AF_INET, SOCK_STREAM, 0); if (sock < 0) { std::cerr << "创建Socket失败: " << strerror(errno) << std::endl; return false; } // 3. 连接服务器 sockaddr_in serverAddr; memset(&serverAddr, 0, sizeof(serverAddr)); serverAddr.sin_family = AF_INET; serverAddr.sin_port = htons(port); if (inet_pton(AF_INET, serverIP.c_str(), &serverAddr.sin_addr) <= 0) { std::cerr << "无效的IP地址: " << serverIP << std::endl; close(sock); return false; } if (connect(sock, (sockaddr*)&serverAddr, sizeof(serverAddr)) < 0) { std::cerr << "连接服务器失败: " << strerror(errno) << std::endl; close(sock); return false; } // 4. 发送文件信息 if (!sendData(sock, remotePath, buffer.data(), fileSize)) { close(sock); return false; } close(sock); std::cout << "文件已发送到 " << serverIP << ":" << port << " 保存为 " << remotePath << std::endl; return true; } // 功能3:阻塞等待接收文件并读取内容 std::string FileTransfer::receiveAndRead(int port, int timeoutMs ) { // 确保服务器正在运行 if (!m_running) { startServer(port); } // 等待文件到达 ReceivedFile file; if (!waitForFile(file, timeoutMs)) { throw std::runtime_error("等待文件超时或服务器停止"); } stopServer(); // 返回文件内容 return std::string(file.content.data(), file.content.size()); } // 启动服务器(后台线程) void FileTransfer::startServer(int port) { if (m_running) { stopServer(); } m_running = true; m_serverThread = std::thread(&FileTransfer::serverThreadFunc, this, port); } // 停止服务器 void FileTransfer::stopServer() { if (m_running) { m_running = false; if (m_serverThread.joinable()) { m_serverThread.join(); } } } // 创建目录 bool FileTransfer::createDirectory(const std::string& path) { if (mkdir(path.c_str(), 0777) == -1 && errno != EEXIST) { std::cerr << "无法创建目录: " << path << " - " << strerror(errno) << std::endl; return false; } return true; } // 发送数据到socket bool FileTransfer::sendData(int sock, const std::string& remotePath, const char* data, size_t size) { // 1. 发送路径长度和路径 uint32_t pathLen = htonl(static_cast<uint32_t>(remotePath.size())); if (send(sock, &pathLen, sizeof(pathLen), 0) != sizeof(pathLen)) { std::cerr << "发送路径长度失败" << std::endl; return false; } if (send(sock, remotePath.c_str(), remotePath.size(), 0) != static_cast<ssize_t>(remotePath.size())) { std::cerr << "发送路径失败" << std::endl; return false; } // 2. 发送文件长度和内容 uint32_t netSize = htonl(static_cast<uint32_t>(size)); if (send(sock, &netSize, sizeof(netSize), 0) != sizeof(netSize)) { std::cerr << "发送文件长度失败" << std::endl; return false; } ssize_t totalSent = 0; while (totalSent < static_cast<ssize_t>(size)) { ssize_t sent = send(sock, data + totalSent, size - totalSent, 0); if (sent < 0) { std::cerr << "发送文件内容失败: " << strerror(errno) << std::endl; return false; } totalSent += sent; } return true; } // 服务器线程函数 void FileTransfer::serverThreadFunc(int port) { // 1. 创建Socket int listenSock = socket(AF_INET, SOCK_STREAM, 0); if (listenSock < 0) { std::cerr << "创建Socket失败: " << strerror(errno) << std::endl; return; } // 2. 设置SO_REUSEADDR int opt = 1; setsockopt(listenSock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); // 3. 绑定端口 sockaddr_in serverAddr; memset(&serverAddr, 0, sizeof(serverAddr)); serverAddr.sin_family = AF_INET; serverAddr.sin_addr.s_addr = INADDR_ANY; serverAddr.sin_port = htons(port); if (bind(listenSock, (sockaddr*)&serverAddr, sizeof(serverAddr)) < 0) { std::cerr << "绑定端口失败: " << strerror(errno) << std::endl; close(listenSock); return; } // 4. 开始监听 if (listen(listenSock, 5) < 0) { std::cerr << "监听失败: " << strerror(errno) << std::endl; close(listenSock); return; } std::cout << "文件接收服务器启动,监听端口: " << port << std::endl; // 5. 接受连接循环 bool receivedFile = false; while (m_running&& !receivedFile) { // 设置超时以定期检查停止条件 fd_set readSet; FD_ZERO(&readSet); FD_SET(listenSock, &readSet); timeval timeout{0, 100000}; // 100ms int ready = select(listenSock + 1, &readSet, nullptr, nullptr, &timeout); if (ready < 0) { if (errno != EINTR) { std::cerr << "select错误: " << strerror(errno) << std::endl; } continue; } if (ready == 0) continue; // 超时,继续循环 // 6. 接受客户端连接 sockaddr_in clientAddr; socklen_t clientLen = sizeof(clientAddr); int clientSock = accept(listenSock, (sockaddr*)&clientAddr, &clientLen); if (clientSock < 0) { if (errno != EAGAIN && errno != EWOULDBLOCK) { std::cerr << "接受连接失败: " << strerror(errno) << std::endl; } continue; } char clientIP[INET_ADDRSTRLEN]; inet_ntop(AF_INET, &clientAddr.sin_addr, clientIP, INET_ADDRSTRLEN); std::cout << "收到来自 " << clientIP << " 的文件传输请求" << std::endl; // 7. 接收文件 ReceivedFile file; if (receiveFile(clientSock, file)) { std::lock_guard<std::mutex> lock(m_mutex); m_receivedFiles.push(std::move(file)); receivedFile = true; m_cv.notify_one(); // 通知等待线程 } close(clientSock); } close(listenSock); std::cout << "文件接收服务器已停止" << std::endl; } // 接收文件 bool FileTransfer::receiveFile(int sock, ReceivedFile& file) { // 1. 接收路径长度和路径 uint32_t pathLen; if (recv(sock, &pathLen, sizeof(pathLen), 0) != sizeof(pathLen)) { std::cerr << "接收路径长度失败" << std::endl; return false; } pathLen = ntohl(pathLen); std::vector<char> pathBuffer(pathLen + 1); ssize_t received = recv(sock, pathBuffer.data(), pathLen, 0); if (received != static_cast<ssize_t>(pathLen)) { std::cerr << "接收路径失败" << std::endl; return false; } pathBuffer[pathLen] = '\0'; file.filename = pathBuffer.data(); // 2. 接收文件长度 uint32_t fileSize; if (recv(sock, &fileSize, sizeof(fileSize), 0) != sizeof(fileSize)) { std::cerr << "接收文件长度失败" << std::endl; return false; } fileSize = ntohl(fileSize); // 3. 接收文件内容 file.content.resize(fileSize); ssize_t totalReceived = 0; while (totalReceived < static_cast<ssize_t>(fileSize) && m_running) { ssize_t bytes = recv(sock, file.content.data() + totalReceived, fileSize - totalReceived, 0); if (bytes <= 0) { if (bytes < 0) { std::cerr << "接收文件内容失败: " << strerror(errno) << std::endl; } return false; } totalReceived += bytes; } std::cout << "成功接收文件: " << file.filename << " (" << fileSize << " 字节)" << std::endl; return true; } // 等待文件到达 bool FileTransfer::waitForFile(ReceivedFile& file, int timeoutMs) { std::unique_lock<std::mutex> lock(m_mutex); // 只要有文件就立即返回 auto pred = [&] { return !m_receivedFiles.empty(); // 只需检查队列是否非空 }; if (timeoutMs > 0) { if (!m_cv.wait_for(lock, std::chrono::milliseconds(timeoutMs), pred)) { return false; // 超时 } } else { m_cv.wait(lock, pred); } if (m_receivedFiles.empty()) return false; file = std::move(m_receivedFiles.front()); m_receivedFiles.pop(); return true; } // 接收文件并读取两行内容 bool FileTransfer::receiveAndReadTwoStrings(int port, std::string& outStr1, std::string& outStr2, int timeoutMs) { // 确保服务器正在运行 if (!m_running) { startServer(port); } // 等待文件到达 ReceivedFile file; if (!waitForFile(file, timeoutMs)) { throw std::runtime_error("等待文件超时或服务器停止"); } // 读取文件内容 std::string content(file.content.data(), file.content.size()); // 查找第一行结尾 size_t pos = content.find('\n'); if (pos == std::string::npos) { // 没有换行符,整个内容作为第一行 outStr1 = content; outStr2 = ""; } else { // 提取第一行 outStr1 = content.substr(0, pos); // 提取第二行(跳过换行符) outStr2 = content.substr(pos + 1); // 移除第二行可能的多余换行符 if (!outStr2.empty() && outStr2.back() == '\n') { outStr2.pop_back(); } } return true; } bool Ucar::navigateTo(const geometry_msgs::Pose& target) { move_base_msgs::MoveBaseGoal goal; goal.target_pose.header.frame_id = "map"; goal.target_pose.pose = target; move_base_client_.sendGoal(goal); return move_base_client_.waitForResult(navigation_timeout_); } // void Ucar::recovery() { // setlocale(LC_ALL, ""); // std_srvs::Empty srv; // if (clear_costmaps_client_.call(srv)) { // ROS_INFO("代价地图清除成功"); // } else { // ROS_ERROR("代价地图清除服务调用失败"); // } // } Ucar::Ucar(ros::NodeHandle& nh) : nh_(nh), retry_count_(0), current_state_(State::INIT) , control_rate_(10) ,move_base_client_("move_base", true) { latest_odom_.reset(); // 等待move_base服务器就绪(参考网页6的actionlib使用规范) if(!move_base_client_.waitForServer(ros::Duration(5.0))) { setlocale(LC_ALL, ""); ROS_ERROR("无法连接move_base服务器"); } scanner.set_config(zbar::ZBAR_NONE, zbar::ZBAR_CFG_ENABLE, 1); // 初始化代价地图清除服务 clear_costmaps_client_ = nh_.serviceClient<std_srvs::Empty>("/move_base/clear_costmaps"); setlocale(LC_ALL, ""); // 标记所有的点位总共21个点位 nh_.param("pose1_x", pose_1.position.x, 1.67); nh_.param("pose1_y", pose_1.position.y, 0.04); pose_1.orientation.x = 0.0; pose_1.orientation.y = 0.0; pose_1.orientation.z = 0.707; pose_1.orientation.w = 0.707; nh_.param("pose2_x", pose_2.position.x, 1.83); nh_.param("pose2_y", pose_2.position.y, 0.380); pose_2.orientation.x = 0.0; pose_2.orientation.y = 0.0; pose_2.orientation.z = 1; pose_2.orientation.w = 0; nh_.param("pose3_x", pose_3.position.x, 1.0); nh_.param("pose3_y", pose_3.position.y, 0.494); pose_3.orientation.x = 0.0; pose_3.orientation.y = 0.0; pose_3.orientation.z = 1; pose_3.orientation.w = 0; nh_.param("pose4_x", pose_4.position.x, 0.15166891130059032); nh_.param("pose4_y", pose_4.position.y, 0.5446138339072089); pose_4.orientation.x = 0.0; pose_4.orientation.y = 0.0; pose_4.orientation.z = 0.707; pose_4.orientation.w = 0.707; nh_.param("pose5_x", pose_5.position.x, 0.387605134459779); nh_.param("pose5_y", pose_5.position.y, 0.949243539748394); pose_5.orientation.x = 0.0; pose_5.orientation.y = 0.0; pose_5.orientation.z = 0.0; pose_5.orientation.w = 1.0; nh_.param("pose6_x", pose_6.position.x, 1.0250469329539987); nh_.param("pose6_y", pose_6.position.y, 1.0430107266961729); pose_6.orientation.x = 0.0; pose_6.orientation.y = 0.0; pose_6.orientation.z = 0.0; pose_6.orientation.w = 1.0; nh_.param("pose7_x", pose_7.position.x, 1.715746358650675); nh_.param("pose7_y", pose_7.position.y, 1.0451169673664757); pose_7.orientation.x = 0.0; pose_7.orientation.y = 0.0; pose_7.orientation.z = 0.707; pose_7.orientation.w = 0.707; nh_.param("pose8_x", pose_8.position.x, 1.820954899866641); nh_.param("pose8_y", pose_8.position.y, 1.405578846446346); pose_8.orientation.x = 0.0; pose_8.orientation.y = 0.0; pose_8.orientation.z = 1; pose_8.orientation.w = 0; nh_.param("pose9_x", pose_9.position.x, 1.287663212010699); nh_.param("pose9_y", pose_9.position.y, 1.4502232396357953); pose_9.orientation.x = 0.0; pose_9.orientation.y = 0.0; pose_9.orientation.z = 1; pose_9.orientation.w = 0; nh_.param("pose10_x", pose_10.position.x, 0.433025661760874); nh_.param("pose10_y", pose_10.position.y, 1.5362058814619577); pose_10.orientation.x = 0.0; pose_10.orientation.y = 0.0; pose_10.orientation.z = 0.707; pose_10.orientation.w = 0.707; //开始进入视觉定位区域 中心点加上四个中线点对应四面墙 nh_.param("pose_center_x", pose_11.position.x, 1.13); nh_.param("pose_center_y", pose_11.position.y, 3.04); nh_.param("pose_center_x", pose_12.position.x, 1.13); nh_.param("pose_center_y", pose_12.position.y, 3.04); nh_.param("pose_center_x", pose_13.position.x, 1.13); nh_.param("pose_center_y", pose_13.position.y, 3.04); nh_.param("pose_center_x", pose_14.position.x, 1.13); nh_.param("pose_center_y", pose_14.position.y, 3.04); nh_.param("pose_center_x", pose_15.position.x, 1.13); nh_.param("pose_center_y", pose_15.position.y, 3.04); //退出视觉区域进入路灯识别区域 nh_.param("pose_center_x", pose_16.position.x, 1.13); nh_.param("pose_center_y", pose_16.position.y, 3.04); nh_.param("pose_center_x", pose_17.position.x, 1.13); nh_.param("pose_center_y", pose_17.position.y, 3.04); nh_.param("pose_center_x", pose_18.position.x, 1.13); nh_.param("pose_center_y", pose_18.position.y, 3.04); //退出路灯识别区域,进入巡线区域 注意两个点位取一个,必须标定正确的方向 nh_.param("pose_center_x", pose_19.position.x, 1.13); nh_.param("pose_center_y", pose_19.position.y, 3.04); pose_19.orientation.x = 0.0; pose_19.orientation.y = 0.0; pose_19.orientation.z = 0.707; pose_19.orientation.w = 0.707; nh_.param("pose_center_x", pose_20.position.x, 1.13); nh_.param("pose_center_y", pose_20.position.y, 3.04); pose_20.orientation.x = 0.0; pose_20.orientation.y = 0.0; pose_20.orientation.z = 0.707; pose_20.orientation.w = 0.707; //result_sub_ = nh_.subscribe("result_of_object", 1, &Ucar::detectionCallback, this); result_client_ = nh_.serviceClient<rfbot_yolov8_ros::DetectGood>("object_realsense_recognization"); cmd_vel_pub = nh_.advertise<geometry_msgs::Twist>("/cmd_vel", 10); odom_sub = nh_.subscribe("/odom", 10, &Ucar::odomCallback, this); interaction_client = nh_.serviceClient<ucar::ObjectDetection>("object_detection"); ROS_INFO_STREAM("状态机初始化完成"); } void Ucar::navigate_to_aruco_place(){ setlocale(LC_ALL, ""); navigateTo(pose_1);ROS_INFO("到达pose_1"); navigateTo(pose_2);ROS_INFO("到达pose_2"); navigateTo(pose_3);ROS_INFO("到达pose_3"); } void Ucar::navigate_to_recongnition_place(){ setlocale(LC_ALL, ""); navigateTo(pose_4);ROS_INFO("到达pose_4"); navigateTo(pose_5);ROS_INFO("到达pose_5"); navigateTo(pose_6);ROS_INFO("到达pose_6"); navigateTo(pose_7);ROS_INFO("到达pose_7"); navigateTo(pose_8);ROS_INFO("到达pose_8"); navigateTo(pose_9);ROS_INFO("到达pose_9"); navigateTo(pose_10);ROS_INFO("到达pose_10"); } void Ucar::run() { while (ros::ok()) { ros::spinOnce(); switch(current_state_) { case State::INIT: {handleInit(); break;} case State::ARUCO: {navigate_to_aruco_place(); ROS_INFO("导航到二维码区域"); see_aruco(); if(target_object=="vegetable") playAudioFile("/home/ucar/ucar_ws/src/wav/sc.wav"); if(target_object=="fruit") playAudioFile("/home/ucar/ucar_ws/src/wav/sg.wav"); if(target_object=="dessert") playAudioFile("/home/ucar/ucar_ws/src/wav/tp.wav"); break;} case State::FIND: {navigate_to_recongnition_place(); spin_to_find();//转着找目标 break;} case State::GAZEBO: {gazebo(); break;} } control_rate_.sleep(); } } void Ucar::handleInit() { setlocale(LC_ALL, ""); ROS_DEBUG("执行初始化流程"); current_state_ = State::ARUCO; } void Ucar::see_aruco() { qr_found_ = false; image_transport::ImageTransport it(nh_); // 2. 创建订阅器,订阅/usb_cam/image_raw话题 image_transport::Subscriber sub = it.subscribe( "/usb_cam/image_raw", 1, &Ucar::imageCallback, this ); std::cout << "已订阅摄像头话题,等待图像数据..." << std::endl; // 3. 创建ZBar扫描器 scanner.set_config(zbar::ZBAR_NONE, zbar::ZBAR_CFG_ENABLE, 1); target_object = ""; // 重置结果 // 4. 设置超时检测 const int MAX_SCAN_DURATION = 30; // 最大扫描时间(秒) auto scan_start_time = std::chrono::steady_clock::now(); // 5. ROS事件循环 ros::Rate loop_rate(30); // 30Hz while (ros::ok() && !qr_found_) { // 检查超时 auto elapsed = std::chrono::steady_clock::now() - scan_start_time; if (std::chrono::duration_cast<std::chrono::seconds>(elapsed).count() > MAX_SCAN_DURATION) { std::cout << "扫描超时" << std::endl; break; } ros::spinOnce(); loop_rate.sleep(); } // 6. 清理资源 if (!qr_found_) target_object = ""; } void Ucar::imageCallback(const sensor_msgs::ImageConstPtr& msg) { try { // 7. 将ROS图像消息转换为OpenCV格式 cv_bridge::CvImagePtr cv_ptr = cv_bridge::toCvCopy(msg, sensor_msgs::image_encodings::BGR8); cv::Mat frame = cv_ptr->image; cv::Mat gray; cv::cvtColor(frame, gray, cv::COLOR_BGR2GRAY); // 8. 准备ZBar图像 cv::Mat gray_cont = gray.clone(); zbar::Image image(gray.cols, gray.rows, "Y800", gray_cont.data, gray.cols * gray.rows); // 9. 扫描二维码 if (scanner.scan(image) >= 0) { for (zbar::Image::SymbolIterator symbol = image.symbol_begin(); symbol != image.symbol_end(); ++symbol) { // 获取原始结果 std::string rawResult = symbol->get_data(); // 在存储到全局变量前将首字母转换为小写 target_object = toLowerFirstChar(rawResult); ROS_INFO("识别到二维码: %s", target_object.c_str()); current_state_ = State::FIND; qr_found_ = true; // 在视频帧上绘制结果 std::vector<cv::Point> points; for (int i = 0; i < symbol->get_location_size(); i++) { points.push_back(cv::Point(symbol->get_location_x(i), symbol->get_location_y(i))); } // 绘制二维码边界框 cv::RotatedRect rect = cv::minAreaRect(points); cv::Point2f vertices[4]; rect.points(vertices); for (int i = 0; i < 4; i++) { cv::line(frame, vertices[i], vertices[(i + 1) % 4], cv::Scalar(0, 255, 0), 2); } // 显示原始二维码内容 cv::putText(frame, rawResult, cv::Point(10, 30), cv::FONT_HERSHEY_SIMPLEX, 0.7, cv::Scalar(0, 255, 0), 2); // 显示转换后的结果 cv::putText(frame, "Stored: " + target_object, cv::Point(10, 60), cv::FONT_HERSHEY_SIMPLEX, 0.7, cv::Scalar(0, 0, 255), 2); // 显示最终结果画面 cv::imshow("QR Code Scanner", frame); cv::waitKey(250); // 短暂显示结果 } } // 显示当前帧 cv::imshow("QR Code Scanner", frame); cv::waitKey(1); } catch (cv_bridge::Exception& e) { ROS_ERROR("cv_bridge异常: %s", e.what()); } } //播放音频文件函数 bool Ucar::playAudioFile(const std::string& filePath) { // 创建子进程播放音频 pid_t pid = fork(); if (pid == 0) { // 子进程 // 尝试使用 aplay (适用于 WAV 文件) execlp("aplay", "aplay", "-q", filePath.c_str(), (char*)NULL); // 如果 aplay 失败,尝试 ffplay execlp("ffplay", "ffplay", "-nodisp", "-autoexit", "-loglevel", "quiet", filePath.c_str(), (char*)NULL); // 如果 ffplay 失败,尝试 mpg123 (适用于 MP3) execlp("mpg123", "mpg123", "-q", filePath.c_str(), (char*)NULL); // 如果所有播放器都不可用,退出 exit(1); } else if (pid > 0) { // 父进程 int status; waitpid(pid, &status, 0); return WIFEXITED(status) && WEXITSTATUS(status) == 0; } else { // fork 失败 perror("fork failed"); return false; } } // 辅助函数:将字符串首字母转换为小写 std::string Ucar::toLowerFirstChar(const std::string& str) { if (str.empty()) return str; std::string result = str; result[0] = static_cast<char>(std::tolower(static_cast<unsigned char>(result[0]))); return result; } // 在odomCallback中更新最新里程计数据 void Ucar::odomCallback(const nav_msgs::Odometry::ConstPtr& msg) { latest_odom_ = msg; // 保存最新里程计数据 if (!position_recorded) { initial_position = msg->pose.pose.position; position_recorded = true; //ROS_INFO("初始位置记录完成: (%.3f, %.3f)", // initial_position.x, initial_position.y); } } void Ucar::moveLeftDistance(double distance_m, double linear_speed) { // 订阅里程计话题(根据实际机器人配置修改话题名) // 等待位置记录完成 position_recorded = false; while (!position_recorded && ros::ok()) { ros::spinOnce(); ros::Duration(0.1).sleep(); } // 计算理论运动时间 double duration = distance_m / linear_speed; //ROS_INFO("开始左移: 距离=%.2fm, 速度=%.2fm/s, 理论时间=%.1fs", // distance_m, linear_speed, duration); // 创建控制消息 geometry_msgs::Twist move_cmd; move_cmd.linear.y = linear_speed; // 全向移动Y轴速度控制左右移动 // 记录开始时间 auto start_time = ros::Time::now(); // 持续发送控制命令 while ((ros::Time::now() - start_time).toSec() < duration && ros::ok()) { cmd_vel_pub.publish(move_cmd); ros::Duration(0.05).sleep(); // 50ms控制周期 } // 发送停止指令 move_cmd.linear.y = 0; cmd_vel_pub.publish(move_cmd); //ROS_INFO("左移完成"); } void Ucar::moveRightDistance(double distance_m, double linear_speed) { // 等待位置记录完成 position_recorded = false; while (!position_recorded && ros::ok()) { ros::spinOnce(); ros::Duration(0.1).sleep(); } // 计算理论运动时间 double duration = distance_m / linear_speed; //ROS_INFO("开始右移: 距离=%.2fm, 速度=%.2fm/s, 理论时间=%.1fs", // distance_m, linear_speed, duration); // 创建控制消息 geometry_msgs::Twist move_cmd; move_cmd.linear.y = -linear_speed; // 全向移动Y轴速度控制左右移动 // 记录开始时间 auto start_time = ros::Time::now(); // 持续发送控制命令 while ((ros::Time::now() - start_time).toSec() < duration && ros::ok()) { cmd_vel_pub.publish(move_cmd); ros::Duration(0.05).sleep(); // 50ms控制周期 } // 发送停止指令 move_cmd.linear.y = 0; cmd_vel_pub.publish(move_cmd); //ROS_INFO("右移完成"); } void Ucar::moveForwardDistance(double distance_m, double linear_speed) { // 确保速度为正值(前进方向) if (linear_speed < 0) { ROS_WARN("前进速度应为正值,自动取绝对值"); linear_speed = fabs(linear_speed); } // 等待位置记录完成 position_recorded = false; while (!position_recorded && ros::ok()) { ros::spinOnce(); ros::Duration(0.1).sleep(); } // 计算理论运动时间 double duration = distance_m / linear_speed; //ROS_INFO("开始前进: 距离=%.2fm, 速度=%.2fm/s, 理论时间=%.1fs", // distance_m, linear_speed, duration); // 创建控制消息 geometry_msgs::Twist move_cmd; move_cmd.linear.x = linear_speed; // X轴速度控制前后移动 // 记录开始时间 auto start_time = ros::Time::now(); // 持续发送控制命令 while ((ros::Time::now() - start_time).toSec() < duration && ros::ok()) { cmd_vel_pub.publish(move_cmd); ros::Duration(0.05).sleep(); // 50ms控制周期 } // 发送停止指令 move_cmd.linear.x = 0.0; cmd_vel_pub.publish(move_cmd); ROS_INFO("前进完成"); } //输入1逆时针,输入-1顺时针 void Ucar::rotateCounterClockwise5Degrees(int a) { // 设置旋转参数 const double angular_speed = 0.2; // rad/s (约11.5度/秒) const double degrees = 5.0; const double duration = degrees * (M_PI / 180.0) / angular_speed; // 约0.436秒 //if(a==1) //ROS_INFO("开始逆时针旋转5度: 速度=%.2f rad/s, 时间=%.3f秒", // angular_speed, duration); //else if(a==-1) //ROS_INFO("开始顺时针旋转5度: 速度=%.2f rad/s, 时间=%.3f秒", // angular_speed, duration); // 创建控制消息 geometry_msgs::Twist twist_msg; twist_msg.angular.z = angular_speed*a; // 正值表示逆时针 // 记录开始时间 auto start_time = ros::Time::now(); // 持续发送控制命令 while ((ros::Time::now() - start_time).toSec() < duration && ros::ok()) { cmd_vel_pub.publish(twist_msg); ros::Duration(0.05).sleep(); // 20Hz控制周期 } // 发送停止命令(确保接收) twist_msg.angular.z = 0.0; for (int i = 0; i < 3; i++) { cmd_vel_pub.publish(twist_msg); ros::Duration(0.02).sleep(); } if(a==1) ROS_INFO("逆时针旋转5度完成"); else if (a==-1) ROS_INFO("顺时针旋转5度完成"); } void Ucar::rotateCounterClockwise360Degrees() { // 设置旋转参数 const double angular_speed = 1; // rad/s (约11.5度/秒) const double degrees = 360.0; const double duration = degrees * (M_PI / 180.0) / angular_speed; // 约0.436秒 // 创建控制消息 geometry_msgs::Twist twist_msg; twist_msg.angular.z = angular_speed; // 正值表示逆时针 // 记录开始时间 auto start_time = ros::Time::now(); // 持续发送控制命令 while ((ros::Time::now() - start_time).toSec() < duration && ros::ok()) { cmd_vel_pub.publish(twist_msg); ros::Duration(0.05).sleep(); // 20Hz控制周期 } // 发送停止命令(确保接收) twist_msg.angular.z = 0.0; for (int i = 0; i < 3; i++) { cmd_vel_pub.publish(twist_msg); ros::Duration(0.02).sleep(); } } void Ucar::left_and_right_move_old(){ rfbot_yolov8_ros::DetectGood srv; while((find_object_x2_old+find_object_x1_old)/2>324){ if((find_object_x2_old+find_object_x1_old)>340) moveLeftDistance(0.15,0.1);//控制小车往左移动15cm else moveLeftDistance(0.05,0.1);//控制小车往左移动5cm moveForwardDistance(0.05,0.1); Ucar::result_client_.call(srv); for (size_t j = 0; j < srv.response.goodName.size(); ++j) { ROS_INFO("响应结果:"); ROS_INFO("位置: x1: %d, y1: %d, x2: %d, y2: %d", srv.response.u1[j], srv.response.v1[j], srv.response.u2[j], srv.response.v2[j]); //ROS_INFO("置信度: %f", srv.response.confidence[j]); find_object_x1_old=srv.response.u1[0]; find_object_y1_old=srv.response.v1[0]; find_object_x2_old=srv.response.u2[0]; find_object_y2_old=srv.response.v2[0]; } ROS_INFO("当前目标中心横坐标为:%d",(find_object_x2_old+find_object_x1_old)/2); } while((find_object_x2_old+find_object_x1_old)/2<316){ if((find_object_x2_old+find_object_x1_old)<300) moveRightDistance(0.15,0.1);//控制小车往右移动15cm else moveRightDistance(0.05,0.1);//控制小车往右移动5cm moveForwardDistance(0.05,0.1); Ucar::result_client_.call(srv); for (size_t j = 0; j < srv.response.goodName.size(); ++j) { ROS_INFO("响应结果:"); ROS_INFO("位置: x1: %d, y1: %d, x2: %d, y2: %d", srv.response.u1[j], srv.response.v1[j], srv.response.u2[j], srv.response.v2[j]); //ROS_INFO("置信度: %f", srv.response.confidence[j]); find_object_x1_old=srv.response.u1[0]; find_object_y1_old=srv.response.v1[0]; find_object_x2_old=srv.response.u2[0]; find_object_y2_old=srv.response.v2[0]; } ROS_INFO("当前目标中心横坐标为:%d",(find_object_x2_old+find_object_x1_old)/2); } ROS_INFO("左右移动完成"); } //前进函数(涵盖第二种停靠算法) void Ucar::go(){ rfbot_yolov8_ros::DetectGood srv; while(1){ moveForwardDistance(0.05,0.1);//控制小车前进 Ucar::result_client_.call(srv); for (size_t j = 0; j < srv.response.goodName.size(); ++j) { ROS_INFO("响应结果:"); ROS_INFO("位置: x1: %d, y1: %d, x2: %d, y2: %d", srv.response.u1[j], srv.response.v1[j], srv.response.u2[j], srv.response.v2[j]); //ROS_INFO("置信度: %f", srv.response.confidence[j]); find_object_x1_new=srv.response.u1[0]; find_object_y1_new=srv.response.v1[0]; find_object_x2_new=srv.response.u2[0]; find_object_y2_new=srv.response.v2[0]; } //图像左边先到达边线——>逆时针往右 if(find_object_x2_new==640&&find_object_y1_new==0&&find_object_x1_new!=0&&find_object_y2_new>=350){ if(find_object_x1_new>240||(find_object_x2_new-find_object_x1_new)<=(find_object_y2_new-find_object_y1_new)){ rotateCounterClockwise5Degrees(1); rotateCounterClockwise5Degrees(1); rotateCounterClockwise5Degrees(1); rotateCounterClockwise5Degrees(1); rotateCounterClockwise5Degrees(1); moveRightDistance(0.35,0.1); ROS_INFO("大摆头"); break; } else if(find_object_x1_new>120){ rotateCounterClockwise5Degrees(1); rotateCounterClockwise5Degrees(1); rotateCounterClockwise5Degrees(1); moveRightDistance(0.25,0.1); ROS_INFO("中摆头"); break; } else{ rotateCounterClockwise5Degrees(1);//逆时针 moveRightDistance(0.1,0.1); ROS_INFO("小摆头"); break; } } //图像右边先到达边线——>顺时针往左 else if(find_object_x1_new==0&&find_object_y1_new==0&&find_object_x2_new!=640&&find_object_y2_new>=350){ if(find_object_x2_new<400||(find_object_x2_new-find_object_x1_new)<=(find_object_y2_new-find_object_y1_new)){ rotateCounterClockwise5Degrees(-1); rotateCounterClockwise5Degrees(-1); rotateCounterClockwise5Degrees(-1); rotateCounterClockwise5Degrees(-1); rotateCounterClockwise5Degrees(-1); moveLeftDistance(0.35,0.1); ROS_INFO("大摆头"); break; } else if(find_object_x2_new<520){ rotateCounterClockwise5Degrees(-1); rotateCounterClockwise5Degrees(-1); rotateCounterClockwise5Degrees(-1); moveLeftDistance(0.25,0.1); ROS_INFO("中摆头"); break; } else{ rotateCounterClockwise5Degrees(-1);//顺时针 moveLeftDistance(0.1,0.1); ROS_INFO("小摆头"); break; } } } } void Ucar::visualservo(){ rfbot_yolov8_ros::DetectGood srv; //左移右移 left_and_right_move_old(); //提取长宽比 Ucar::result_client_.call(srv); for (size_t j = 0; j < srv.response.goodName.size(); ++j) { ROS_INFO("响应结果:"); ROS_INFO("位置: x1: %d, y1: %d, x2: %d, y2: %d", srv.response.u1[j], srv.response.v1[j], srv.response.u2[j], srv.response.v2[j]); //ROS_INFO("置信度: %f", srv.response.confidence[j]); find_object_x1_old=srv.response.u1[0]; find_object_y1_old=srv.response.v1[0]; find_object_x2_old=srv.response.u2[0]; find_object_y2_old=srv.response.v2[0]; } changkuanbi_old=(find_object_x2_old-find_object_x1_old)/(find_object_y2_old-find_object_y1_old); ROS_INFO("长宽比为:%f",changkuanbi_old);go(); if(find_object=="dessert1") playAudioFile("/home/ucar/ucar_ws/src/wav/kl.wav"); if(find_object=="dessert2") playAudioFile("/home/ucar/ucar_ws/src/wav/dg.wav"); if(find_object=="dessert3") playAudioFile("/home/ucar/ucar_ws/src/wav/nn.wav"); if(find_object=="vegetable1") playAudioFile("/home/ucar/ucar_ws/src/wav/lj.wav"); if(find_object=="vegetable2") playAudioFile("/home/ucar/ucar_ws/src/wav/xhs.wav"); if(find_object=="vegetable3") playAudioFile("/home/ucar/ucar_ws/src/wav/td.wav"); if(find_object=="fruit1") playAudioFile("/home/ucar/ucar_ws/src/wav/xj.wav"); if(find_object=="fruit2") playAudioFile("/home/ucar/ucar_ws/src/wav/pg.wav"); if(find_object=="fruit3") playAudioFile("/home/ucar/ucar_ws/src/wav/xg.wav"); // if(abs(changkuanbi_old-1.666666667)<0.05){ // ROS_INFO("比较接近16:9,不需要旋转"); // //前进 // go(); // } // else { // //先逆时针转个10度 // rotateCounterClockwise5Degrees(1); // rotateCounterClockwise5Degrees(1); // Ucar::result_client_.call(srv); // for (size_t j = 0; j < srv.response.goodName.size(); ++j) { // ROS_INFO("响应结果:"); // ROS_INFO("位置: x1: %d, y1: %d, x2: %d, y2: %d", // srv.response.u1[j], // srv.response.v1[j], // srv.response.u2[j], // srv.response.v2[j]); // //ROS_INFO("置信度: %f", srv.response.confidence[j]); // find_object_x1_new=srv.response.u1[0]; // find_object_y1_new=srv.response.v1[0]; // find_object_x2_new=srv.response.u2[0]; // find_object_y2_new=srv.response.v2[0]; // } // changkuanbi_new=(find_object_x2_new-find_object_x1_new)/(find_object_y2_new-find_object_y1_new); // ROS_INFO("长宽比为:%f",changkuanbi_new); // if(changkuanbi_new<changkuanbi_old)//方向错了 // { // while(abs(changkuanbi_new-1.666666667)>0.4)//不准就再转 // { // rotateCounterClockwise5Degrees(-1); // Ucar::result_client_.call(srv); // for (size_t j = 0; j < srv.response.goodName.size(); ++j) { // ROS_INFO("响应结果:"); // ROS_INFO("位置: x1: %d, y1: %d, x2: %d, y2: %d", // srv.response.u1[j], // srv.response.v1[j], // srv.response.u2[j], // srv.response.v2[j]); // //ROS_INFO("置信度: %f", srv.response.confidence[j]); // find_object_x1_new=srv.response.u1[0]; // find_object_y1_new=srv.response.v1[0]; // find_object_x2_new=srv.response.u2[0]; // find_object_y2_new=srv.response.v2[0]; // //保持正对目标 // while((find_object_x2_new+find_object_x1_new)/2>324) // {moveLeftDistance(0.05,0.1);//控制小车往左移动5cm // Ucar::result_client_.call(srv); // for (size_t j = 0; j < srv.response.goodName.size(); ++j) { // ROS_INFO("响应结果:"); // ROS_INFO("位置: x1: %d, y1: %d, x2: %d, y2: %d", // srv.response.u1[j], // srv.response.v1[j], // srv.response.u2[j], // srv.response.v2[j]); // //ROS_INFO("置信度: %f", srv.response.confidence[j]); // find_object_x1_new=srv.response.u1[0]; // find_object_y1_new=srv.response.v1[0]; // find_object_x2_new=srv.response.u2[0]; // find_object_y2_new=srv.response.v2[0]; // } // changkuanbi_new=(find_object_x2_new-find_object_x1_new)/(find_object_y2_new-find_object_y1_new); // ROS_INFO("长宽比为:%f",changkuanbi_new);} // while((find_object_x2_new+find_object_x1_new)/2<316) // {moveRightDistance(0.05,0.1);//控制小车往右移动5cm // Ucar::result_client_.call(srv); // for (size_t j = 0; j < srv.response.goodName.size(); ++j) { // ROS_INFO("响应结果:"); // ROS_INFO("位置: x1: %d, y1: %d, x2: %d, y2: %d", // srv.response.u1[j], // srv.response.v1[j], // srv.response.u2[j], // srv.response.v2[j]); // //ROS_INFO("置信度: %f", srv.response.confidence[j]); // find_object_x1_new=srv.response.u1[0]; // find_object_y1_new=srv.response.v1[0]; // find_object_x2_new=srv.response.u2[0]; // find_object_y2_new=srv.response.v2[0]; // } // changkuanbi_new=(find_object_x2_new-find_object_x1_new)/(find_object_y2_new-find_object_y1_new); // ROS_INFO("长宽比为:%f",changkuanbi_new);} // } // } // } // else{//方向对了 // while(abs(changkuanbi_new-1.666666667)>0.4)//不准就再转 // { // rotateCounterClockwise5Degrees(1); // //保持正对目标 // while((find_object_x2_new+find_object_x1_new)/2>324) moveLeftDistance(0.05,0.1);//控制小车往左移动5cm // while((find_object_x2_new+find_object_x1_new)/2<316) moveRightDistance(0.05,0.1);//控制小车往右移动5cm // Ucar::result_client_.call(srv); // for (size_t j = 0; j < srv.response.goodName.size(); ++j) { // ROS_INFO("响应结果:"); // ROS_INFO("位置: x1: %d, y1: %d, x2: %d, y2: %d", // srv.response.u1[j], // srv.response.v1[j], // srv.response.u2[j], // srv.response.v2[j]); // //ROS_INFO("置信度: %f", srv.response.confidence[j]); // find_object_x1_new=srv.response.u1[0]; // find_object_y1_new=srv.response.v1[0]; // find_object_x2_new=srv.response.u2[0]; // find_object_y2_new=srv.response.v2[0]; // } // changkuanbi_new=(find_object_x2_new-find_object_x1_new)/(find_object_y2_new-find_object_y1_new); // ROS_INFO("长宽比为:%f",changkuanbi_new); // } // } // //前进 // go(); // } ROS_INFO("导航完成"); ros::Duration(3000).sleep(); current_state_ = State::GAZEBO; } void Ucar::spin_to_find(){ setlocale(LC_ALL, ""); for(int i=0;i<9;i++){ navigateTo(pose_center[i]);//导航到i号点位 ros::Duration(3).sleep();//停留3秒 rfbot_yolov8_ros::DetectGood srv; Ucar::result_client_.call(srv); for (size_t j = 0; j < srv.response.goodName.size(); ++j) { ROS_INFO("响应结果:"); ROS_INFO("位置: x1: %d, y1: %d, x2: %d, y2: %d", srv.response.u1[j], srv.response.v1[j], srv.response.u2[j], srv.response.v2[j]); //ROS_INFO("置信度: %f", srv.response.confidence[j]); find_object_x1_old=srv.response.u1[0]; find_object_y1_old=srv.response.v1[0]; find_object_x2_old=srv.response.u2[0]; find_object_y2_old=srv.response.v2[0]; pose_center_object[i] = srv.response.goodName[0]; //看看这个方向有没有目标 } if(pose_center_object[i].find(target_object)!=std::string::npos&&(find_object_x2_old-find_object_x1_old)>=(find_object_y2_old-find_object_y1_old)) {ROS_INFO("本次任务目标识别成功"); find_object=pose_center_object[i]; visualservo(); break;} else{ ROS_INFO("本次任务目标识别失败,尝试下一个目标"); continue; } } } void Ucar::gazebo(){ navigateTo(pose_gazebo); //主从机通信 FileTransfer ft("/home/ucar/ucar_ws/src/ucar"); ft.saveToFile(target_object, "target.txt"); //电脑的ip ft.sendTo("192.168.1.100", 8080, "/home/ucar/ucar_ws/src/ucar/target.txt", "/home/zzs/gazebo_test_ws/src/ucar2/target.txt"); try { // 示例3:等待接收文件并读取内容 std::cout << "等待接收文件..." << std::endl; ft.receiveAndReadTwoStrings(8080, gazebo_object, gazebo_room); std::cout << "接收到的内容:\n" << gazebo_object << "\n"<<gazebo_room << std::endl; } catch (const std::exception& e) { std::cerr << "错误: " << e.what() << std::endl;} ros::Duration(30000).sleep();//停留3秒 } int main(int argc, char** argv) { ros::init(argc, argv, "multi_room_navigation_node"); ros::NodeHandle nh; Ucar ucar(nh); ucar.run(); return 0; } 帮我修改上述代码,其中导航到nh_.param("pose_center_x", pose_11.position.x, 1.13); nh_.param("pose_center_y", pose_11.position.y, 3.04); nh_.param("pose_center_x", pose_12.position.x, 1.13); nh_.param("pose_center_y", pose_12.position.y, 3.04); nh_.param("pose_center_x", pose_13.position.x, 1.13); nh_.param("pose_center_y", pose_13.position.y, 3.04); nh_.param("pose_center_x", pose_14.position.x, 1.13); nh_.param("pose_center_y", pose_14.position.y, 3.04); nh_.param("pose_center_x", pose_15.position.x, 1.13); nh_.param("pose_center_y", pose_15.position.y, 3.04);时候时,删除原来旋转十五度停下的情况,改成每个点都停留,然后开始原地旋转,每旋转0.2秒停顿0.5秒,然后旋转360度之后,前往下一个点,在其中任意一个点识别到目标时,就不前往之后的点而是直接进入视觉定位,最后直接前往 nh_.param("pose_center_x", pose_16.position.x, 1.13); nh_.param("pose_center_y", pose_16.position.y, 3.04);
最新发布
08-09
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

iowin888

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值