【Moveit2官方教程】使用 MoveIt Task Constructor (MTC) 框架来定义和执行一个机器人任务
#include <rclcpp/rclcpp.hpp> // ROS 2 的核心库
#include <moveit/planning_scene/planning_scene.h> // MoveIt 规划场景相关的头文件
#include <moveit/planning_scene_interface/planning_scene_interface.h> // MoveIt 规划场景接口
#include <moveit/task_constructor/task.h> // MTC 任务的头文件
#include <moveit/task_constructor/solvers.h> // MTC 求解器相关的头文件
#include <moveit/task_constructor/stages.h> // MTC 阶段定义的头文件
#if __has_include(<tf2_geometry_msgs/tf2_geometry_msgs.hpp>)
#include <tf2_geometry_msgs/tf2_geometry_msgs.hpp> // 包含用于处理几何消息的 TF2 转换
#else
#include <tf2_geometry_msgs/tf2_geometry_msgs.h>
#endif
#if __has_include(<tf2_eigen/tf2_eigen.hpp>)
#include <tf2_eigen/tf2_eigen.hpp> // 包含用于处理 Eigen 矩阵的 TF2 转换
#else
#include <tf2_eigen/tf2_eigen.h>
#endifstatic const rclcpp::Logger LOGGER = rclcpp::get_logger("mtc_tutorial"); // 定义日志器,用于输出调试信息
namespace mtc = moveit::task_constructor; // 为 moveit::task_constructor 创建别名 mtc// 定义 MTC 任务节点类
class MTCTaskNode
{
public:MTCTaskNode(const rclcpp::NodeOptions& options); // 构造函数rclcpp::node_interfaces::NodeBaseInterface::SharedPtr getNodeBaseInterface(); // 获取节点基础接口void doTask(); // 执行任务的函数void setupPlanningScene(); // 设置规划场景的函数
private:mtc::Task createTask(); // 创建任务的函数mtc::Task task_; // MTC 任务对象rclcpp::Node::SharedPtr node_; // ROS 2 节点对象
};// 获取节点基础接口的实现
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr MTCTaskNode::getNodeBaseInterface()
{return node_->get_node_base_interface();
}// 构造函数的实现,创建节点对象
MTCTaskNode::MTCTaskNode(const rclcpp::NodeOptions& options): node_{ std::make_shared<rclcpp::Node>("mtc_node", options) } // 初始化节点名称为 "mtc_node"
{
}// 设置规划场景的实现
void MTCTaskNode::setupPlanningScene()
{// 创建一个碰撞对象(障碍物)moveit_msgs::msg::CollisionObject object;object.id = "object"; // 定义对象 IDobject.header.frame_id = "world"; // 对象的参考坐标系object.primitives.resize(1); // 定义对象的几何形状数组大小为 1object.primitives[0].type = shape_msgs::msg::SolidPrimitive::CYLINDER; // 设置对象为圆柱体object.primitives[0].dimensions = { 0.1, 0.02 }; // 定义圆柱体的高度和半径// 定义对象的位置和姿态geometry_msgs::msg::Pose pose;pose.position.x = 0.5;pose.position.y = -0.25;pose.orientation.w = 1.0; // 设置无旋转的四元数object.pose = pose; // 赋值给碰撞对象的位姿// 创建规划场景接口并将碰撞对象添加到场景中moveit::planning_interface::PlanningSceneInterface psi;psi.applyCollisionObject(object); // 应用碰撞对象到规划场景
}// 执行任务的实现
void MTCTaskNode::doTask()
{task_ = createTask(); // 创建任务// 尝试初始化任务try{task_.init(); // 初始化任务}catch (mtc::InitStageException& e) // 捕获初始化失败的异常{RCLCPP_ERROR_STREAM(LOGGER, e); // 打印错误信息return;}// 规划任务路径,最大规划尝试次数为 5if (!task_.plan(5)){RCLCPP_ERROR_STREAM(LOGGER, "Task planning failed"); // 打印任务规划失败的日志return;}// 发布任务解决方案以供检查task_.introspection().publishSolution(*task_.solutions().front());// 执行规划的解决方案auto result = task_.execute(*task_.solutions().front());if (result.val != moveit_msgs::msg::MoveItErrorCodes::SUCCESS){RCLCPP_ERROR_STREAM(LOGGER, "Task execution failed"); // 执行失败的错误日志return;}return;
}// 创建任务的实现
mtc::Task MTCTaskNode::createTask()
{mtc::Task task; // 创建一个 MTC 任务对象task.stages()->setName("demo task"); // 为任务命名task.loadRobotModel(node_); // 加载机器人模型// 定义机器人操作相关的参数const auto& arm_group_name = "panda_arm"; // 机械臂的操作组名称const auto& hand_group_name = "hand"; // 手部操作组名称const auto& hand_frame = "panda_hand"; // 机械手的坐标系// 设置任务的属性task.setProperty("group", arm_group_name);task.setProperty("eef", hand_group_name);task.setProperty("ik_frame", hand_frame);// 忽略未使用变量的编译器警告
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-but-set-variable"mtc::Stage* current_state_ptr = nullptr; // 当前状态指针,设置但不使用
#pragma GCC diagnostic pop// 创建并添加获取当前状态的阶段auto stage_state_current = std::make_unique<mtc::stages::CurrentState>("current");current_state_ptr = stage_state_current.get();task.add(std::move(stage_state_current)); // 添加当前状态阶段到任务中// 创建不同的规划器auto sampling_planner = std::make_shared<mtc::solvers::PipelinePlanner>(node_); // 创建采样规划器auto interpolation_planner = std::make_shared<mtc::solvers::JointInterpolationPlanner>(); // 创建插值规划器// 创建笛卡尔路径规划器,并设置最大速度和加速度auto cartesian_planner = std::make_shared<mtc::solvers::CartesianPath>();cartesian_planner->setMaxVelocityScalingFactor(1.0); // 设置最大速度缩放因子为 1.0cartesian_planner->setMaxAccelerationScalingFactor(1.0); // 设置最大加速度缩放因子为 1.0cartesian_planner->setStepSize(.01); // 设置步长为 0.01// 创建并添加手部动作的阶段(打开手)auto stage_open_hand =std::make_unique<mtc::stages::MoveTo>("open hand", interpolation_planner); // 创建移动到目标状态的阶段stage_open_hand->setGroup(hand_group_name); // 设置操作组为手部stage_open_hand->setGoal("open"); // 设置手部打开的目标状态task.add(std::move(stage_open_hand)); // 将阶段添加到任务中return task; // 返回创建的任务
}// 程序的主函数
int main(int argc, char** argv)
{rclcpp::init(argc, argv); // 初始化 ROS 2rclcpp::NodeOptions options; // 创建节点选项options.automatically_declare_parameters_from_overrides(true); // 自动声明节点参数// 创建 MTC 任务节点对象auto mtc_task_node = std::make_shared<MTCTaskNode>(options);rclcpp::executors::MultiThreadedExecutor executor; // 创建多线程执行器// 创建一个新线程用于节点执行auto spin_thread = std::make_unique<std::thread>([&executor, &mtc_task_node]() {executor.add_node(mtc_task_node->getNodeBaseInterface()); // 将节点添加到执行器中executor.spin(); // 开始执行节点任务executor.remove_node(mtc_task_node->getNodeBaseInterface()); // 从执行器中移除节点});mtc_task_node->setupPlanningScene(); // 设置规划场景mtc_task_node->doTask(); // 执行任务spin_thread->join(); // 等待线程执行完毕rclcpp::shutdown(); // 关闭 ROS 2return 0;
}
包含的头文件
#include <rclcpp/rclcpp.hpp>
- 包含 ROS 2 的核心库,用于节点的创建和管理。
#include <moveit/planning_scene/planning_scene.h>
#include <moveit/planning_scene_interface/planning_scene_interface.h>
- 包含 MoveIt 的规划场景相关的头文件,允许你在场景中设置物体(如障碍物)进行规划。
#include <moveit/task_constructor/task.h>
#include <moveit/task_constructor/solvers.h>
#include <moveit/task_constructor/stages.h>
- 包含 MoveIt Task Constructor 的头文件,用于任务的创建、规划和求解。
task.h
管理任务的整体流程,solvers.h
和stages.h
用于定义和解决任务中的不同阶段。
#if __has_include(<tf2_geometry_msgs/tf2_geometry_msgs.hpp>)
#include <tf2_geometry_msgs/tf2_geometry_msgs.hpp>
#else
#include <tf2_geometry_msgs/tf2_geometry_msgs.h>
#endif
- 条件包含头文件,用于处理几何消息的 TF2 转换。TF2 是 ROS 中用于处理坐标变换的工具。
#if __has_include(<tf2_eigen/tf2_eigen.hpp>)
#include <tf2_eigen/tf2_eigen.hpp>
#else
#include <tf2_eigen/tf2_eigen.h>
#endif
- 类似于上一个
tf2_geometry_msgs
,这个条件编译块用于包含 Eigen 库的 TF2 转换接口。
定义日志器
static const rclcpp::Logger LOGGER = rclcpp::get_logger("mtc_tutorial");
- 定义一个用于输出日志的 ROS 2 日志器,名称为
mtc_tutorial
。
使用命名空间
namespace mtc = moveit::task_constructor;
- 为
moveit::task_constructor
命名空间定义简短别名mtc
,便于后续使用。
定义 MTCTaskNode
类
class MTCTaskNode
{
public:MTCTaskNode(const rclcpp::NodeOptions& options);rclcpp::node_interfaces::NodeBaseInterface::SharedPtr getNodeBaseInterface();void doTask();void setupPlanningScene();
private:mtc::Task createTask();mtc::Task task_;rclcpp::Node::SharedPtr node_;
};
MTCTaskNode
是一个类,表示 ROS 2 节点,并包含执行任务的功能:MTCTaskNode
: 构造函数,接受NodeOptions
参数用于节点配置。getNodeBaseInterface
: 返回节点的基础接口,供 ROS 2 的执行器使用。doTask
: 定义并执行一个任务。setupPlanningScene
: 设置规划场景,定义场景中的物体。createTask
: 创建任务,并添加不同阶段的规划步骤。task_
: MTC 任务对象。node_
: ROS 2 节点共享指针。
实现 getNodeBaseInterface
函数
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr MTCTaskNode::getNodeBaseInterface()
{return node_->get_node_base_interface();
}
- 返回节点的基础接口,用于与 ROS 执行器交互。
实现 MTCTaskNode
构造函数
MTCTaskNode::MTCTaskNode(const rclcpp::NodeOptions& options): node_{ std::make_shared<rclcpp::Node>("mtc_node", options) }
{
}
- 初始化函数,创建一个名为
mtc_node
的 ROS 2 节点,并传入选项。
1. 构造函数定义
MTCTaskNode::MTCTaskNode(const rclcpp::NodeOptions& options)
- 这是
MTCTaskNode
类的构造函数,参数options
是rclcpp::NodeOptions
类型的对象,表示 ROS 2 节点的选项配置。 - 当用户创建
MTCTaskNode
的实例时,构造函数会被调用,用于初始化节点对象和类中的其他成员变量。
2. 成员初始化列表
: node_{ std::make_shared<rclcpp::Node>("mtc_node", options) }
:
后面的部分是成员初始化列表,用于直接初始化类的成员变量。相比在构造函数内部赋值,成员初始化列表在效率上可能更高,特别是当成员变量是对象或者共享指针时。node_
是类中的私有成员变量,类型为rclcpp::Node::SharedPtr
,即 ROS 2 节点的共享指针。
3. std::make_shared<rclcpp::Node>()
std::make_shared<rclcpp::Node>("mtc_node", options)
std::make_shared<rclcpp::Node>()
用于创建一个新的rclcpp::Node
对象,并返回一个指向该对象的std::shared_ptr
(共享指针)。- 这个
Node
对象代表一个 ROS 2 节点,节点的名称为"mtc_node"
,并且使用传入的options
参数来配置该节点。
4. 成员变量 node_ 的赋值
- 构造函数中的成员初始化列表将
std::make_shared<rclcpp::Node>
创建的共享指针赋值给类的成员变量node_
,这意味着MTCTaskNode
类的实例会持有一个指向 ROS 2 节点的共享指针。
5. 节点名称和选项
"mtc_node"
是这个 ROS 2 节点的名称,它可以用于在 ROS 网络中唯一标识该节点。options
是rclcpp::NodeOptions
对象,允许用户配置节点的一些选项(如参数自动声明等)。
总结
这段代码的作用是在构造 MTCTaskNode
类的实例时,通过 std::make_shared
创建了一个 ROS 2 节点对象,并将其存储在成员变量 node_
中。通过成员初始化列表的方式,保证了对象的高效初始化,并且节点名称为 "mtc_node"
,选项通过参数 options
进行配置。
实现 setupPlanningScene
void MTCTaskNode::setupPlanningScene()
{moveit_msgs::msg::CollisionObject object;object.id = "object";object.header.frame_id = "world";object.primitives.resize(1);object.primitives[0].type = shape_msgs::msg::SolidPrimitive::CYLINDER;object.primitives[0].dimensions = { 0.1, 0.02 };geometry_msgs::msg::Pose pose;pose.position.x = 0.5;pose.position.y = -0.25;pose.orientation.w = 1.0;object.pose = pose;moveit::planning_interface::PlanningSceneInterface psi;psi.applyCollisionObject(object);
}
- 创建一个障碍物对象(圆柱体),并将其添加到规划场景中。
CollisionObject
: 定义碰撞对象的几何形状和位置信息。PlanningSceneInterface
: 用于管理与规划场景的交互。
实现 doTask
函数
void MTCTaskNode::doTask()
{task_ = createTask();try{task_.init();}catch (mtc::InitStageException& e){RCLCPP_ERROR_STREAM(LOGGER, e);return;}if (!task_.plan(5)){RCLCPP_ERROR_STREAM(LOGGER, "Task planning failed");return;}task_.introspection().publishSolution(*task_.solutions().front());auto result = task_.execute(*task_.solutions().front());if (result.val != moveit_msgs::msg::MoveItErrorCodes::SUCCESS){RCLCPP_ERROR_STREAM(LOGGER, "Task execution failed");return;}return;
}
- 创建任务并尝试执行:
task_.init()
: 初始化任务。task_.plan(5)
: 规划 5 个不同的路径。task_.execute()
: 执行规划的解决方案。
实现 createTask
函数
mtc::Task MTCTaskNode::createTask()
{mtc::Task task;task.stages()->setName("demo task");task.loadRobotModel(node_);const auto& arm_group_name = "panda_arm";const auto& hand_group_name = "hand";const auto& hand_frame = "panda_hand";task.setProperty("group", arm_group_name);task.setProperty("eef", hand_group_name);task.setProperty("ik_frame", hand_frame);mtc::Stage* current_state_ptr = nullptr;auto stage_state_current = std::make_unique<mtc::stages::CurrentState>("current");current_state_ptr = stage_state_current.get();task.add(std::move(stage_state_current));auto sampling_planner = std::make_shared<mtc::solvers::PipelinePlanner>(node_);auto interpolation_planner = std::make_shared<mtc::solvers::JointInterpolationPlanner>();auto stage_open_hand =std::make_unique<mtc::stages::MoveTo>("open hand", interpolation_planner);stage_open_hand->setGroup(hand_group_name);stage_open_hand->setGoal("open");task.add(std::move(stage_open_hand));return task;
}
- 定义任务并设置不同的阶段:
CurrentState
: 获取当前状态。PipelinePlanner
: 采样规划器。MoveTo
: 指定机器人末端执行器移动到某个目标状态。
main
函数
int main(int argc, char** argv)
{rclcpp::init(argc, argv);rclcpp::NodeOptions options;options.automatically_declare_parameters_from_overrides(true);auto mtc_task_node = std::make_shared<MTCTaskNode>(options);rclcpp::executors::MultiThreadedExecutor executor;auto spin_thread = std::make_unique<std::thread>([&executor, &mtc_task_node]() {executor.add_node(mtc_task_node->getNodeBaseInterface());executor.spin();executor.remove_node(mtc_task_node->getNodeBaseInterface());});mtc_task_node->setupPlanningScene();mtc_task_node->doTask();spin_thread->join();rclcpp::shutdown();return 0;
}
main
函数是程序的入口点,初始化 ROS 2 并创建执行器与任务线程:rclcpp::init
: 初始化 ROS 2。rclcpp::NodeOptions
: 设置节点选项。MultiThreadedExecutor
: 用于多线程执行节点操作。- 创建并启动执行器线程来处理任务。
相关文章:

