亚博microros小车-原生ubuntu支持系列 27、手掌控制小车运动

背景知识

本节跟上一个测试类似:亚博microros小车-原生ubuntu支持系列:26手势控制小车基础运动-CSDN博客

都是基于MediaPipe hands做手掌、手指识别的。

为了方便理解,在贴一下手指关键点分布。手掌位置就是靠第9点来识别的。

2、程序说明

本节案例在机器人主控上可能会运行速度很卡顿,可以识别到手掌之后先把小车架起来测试,这样效果会好一些。

小车会根据手掌在画面中的位置,控制底盘的运动。

手掌在画面上方->小车前进

手掌在画面下方->小车后退

手掌在画面左方->小车左移

手掌在画面下方->小车右移

3 启动命令

启动小车代理、图像代理

sudo docker run -it --rm -v /dev:/dev -v /dev/shm:/dev/shm --privileged --net=host microros/micro-ros-agent:humble udp4 --port 8090 -v4

sudo docker run -it --rm -v /dev:/dev -v /dev/shm:/dev/shm --privileged --net=host microros/micro-ros-agent:humble udp4 --port 9999 -v4

终端输入,

ros2 run yahboom_esp32ai_car RobotCtrl 

不太好区别,加上指点图

我大概用画笔简单示意下。判断标准可以自行调整x,y的值,运行日志

ohu@bohu-TM1701:~/yahboomcar/yahboomcar_ws$ ros2 run yahboom_esp32ai_car RobotCtrl 
WARNING: All log messages before absl::InitializeLog() is called are written to STDERR
I0000 00:00:1739176022.123238  464141 gl_context_egl.cc:85] Successfully initialized EGL. Major : 1 Minor: 5
I0000 00:00:1739176022.187429  464194 gl_context.cc:369] GL version: 3.2 (OpenGL ES 3.2 Mesa 23.2.1-1ubuntu3.1~22.04.3), renderer: Mesa Intel(R) UHD Graphics 620 (KBL GT2)
start it
INFO: Created TensorFlow Lite XNNPACK delegate for CPU.
W0000 00:00:1739176026.985982  464181 inference_feedback_manager.cc:114] Feedback manager requires a model with a single signature inference. Disabling support for feedback tensors.
W0000 00:00:1739176027.850109  464183 inference_feedback_manager.cc:114] Feedback manager requires a model with a single signature inference. Disabling support for feedback tensors.
W0000 00:00:1739176027.890610  464180 landmark_projection_calculator.cc:186] Using NORM_RECT without IMAGE_DIMENSIONS is only supported for the square ROI. Provide IMAGE_DIMENSIONS or use PROJECTION_MATRIX.
x 295
value: x:0.2,y:0.2
x 277
value: x:0.2,y:0.2
x 280
value: x:0.2,y:0.2
x 612
value: x:0.0,y:-0.2
x 622
value: x:0.0,y:-0.2
x 622
value: x:0.0,y:-0.2
x 614
value: x:0.0,y:-0.2
x 620
value: x:0.0,y:-0.2
x 607
value: x:0.0,y:-0.2
x 588
value: x:0.0,y:-0.2
x 586
value: x:0.0,y:-0.2
x 569
value: x:0.0,y:-0.2
x 562
value: x:0.0,y:-0.2
x 564
value: x:0.0,y:-0.2
x 550
value: x:0.0,y:-0.2
x 537
value: x:0.0,y:-0.2
x 463
value: x:0.0,y:-0.2
x 384
value: x:0.0,y:-0.2
x 313
value: x:0.0,y:0.0
x 262
value: x:0.0,y:0.2
x 231
value: x:0.0,y:0.2

代码

#!/usr/bin/env python3
# encoding: utf-8
import threading
import cv2 as cv
import numpy as np
from yahboom_esp32ai_car.media_library import *
import time
import rclpy
from rclpy.node import Node
from std_msgs.msg import Int32, Bool,UInt16
from cv_bridge import CvBridge
from sensor_msgs.msg import Image, CompressedImage

from rclpy.time import Time
import datetime


