ros2 action server示例、拓展、练习
注意:以下代码全部由ai生成,没有大问题,运用时需根据报错逐步调试
action server示例
将 goal
、result
和 feedback
作为类的成员变量的 C++ 示例代码:
示例代码
#include "rclcpp/rclcpp.hpp"
#include "rclcpp_action/rclcpp_action.hpp"
#include "your_package/action/my_action.hpp"
#include "your_package/srv/my_service.hpp"class MyActionServer : public rclcpp::Node
{
public:using MyAction = your_package::action::MyAction;using GoalHandleMyAction = rclcpp_action::ServerGoalHandle<MyAction>;MyActionServer(): Node("my_action_server"),feedback_(std::make_shared<MyAction::Feedback>()),result_(std::make_shared<MyAction::Result>()){// 创建 Action 服务器action_server_ = rclcpp_action::create_server<MyAction>(this,"my_action",std::bind(&MyActionServer::handle_goal, this, std::placeholders::_1, std::placeholders::_2),std::bind(&MyActionServer::handle_cancel, this, std::placeholders::_1),std::bind(&MyActionServer::handle_accepted, this, std::placeholders::_1));// 创建服务service_ = this->create_service<your_package::srv::MyService>("my_service",std::bind(&MyActionServer::handle_service, this, std::placeholders::_1, std::placeholders::_2));}private:rclcpp_action::Server<MyAction>::SharedPtr action_server_;rclcpp::Service<your_package::srv::MyService>::SharedPtr service_;std::shared_ptr<const MyAction::Goal> goal_;std::shared_ptr<MyAction::Result> result_;std::shared_ptr<MyAction::Feedback> feedback_;// 处理目标rclcpp_action::GoalResponse handle_goal(const rclcpp_action::GoalUUID & uuid,std::shared_ptr<const MyAction::Goal> goal){RCLCPP_INFO(this->get_logger(), "Received goal: %f", goal->goal_value);goal_ = goal; // 存储目标return rclcpp_action::GoalResponse::YES;}// 处理取消请求rclcpp_action::CancelResponse handle_cancel(const std::shared_ptr<GoalHandleMyAction> goal_handle){RCLCPP_INFO(this->get_logger(), "Canceling goal");return rclcpp_action::CancelResponse::ACCEPT;}// 处理已接受的目标void handle_accepted(const std::shared_ptr<GoalHandleMyAction> goal_handle){std::thread([this, goal_handle]() {this->execute(goal_handle);}).detach();}// 执行目标void execute(const std::shared_ptr<GoalHandleMyAction> goal_handle){for (int i = 1; i <= 5; ++i) {feedback_->current_value = i * goal_->goal_value;goal_handle->publish_feedback(feedback_);RCLCPP_INFO(this->get_logger(), "Feedback: %f", feedback_->current_value);std::this_thread::sleep_for(std::chrono::seconds(1));}// 设置结果result_->result_value = goal_->goal_value * 10;goal_handle->succeed(result_);RCLCPP_INFO(this->get_logger(), "Action succeeded with result: %f", result_->result_value);}// 处理服务void handle_service(const std::shared_ptr<your_package::srv::MyService::Request> request,std::shared_ptr<your_package::srv::MyService::Response> response){response->response_value = request->request_value * 2; // 示例处理RCLCPP_INFO(this->get_logger(), "Service called with value: %f, response: %f",request->request_value, response->response_value);}
};int main(int argc, char ** argv)
{rclcpp::init(argc, argv);rclcpp::spin(std::make_shared<MyActionServer>());rclcpp::shutdown();return 0;
}
代码说明
-
成员变量:
goal_
: 存储接收到的目标。result_
: 存储结果信息。feedback_
: 存储反馈信息。
-
在
handle_goal
方法中,接收到的目标被存储到goal_
中。 -
在
execute
方法中,根据goal_
的值生成反馈,并发布反馈和结果。
拓展1 在execute中创建一个导航action client,并发布。
要在 execute
方法中创建一个导航目标点的 Action 客户端并发布一个固定点,你需要确保在代码中添加相关的导航 Action 依赖。以下是更新后的 C++ 示例代码:
示例代码
#include "rclcpp/rclcpp.hpp"
#include "rclcpp_action/rclcpp_action.hpp"
#include "your_package/action/my_action.hpp"
#include "your_package/srv/my_service.hpp"
#include "nav2_msgs/action/navigate_to_pose.hpp" // 导航 Actionclass MyActionServer : public rclcpp::Node
{
public:using MyAction = your_package::action::MyAction;using GoalHandleMyAction = rclcpp_action::ServerGoalHandle<MyAction>;using NavigateToPose = nav2_msgs::action::NavigateToPose;using NavigateToPoseClient = rclcpp_action::Client<NavigateToPose>;MyActionServer(): Node("my_action_server"),feedback_(std::make_shared<MyAction::Feedback>()),result_(std::make_shared<MyAction::Result>()),navigate_client_(rclcpp_action::create_client<NavigateToPose>(this, "navigate_to_pose")){action_server_ = rclcpp_action::create_server<MyAction>(this,"my_action",std::bind(&MyActionServer::handle_goal, this, std::placeholders::_1, std::placeholders::_2),std::bind(&MyActionServer::handle_cancel, this, std::placeholders::_1),std::bind(&MyActionServer::handle_accepted, this, std::placeholders::_1));service_ = this->create_service<your_package::srv::MyService>("my_service",std::bind(&MyActionServer::handle_service, this, std::placeholders::_1, std::placeholders::_2));}private:rclcpp_action::Server<MyAction>::SharedPtr action_server_;rclcpp::Service<your_package::srv::MyService>::SharedPtr service_;std::shared_ptr<const MyAction::Goal> goal_;std::shared_ptr<MyAction::Result> result_;std::shared_ptr<MyAction::Feedback> feedback_;rclcpp_action::Client<NavigateToPose>::SharedPtr navigate_client_;rclcpp_action::GoalResponse handle_goal(const rclcpp_action::GoalUUID & uuid,std::shared_ptr<const MyAction::Goal> goal){RCLCPP_INFO(this->get_logger(), "Received goal: %f", goal->goal_value);goal_ = goal;return rclcpp_action::GoalResponse::YES;}rclcpp_action::CancelResponse handle_cancel(const std::shared_ptr<GoalHandleMyAction> goal_handle){RCLCPP_INFO(this->get_logger(), "Canceling goal");return rclcpp_action::CancelResponse::ACCEPT;}void handle_accepted(const std::shared_ptr<GoalHandleMyAction> goal_handle){std::thread([this, goal_handle]() {this->execute(goal_handle);}).detach();}void execute(const std::shared_ptr<GoalHandleMyAction> goal_handle){// 创建导航目标点auto navigation_goal = NavigateToPose::Goal();navigation_goal.pose.header.frame_id = "map"; // 或者其他适当的坐标框架navigation_goal.pose.header.stamp = this->now();navigation_goal.pose.pose.position.x = 1.0; // 固定点的坐标navigation_goal.pose.pose.position.y = 1.0;navigation_goal.pose.pose.orientation.w = 1.0; // 方向// 调用导航客户端if (!navigate_client_->wait_for_action_server(std::chrono::seconds(5))) {RCLCPP_ERROR(this->get_logger(), "Navigation action server not available");goal_handle->abort(result_);return;}auto send_goal_options = rclcpp_action::Client<NavigateToPose>::SendGoalOptions();send_goal_options.result_callback = [](const rclcpp_action::ClientGoalHandle<NavigateToPose>::SharedPtr &) {RCLCPP_INFO(rclcpp::get_logger("rclcpp"), "Navigation goal accepted");};auto goal_handle_navigation = navigate_client_->async_send_goal(navigation_goal, send_goal_options);// 处理导航反馈while (rclcpp::ok()) {// 这里可以添加导航反馈处理逻辑std::this_thread::sleep_for(std::chrono::milliseconds(500));}// 返回结果result_->result_value = goal_->goal_value * 10;goal_handle->succeed(result_);RCLCPP_INFO(this->get_logger(), "Action succeeded with result: %f", result_->result_value);}void handle_service(const std::shared_ptr<your_package::srv::MyService::Request> request,std::shared_ptr<your_package::srv::MyService::Response> response){response->response_value = request->request_value * 2;RCLCPP_INFO(this->get_logger(), "Service called with value: %f, response: %f",request->request_value, response->response_value);}
};int main(int argc, char ** argv)
{rclcpp::init(argc, argv);rclcpp::spin(std::make_shared<MyActionServer>());rclcpp::shutdown();return 0;
}
代码说明
-
导航 Action 客户端:
- 创建
NavigateToPose
的 Action 客户端。 - 使用
navigate_client_
来发送导航目标。
- 创建
-
导航目标点:
- 在
execute
方法中定义固定的导航目标点(例如(1.0, 1.0)
)。 - 设置导航目标的坐标和方向。
- 在
-
异步发送目标:
- 使用
async_send_goal
方法发送导航目标,处理结果和反馈。 - 可以在循环中添加对导航状态的反馈处理逻辑。
- 使用
使用
- 确保导航 Action 服务器(例如 Nav2)正在运行。
- 启动此 Action 服务器节点。
- 在客户端调用 Action 和服务,观察服务器的导航行为。
拓展2 针对send_goal_options配置结构,创建一个新成员函数,替代上一段的lambda函数, 并使用send_goal_options的所有成员
好的,下面是更新后的代码示例,其中我们创建了一个新的成员函数来处理 send_goal_options
的配置,替代了之前使用的 Lambda 函数。这一新函数将使用 send_goal_options
的所有成员。
更新后的示例代码
#include "rclcpp/rclcpp.hpp"
#include "rclcpp_action/rclcpp_action.hpp"
#include "your_package/action/my_action.hpp"
#include "your_package/srv/my_service.hpp"
#include "nav2_msgs/action/navigate_to_pose.hpp" // 导航 Actionclass MyActionServer : public rclcpp::Node
{
public:using MyAction = your_package::action::MyAction;using GoalHandleMyAction = rclcpp_action::ServerGoalHandle<MyAction>;using NavigateToPose = nav2_msgs::action::NavigateToPose;using NavigateToPoseClient = rclcpp_action::Client<NavigateToPose>;MyActionServer(): Node("my_action_server"),feedback_(std::make_shared<MyAction::Feedback>()),result_(std::make_shared<MyAction::Result>()),navigate_client_(rclcpp_action::create_client<NavigateToPose>(this, "navigate_to_pose")){action_server_ = rclcpp_action::create_server<MyAction>(this,"my_action",std::bind(&MyActionServer::handle_goal, this, std::placeholders::_1, std::placeholders::_2),std::bind(&MyActionServer::handle_cancel, this, std::placeholders::_1),std::bind(&MyActionServer::handle_accepted, this, std::placeholders::_1));service_ = this->create_service<your_package::srv::MyService>("my_service",std::bind(&MyActionServer::handle_service, this, std::placeholders::_1, std::placeholders::_2));}private:rclcpp_action::Server<MyAction>::SharedPtr action_server_;rclcpp::Service<your_package::srv::MyService>::SharedPtr service_;std::shared_ptr<const MyAction::Goal> goal_;std::shared_ptr<MyAction::Result> result_;std::shared_ptr<MyAction::Feedback> feedback_;rclcpp_action::Client<NavigateToPose>::SharedPtr navigate_client_;rclcpp_action::GoalResponse handle_goal(const rclcpp_action::GoalUUID & uuid,std::shared_ptr<const MyAction::Goal> goal){RCLCPP_INFO(this->get_logger(), "Received goal: %f", goal->goal_value);goal_ = goal;return rclcpp_action::GoalResponse::YES;}rclcpp_action::CancelResponse handle_cancel(const std::shared_ptr<GoalHandleMyAction> goal_handle){RCLCPP_INFO(this->get_logger(), "Canceling goal");return rclcpp_action::CancelResponse::ACCEPT;}void handle_accepted(const std::shared_ptr<GoalHandleMyAction> goal_handle){std::thread([this, goal_handle]() {this->execute(goal_handle);}).detach();}void execute(const std::shared_ptr<GoalHandleMyAction> goal_handle){// 创建导航目标点auto navigation_goal = NavigateToPose::Goal();navigation_goal.pose.header.frame_id = "map";navigation_goal.pose.header.stamp = this->now();navigation_goal.pose.pose.position.x = 1.0;navigation_goal.pose.pose.position.y = 1.0;navigation_goal.pose.pose.orientation.w = 1.0;// 调用导航客户端if (!navigate_client_->wait_for_action_server(std::chrono::seconds(5))) {RCLCPP_ERROR(this->get_logger(), "Navigation action server not available");goal_handle->abort(result_);return;}// 使用新成员函数配置 send_goal_optionsconfigure_send_goal_options(goal_handle, navigation_goal);}void configure_send_goal_options(const std::shared_ptr<GoalHandleMyAction> goal_handle, const NavigateToPose::Goal &navigation_goal){auto send_goal_options = rclcpp_action::Client<NavigateToPose>::SendGoalOptions();// 设置 result_callbacksend_goal_options.result_callback = [this](const rclcpp_action::ClientGoalHandle<NavigateToPose>::SharedPtr &goal_handle) {if (goal_handle->get_status() == rclcpp_action::GoalStatus::SUCCEEDED) {RCLCPP_INFO(this->get_logger(), "Navigation goal succeeded");} else {RCLCPP_ERROR(this->get_logger(), "Navigation goal failed");}};// 设置 feedback_callbacksend_goal_options.feedback_callback = [this](const rclcpp_action::ClientGoalHandle<NavigateToPose>::SharedPtr &goal_handle, const std::shared_ptr<const NavigateToPose::Feedback> feedback) {RCLCPP_INFO(this->get_logger(), "Navigation feedback: current position %f, %f",feedback->current_pose.position.x, feedback->current_pose.position.y);};// 设置 goal_response_callbacksend_goal_options.goal_response_callback = [](const rclcpp_action::ClientGoalHandle<NavigateToPose>::SharedPtr &goal_handle) {if (goal_handle) {RCLCPP_INFO(rclcpp::get_logger("rclcpp"), "Navigation goal accepted");} else {RCLCPP_ERROR(rclcpp::get_logger("rclcpp"), "Navigation goal rejected");}};// 发送导航目标auto goal_handle_navigation = navigate_client_->async_send_goal(navigation_goal, send_goal_options);}void handle_service(const std::shared_ptr<your_package::srv::MyService::Request> request,std::shared_ptr<your_package::srv::MyService::Response> response){response->response_value = request->request_value * 2;RCLCPP_INFO(this->get_logger(), "Service called with value: %f, response: %f",request->request_value, response->response_value);}
};int main(int argc, char ** argv)
{rclcpp::init(argc, argv);rclcpp::spin(std::make_shared<MyActionServer>());rclcpp::shutdown();return 0;
}
代码说明
-
新成员函数
configure_send_goal_options
:- 此函数负责配置
send_goal_options
的所有成员,包括result_callback
、feedback_callback
和goal_response_callback
。 - 通过捕获
this
,可以在回调中访问类的成员函数和变量。
- 此函数负责配置
-
回调函数的实现:
result_callback
: 检查导航目标的状态,并根据成功或失败打印日志信息。feedback_callback
: 输出当前导航位置的反馈信息。goal_response_callback
: 检查目标是否被接受,并输出相应的日志信息。
-
调用导航目标:
- 在
execute
方法中,调用configure_send_goal_options
来配置并发送导航目标。
- 在
这种方式将发送目标的逻辑与配置的回调逻辑分离,使代码更清晰、可维护。如果你有其他问题或者需要进一步的解释,请随时告诉我!
注意
:只要设置了 send_goal_options.feedback_callback,回调函数就会在导航服务器发送反馈时被调用,可以在函数内部获取并处理这些反馈信息。
示例:
将其改写为
send_goal_options.feedback_callback =
[this](const rclcpp_action::ClientGoalHandle<NavigateToPose>::SharedPtr &goal_handle
, const std::shared_ptr<const NavigateToPose::Feedback> feedback)
{};
根据定义
#goal definition
geometry_msgs/PoseStamped pose
string behavior_tree
---
#result definition
std_msgs/Empty result
---
#feedback definition
geometry_msgs/PoseStamped current_pose
builtin_interfaces/Duration navigation_time
builtin_interfaces/Duration estimated_time_remaining
int16 number_of_recoveries
float32 distance_remaining
】
action的客户端也能获取
【geometry_msgs/PoseStamped current_pose
builtin_interfaces/Duration navigation_time
builtin_interfaces/Duration estimated_time_remaining
int16 number_of_recoveries
float32 distance_remaining】
这些信息
练习1
1.实现拓展中创建的navigation的导航action与自定义的action通信
2.找到isaac_mission_client实现其中自定义action与isaac_mission_client的通信,注意参考mqtt协议。
相关文章:
ros2 action server示例、拓展、练习
注意:以下代码全部由ai生成,没有大问题,运用时需根据报错逐步调试 action server示例 将 goal、result 和 feedback 作为类的成员变量的 C 示例代码: 示例代码 #include "rclcpp/rclcpp.hpp" #include "rclcpp…...
【Go语言】安装及使用基础教程
文章目录 1. 下载安装Go官网安装使用 Homebrew 安装 (Mac)创建工作目录 (Workspace)设置环境变量通过 VSCode 扩展商店安装 Go 插件处理权限问题 2. Hello, World 示例3. 语法基础变量声明常量数组切片(Slice)Map(集合)控制结构fo…...

【大模型】3分钟了解提示(Prompt)工程、检索增强(RAG)和微调
我们先看下面这个图: 简单理解大模型是通过海量训练数据训练出来的,它的能力非常强,但是有时候会给出错误的回答。那产生错误的原因可能是什么呢? 1.提问错误(提示工程) 在我们提问的方式不对的情况下&a…...

太速科技-509-基于XCVU13P的4路QSFP28光纤PCIeX16收发卡
基于XCVU13P的4路QSFP28光纤PCIeX16收发卡 一、板卡概述 基于XCVU13P的4路QSFP28光纤PCIeX16收发卡。该板卡要求符合PCIe 3.0标准,包含一片XCVU13P-2FLGA2014I、4组64-bit/8GB DDR4;4路QSFP28 4X光纤,每路光纤支持4X25Gbps&#…...

C#从零开始学习(基本语法概念)(2)
深入C# 本章所有的代码都放在 https://github.com/hikinazimi/head-first-Csharp 控制台项目结构 每个C#程序采用同样的方式组织,命名空间,类和方法 using System;namespace helloworld//命名空间 {class Program//类{static void Main(string[] args)//程序入口{Console.Writ…...

基于SSM+微信小程序的家庭记账本管理系统(家庭1)
👉文末查看项目功能视频演示获取源码sql脚本视频导入教程视频 1、项目介绍 1、管理员端功能有首页、个人中心、用户管理,消费详情管理、收入详情管理、系统管理等。 2、用户端功能有首页、消费详情、收入详情、论坛信息、我的等功能。 2、项目技术 …...

MEMC功能详解
文章目录 MEMC的工作原理:优点:缺点:适用场景:1. Deblur(去模糊)2. Dejudder(去抖动)总结两者区别: MEMC(Motion Estimation and Motion Compensation&#x…...

C++ | Leetcode C++题解之第493题翻转对
题目: 题解: class BIT { private:vector<int> tree;int n;public:BIT(int _n) : n(_n), tree(_n 1) {}static constexpr int lowbit(int x) {return x & (-x);}void update(int x, int d) {while (x < n) {tree[x] d;x lowbit(x);}}in…...
Git 修改分支名
在Git中修改分支名称,可以使用以下步骤: 切换到要重命名分支之外的其他分支: git checkout <其他分支名>重命名本地分支: git branch -m <旧分支名> <新分支名>如果需要删除远程的旧分支并创建新分支࿱…...

[自动化测试:Selenium]:环境部署和Webdriver的使用
文章目录 修改安装源打开Python Packages。点击梅花按钮。在弹出的对话框中,填入Name(随便填),Repository URL,选择下列的源,一般先选择清华源按OK确认。配置完成 安装seleniumFile→Settings→Project&…...

51单片机——OLED显示图片
取模软件:链接:https://pan.baidu.com/s/1UcrbS7nU4bsawNxsaaULfQ 提取码:gclc 1、如果图片大小和格式不合适,可以先用Img2Lcd软件进行调整图片大小,一般取模软件使用的是.bmp图片,可以进行输出.bmp格式。软件界面如下࿱…...

Gin 协程mysql客户端
一、Gin框架 mysql配置 这里选择yaml文件配置 二、配置读取 viper 读取yaml文件中对应配置 三、mysql 的协程客户端 文件位置 package databaseimport ("database/sql""fmt""github.com/spf13/viper""log""net/http"&quo…...

量子门电路开销——T门、clifford门、toffoli门、fredkin门
在量子计算中,T门的成本比Clifford门高出很多倍的原因与量子计算中纠错的实现、物理门操作的复杂性以及容错量子计算架构中的成本评估有关。以下是几个关键原因,解释了为什么 T 门的成本在量子计算中远远高于 Clifford 门: 1. T 门和 Cliffo…...
C++之《剑指offer》学习记录(1):类型转换关键字
笔者最近在找工作时,无意间读到了一本名为《剑指offer》的书,粗略翻阅了一下,感觉这将会是一本能让我不再苦恼于笔试和面试“手搓代码”的书。故笔者写下该系列博客记录自己的学习历程,希望能和这本书的读者朋友们一起交流学习心得…...

【Linux】平台设备驱动
在设备驱动模型中,引入总线的概念可以对驱动代码和设备信息进行分离。但是驱动中总线的概念是软件层面的一种抽象,与我们SOC中物理总线的概念并不严格相等。 物理总线:芯片与各个功能外设之间传送信息的公共通信干线,其中又包括数…...

【Linux】命令行参数环境变量
文章目录 命令行参数环境变量环境变量的概念常见环境变量查看环境变量测试PATH修改PATH HOME和环境变量相关的命令环境变量是如何被组织的通过系统调用putenv和getenv获取或设置环境变量环境变量通常是具有全局属性的普通变量与环境变量的区别 命令行参数 main函数有三种形式&…...

libaom 源码分析:twopass_encoder.c 文件
libaom libaom 是 AOMedia(开放媒体联盟)开发的一个开源视频编解码器库,它是 AV1 视频压缩格式的参考实现,并被广泛用于多种生产系统中。libaom 支持多种功能,包括可扩展视频编码(SVC)、实时通信…...
ruoyi同时支持mysql+sqlserver+oracle+postgresql
需求背景 最近需要一个小demo,项目中需要同时连接sqlserver和mysql数据库。 操作教程 1、pom.xml -- 修改common/pom.xml<!-- 动态数据源 --> <dependency><groupId>com.baomidou</groupId><artifactId>dynamic-datasource-spring-boot-star…...

微信小程序绘制轨迹
1、map | uni-app官网 根据官网描述:通过从数据库获取POI数据,并通过 uni-id-common 内的路线规划API,计算路线、距离、时间。 2、 <map style"width:100%;height:96%;" id"myMap" :scale"scale" :longi…...

UNION 联合查询
1.UNION ALL联合查询 同样为了演示方便,先向 teacher 表插入多条测试数据: INSERT INTO teacher (name,age,id_number,email) VALUES (姓名一,17,42011720200604077X,NULL), (姓名二,18,42011720200604099X,123qq.com), (姓名三,19,42011720200604020X…...

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造,完美适配AGV和无人叉车。同时,集成以太网与语音合成技术,为各类高级系统(如MES、调度系统、库位管理、立库等)提供高效便捷的语音交互体验。 L…...
【Linux】shell脚本忽略错误继续执行
在 shell 脚本中,可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行,可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令,并忽略错误 rm somefile…...

8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂
蛋白质结合剂(如抗体、抑制肽)在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上,高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术,但这类方法普遍面临资源消耗巨大、研发周期冗长…...
【磁盘】每天掌握一个Linux命令 - iostat
目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat(I/O Statistics)是Linux系统下用于监视系统输入输出设备和CPU使…...
Java多线程实现之Callable接口深度解析
Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...
Spring AI 入门:Java 开发者的生成式 AI 实践之路
一、Spring AI 简介 在人工智能技术快速迭代的今天,Spring AI 作为 Spring 生态系统的新生力量,正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务(如 OpenAI、Anthropic)的无缝对接&…...
OpenLayers 分屏对比(地图联动)
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 地图分屏对比在WebGIS开发中是很常见的功能,和卷帘图层不一样的是,分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。…...
#Uniapp篇:chrome调试unapp适配
chrome调试设备----使用Android模拟机开发调试移动端页面 Chrome://inspect/#devices MuMu模拟器Edge浏览器:Android原生APP嵌入的H5页面元素定位 chrome://inspect/#devices uniapp单位适配 根路径下 postcss.config.js 需要装这些插件 “postcss”: “^8.5.…...

论文笔记——相干体技术在裂缝预测中的应用研究
目录 相关地震知识补充地震数据的认识地震几何属性 相干体算法定义基本原理第一代相干体技术:基于互相关的相干体技术(Correlation)第二代相干体技术:基于相似的相干体技术(Semblance)基于多道相似的相干体…...
return this;返回的是谁
一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请,不同级别的经理有不同的审批权限: // 抽象处理者:审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...