diff --git a/keyboard_control.py b/keyboard_control.py new file mode 100755 index 0000000..3f9ec01 --- /dev/null +++ b/keyboard_control.py @@ -0,0 +1,121 @@ +#!/usr/bin/env python3 +""" +Keyboard control node for robot chassis. +W/S: forward/backward +A/D: turn left/right +I/K: increase/decrease linear speed +J/L: increase/decrease angular speed +X: stop +Q: quit +""" + +import rclpy +from rclpy.node import Node +from geometry_msgs.msg import Twist +import sys +import select +import termios +import tty + +HELP = """ +======================================== + Keyboard Control +======================================== + W/S : forward / backward + A/D : turn left / turn right + I/K : linear speed +/- (step 0.05) + J/L : angular speed +/- (step 0.1) + X/Space: stop + Q : quit +======================================== + Current: lin=%.2f ang=%.2f +""" + + +class KeyboardControl(Node): + def __init__(self): + super().__init__("keyboard_control") + self.pub = self.create_publisher(Twist, "/cmd_vel", 10) + + self.lin_speed = 0.2 + self.ang_speed = 0.5 + self.lin_step = 0.05 + self.ang_step = 0.1 + + self.print_help() + self.create_timer(0.05, self.read_key) + + def print_help(self): + print(HELP % (self.lin_speed, self.ang_speed)) + + def get_key(self): + fd = sys.stdin.fileno() + old = termios.tcgetattr(fd) + try: + tty.setraw(fd) + r, _, _ = select.select([sys.stdin], [], [], 0.05) + if r: + return sys.stdin.read(1) + return None + finally: + termios.tcsetattr(fd, termios.TCSADRAIN, old) + + def read_key(self): + key = self.get_key() + if key is None: + return + + twist = Twist() + + if key == 'w': + twist.linear.x = self.lin_speed + elif key == 's': + twist.linear.x = -self.lin_speed + elif key == 'a': + twist.angular.z = self.ang_speed + elif key == 'd': + twist.angular.z = -self.ang_speed + elif key == 'i': + self.lin_speed = round(self.lin_speed + self.lin_step, 2) + self.print_help() + return + elif key == 'k': + self.lin_speed = round(max(0.0, self.lin_speed - self.lin_step), 2) + self.print_help() + return + elif key == 'j': + self.ang_speed = round(self.ang_speed + self.ang_step, 2) + self.print_help() + return + elif key == 'l': + self.ang_speed = round(max(0.0, self.ang_speed - self.ang_step), 2) + self.print_help() + return + elif key == 'x' or key == ' ': + twist.linear.x = 0.0 + twist.angular.z = 0.0 + print("*** STOP ***") + elif key == 'q' or ord(key) == 3: + twist.linear.x = 0.0 + twist.angular.z = 0.0 + self.pub.publish(twist) + self.get_logger().info("Quitting...") + raise SystemExit + else: + return + + self.pub.publish(twist) + + +def main(): + rclpy.init() + try: + rclpy.spin(KeyboardControl()) + except SystemExit: + pass + finally: + rclpy.shutdown() + + +if __name__ == "__main__": + main() diff --git a/src/gc_navigation2_slamtoolbox/params/gc_navigation_slam.yaml b/src/gc_navigation2_slamtoolbox/params/gc_navigation_slam.yaml index fd49aff..9ebc641 100644 --- a/src/gc_navigation2_slamtoolbox/params/gc_navigation_slam.yaml +++ b/src/gc_navigation2_slamtoolbox/params/gc_navigation_slam.yaml @@ -147,7 +147,7 @@ controller_server_rclcpp_node: local_costmap: local_costmap: ros__parameters: - update_frequency: 5.0 + update_frequency: 1.0 publish_frequency: 2.0 transform_tolerance: 0.5 global_frame: odom diff --git a/src/qr_detection/CMakeLists.txt b/src/qr_detection/CMakeLists.txt new file mode 100644 index 0000000..6813adf --- /dev/null +++ b/src/qr_detection/CMakeLists.txt @@ -0,0 +1,75 @@ +cmake_minimum_required(VERSION 3.5) +project(qr_detection) + +# Default to C99 +if(NOT CMAKE_C_STANDARD) + set(CMAKE_C_STANDARD 99) +endif() + +# Default to C++14 +if(NOT CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 14) +endif() + +if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wall -Wextra -Wpedantic) +endif() + +# Find dependencies +find_package(ament_cmake REQUIRED) +find_package(rclcpp REQUIRED) +find_package(std_msgs REQUIRED) +find_package(dnn_node REQUIRED) +# find_package(hbm_img_msgs REQUIRED) +find_package(sensor_msgs REQUIRED) +find_package(ai_msgs REQUIRED) +find_package(OpenCV REQUIRED) +find_package(geometry_msgs REQUIRED) +find_package(rosidl_default_generators REQUIRED) +find_package(PkgConfig REQUIRED) +pkg_check_modules(ZBar REQUIRED zbar) + +# rosidl_generate_interfaces(${PROJECT_NAME} +# "msg/SampleMessage.msg" +# ) + +# # Define executables +# add_executable(talker src/publisher_hbmem.cpp) +# ... + +# add_executable(qr_dete_node src/qr_dete.cpp) +# ... + +# install(DIRECTORY +# ${PROJECT_SOURCE_DIR}/launch/ +# DESTINATION share/${PROJECT_NAME}/launch) + +# ---- qr_dete_depth_node (sensor_msgs::Image, no hbmem) ---- +add_executable(qr_dete_depth_node src/qr_dete_depth.cpp) +ament_target_dependencies(qr_dete_depth_node + rclcpp + std_msgs + sensor_msgs + geometry_msgs +) + +target_include_directories(qr_dete_depth_node PUBLIC + $ + $ + ${OpenCV_INCLUDE_DIRS} ${ZBar_INCLUDE_DIRS}) + +target_link_libraries(qr_dete_depth_node + ${OpenCV_LIBS} ${ZBar_LIBRARIES} +) + +install(TARGETS qr_dete_depth_node + DESTINATION lib/${PROJECT_NAME}) + +if(BUILD_TESTING) + find_package(ament_lint_auto REQUIRED) + set(ament_cmake_copyright_FOUND TRUE) + set(ament_cmake_cpplint_FOUND TRUE) + ament_lint_auto_find_test_dependencies() +endif() + +ament_package() diff --git a/src/qr_detection/launch/qr_detection.launch.py b/src/qr_detection/launch/qr_detection.launch.py new file mode 100644 index 0000000..2211d76 --- /dev/null +++ b/src/qr_detection/launch/qr_detection.launch.py @@ -0,0 +1,37 @@ +import os + +from launch import LaunchDescription +from launch.actions import DeclareLaunchArgument +from launch.actions import IncludeLaunchDescription +from launch_ros.actions import Node +from launch.substitutions import TextSubstitution +from launch.substitutions import LaunchConfiguration +from launch.launch_description_sources import PythonLaunchDescriptionSource +from ament_index_python import get_package_share_directory + +def generate_launch_description(): + nv12_codec_node = IncludeLaunchDescription( + PythonLaunchDescriptionSource( + os.path.join( + get_package_share_directory('hobot_codec'), + 'launch/hobot_codec_decode.launch.py')), + launch_arguments={ + # 'codec_channel': '2', + 'codec_in_mode': 'ros', + 'codec_out_mode': 'shared_mem', + 'codec_sub_topic': '/image', + 'codec_pub_topic': '/hbmem_img' + }.items() + ) + + qr_detection_node = Node( + package='qr_detection', + executable='qr_dete_node', + name='qr_dete_node', + output='screen' + ) + + return LaunchDescription([ + nv12_codec_node, + qr_detection_node + ]) diff --git a/src/qr_detection/msg/SampleMessage.msg b/src/qr_detection/msg/SampleMessage.msg new file mode 100644 index 0000000..ecffd87 --- /dev/null +++ b/src/qr_detection/msg/SampleMessage.msg @@ -0,0 +1,5 @@ +int32 index +uint64 time_stamp +uint8[4194304] data + +uint32 MAX_SIZE=4194304 \ No newline at end of file diff --git a/src/qr_detection/package.xml b/src/qr_detection/package.xml new file mode 100644 index 0000000..e6e8971 --- /dev/null +++ b/src/qr_detection/package.xml @@ -0,0 +1,22 @@ + + + + qr_detection + 0.0.0 + TODO: Package description + root + TODO: License declaration + + ament_cmake + rosidl_default_generators + rosidl_default_runtime + rosidl_interface_packages + rclcpp + + ament_lint_auto + ament_lint_common + + + ament_cmake + + diff --git a/src/qr_detection/src/publisher_hbmem.cpp b/src/qr_detection/src/publisher_hbmem.cpp new file mode 100644 index 0000000..4a73e6d --- /dev/null +++ b/src/qr_detection/src/publisher_hbmem.cpp @@ -0,0 +1,70 @@ +#include +#include +#include +#include + +#include "rclcpp/rclcpp.hpp" +#include "qr_detection/msg/sample_message.hpp" + +using namespace std::chrono_literals; + +class MinimalHbmemPublisher : public rclcpp::Node { + public: + MinimalHbmemPublisher () : Node("minimal_hbmem_publisher"), count_(0) { + // 创建publisher_hbmem,topic为"topic" + publisher_ = this->create_publisher_hbmem( + "topic", rclcpp::SensorDataQoS()); + + // 定时器,每隔40毫秒调用一次timer_callback进行消息发送 + timer_ = this->create_wall_timer( + 40ms, std::bind(&MinimalHbmemPublisher::timer_callback, this)); + } + + private: + // 定时器回调函数 + void timer_callback() { + // 获取要发送的消息 + auto loanedMsg = publisher_->borrow_loaned_message(); + // 判断消息是否可用,可能出现获取消息失败导致消息不可用的情况 + if (loanedMsg.is_valid()) { + // 引用方式获取实际的消息 + auto& msg = loanedMsg.get(); + + // 获取当前时间,单位为us + auto time_now = + std::chrono::duration_cast( + std::chrono::steady_clock::now().time_since_epoch()).count(); + + // 对消息的index和time_stamp进行赋值 + msg.index = count_; + msg.time_stamp = time_now; + + // 打印发送消息 + RCLCPP_INFO(this->get_logger(), "message: %d", msg.index); + publisher_->publish(std::move(loanedMsg)); + // 注意,发送后,loanedMsg已不可用 + // 计数器加一 + count_++; + } else { + // 获取消息失败,丢弃该消息 + RCLCPP_INFO(this->get_logger(), "Failed to get LoanMessage!"); + } + } + + // 定时器 + rclcpp::TimerBase::SharedPtr timer_; + + // hbmem publisher + rclcpp::PublisherHbmem::SharedPtr publisher_; + + // 计数器 + size_t count_; +}; + +int main(int argc, char * argv[]) +{ + rclcpp::init(argc, argv); + rclcpp::spin(std::make_shared()); + rclcpp::shutdown(); + return 0; +} \ No newline at end of file diff --git a/src/qr_detection/src/qr_dete.cpp b/src/qr_detection/src/qr_dete.cpp new file mode 100644 index 0000000..c86a999 --- /dev/null +++ b/src/qr_detection/src/qr_dete.cpp @@ -0,0 +1,290 @@ +#include +#include +#include +#include +#include "rclcpp/rclcpp.hpp" +#include "std_msgs/msg/int32.hpp" +#include "std_msgs/msg/string.hpp" +#include "hbm_img_msgs/msg/hbm_msg1080_p.hpp" + +class MinimalHbmemSubscriber : public rclcpp::Node +{ +public: + MinimalHbmemSubscriber() + : Node("qr_detection"), detect_qr_code_(true) // 默认不检测二维码 + { + // 创建 subscription_hbmem,topic 为 "hbmem_img" + subscription_hbmem_ = + this->create_subscription_hbmem( + "hbmem_img", + 10, + std::bind(&MinimalHbmemSubscriber::hbmem_callback, this, std::placeholders::_1)); + + // 创建订阅器,订阅 'sign4return' 话题 + subscription_sign_ = + this->create_subscription( + "sign4return", + 10, + std::bind(&MinimalHbmemSubscriber::sign_callback, this, std::placeholders::_1)); + + // 创建 publisher,topic 为 "qr_results" + publisher_ = + this->create_publisher("qr_results", 10); + } + +private: + // 消息回调函数,处理 hbmem_img 话题 + void hbmem_callback(const hbm_img_msgs::msg::HbmMsg1080P::SharedPtr msg) + { + if (!detect_qr_code_) + { + RCLCPP_INFO(this->get_logger(), "QR detection is disabled"); + return; // 如果标志位为 false,则不进行二维码检测 + } + + // 创建 Clock 对象并获取当前时间 + auto clock = std::make_shared(RCL_SYSTEM_TIME); + auto now = clock->now(); + + // 转换消息时间戳为 ROS 时间 + auto msg_time = rclcpp::Time(msg->time_stamp.sec, msg->time_stamp.nanosec); + + // 计算延时(单位:微秒) + auto duration = now - msg_time; + auto delay_us = duration.nanoseconds() / 1000; // 转换为微秒 + + // 打印延迟 + RCLCPP_INFO(this->get_logger(), "msg index: %d, time cost %dus", msg->index, delay_us); + + // 获取图像数据并将其转换为 OpenCV 格式 + cv::Mat image(msg->height, msg->width, CV_8UC1, const_cast(msg->data.data())); + + // 初始化 ZBar 扫描器 + zbar::ImageScanner scanner; + scanner.set_config(zbar::ZBAR_NONE, zbar::ZBAR_CFG_ENABLE, 1); + + // 将 OpenCV 图像数据包装成 ZBar 图像 + zbar::Image zbar_image(image.cols, image.rows, "Y800", image.data, image.cols * image.rows); + + // 扫描图像中的条形码和二维码 + std::string qr_results; + int n = scanner.scan(zbar_image); + if (n > 0) { + for (auto symbol = zbar_image.symbol_begin(); symbol != zbar_image.symbol_end(); ++symbol) { + qr_results += symbol->get_data(); + RCLCPP_INFO(this->get_logger(), "Decoded %s symbol \"%s\"", symbol->get_type_name().c_str(), symbol->get_data().c_str()); + } + } else { + qr_results = "QR Code not detected"; + RCLCPP_INFO(this->get_logger(), "QR Code not detected"); + } + + // 发布 QR 结果 + auto message = std_msgs::msg::String(); + message.data = qr_results; + publisher_->publish(message); + } + + // 消息回调函数,处理 sign4return 话题 + void sign_callback(const std_msgs::msg::Int32::SharedPtr msg) + { + if (msg->data == 0) + { + detect_qr_code_ = true; // 启动二维码检测 + RCLCPP_INFO(this->get_logger(), "QR detection started"); + } + else if (msg->data == 5) + { + detect_qr_code_ = false; // 停止二维码检测 + RCLCPP_INFO(this->get_logger(), "QR detection stopped"); + } + } + + // hbmem_img 订阅器 + rclcpp::SubscriptionHbmem::SharedPtr subscription_hbmem_; + // sign4return 订阅器 + rclcpp::Subscription::SharedPtr subscription_sign_; + // QR code results 发布器 + rclcpp::Publisher::SharedPtr publisher_; + + // 二维码检测标志位 + bool detect_qr_code_; +}; + +int main(int argc, char * argv[]) +{ + rclcpp::init(argc, argv); + rclcpp::spin(std::make_shared()); + rclcpp::shutdown(); + return 0; +} + +/* +实现接收和发布 +*/ +//#include +//#include +//#include +//#include +//#include "rclcpp/rclcpp.hpp" +//#include "std_msgs/msg/string.hpp" +//#include "hbm_img_msgs/msg/hbm_msg1080_p.hpp" +// +//class MinimalHbmemSubscriber : public rclcpp::Node +//{ +//public: +// MinimalHbmemSubscriber() +// : Node("qr_detection") +// { +// // 创建 subscription_hbmem,topic 为 "hbmem_img" +// // 消息回调函数为 topic_callback +// subscription_ = +// this->create_subscription_hbmem( +// "hbmem_img", +// 10, +// std::bind(&MinimalHbmemSubscriber::topic_callback, this, std::placeholders::_1)); +// +// // 创建 publisher,topic 为 "qr_results" +// publisher_ = +// this->create_publisher("qr_results", 10); +// } +// +//private: +// // 消息回调函数 +// void topic_callback(const hbm_img_msgs::msg::HbmMsg1080P::SharedPtr msg) const +// { +// // 创建 Clock 对象并获取当前时间 +// auto clock = std::make_shared(RCL_SYSTEM_TIME); +// auto now = clock->now(); +// +// // 转换消息时间戳为 ROS 时间 +// auto msg_time = rclcpp::Time(msg->time_stamp.sec, msg->time_stamp.nanosec); +// +// // 计算延时(单位:微秒) +// auto duration = now - msg_time; +// auto delay_us = duration.nanoseconds() / 1000; // 转换为微秒 +// +// // 打印延迟 +// RCLCPP_INFO(this->get_logger(), "msg index: %d, time cost %dus", msg->index, delay_us); +// +// // 获取图像数据并将其转换为 OpenCV 格式 +// cv::Mat image(msg->height, msg->width, CV_8UC1, const_cast(msg->data.data())); +// +// // 初始化 ZBar 扫描器 +// zbar::ImageScanner scanner; +// scanner.set_config(zbar::ZBAR_NONE, zbar::ZBAR_CFG_ENABLE, 1); +// +// // 将 OpenCV 图像数据包装成 ZBar 图像 +// zbar::Image zbar_image(image.cols, image.rows, "Y800", image.data, image.cols * image.rows); +// +// // 扫描图像中的条形码和二维码 +// std::string qr_results; +// int n = scanner.scan(zbar_image); +// if (n > 0) { +// for (auto symbol = zbar_image.symbol_begin(); symbol != zbar_image.symbol_end(); ++symbol) { +// qr_results += symbol->get_data() ; +// RCLCPP_INFO(this->get_logger(), "Decoded %s symbol \"%s\"", symbol->get_type_name().c_str(), symbol->get_data().c_str()); +// } +// } else { +// qr_results = "QR Code not detected"; +// RCLCPP_INFO(this->get_logger(), "QR Code not detected"); +// } +// +// // 发布 QR 结果 +// auto message = std_msgs::msg::String(); +// message.data = qr_results; +// publisher_->publish(message); +// } +// +// // hbmem subscription +// rclcpp::SubscriptionHbmem::SharedPtr subscription_; +// // QR code results publisher +// rclcpp::Publisher::SharedPtr publisher_; +//}; +// +//int main(int argc, char * argv[]) +//{ +// rclcpp::init(argc, argv); +// rclcpp::spin(std::make_shared()); +// rclcpp::shutdown(); +// return 0; +//} + + +/* +只实现接收消息,不进行发布 +*/ + + +//#include +//#include +//#include +//#include +//#include "rclcpp/rclcpp.hpp" +//#include "hbm_img_msgs/msg/hbm_msg1080_p.hpp" +// +//class MinimalHbmemSubscriber : public rclcpp::Node +//{ +//public: +// MinimalHbmemSubscriber() +// : Node("qr_detection") +// { +// // 创建 subscription_hbmem,topic 为 "hbmem_img" +// // 消息回调函数为 topic_callback +// subscription_ = +// this->create_subscription_hbmem( +// "hbmem_img", +// 10, +// std::bind(&MinimalHbmemSubscriber::topic_callback, this, std::placeholders::_1)); +// } +//private: +// // 消息回调函数 +// void topic_callback( +// const hbm_img_msgs::msg::HbmMsg1080P::SharedPtr msg) const +// { +// // 创建 Clock 对象并获取当前时间 +// auto clock = std::make_shared(RCL_SYSTEM_TIME); +// auto now = clock->now(); +// +// // 转换消息时间戳为 ROS 时间 +// auto msg_time = rclcpp::Time(msg->time_stamp.sec, msg->time_stamp.nanosec); +// +// // 计算延时(单位:微秒) +// auto duration = now - msg_time; +// auto delay_us = duration.nanoseconds() / 1000; // 转换为微秒 +// +// // 打印延迟 +// RCLCPP_INFO(this->get_logger(), "msg index: %d, time cost %dus", msg->index, delay_us); +// +// // 获取图像数据并将其转换为 OpenCV 格式 +// cv::Mat image(msg->height, msg->width, CV_8UC1, const_cast(msg->data.data())); +// +// // 初始化 ZBar 扫描器 +// zbar::ImageScanner scanner; +// scanner.set_config(zbar::ZBAR_NONE, zbar::ZBAR_CFG_ENABLE, 1); +// +// // 将 OpenCV 图像数据包装成 ZBar 图像 +// zbar::Image zbar_image(image.cols, image.rows, "Y800", image.data, image.cols * image.rows); +// +// // 扫描图像中的条形码和二维码 +// int n = scanner.scan(zbar_image); +// if (n > 0) { +// for (auto symbol = zbar_image.symbol_begin(); symbol != zbar_image.symbol_end(); ++symbol) { +// RCLCPP_INFO(this->get_logger(), "Decoded %s symbol \"%s\"", symbol->get_type_name().c_str(), symbol->get_data().c_str()); +// } +// } else { +// RCLCPP_INFO(this->get_logger(), "QR Code not detected"); +// } +// } +// +// // hbmem subscription +// rclcpp::SubscriptionHbmem::SharedPtr subscription_; +//}; +// +//int main(int argc, char * argv[]) +//{ +// rclcpp::init(argc, argv); +// rclcpp::spin(std::make_shared()); +// rclcpp::shutdown(); +// return 0; +//} diff --git a/src/qr_detection/src/qr_dete_depth.cpp b/src/qr_detection/src/qr_dete_depth.cpp new file mode 100644 index 0000000..d3c9efc --- /dev/null +++ b/src/qr_detection/src/qr_dete_depth.cpp @@ -0,0 +1,131 @@ +#include +#include +#include +#include +#include "rclcpp/rclcpp.hpp" +#include "std_msgs/msg/int32.hpp" +#include "std_msgs/msg/string.hpp" +#include "sensor_msgs/msg/image.hpp" + +class MinimalHbmemSubscriber : public rclcpp::Node +{ +public: + MinimalHbmemSubscriber() + : Node("qr_detection"), detect_qr_code_(true) // 默认检测二维码 + { + // 订阅 /aurora/rgb/image_raw(sensor_msgs::msg::Image 格式) + subscription_image_ = + this->create_subscription( + "/aurora/rgb/image_raw", + 10, + std::bind(&MinimalHbmemSubscriber::image_callback, this, std::placeholders::_1)); + + // 创建订阅器,订阅 'sign4return' 话题 + subscription_sign_ = + this->create_subscription( + "sign4return", + 10, + std::bind(&MinimalHbmemSubscriber::sign_callback, this, std::placeholders::_1)); + + // 创建 publisher,topic 为 "qr_results" + publisher_ = + this->create_publisher("qr_results", 10); + } + +private: + // 图像回调函数,处理 /aurora/rgb/image_raw 话题 + void image_callback(const sensor_msgs::msg::Image::SharedPtr msg) + { + if (!detect_qr_code_) + { + RCLCPP_INFO(this->get_logger(), "QR detection is disabled"); + return; + } + + // 创建 Clock 对象并获取当前时间 + auto clock = std::make_shared(RCL_SYSTEM_TIME); + auto now = clock->now(); + + // 转换消息时间戳为 ROS 时间 + auto msg_time = rclcpp::Time(msg->header.stamp.sec, msg->header.stamp.nanosec); + + // 计算延时(单位:微秒) + auto duration = now - msg_time; + auto delay_us = duration.nanoseconds() / 1000; // 转换为微秒 + + // 打印延迟 + RCLCPP_INFO(this->get_logger(), "frame_id: %s, time cost %ldus", + msg->header.frame_id.c_str(), delay_us); + + // 将 sensor_msgs::Image 转换为 OpenCV 格式(Aurora RGB 为 bgr8 编码,需转为灰度给 ZBar) + if (msg->encoding != "bgr8") { + RCLCPP_ERROR(this->get_logger(), "Expected bgr8 encoding, got %s", msg->encoding.c_str()); + return; + } + cv::Mat rgb_image(msg->height, msg->width, CV_8UC3, + const_cast(msg->data.data())); + cv::Mat gray_image; + cv::cvtColor(rgb_image, gray_image, cv::COLOR_BGR2GRAY); + + // 初始化 ZBar 扫描器 + zbar::ImageScanner scanner; + scanner.set_config(zbar::ZBAR_NONE, zbar::ZBAR_CFG_ENABLE, 1); + + // 将 OpenCV 图像数据包装成 ZBar 图像 + zbar::Image zbar_image(gray_image.cols, gray_image.rows, "Y800", + gray_image.data, gray_image.cols * gray_image.rows); + + // 扫描图像中的条形码和二维码 + std::string qr_results; + int n = scanner.scan(zbar_image); + if (n > 0) { + for (auto symbol = zbar_image.symbol_begin(); + symbol != zbar_image.symbol_end(); ++symbol) { + qr_results += symbol->get_data(); + RCLCPP_INFO(this->get_logger(), "Decoded %s symbol \"%s\"", + symbol->get_type_name().c_str(), symbol->get_data().c_str()); + } + } else { + qr_results = "QR Code not detected"; + RCLCPP_INFO(this->get_logger(), "QR Code not detected"); + } + + // 发布 QR 结果 + auto message = std_msgs::msg::String(); + message.data = qr_results; + publisher_->publish(message); + } + + // 消息回调函数,处理 sign4return 话题 + void sign_callback(const std_msgs::msg::Int32::SharedPtr msg) + { + if (msg->data == 0) + { + detect_qr_code_ = true; // 启动二维码检测 + RCLCPP_INFO(this->get_logger(), "QR detection started"); + } + else if (msg->data == 5) + { + detect_qr_code_ = false; // 停止二维码检测 + RCLCPP_INFO(this->get_logger(), "QR detection stopped"); + } + } + + // /aurora/rgb/image_raw 订阅器 + rclcpp::Subscription::SharedPtr subscription_image_; + // sign4return 订阅器 + rclcpp::Subscription::SharedPtr subscription_sign_; + // QR code results 发布器 + rclcpp::Publisher::SharedPtr publisher_; + + // 二维码检测标志位 + bool detect_qr_code_; +}; + +int main(int argc, char * argv[]) +{ + rclcpp::init(argc, argv); + rclcpp::spin(std::make_shared()); + rclcpp::shutdown(); + return 0; +} diff --git a/src/qr_detection/src/qr_detection_node.cpp b/src/qr_detection/src/qr_detection_node.cpp new file mode 100644 index 0000000..6f349d2 --- /dev/null +++ b/src/qr_detection/src/qr_detection_node.cpp @@ -0,0 +1,50 @@ +#include +#include "rclcpp/rclcpp.hpp" +#include "hbm_img_msgs/msg/hbm_msg1080_p.hpp" + +class MinimalHbmemSubscriber : public rclcpp::Node +{ +public: + MinimalHbmemSubscriber() + : Node("qr_detection") + { + // 创建 subscription_hbmem,topic 为 "hbmem_img" + // 消息回调函数为 topic_callback + subscription_ = + this->create_subscription_hbmem( + "hbmem_img", + 10, + std::bind(&MinimalHbmemSubscriber::topic_callback, this, std::placeholders::_1)); + } + +private: + // 消息回调函数 + void topic_callback( + const hbm_img_msgs::msg::HbmMsg1080P::SharedPtr msg) const + { + // 创建 Clock 对象并获取当前时间 + auto clock = std::make_shared(RCL_SYSTEM_TIME); + auto now = clock->now(); + + // 转换消息时间戳为 ROS 时间 + auto msg_time = rclcpp::Time(msg->time_stamp.sec, msg->time_stamp.nanosec); + + // 计算延时(单位:微秒) + auto duration = now - msg_time; + auto delay_us = duration.nanoseconds() / 1000; // 转换为微秒 + + // 打印延迟 + RCLCPP_INFO(this->get_logger(), "msg index: %d, time cost %dus", msg->index, delay_us); + } + + // hbmem subscription + rclcpp::SubscriptionHbmem::SharedPtr subscription_; +}; + +int main(int argc, char * argv[]) +{ + rclcpp::init(argc, argv); + rclcpp::spin(std::make_shared()); + rclcpp::shutdown(); + return 0; +} diff --git a/src/qr_detection/src/sameple_zbar.cpp b/src/qr_detection/src/sameple_zbar.cpp new file mode 100644 index 0000000..381808a --- /dev/null +++ b/src/qr_detection/src/sameple_zbar.cpp @@ -0,0 +1,36 @@ +#include +#include +#include + +int main(int argc, char* argv[]) { + if (argc != 2) { + std::cerr << "Usage: " << argv[0] << " " << std::endl; + return -1; + } + + std::string image_path = argv[1]; + cv::Mat image = cv::imread(image_path, cv::IMREAD_GRAYSCALE); + if (image.empty()) { + std::cerr << "Could not open or find the image: " << image_path << std::endl; + return -1; + } + + // Initialize ZBar scanner + zbar::ImageScanner scanner; + scanner.set_config(zbar::ZBAR_NONE, zbar::ZBAR_CFG_ENABLE, 1); + + // Wrap OpenCV image data in a ZBar image + zbar::Image zbar_image(image.cols, image.rows, "Y800", image.data, image.cols * image.rows); + + // Scan the image for barcodes and QR codes + int n = scanner.scan(zbar_image); + if (n > 0) { + for (auto symbol = zbar_image.symbol_begin(); symbol != zbar_image.symbol_end(); ++symbol) { + std::cout << "Decoded " << symbol->get_type_name() << " symbol \"" << symbol->get_data() << '"' << std::endl; + } + } else { + std::cout << "QR Code not detected" << std::endl; + } + + return 0; +} \ No newline at end of file diff --git a/src/qr_detection/src/subscriber_hbmem.cpp b/src/qr_detection/src/subscriber_hbmem.cpp new file mode 100644 index 0000000..5396c3d --- /dev/null +++ b/src/qr_detection/src/subscriber_hbmem.cpp @@ -0,0 +1,45 @@ +#include + +#include "rclcpp/rclcpp.hpp" +#include "qr_detection/msg/sample_message.hpp" + +class MinimalHbmemSubscriber : public rclcpp::Node { + public: + MinimalHbmemSubscriber () : Node("minimal_hbmem_subscriber") { + // 创建subscription_hbmem,topic为"sample" + // 消息回调函数为topic_callback + subscription_ = + this->create_subscription_hbmem( + "topic", rclcpp::SensorDataQoS(), + std::bind(&MinimalHbmemSubscriber ::topic_callback, this, + std::placeholders::_1)); + } + + private: + // 消息回调函数 + void topic_callback( + const qr_detection::msg::SampleMessage::SharedPtr msg) const { + // 注意,msg只能在回调函数中使用,回调函数返回后,该消息就会被释放 + // 获取当前时间 + auto time_now = + std::chrono::duration_cast( + std::chrono::steady_clock::now().time_since_epoch()) + .count(); + // 计算延时并打印出来 + RCLCPP_INFO(this->get_logger(), "msg %d, time cost %dus", msg->index, + time_now - msg->time_stamp); + } + + // hbmem subscription + rclcpp::SubscriptionHbmem::SharedPtr + subscription_; +}; + + +int main(int argc, char * argv[]) +{ + rclcpp::init(argc, argv); + rclcpp::spin(std::make_shared()); + rclcpp::shutdown(); + return 0; +} \ No newline at end of file diff --git a/src/vlm_detect/package.xml b/src/vlm_detect/package.xml new file mode 100644 index 0000000..3f6c53c --- /dev/null +++ b/src/vlm_detect/package.xml @@ -0,0 +1,18 @@ + + + + vlm_detect + 0.0.0 + TODO: Package description + root + TODO: License declaration + + ament_copyright + ament_flake8 + ament_pep257 + python3-pytest + + + ament_python + + diff --git a/src/vlm_detect/resource/vlm_detect b/src/vlm_detect/resource/vlm_detect new file mode 100644 index 0000000..e69de29 diff --git a/src/vlm_detect/setup.cfg b/src/vlm_detect/setup.cfg new file mode 100644 index 0000000..df6a351 --- /dev/null +++ b/src/vlm_detect/setup.cfg @@ -0,0 +1,4 @@ +[develop] +script_dir=$base/lib/vlm_detect +[install] +install_scripts=$base/lib/vlm_detect diff --git a/src/vlm_detect/setup.py b/src/vlm_detect/setup.py new file mode 100644 index 0000000..bc6e34e --- /dev/null +++ b/src/vlm_detect/setup.py @@ -0,0 +1,26 @@ +from setuptools import find_packages, setup + +package_name = 'vlm_detect' + +setup( + name=package_name, + version='0.0.0', + packages=find_packages(exclude=['test']), + data_files=[ + ('share/ament_index/resource_index/packages', + ['resource/' + package_name]), + ('share/' + package_name, ['package.xml']), + ], + install_requires=['setuptools'], + zip_safe=True, + maintainer='root', + maintainer_email='root@todo.todo', + description='TODO: Package description', + license='TODO: License declaration', + tests_require=['pytest'], + entry_points={ + 'console_scripts': [ + 'vlm_node = vlm_detect.vlm_node:main', + ], + }, +) diff --git a/src/vlm_detect/test/test_copyright.py b/src/vlm_detect/test/test_copyright.py new file mode 100644 index 0000000..97a3919 --- /dev/null +++ b/src/vlm_detect/test/test_copyright.py @@ -0,0 +1,25 @@ +# Copyright 2015 Open Source Robotics Foundation, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from ament_copyright.main import main +import pytest + + +# Remove the `skip` decorator once the source file(s) have a copyright header +@pytest.mark.skip(reason='No copyright header has been placed in the generated source file.') +@pytest.mark.copyright +@pytest.mark.linter +def test_copyright(): + rc = main(argv=['.', 'test']) + assert rc == 0, 'Found errors' diff --git a/src/vlm_detect/test/test_flake8.py b/src/vlm_detect/test/test_flake8.py new file mode 100644 index 0000000..27ee107 --- /dev/null +++ b/src/vlm_detect/test/test_flake8.py @@ -0,0 +1,25 @@ +# Copyright 2017 Open Source Robotics Foundation, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from ament_flake8.main import main_with_errors +import pytest + + +@pytest.mark.flake8 +@pytest.mark.linter +def test_flake8(): + rc, errors = main_with_errors(argv=[]) + assert rc == 0, \ + 'Found %d code style errors / warnings:\n' % len(errors) + \ + '\n'.join(errors) diff --git a/src/vlm_detect/test/test_pep257.py b/src/vlm_detect/test/test_pep257.py new file mode 100644 index 0000000..b234a38 --- /dev/null +++ b/src/vlm_detect/test/test_pep257.py @@ -0,0 +1,23 @@ +# Copyright 2015 Open Source Robotics Foundation, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from ament_pep257.main import main +import pytest + + +@pytest.mark.linter +@pytest.mark.pep257 +def test_pep257(): + rc = main(argv=['.', 'test']) + assert rc == 0, 'Found code style errors / warnings' diff --git a/src/vlm_detect/vlm_detect/__init__.py b/src/vlm_detect/vlm_detect/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/vlm_detect/vlm_detect/__pycache__/__init__.cpython-38.pyc b/src/vlm_detect/vlm_detect/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000..7b24d34 Binary files /dev/null and b/src/vlm_detect/vlm_detect/__pycache__/__init__.cpython-38.pyc differ diff --git a/src/vlm_detect/vlm_detect/__pycache__/vlm_node.cpython-38.pyc b/src/vlm_detect/vlm_detect/__pycache__/vlm_node.cpython-38.pyc new file mode 100644 index 0000000..665ce15 Binary files /dev/null and b/src/vlm_detect/vlm_detect/__pycache__/vlm_node.cpython-38.pyc differ diff --git a/src/vlm_detect/vlm_detect/vlm_node.py b/src/vlm_detect/vlm_detect/vlm_node.py new file mode 100644 index 0000000..ee1eb21 --- /dev/null +++ b/src/vlm_detect/vlm_detect/vlm_node.py @@ -0,0 +1,144 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +import rclpy +from rclpy.node import Node +from std_msgs.msg import Int32, String +from sensor_msgs.msg import CompressedImage +from cv_bridge import CvBridge +import cv2 +import base64 +import threading +from openai import OpenAI +import os +import time +import numpy as np + +class VLMProcessor(Node): + def __init__(self): + super().__init__('vlm_dtetct') + + # 初始化 OpenAI 客户端 + self.client = OpenAI( + base_url="http://192.168.1.103:8000/v1", + api_key="EMPTY" + ) + + # ROS2 组件 + self.bridge = CvBridge() + self.latest_image = None + self.image_lock = threading.Lock() + + # 订阅图像话题 + self.image_sub = self.create_subscription( + CompressedImage, + '/image', + self.image_callback, + 10 + ) + + # 订阅触发信号 + self.sign_sub = self.create_subscription( + Int32, + '/sign4return', + self.sign_callback, + 10 + ) + + # 发布结果 + self.result_pub = self.create_publisher( + String, + '/vlm_result', + 10 + ) + + self.get_logger().info("VLM Processor...") + + def image_callback(self, msg): + """保存最新的图像""" + with self.image_lock: + try: + np_arr = np.frombuffer(msg.data, np.uint8) + # 使用 OpenCV 解码图像 + cv_image = cv2.imdecode(np_arr, cv2.IMREAD_COLOR) + self.latest_image = cv_image + self.get_logger().debug("recive picture") + except Exception as e: + self.get_logger().error("err picture") + + def sign_callback(self, msg): + """处理触发信号""" + if msg.data == 9: + self.get_logger().info("收到触发信号 (6),开始处理图像...") + + # 检查是否有可用图像 + with self.image_lock: + if self.latest_image is None: + self.get_logger().warning("没有可用图像") + return + + # 保存临时图像文件 + temp_path = "/tmp/vlm_temp_image.jpg" + cv2.imwrite(temp_path, self.latest_image) + self.get_logger().info("已保存临时图像}") + + # 处理图像 + try: + description = self.process_image(temp_path) + self.get_logger().info(f"图像描述结果:") + + # 发布结果 + result_msg = String() + result_msg.data = description + self.result_pub.publish(result_msg) + + # 清理临时文件 + os.remove(temp_path) + except Exception as e: + self.get_logger().error(f"处理图像时出错:{e}") + + def process_image(self, image_path): + """使用 VLM 模型处理图像""" + # 读取并编码图像 + with open(image_path, "rb") as image_file: + base64_image = base64.b64encode(image_file.read()).decode('utf-8') + + # 发送请求到 VLM 模型 + start_time = time.time() + + response = self.client.chat.completions.create( + model="/home/yyh/vllm_test/model/InternVL3-1B", + messages=[ + { + "role": "user", + "content": [ + {"type": "text", "text": "描述图片中的动漫病人"}, + { + "type": "image_url", + "image_url": { + "url": f"data:image/jpeg;base64,{base64_image}" + } + } + ] + } + ], + max_tokens=100 + ) + + processing_time = time.time() - start_time + self.get_logger().info("VLM 处理耗时秒") + + return response.choices[0].message.content + +def main(args=None): + rclpy.init(args=args) + node = VLMProcessor() + try: + rclpy.spin(node) + except KeyboardInterrupt: + pass + finally: + node.destroy_node() + rclpy.shutdown() + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/src/yolov8_launch/class_list/cone.list b/src/yolov8_launch/class_list/cone.list new file mode 100644 index 0000000..d275e93 --- /dev/null +++ b/src/yolov8_launch/class_list/cone.list @@ -0,0 +1 @@ +cone \ No newline at end of file diff --git a/src/yolov8_launch/launch/dnn_node_example.launch.py b/src/yolov8_launch/launch/dnn_node_example.launch.py new file mode 100644 index 0000000..47b956c --- /dev/null +++ b/src/yolov8_launch/launch/dnn_node_example.launch.py @@ -0,0 +1,239 @@ +# Copyright (c) 2024,D-Robotics. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os + +from launch import LaunchDescription +from launch.actions import DeclareLaunchArgument +from launch.actions import IncludeLaunchDescription +from launch_ros.actions import Node +from launch.substitutions import TextSubstitution +from launch.substitutions import LaunchConfiguration +from launch.launch_description_sources import PythonLaunchDescriptionSource +from ament_index_python import get_package_share_directory +from ament_index_python.packages import get_package_prefix + + +def generate_launch_description(): + + # args that can be set from the command line or a default will be used + config_file_launch_arg = DeclareLaunchArgument( + "dnn_example_config_file", default_value=TextSubstitution(text="/root/yolov8workconfig.json") + ) + dump_render_launch_arg = DeclareLaunchArgument( + "dnn_example_dump_render_img", default_value=TextSubstitution(text="0") + ) + image_width_launch_arg = DeclareLaunchArgument( + "dnn_example_image_width", default_value=TextSubstitution(text="640") + ) + image_height_launch_arg = DeclareLaunchArgument( + "dnn_example_image_height", default_value=TextSubstitution(text="480") + ) + msg_pub_topic_name_launch_arg = DeclareLaunchArgument( + "dnn_example_msg_pub_topic_name", default_value=TextSubstitution(text="hobot_dnn_detection") + ) + + camera_type = os.getenv('CAM_TYPE') + camera_type = 'usb' + print("camera_type is ", camera_type) + + cam_node = None + camera_type_mipi = None + camera_device_arg = None + + if camera_type == "usb": + # usb cam图片发布pkg + usb_cam_device_arg = DeclareLaunchArgument( + 'device', + default_value='/dev/video8', + description='usb camera device') + + usb_node = IncludeLaunchDescription( + PythonLaunchDescriptionSource( + os.path.join( + get_package_share_directory('hobot_usb_cam'), + 'launch/hobot_usb_cam.launch.py')), + launch_arguments={ + 'usb_image_width': LaunchConfiguration('dnn_example_image_width'), + 'usb_image_height': LaunchConfiguration('dnn_example_image_height'), + 'usb_video_device': LaunchConfiguration('device') + }.items() + ) + print("using usb cam") + cam_node = usb_node + camera_type_mipi = False + camera_device_arg = usb_cam_device_arg + + elif camera_type == "fb": + # 本地图片发布 + feedback_picture_arg = DeclareLaunchArgument( + 'publish_image_source', + default_value='./config/target.jpg', + description='feedback picture') + + publish_image_fps = DeclareLaunchArgument( + 'publish_image_fps', + default_value='5', + description='publish_image_fps picture') + + fb_node = IncludeLaunchDescription( + PythonLaunchDescriptionSource( + os.path.join( + get_package_share_directory('hobot_image_publisher'), + 'launch/hobot_image_publisher.launch.py')), + launch_arguments={ + 'publish_image_source': LaunchConfiguration('publish_image_source'), + 'publish_image_format': LaunchConfiguration('publish_image_format'), + 'publish_message_topic_name': '/hbmem_img', + 'publish_fps': LaunchConfiguration('publish_image_fps') + }.items() + ) + + print("using feedback") + cam_node = fb_node + camera_type_mipi = True + camera_device_arg = feedback_picture_arg + + else: + if camera_type == "mipi": + print("using mipi cam") + else: + print("invalid camera_type ", camera_type, + ", which is set with export CAM_TYPE=usb/mipi/fb, using default mipi cam") + # mipi cam图片发布pkg + mipi_cam_device_arg = DeclareLaunchArgument( + 'device', + default_value='F37', + description='mipi camera device') + mipi_node = IncludeLaunchDescription( + PythonLaunchDescriptionSource( + os.path.join( + get_package_share_directory('mipi_cam'), + 'launch/mipi_cam.launch.py')), + launch_arguments={ + 'mipi_image_width': LaunchConfiguration('dnn_example_image_width'), + 'mipi_image_height': LaunchConfiguration('dnn_example_image_height'), + 'mipi_io_method': 'shared_mem', + 'mipi_frame_ts_type': 'realtime', + 'mipi_video_device': LaunchConfiguration('device') + }.items() + ) + + cam_node = mipi_node + camera_type_mipi = True + camera_device_arg = mipi_cam_device_arg + + # jpeg图片编码&发布pkg + jpeg_codec_node = IncludeLaunchDescription( + PythonLaunchDescriptionSource( + os.path.join( + get_package_share_directory('hobot_codec'), + 'launch/hobot_codec_encode.launch.py')), + launch_arguments={ + 'codec_in_mode': 'shared_mem', + 'codec_out_mode': 'ros', + 'codec_sub_topic': '/hbmem_img', + 'codec_pub_topic': '/image' + }.items() + ) + + # nv12图片解码&发布pkg + nv12_codec_node = IncludeLaunchDescription( + PythonLaunchDescriptionSource( + os.path.join( + get_package_share_directory('hobot_codec'), + 'launch/hobot_codec_decode.launch.py')), + launch_arguments={ + 'codec_in_mode': 'ros', + 'codec_out_mode': 'shared_mem', + 'codec_sub_topic': '/image', + 'codec_pub_topic': '/hbmem_img' + }.items() + ) + + # web展示pkg + web_node = IncludeLaunchDescription( + PythonLaunchDescriptionSource( + os.path.join( + get_package_share_directory('websocket'), + 'launch/websocket.launch.py')), + launch_arguments={ + 'websocket_image_topic': '/image', + 'websocket_image_type': 'mjpeg', + 'websocket_smart_topic': LaunchConfiguration("dnn_example_msg_pub_topic_name") + }.items() + ) + + # 算法pkg + dnn_node_example_node = Node( + package='dnn_node_example', + executable='example', + output='screen', + parameters=[ + {"config_file": LaunchConfiguration('dnn_example_config_file')}, + {"dump_render_img": LaunchConfiguration( + 'dnn_example_dump_render_img')}, + {"feed_type": 1}, + {"is_shared_mem_sub": 1}, + {"msg_pub_topic_name": LaunchConfiguration( + "dnn_example_msg_pub_topic_name")} + ], + arguments=['--ros-args', '--log-level', 'warn'] + ) + + shared_mem_node = IncludeLaunchDescription( + PythonLaunchDescriptionSource( + os.path.join( + get_package_share_directory('hobot_shm'), + 'launch/hobot_shm.launch.py')) + ) + + if camera_type_mipi: + return LaunchDescription([ + camera_device_arg, + config_file_launch_arg, + dump_render_launch_arg, + image_width_launch_arg, + image_height_launch_arg, + msg_pub_topic_name_launch_arg, + # 启动零拷贝环境配置node + # shared_mem_node, + # 图片发布pkg + cam_node, + # 图片编解码&发布pkg + nv12_codec_node, + # 启动example pkg + dnn_node_example_node, + # 启动web展示pkg + web_node + ]) + else: + return LaunchDescription([ + camera_device_arg, + config_file_launch_arg, + dump_render_launch_arg, + image_width_launch_arg, + image_height_launch_arg, + msg_pub_topic_name_launch_arg, + # 启动零拷贝环境配置node + # shared_mem_node, + # 图片发布pkg + cam_node, + # 图片编解码&发布pkg + nv12_codec_node, + # 启动example pkg + dnn_node_example_node, + # 启动web展示pkg + web_node + ]) diff --git a/src/yolov8_launch/package.xml b/src/yolov8_launch/package.xml new file mode 100644 index 0000000..3f20410 --- /dev/null +++ b/src/yolov8_launch/package.xml @@ -0,0 +1,18 @@ + + + + yolov8_launch + 0.0.0 + TODO: Package description + root + TODO: License declaration + + ament_copyright + ament_flake8 + ament_pep257 + python3-pytest + + + ament_python + + diff --git a/src/yolov8_launch/resource/yolov8_launch b/src/yolov8_launch/resource/yolov8_launch new file mode 100644 index 0000000..e69de29 diff --git a/src/yolov8_launch/setup.cfg b/src/yolov8_launch/setup.cfg new file mode 100644 index 0000000..ac28128 --- /dev/null +++ b/src/yolov8_launch/setup.cfg @@ -0,0 +1,4 @@ +[develop] +script_dir=$base/lib/yolov8_launch +[install] +install_scripts=$base/lib/yolov8_launch diff --git a/src/yolov8_launch/setup.py b/src/yolov8_launch/setup.py new file mode 100644 index 0000000..55e5c9d --- /dev/null +++ b/src/yolov8_launch/setup.py @@ -0,0 +1,27 @@ +from setuptools import find_packages, setup +import os +from glob import glob +package_name = 'yolov8_launch' + +setup( + name=package_name, + version='0.0.0', + packages=find_packages(exclude=['test']), + data_files=[ + ('share/ament_index/resource_index/packages', + ['resource/' + package_name]), + ('share/' + package_name, ['package.xml']), + ('share/' + package_name + '/launch', glob('launch/*.launch.py')), + ], + install_requires=['setuptools'], + zip_safe=True, + maintainer='root', + maintainer_email='root@todo.todo', + description='TODO: Package description', + license='TODO: License declaration', + tests_require=['pytest'], + entry_points={ + 'console_scripts': [ + ], + }, +) diff --git a/src/yolov8_launch/test/test_copyright.py b/src/yolov8_launch/test/test_copyright.py new file mode 100644 index 0000000..97a3919 --- /dev/null +++ b/src/yolov8_launch/test/test_copyright.py @@ -0,0 +1,25 @@ +# Copyright 2015 Open Source Robotics Foundation, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from ament_copyright.main import main +import pytest + + +# Remove the `skip` decorator once the source file(s) have a copyright header +@pytest.mark.skip(reason='No copyright header has been placed in the generated source file.') +@pytest.mark.copyright +@pytest.mark.linter +def test_copyright(): + rc = main(argv=['.', 'test']) + assert rc == 0, 'Found errors' diff --git a/src/yolov8_launch/test/test_flake8.py b/src/yolov8_launch/test/test_flake8.py new file mode 100644 index 0000000..27ee107 --- /dev/null +++ b/src/yolov8_launch/test/test_flake8.py @@ -0,0 +1,25 @@ +# Copyright 2017 Open Source Robotics Foundation, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from ament_flake8.main import main_with_errors +import pytest + + +@pytest.mark.flake8 +@pytest.mark.linter +def test_flake8(): + rc, errors = main_with_errors(argv=[]) + assert rc == 0, \ + 'Found %d code style errors / warnings:\n' % len(errors) + \ + '\n'.join(errors) diff --git a/src/yolov8_launch/test/test_pep257.py b/src/yolov8_launch/test/test_pep257.py new file mode 100644 index 0000000..b234a38 --- /dev/null +++ b/src/yolov8_launch/test/test_pep257.py @@ -0,0 +1,23 @@ +# Copyright 2015 Open Source Robotics Foundation, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from ament_pep257.main import main +import pytest + + +@pytest.mark.linter +@pytest.mark.pep257 +def test_pep257(): + rc = main(argv=['.', 'test']) + assert rc == 0, 'Found code style errors / warnings' diff --git a/src/yolov8_launch/yolov8_launch/__init__.py b/src/yolov8_launch/yolov8_launch/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/wget-log b/wget-log new file mode 100644 index 0000000..ae820b4 --- /dev/null +++ b/wget-log @@ -0,0 +1,47 @@ +--2026-06-15 22:41:04-- https://github.com/xiongqi123123/dtop/releases/download/v1.1.0/dtop-arm64-ubuntu22.04.tar.gz +Resolving github.com (github.com)... 20.205.243.166 +Connecting to github.com (github.com)|20.205.243.166|:443... connected. +HTTP request sent, awaiting response... No data received. +Retrying. + +--2026-06-15 22:42:35-- (try: 2) https://github.com/xiongqi123123/dtop/releases/download/v1.1.0/dtop-arm64-ubuntu22.04.tar.gz +Connecting to github.com (github.com)|20.205.243.166|:443... connected. +HTTP request sent, awaiting response... No data received. +Retrying. + +--2026-06-15 22:44:23-- (try: 3) https://github.com/xiongqi123123/dtop/releases/download/v1.1.0/dtop-arm64-ubuntu22.04.tar.gz +Connecting to github.com (github.com)|20.205.243.166|:443... connected. +HTTP request sent, awaiting response... No data received. +Retrying. + +--2026-06-15 22:45:57-- (try: 4) https://github.com/xiongqi123123/dtop/releases/download/v1.1.0/dtop-arm64-ubuntu22.04.tar.gz +Connecting to github.com (github.com)|20.205.243.166|:443... failed: Connection timed out. +Resolving github.com (github.com)... 20.205.243.166 +Connecting to github.com (github.com)|20.205.243.166|:443... failed: Connection timed out. +Retrying. + +--2026-06-15 22:50:24-- (try: 5) https://github.com/xiongqi123123/dtop/releases/download/v1.1.0/dtop-arm64-ubuntu22.04.tar.gz +Connecting to github.com (github.com)|20.205.243.166|:443... connected. +HTTP request sent, awaiting response... 302 Found +Location: https://release-assets.githubusercontent.com/github-production-release-asset/1029081525/f827fe4e-a10d-4add-b5e0-0826bb0ab476?sp=r&sv=2018-11-09&sr=b&spr=https&se=2026-06-15T15%3A45%3A59Z&rscd=attachment%3B+filename%3Ddtop-arm64-ubuntu22.04.tar.gz&rsct=application%2Foctet-stream&skoid=96c2d410-5711-43a1-aedd-ab1947aa7ab0&sktid=398a6654-997b-47e9-b12b-9515b896b4de&skt=2026-06-15T14%3A45%3A25Z&ske=2026-06-15T15%3A45%3A59Z&sks=b&skv=2018-11-09&sig=kk4nXxUt6miqrbhECM%2FuKWbFpwRp9VUofTHRECaQVq0%3D&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmVsZWFzZS1hc3NldHMuZ2l0aHVidXNlcmNvbnRlbnQuY29tIiwia2V5Ijoia2V5MSIsImV4cCI6MTc4MTUzNTMyNSwibmJmIjoxNzgxNTM1MDI1LCJwYXRoIjoicmVsZWFzZWFzc2V0cHJvZHVjdGlvbi5ibG9iLmNvcmUud2luZG93cy5uZXQifQ.utpBoEPybhRRSyqA_PRGkEHpxOA5k0qAXygmA87AjhQ&response-content-disposition=attachment%3B%20filename%3Ddtop-arm64-ubuntu22.04.tar.gz&response-content-type=application%2Foctet-stream [following] +--2026-06-15 22:50:25-- https://release-assets.githubusercontent.com/github-production-release-asset/1029081525/f827fe4e-a10d-4add-b5e0-0826bb0ab476?sp=r&sv=2018-11-09&sr=b&spr=https&se=2026-06-15T15%3A45%3A59Z&rscd=attachment%3B+filename%3Ddtop-arm64-ubuntu22.04.tar.gz&rsct=application%2Foctet-stream&skoid=96c2d410-5711-43a1-aedd-ab1947aa7ab0&sktid=398a6654-997b-47e9-b12b-9515b896b4de&skt=2026-06-15T14%3A45%3A25Z&ske=2026-06-15T15%3A45%3A59Z&sks=b&skv=2018-11-09&sig=kk4nXxUt6miqrbhECM%2FuKWbFpwRp9VUofTHRECaQVq0%3D&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmVsZWFzZS1hc3NldHMuZ2l0aHVidXNlcmNvbnRlbnQuY29tIiwia2V5Ijoia2V5MSIsImV4cCI6MTc4MTUzNTMyNSwibmJmIjoxNzgxNTM1MDI1LCJwYXRoIjoicmVsZWFzZWFzc2V0cHJvZHVjdGlvbi5ibG9iLmNvcmUud2luZG93cy5uZXQifQ.utpBoEPybhRRSyqA_PRGkEHpxOA5k0qAXygmA87AjhQ&response-content-disposition=attachment%3B%20filename%3Ddtop-arm64-ubuntu22.04.tar.gz&response-content-type=application%2Foctet-stream +Resolving release-assets.githubusercontent.com (release-assets.githubusercontent.com)... 185.199.109.133, 185.199.110.133, 185.199.108.133, ... +Connecting to release-assets.githubusercontent.com (release-assets.githubusercontent.com)|185.199.109.133|:443... connected. +HTTP request sent, awaiting response... 200 OK +Length: 529991 (518K) [application/octet-stream] +Saving to: ‘dtop-arm64-ubuntu22.04.tar.gz’ + + 0K .......... .......... .......... .......... .......... 9% 206K 2s + 50K .......... .......... .......... .......... .......... 19% 258K 2s + 100K .......... .......... .......... .......... .......... 28% 915K 1s + 150K .......... .......... .......... .......... .......... 38% 1.11M 1s + 200K .......... .......... .......... .......... .......... 48% 460K 1s + 250K .......... .......... .......... .......... .......... 57% 1.48M 0s + 300K .......... .......... .......... .......... .......... 67% 1.36M 0s + 350K .......... .......... .......... .......... .......... 77% 1.30M 0s + 400K .......... .......... .......... .......... .......... 86% 2.84M 0s + 450K .......... .......... .......... .......... .......... 96% 2.01M 0s + 500K .......... ....... 100% 390K=0.8s + +2026-06-15 22:50:27 (619 KB/s) - ‘dtop-arm64-ubuntu22.04.tar.gz’ saved [529991/529991] +