class HandCtrlArm(Node):
    def __init__(self,name):
        super().__init__(name)
        self.pub_Servo1 = self.create_publisher(Int32,"servo_s1" , 10)
        self.pub_Servo2 = self.create_publisher(Int32,"servo_s2" , 10)

        self.PWMServo_X = 0
        self.PWMServo_Y = 45
        self.s1_init_angle = Int32()
        self.s1_init_angle.data = self.PWMServo_X
        self.s2_init_angle = Int32()
        self.s2_init_angle.data = self.PWMServo_Y
        self.media_ros = Media_ROS()

        #确保角度正常处于中间
        for i in range(10):
            self.pub_Servo1.publish(self.s1_init_angle)
            self.pub_Servo2.publish(self.s2_init_angle)
            time.sleep(0.1)

        self.hand_detector = HandDetector()
        self.arm_status = True
        self.locking = True
        self.init = True
        self.pTime = 0
        self.add_lock = self.remove_lock = 0
        self.event = threading.Event()
        self.event.set()

    def process(self, frame):
        frame, lmList, bbox = self.hand_detector.findHands(frame)
        if len(lmList) != 0:
            threading.Thread(target=self.arm_ctrl_threading, args=(lmList,bbox)).start()
        else:
            self.media_ros.pub_vel(0.0,0.0,0.0)
        self.media_ros.pub_imgMsg(frame)
        return frame

    def arm_ctrl_threading(self, lmList,bbox):
        if self.event.is_set():
            self.event.clear()
            fingers = self.hand_detector.fingersUp(lmList)
            self.hand_detector.draw = True
            #gesture = self.hand_detector.get_gesture(lmList)
            self.arm_status = False
            point_x = lmList[9][1]
            point_y = lmList[9][2]

            print("x",point_x)
            if point_y >= 270: x = -0.2
            elif point_y <= 150: x = 0.2
            else: x = 0.0
            if point_x >= 350: y = -0.2
            elif point_x <= 300: y = 0.2
            else: y = 0.0
            self.media_ros.pub_vel(x,0.0,y)
            print(f'value: x:{x},y:{y}')
            self.arm_status = True
            self.event.set()


class MY_Picture(Node):
    def __init__(self, name):
        super().__init__(name)
        self.bridge = CvBridge()
        self.sub_img = self.create_subscription(
            CompressedImage, '/espRos/esp32camera', self.handleTopic, 1) #获取esp32传来的图像
        
        self.handctrlarm = HandCtrlArm('handctrl')
        self.last_stamp = None
        self.new_seconds = 0
        self.fps_seconds = 1

    def handleTopic(self, msg):
        self.last_stamp = msg.header.stamp  
        if self.last_stamp:
            total_secs = Time(nanoseconds=self.last_stamp.nanosec, seconds=self.last_stamp.sec).nanoseconds
            delta = datetime.timedelta(seconds=total_secs * 1e-9)
            seconds = delta.total_seconds()*100

            if self.new_seconds != 0:
                self.fps_seconds = seconds - self.new_seconds

            self.new_seconds = seconds#保留这次的值

        start = time.time()
        frame = self.bridge.compressed_imgmsg_to_cv2(msg)
        frame = cv.resize(frame, (640, 480))

        action = cv.waitKey(1) & 0xFF
        frame = self.handctrlarm.process(frame)
        if action == ord('q'):
            self.handctrlarm.media_ros.cancel()

        
        end = time.time()
        fps = 1 / ((end - start)+self.fps_seconds)
        
        text = "FPS : " + str(int(fps))
        cv.putText(frame, text, (10,20), cv.FONT_HERSHEY_SIMPLEX, 0.8, (0,255,255), 2)
        cv.imshow('frame', frame)



def main():
    rclpy.init() 
    esp_img = MY_Picture("My_Picture")
    print("start it")
    try:
        rclpy.spin(esp_img)
    except KeyboardInterrupt:
        pass
    finally:
        esp_img.destroy_node()
        rclpy.shutdown()

主要逻辑:其实获取到的就是咱们手掌中指的第一个关节的坐标(第9点),通过判断这个坐标在画面中的位置来发送给底盘xy方向上的速度,即可实现控制。 

补充一个节点通信图

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/967623.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MySQL第五次作业