【Moveit2官方教程】使用 MoveIt Task Constructor (MTC) 框架来定义和执行一个机器人任务
#include <rclcpp/rclcpp.hpp> // ROS 2 的核心库 #include <moveit/planning_scene/planning_scene.h> // MoveIt 规划场景相关的头文件 #include <moveit/planning_scene_interface/planning_scene_interface.h> // MoveIt 规划场景接口 #include <m…...

使用docker配置wordpress
docker的安装 配置docker yum源 sudo yum install -y yum-utils sudo yum-config-manager \ --add-repo \ http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo下载最新版本docker sudo yum install -y docker-ce docker-ce-cli containerd.io docker-buildx-…...

JVM字节码
JVM字节码详解 引言 JVM(Java Virtual Machine,Java虚拟机)字节码是一种中间代码,主要用于Java平台上的程序在不同硬件平台上的移植。Java程序通过编译器将源代码编译成字节码,然后通过JVM解释或即时编译(…...

python访问mysql
要在 Python 中访问 MySQL 数据库,通常会使用 mysql-connector-python 或 pymysql 这两个库之一。以下是使用这两个库的基本示例: 使用 mysql-connector-python 安装库: pip install mysql-connector-python示例代码: import mysql.connector# 连接到 M…...

Java工具插件
一、springboot集成mqtt订阅 阿里云MQTT使用教程_复杂的世界311的博客-CSDN博客_阿里云mqtt 阿里云创建MQTT服务 先找到产品与服务,然后选择物联网平台,找到公共实例,创建一个产品。 创建产品 然后在左侧下拉栏找到设备管理,在设备管理下拉栏找到设备,然后添加设备。添加…...

Class3——Esp32|Thonny——网络连接主机-wifi连接(源代码带教程)
废话不多说——直接上配置源码和图片 一.电脑连接到wifi上(不能是5G) 二.网络调试助手信息设置绑定 1.获取电脑wifi信息 2.设置网络调试助手为一致,然后打开,主机地址是上面的192.168.2.149端口自己设置,UDP然后打开…...

特效【生日视频制作】小车汽车黄金色版悍马车身AE模板修改文字软件生成器教程特效素材【AE模板】
生日视频制作教程小车汽车黄金色版悍马车身AE模板修改文字特效广告生成神器素材祝福玩法AE模板工程 怎么如何做的【生日视频制作】小车汽车黄金色版悍马车身AE模板修改文字软件生成器教程特效素材【AE模板】 生日视频制作步骤: 下载AE模板 安装AE软件 把AE模板导入…...

如何利用Java进行快速的足球大小球及亚盘数据处理与分析
在当今信息爆炸的时代,大量的数据产生和积累,对于企业和个人来说,如何高效地处理和分析这些数据成为了一项重要的任务。Java作为一门强大的编程语言,提供了丰富的工具和库,可以帮助我们快速进行数据处理与分析。下面将…...

代码随想录打卡Day29
今天的题目尊嘟好难…除了第三题没看视频,其他的题目都是看了视频才做出来的。二刷等我。 134. 加油站 感觉这道题和之前的53. 最大子序和有点像,最大子序和是一旦当前总和为负数则立即抛弃当前的总和,从下个位置重新开始计算,而…...

图分类!!!
deepwalk 使用图中节点与节点的共现关系来学习节点的向量表示。那么关键的问题就是如何来描述节点与节点的共现关系,DeepWalk给出的方法是使用随机游走(RandomWalk)的方式在图中进行节点采样,RandomWalk是一种可重复访问已访问节点的深度优先遍历算法。给定当前访问…...

高防IP是如何防御攻击
DDoS攻击作为网络攻击中最常见的一种,一般利用大量的虚假流量向目标服务器发起攻击,进而堵塞网络损耗服务器性能,使服务器呈现崩溃状态,令真正的用户无法正常访问发送请求。以前的大型企业通常都是使用高防服务器来抵抗这类攻击&a…...

Kubernetes 系列 | k8s入门运维
目录 一、K8S集群搭建1.1 部署方式1.2 了解kubeadm1.3 部署流程1.3.1 初始化配置1.3.2 安装容器运行时1.3.3 安装K8S软件包1.3.4 创建集群 二、集群高可用1.1 集群高可用-堆叠1.2 集群高可用-集群外etcd 三、Pod运维3.1 Pod运维3.2 Pod的生命周期3.3 Pod状况3.4 Pod阶段3.5 容器…...

yolov8+deepsort+botsort+bytetrack车辆检测和测速系统
结合YOLOv8、DeepSORT、BoTSORT和ByteTrack等技术,可以实现一个高效的车辆检测和测速系统。这样的系统适用于交通监控、智能交通管理系统(ITS)等领域,能够实时识别并跟踪车辆,并估算其速度。 项目介绍 本项目旨在开发…...

基于准静态自适应环型缓存器(QSARC)的taskBus万兆吞吐实现
文章目录 概要整体架构流程技术名词解释技术细节1. 数据结构2. 自适应计算队列大小3. 生产者拼接缓存4. 高效地通知消费者 小结1. 性能表现情况2. 主要改进和局限3. 源码和发行版 概要 准静态自适应环形缓存器(Quasi-Static Adaptive Ring Cache)是task…...

C++笔记---指针常量和常量指针
巧记方法(方法来自于网络出处忘记了):const读作常量,*读作指针,按顺序读即可。例如: const int * ptr; //const在前*在后读作常量指针 const * int ptr; //const在前*在后读作常量指针 int * const prt; /…...

Python习题 177:设计银行账户类并实现存取款功能
(编码题)Python 实现一个简单的银行账户类 BankAccount,包含初始化方法、存款、取款、获取余额等功能。 参考答案 分析需求如下。 Python 类 BankAccount,用于模拟银行账户的基本功能。该类应包含以下方法: 初始化方法: 接受两个参数:account_holder(账户持有人的姓…...

IPhone 16:它的 “苹果智能 “包括哪些内容?
IPhone 16 的发布让科技界看到了该公司的人工智能产品 “苹果智能”(Apple Intelligence)究竟能做些什么。 苹果公司发布了拥有人工智能硬件升级的最新款 iPhone 16,进一步进军人工智能领域。苹果公司首席执行官蒂姆-库克(Tim Coo…...

【中国国际航空-注册/登录安全分析报告】
前言 由于网站注册入口容易被黑客攻击,存在如下安全问题: 1. 暴力破解密码,造成用户信息泄露 2. 短信盗刷的安全问题,影响业务及导致用户投诉 3. 带来经济损失,尤其是后付费客户,风险巨大,造…...

【ArcGIS】栅格计算器原理及案例介绍
ArcGIS:栅格计算器原理及案例介绍 栅格计算器(Raster Calculator)原理介绍案例案例1:计算栅格数据平均值 参考 栅格计算器(Raster Calculator)原理介绍 描述:在类似计算器的界面中,…...

LOOKUP函数和VLOOKUP函数知识讲解与案例演示
〇、需求 在 Excel 文档中,根据查找值从查找域和结果域构成的数组中,找到对应的结果值。 一、知识点讲解 LOOKUP函数(比较常用,推荐)和VLOOKUP函数 两个公式都可以实现上述需求。 1. LOOKUP 函数 1.1 单个查询条件…...

Java技术深度探索:高并发场景下的线程安全与性能优化
Java技术深度探索:高并发场景下的线程安全与性能优化 在当今的软件开发领域,随着互联网应用的日益复杂和用户量的激增,高并发成为了一个不可忽视的技术挑战。Java,作为一门广泛应用于企业级开发的编程语言,其内置的并发支持机制如线程(Thread)、锁(Lock)、并发集合(…...

Vulnhub-RickdiculouslyEasy靶场(9个flag)
flag1 端口9090有一个flag flag2 13337端口 flag3 使用dirb进行扫描网站的80端口,发现一些敏感文件 访问80端口,没有发现有效信息 访问passwords目录 访问FLAG.txt 再返回访问passwords.html文件 查看页面源代码发现一个密码 flag4 之前扫描到了robo…...

Android Studio Menu制作
文章目录 在Activity上新建onCreateOptionsMenu新建menu目录及资源文件新建Menu一级菜单在Activity上加载Menu 在Activity上新建onCreateOptionsMenu Overridepublic boolean onCreateOptionsMenu(Menu menu) {return super.onCreateOptionsMenu(menu);}新建menu目录及资源文件…...

【mybatis】使用模糊查询时报错:Encountered unexpected token: “?“ “?“
报错信息如下: Mapper.xml报错代码: AND HILIST_NAME like %#{hilistName}% 解决方案: 把模糊查询的 sql 语句改为使用 CONCAT 命令拼接, 就不会报错了。 AND HILIST_NAME like CONCAT(%, #{hilistName},%)...

【Linux】文件权限与类型全解:你的文件安全指南
欢迎来到 CILMY23 的博客 🏆本篇主题为:文件权限与类型全解:你的文件安全指南 🏆个人主页:CILMY23-CSDN博客 🏆系列专栏:Python | C | C语言 | 数据结构与算法 | 贪心算法 | Linux | 算法专题…...

解析DNS查询报文,探索DNS工作原理
目录 1. 用 tcpdump工具监听抓包 2. 用 host 工具获取域名对应的IP地址 3. 分析DNS以太网查询数据帧 3.1 linux下查询DNS服务器IP地址 3.2 DNS以太网查询数据帧 (1)数据链路层 (2)网络层 (3)传输层…...

Unity让摄像机跟随物体的方法(不借助父子关系)
在Unity中,不使用子对象的方式让相机跟随物体移动,我们通过编写脚本来实现。下面放一个从工程中摘出来的的C#脚本示例,用于将相机绑定到一个Target对象上并跟随其移动: using UnityEngine; public class FollowCamera : MonoBeh…...

misc音频隐写
一、MP3隐写 (1)题解:下载附件之后是一个mp3的音频文件;并且题目提示keysyclovergeek;所以直接使用MP3stego对音频文件进行解密;mp3stego工具是音频数据分析与隐写工具 (2)mp3stego工具的使用:…...

如何启动网络安全计划:首先要做的事情
目录 数据分类:网络安全的基石 为什么它很重要? 如何对数据进行分类? 风险分析 什么是风险分析? 如何进行风险分析? 业务影响分析 (BIA) BIA 的用途是什么? BIA 是如何进行的? 安全解…...

Java零基础-三维数组详解!
哈喽,各位小伙伴们,你们好呀,我是喵手。运营社区:C站/掘金/腾讯云/阿里云/华为云/51CTO;欢迎大家常来逛逛 今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互…...