把去年的二维码检测、图生文客户端、锥桶检测v8给加了进来,二维码检测新增深度相机检测
This commit is contained in:
121
keyboard_control.py
Executable file
121
keyboard_control.py
Executable file
@@ -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()
|
||||
@@ -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
|
||||
|
||||
75
src/qr_detection/CMakeLists.txt
Normal file
75
src/qr_detection/CMakeLists.txt
Normal file
@@ -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
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
||||
$<INSTALL_INTERFACE:include>
|
||||
${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()
|
||||
37
src/qr_detection/launch/qr_detection.launch.py
Normal file
37
src/qr_detection/launch/qr_detection.launch.py
Normal file
@@ -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
|
||||
])
|
||||
5
src/qr_detection/msg/SampleMessage.msg
Normal file
5
src/qr_detection/msg/SampleMessage.msg
Normal file
@@ -0,0 +1,5 @@
|
||||
int32 index
|
||||
uint64 time_stamp
|
||||
uint8[4194304] data
|
||||
|
||||
uint32 MAX_SIZE=4194304
|
||||
22
src/qr_detection/package.xml
Normal file
22
src/qr_detection/package.xml
Normal file
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0"?>
|
||||
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
|
||||
<package format="3">
|
||||
<name>qr_detection</name>
|
||||
<version>0.0.0</version>
|
||||
<description>TODO: Package description</description>
|
||||
<maintainer email="root@todo.todo">root</maintainer>
|
||||
<license>TODO: License declaration</license>
|
||||
|
||||
<buildtool_depend>ament_cmake</buildtool_depend>
|
||||
<build_depend>rosidl_default_generators</build_depend>
|
||||
<exec_depend>rosidl_default_runtime</exec_depend>
|
||||
<member_of_group>rosidl_interface_packages</member_of_group>
|
||||
<depend>rclcpp</depend>
|
||||
|
||||
<test_depend>ament_lint_auto</test_depend>
|
||||
<test_depend>ament_lint_common</test_depend>
|
||||
|
||||
<export>
|
||||
<build_type>ament_cmake</build_type>
|
||||
</export>
|
||||
</package>
|
||||
70
src/qr_detection/src/publisher_hbmem.cpp
Normal file
70
src/qr_detection/src/publisher_hbmem.cpp
Normal file
@@ -0,0 +1,70 @@
|
||||
#include <chrono>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#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<qr_detection::msg::SampleMessage>(
|
||||
"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::microseconds>(
|
||||
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<qr_detection::msg::SampleMessage>::SharedPtr publisher_;
|
||||
|
||||
// 计数器
|
||||
size_t count_;
|
||||
};
|
||||
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
rclcpp::init(argc, argv);
|
||||
rclcpp::spin(std::make_shared<MinimalHbmemPublisher>());
|
||||
rclcpp::shutdown();
|
||||
return 0;
|
||||
}
|
||||
290
src/qr_detection/src/qr_dete.cpp
Normal file
290
src/qr_detection/src/qr_dete.cpp
Normal file
@@ -0,0 +1,290 @@
|
||||
#include <memory>
|
||||
#include <iostream>
|
||||
#include <opencv2/opencv.hpp>
|
||||
#include <zbar.h>
|
||||
#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<hbm_img_msgs::msg::HbmMsg1080P>(
|
||||
"hbmem_img",
|
||||
10,
|
||||
std::bind(&MinimalHbmemSubscriber::hbmem_callback, this, std::placeholders::_1));
|
||||
|
||||
// 创建订阅器,订阅 'sign4return' 话题
|
||||
subscription_sign_ =
|
||||
this->create_subscription<std_msgs::msg::Int32>(
|
||||
"sign4return",
|
||||
10,
|
||||
std::bind(&MinimalHbmemSubscriber::sign_callback, this, std::placeholders::_1));
|
||||
|
||||
// 创建 publisher,topic 为 "qr_results"
|
||||
publisher_ =
|
||||
this->create_publisher<std_msgs::msg::String>("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<rclcpp::Clock>(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<uint8_t*>(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<hbm_img_msgs::msg::HbmMsg1080P>::SharedPtr subscription_hbmem_;
|
||||
// sign4return 订阅器
|
||||
rclcpp::Subscription<std_msgs::msg::Int32>::SharedPtr subscription_sign_;
|
||||
// QR code results 发布器
|
||||
rclcpp::Publisher<std_msgs::msg::String>::SharedPtr publisher_;
|
||||
|
||||
// 二维码检测标志位
|
||||
bool detect_qr_code_;
|
||||
};
|
||||
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
rclcpp::init(argc, argv);
|
||||
rclcpp::spin(std::make_shared<MinimalHbmemSubscriber>());
|
||||
rclcpp::shutdown();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
实现接收和发布
|
||||
*/
|
||||
//#include <memory>
|
||||
//#include <iostream>
|
||||
//#include <opencv2/opencv.hpp>
|
||||
//#include <zbar.h>
|
||||
//#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<hbm_img_msgs::msg::HbmMsg1080P>(
|
||||
// "hbmem_img",
|
||||
// 10,
|
||||
// std::bind(&MinimalHbmemSubscriber::topic_callback, this, std::placeholders::_1));
|
||||
//
|
||||
// // 创建 publisher,topic 为 "qr_results"
|
||||
// publisher_ =
|
||||
// this->create_publisher<std_msgs::msg::String>("qr_results", 10);
|
||||
// }
|
||||
//
|
||||
//private:
|
||||
// // 消息回调函数
|
||||
// void topic_callback(const hbm_img_msgs::msg::HbmMsg1080P::SharedPtr msg) const
|
||||
// {
|
||||
// // 创建 Clock 对象并获取当前时间
|
||||
// auto clock = std::make_shared<rclcpp::Clock>(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<uint8_t*>(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<hbm_img_msgs::msg::HbmMsg1080P>::SharedPtr subscription_;
|
||||
// // QR code results publisher
|
||||
// rclcpp::Publisher<std_msgs::msg::String>::SharedPtr publisher_;
|
||||
//};
|
||||
//
|
||||
//int main(int argc, char * argv[])
|
||||
//{
|
||||
// rclcpp::init(argc, argv);
|
||||
// rclcpp::spin(std::make_shared<MinimalHbmemSubscriber>());
|
||||
// rclcpp::shutdown();
|
||||
// return 0;
|
||||
//}
|
||||
|
||||
|
||||
/*
|
||||
只实现接收消息,不进行发布
|
||||
*/
|
||||
|
||||
|
||||
//#include <memory>
|
||||
//#include <iostream>
|
||||
//#include <opencv2/opencv.hpp>
|
||||
//#include <zbar.h>
|
||||
//#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<hbm_img_msgs::msg::HbmMsg1080P>(
|
||||
// "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<rclcpp::Clock>(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<uint8_t*>(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<hbm_img_msgs::msg::HbmMsg1080P>::SharedPtr subscription_;
|
||||
//};
|
||||
//
|
||||
//int main(int argc, char * argv[])
|
||||
//{
|
||||
// rclcpp::init(argc, argv);
|
||||
// rclcpp::spin(std::make_shared<MinimalHbmemSubscriber>());
|
||||
// rclcpp::shutdown();
|
||||
// return 0;
|
||||
//}
|
||||
131
src/qr_detection/src/qr_dete_depth.cpp
Normal file
131
src/qr_detection/src/qr_dete_depth.cpp
Normal file
@@ -0,0 +1,131 @@
|
||||
#include <memory>
|
||||
#include <iostream>
|
||||
#include <opencv2/opencv.hpp>
|
||||
#include <zbar.h>
|
||||
#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<sensor_msgs::msg::Image>(
|
||||
"/aurora/rgb/image_raw",
|
||||
10,
|
||||
std::bind(&MinimalHbmemSubscriber::image_callback, this, std::placeholders::_1));
|
||||
|
||||
// 创建订阅器,订阅 'sign4return' 话题
|
||||
subscription_sign_ =
|
||||
this->create_subscription<std_msgs::msg::Int32>(
|
||||
"sign4return",
|
||||
10,
|
||||
std::bind(&MinimalHbmemSubscriber::sign_callback, this, std::placeholders::_1));
|
||||
|
||||
// 创建 publisher,topic 为 "qr_results"
|
||||
publisher_ =
|
||||
this->create_publisher<std_msgs::msg::String>("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<rclcpp::Clock>(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<uint8_t*>(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<sensor_msgs::msg::Image>::SharedPtr subscription_image_;
|
||||
// sign4return 订阅器
|
||||
rclcpp::Subscription<std_msgs::msg::Int32>::SharedPtr subscription_sign_;
|
||||
// QR code results 发布器
|
||||
rclcpp::Publisher<std_msgs::msg::String>::SharedPtr publisher_;
|
||||
|
||||
// 二维码检测标志位
|
||||
bool detect_qr_code_;
|
||||
};
|
||||
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
rclcpp::init(argc, argv);
|
||||
rclcpp::spin(std::make_shared<MinimalHbmemSubscriber>());
|
||||
rclcpp::shutdown();
|
||||
return 0;
|
||||
}
|
||||
50
src/qr_detection/src/qr_detection_node.cpp
Normal file
50
src/qr_detection/src/qr_detection_node.cpp
Normal file
@@ -0,0 +1,50 @@
|
||||
#include <memory>
|
||||
#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<hbm_img_msgs::msg::HbmMsg1080P>(
|
||||
"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<rclcpp::Clock>(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<hbm_img_msgs::msg::HbmMsg1080P>::SharedPtr subscription_;
|
||||
};
|
||||
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
rclcpp::init(argc, argv);
|
||||
rclcpp::spin(std::make_shared<MinimalHbmemSubscriber>());
|
||||
rclcpp::shutdown();
|
||||
return 0;
|
||||
}
|
||||
36
src/qr_detection/src/sameple_zbar.cpp
Normal file
36
src/qr_detection/src/sameple_zbar.cpp
Normal file
@@ -0,0 +1,36 @@
|
||||
#include <iostream>
|
||||
#include <zbar.h>
|
||||
#include <opencv2/opencv.hpp>
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
if (argc != 2) {
|
||||
std::cerr << "Usage: " << argv[0] << " <image_path>" << 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;
|
||||
}
|
||||
45
src/qr_detection/src/subscriber_hbmem.cpp
Normal file
45
src/qr_detection/src/subscriber_hbmem.cpp
Normal file
@@ -0,0 +1,45 @@
|
||||
#include <memory>
|
||||
|
||||
#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<qr_detection::msg::SampleMessage>(
|
||||
"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::microseconds>(
|
||||
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<qr_detection::msg::SampleMessage>::SharedPtr
|
||||
subscription_;
|
||||
};
|
||||
|
||||
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
rclcpp::init(argc, argv);
|
||||
rclcpp::spin(std::make_shared<MinimalHbmemSubscriber>());
|
||||
rclcpp::shutdown();
|
||||
return 0;
|
||||
}
|
||||
18
src/vlm_detect/package.xml
Normal file
18
src/vlm_detect/package.xml
Normal file
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0"?>
|
||||
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
|
||||
<package format="3">
|
||||
<name>vlm_detect</name>
|
||||
<version>0.0.0</version>
|
||||
<description>TODO: Package description</description>
|
||||
<maintainer email="root@todo.todo">root</maintainer>
|
||||
<license>TODO: License declaration</license>
|
||||
|
||||
<test_depend>ament_copyright</test_depend>
|
||||
<test_depend>ament_flake8</test_depend>
|
||||
<test_depend>ament_pep257</test_depend>
|
||||
<test_depend>python3-pytest</test_depend>
|
||||
|
||||
<export>
|
||||
<build_type>ament_python</build_type>
|
||||
</export>
|
||||
</package>
|
||||
0
src/vlm_detect/resource/vlm_detect
Normal file
0
src/vlm_detect/resource/vlm_detect
Normal file
4
src/vlm_detect/setup.cfg
Normal file
4
src/vlm_detect/setup.cfg
Normal file
@@ -0,0 +1,4 @@
|
||||
[develop]
|
||||
script_dir=$base/lib/vlm_detect
|
||||
[install]
|
||||
install_scripts=$base/lib/vlm_detect
|
||||
26
src/vlm_detect/setup.py
Normal file
26
src/vlm_detect/setup.py
Normal file
@@ -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',
|
||||
],
|
||||
},
|
||||
)
|
||||
25
src/vlm_detect/test/test_copyright.py
Normal file
25
src/vlm_detect/test/test_copyright.py
Normal file
@@ -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'
|
||||
25
src/vlm_detect/test/test_flake8.py
Normal file
25
src/vlm_detect/test/test_flake8.py
Normal file
@@ -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)
|
||||
23
src/vlm_detect/test/test_pep257.py
Normal file
23
src/vlm_detect/test/test_pep257.py
Normal file
@@ -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'
|
||||
0
src/vlm_detect/vlm_detect/__init__.py
Normal file
0
src/vlm_detect/vlm_detect/__init__.py
Normal file
BIN
src/vlm_detect/vlm_detect/__pycache__/__init__.cpython-38.pyc
Normal file
BIN
src/vlm_detect/vlm_detect/__pycache__/__init__.cpython-38.pyc
Normal file
Binary file not shown.
BIN
src/vlm_detect/vlm_detect/__pycache__/vlm_node.cpython-38.pyc
Normal file
BIN
src/vlm_detect/vlm_detect/__pycache__/vlm_node.cpython-38.pyc
Normal file
Binary file not shown.
144
src/vlm_detect/vlm_detect/vlm_node.py
Normal file
144
src/vlm_detect/vlm_detect/vlm_node.py
Normal file
@@ -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()
|
||||
1
src/yolov8_launch/class_list/cone.list
Normal file
1
src/yolov8_launch/class_list/cone.list
Normal file
@@ -0,0 +1 @@
|
||||
cone
|
||||
239
src/yolov8_launch/launch/dnn_node_example.launch.py
Normal file
239
src/yolov8_launch/launch/dnn_node_example.launch.py
Normal file
@@ -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
|
||||
])
|
||||
18
src/yolov8_launch/package.xml
Normal file
18
src/yolov8_launch/package.xml
Normal file
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0"?>
|
||||
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
|
||||
<package format="3">
|
||||
<name>yolov8_launch</name>
|
||||
<version>0.0.0</version>
|
||||
<description>TODO: Package description</description>
|
||||
<maintainer email="root@todo.todo">root</maintainer>
|
||||
<license>TODO: License declaration</license>
|
||||
|
||||
<test_depend>ament_copyright</test_depend>
|
||||
<test_depend>ament_flake8</test_depend>
|
||||
<test_depend>ament_pep257</test_depend>
|
||||
<test_depend>python3-pytest</test_depend>
|
||||
|
||||
<export>
|
||||
<build_type>ament_python</build_type>
|
||||
</export>
|
||||
</package>
|
||||
0
src/yolov8_launch/resource/yolov8_launch
Normal file
0
src/yolov8_launch/resource/yolov8_launch
Normal file
4
src/yolov8_launch/setup.cfg
Normal file
4
src/yolov8_launch/setup.cfg
Normal file
@@ -0,0 +1,4 @@
|
||||
[develop]
|
||||
script_dir=$base/lib/yolov8_launch
|
||||
[install]
|
||||
install_scripts=$base/lib/yolov8_launch
|
||||
27
src/yolov8_launch/setup.py
Normal file
27
src/yolov8_launch/setup.py
Normal file
@@ -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': [
|
||||
],
|
||||
},
|
||||
)
|
||||
25
src/yolov8_launch/test/test_copyright.py
Normal file
25
src/yolov8_launch/test/test_copyright.py
Normal file
@@ -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'
|
||||
25
src/yolov8_launch/test/test_flake8.py
Normal file
25
src/yolov8_launch/test/test_flake8.py
Normal file
@@ -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)
|
||||
23
src/yolov8_launch/test/test_pep257.py
Normal file
23
src/yolov8_launch/test/test_pep257.py
Normal file
@@ -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'
|
||||
0
src/yolov8_launch/yolov8_launch/__init__.py
Normal file
0
src/yolov8_launch/yolov8_launch/__init__.py
Normal file
47
wget-log
Normal file
47
wget-log
Normal file
@@ -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]
|
||||
|
||||
Reference in New Issue
Block a user