根据图片内容完成作业 1.建表 &#xff08;1&#xff09;建立两个表:goods(商品表)、orders(订单表) mysql> create table goods( -> gid char(8) primary key, -> name varchar(10), -> price decimal(8,2), -> num int); mysql> create t…

Linux:软硬链接和动静态库

hello&#xff0c;各位小伙伴&#xff0c;本篇文章跟大家一起学习《Linux&#xff1a;软硬链接和动静态库》&#xff0c;感谢大家对我上一篇的支持&#xff0c;如有什么问题&#xff0c;还请多多指教 &#xff01; 如果本篇文章对你有帮助&#xff0c;还请各位点点赞&#xff0…

CSS 组合选择符详解与实战示例

在 Web 开发过程中&#xff0c;CSS 用于定义页面元素的样式&#xff0c;而选择器则帮助我们精确定位需要添加样式的元素。今天我们主要来讲解 CSS 中的组合选择符&#xff0c;它们能够根据 DOM 结构中元素之间的关系来选中目标元素&#xff0c;从而写出结构清晰、易于维护的 CS…

【Linux系统】—— 简易进度条的实现

【Linux系统】—— 简易进度条的实现 1 回车和换行2 缓冲区3 进度条的准备代码4 第一版进度条5 第二版进度条 1 回车和换行 先问大家一个问题&#xff1a;回车换行是什么&#xff0c;或者说回车和换行是同一个概念吗&#xff1f;   可能大家对回车换行有一定的误解&#xff0…

Winform开发框架(蝇量级) MiniFramework V2.1

C/S框架网与2022年发布的一款蝇量级开发框架&#xff0c;适用于开发Windows桌面软件、数据管理应用系统、软件工具等轻量级软件&#xff0c;如&#xff1a;PLC上位机软件、数据采集与分析软件、或企业管理软件&#xff0c;进销存等。适合个人开发者快速搭建软件项目。 适用开发…

win10 llamafactory模型微调相关②

微调 使用微调神器LLaMA-Factory轻松改变大语言模型的自我认知_llamafactory 自我认知-CSDN博客 【大模型微调】使用Llama Factory实现中文llama3微调_哔哩哔哩_bilibili 样本数据集 &#xff08;数据集管理脚本处需更改&#xff0c;见报错解决参考1&#xff09; 自我认知微…

AI大模型随机初始化权重并打印网络结构方法(以Deepseekv3为例,单机可跑)

背景 当前大模型的权重加载和调用&#xff0c;主要是通过在HuggingFace官网下载并使用transformer的库来加以实现&#xff1b;其中大模型的权重文件较大&#xff08;部分>100GB&#xff09;&#xff0c;若只是快速研究网络结构和数据流变化&#xff0c;则无需下载权重。本文…

前端项目打包完成后dist本地起node服务测试运行项目

1、新建文件夹 node-test 将打包dist 文件同步自定义本地服务文件夹node-test 中&#xff0c;安装依赖包。 npm install express serve-static cors 2、新创建服务文件js server.js 构建链接及端口 const express require(express); const path require(path); const co…

《语义捕捉全解析:从“我爱自然语言处理”到嵌入向量的全过程》

首先讲在前面&#xff0c;介绍一些背景 RAG&#xff08;Retrieval-Augmented Generation&#xff0c;检索增强生成&#xff09; 是一种结合了信息检索与语言生成模型的技术&#xff0c;通过从外部知识库中检索相关信息&#xff0c;并将其作为提示输入给大型语言模型&#xff…

Word中Ctrl+V粘贴报错问题

Word中CtrlV粘贴时显示“文件未找到&#xff1a;MathPage.WLL”的问题 Word的功能栏中有MathType&#xff0c;但无法使用&#xff0c;显示灰色。 解决方法如下&#xff1a; 首先找到MathType安装目录下MathPage.wll文件以及MathType Commands 2016.dotm文件&#xff0c;分别复…

Git 与 Git常用命令

Git 是一个开源的分布式版本控制系统&#xff0c;广泛用于源代码管理。与传统的集中式版本控制系统不同&#xff0c;Git 允许每个开发者在本地拥有完整的代码库副本&#xff0c;支持离线工作和高效的分支管理。每次提交时&#xff0c;Git 会对当前项目的所有文件创建一个快照&a…

构建jdk17包含maven的基础镜像

1、先拉取jdk17基础镜像 docker pull openjdk:17-jdk-alpine 2、使用jdk17基础镜像创建容器 docker run -it openjdk:17-jdk-alpine sh 或 docker run -it --name jdk17 openjdk:17-jdk-alpine sh 3、修改镜像源地址 cat /etc/apk/repositories https://mirrors.aliyun.com…

【博客之星】GIS老矣尚能饭否?WebGIS项目实战经验与成果展示

目录 一、最前面的话 二、前言 1、关于“夜郎king” 3、GIS的“老骥伏枥” 4、WebGIS的“新程启航” 三、WebGIS技术简介 1、前、后技术简介 2、系统功能架构 四、WebGIS项目应用效果 1、应急灾害 2、交通运输 3、智慧文旅 4、其它项目 五、未来与展望 1、云计算…

如何在Vue中实现事件处理

在Vue中&#xff0c;事件处理是一个核心概念&#xff0c;它让我们能够响应用户的操作&#xff0c;比如点击按钮、输入文本等。Vue提供了一个简洁而强大的方式来绑定事件和处理事件。本文将介绍如何在Vue中实现事件处理&#xff0c;覆盖事件绑定、事件修饰符以及事件处理函数等内…

elementplus 使用日期时间选择器,设置可选范围为前后大于2年且只能选择历史时间不能大于当前时间点

需求&#xff1a;时间选择器可选的时间范围进行限制&#xff0c;-2年<a<2年且a<new Date().getTime()核心&#xff1a;这里需要注意plus版没有picker-options换成disabled-date属性了&#xff0c;使用了visible-change和calendar-change属性逻辑&#xff1a;另设一个参…

【MATLAB源码-第261期】基于matlab的帝企鹅优化算法(EPO)机器人栅格路径规划,输出做短路径图和适应度曲线

操作环境&#xff1a; MATLAB 2022a 1、算法描述 帝企鹅优化算法&#xff08;Emperor Penguin Optimizer&#xff0c;简称EPO&#xff09;是一种基于自然现象的优化算法&#xff0c;灵感来自于帝企鹅在南极极寒环境中的生活习性。帝企鹅是一种群居动物&#xff0c;生活在极端…

协议-ACLLite-ffmpeg

是什么&#xff1f; FFmpeg是一个开源的多媒体处理工具包&#xff0c;它集成了多种功能&#xff0c;包括音视频的录制、转换和流式传输处理。FFmpeg由一系列的库和工具组成&#xff0c;其中最核心的是libavcodec和libavformat库。 libavcodec是一个领先的音频/视频编解码器库&…

DuckDB:pg_duckdb集成DuckDB和PostgreSQL实现高效数据分析

pg_duckdb是PostgreSQL的扩展&#xff0c;它将DuckDB的列矢量化分析引擎和特性嵌入到PostgreSQL中。本文介绍pg_duckdb插件安装、特点以及如何快速入门使用。 pg_duckdb简介 pg_duckdb扩展将完全能够查询DuckDB中存储在云中的数据&#xff0c;就像它是本地的一样。DuckDB的“双…

防火墙安全综合实验

防火墙安全综合实验 一、拓扑信息 二、需求及配置 实验步骤 需求一&#xff1a;根据下表&#xff0c;完成相关配置 设备接口VLAN接口类型SW2GE0/0/2VLAN 10AccessGE0/0/3VLAN 20AccessGE0/0/1VLAN List&#xff1a;10 20Trunk 1、创建vlan10和vlan20 2、将接口划分到对应…

Vue 响应式渲染 - 过滤应用

Vue 渐进式JavaScript 框架 基于Vue2的学习笔记 - Vue响应式渲染综合 - 过滤应用 目录 过滤应用 引入vue Vue设置 设置页面元素 模糊查询过滤实现 函数表达式实现 总结 过滤应用 综合响应式渲染做一个输入框&#xff0c;用来实现&#xff1b;搜索输入框关键词符合列表。…