1. 前言

April Tags 是一种视觉标签(类似 QR 码),用于通过相机进行定位和识别。它们通常用于计算机视觉任务中,帮助机器人识别和定位自己在物理空间中的位置,或者识别和追踪特定对象。

前提条件

  1. 启用 ROS 桥接:确保已经启用了 ROS 桥接插件。

  2. 完成“相机与变换树以及里程计”教程:已掌握相机数据、变换树以及里程计相关知识。

  3. 安装 apriltag-ros 包:需要安装用于 April Tag 检测的 ROS 包。
    执行以下命令来安装 apriltag-ros

    sudo apt-get install ros-$ROS_DISTRO-apriltag-ros
    
  4. 确保已经完成工作空间的 source 操作。 

2. 检测 April Tags

  1. 打开 April Tag 示例:在 Isaac Sim 中,进入 Isaac Examples → ROS → April Tag。这时视口中会显示出三个 April Tags。

  2. 查看 Stage Tree 和打开 Action Graph

    • 打开 Stage Tree,找到场景中的相关对象。

    • 右键点击目标对象,然后选择 Open Graph。此时,Action Graph 将打开,其中应该已自动设置 ROS 时钟发布器、TF 发布器和相机助手节点(用于初始化 camera_inforgb 图像发布器)。

  3. 开始仿真:点击 Play 按钮,开始向 ROS 发布数据。此时,April Tags 的数据会通过 ROS 被传输,你可以在 RViz 或其他 ROS 工具中查看检测到的标签。

在一个新的已 source ROS 环境的终端中,运行以下命令启动 AprilTag 检测节点:

roslaunch isaac_tutorials apriltag_continuous_detection.launch

这将启动一个 ROS 节点,持续检测场景中的 AprilTags。节点会从相机图像中提取标签信息并准备好进行后续处理。

在另一个已 source ROS 环境的终端中,运行以下命令来启动 RViz,并加载 AprilTag 的配置文件,以便可视化检测到的标签:

rviz -d <noetic_ws>/src/isaac_tutorials/rviz/apriltag_config.rviz

选项指定了 RViz 使用的配置文件。该配置文件包括显示相机图像和标记位置的设置。启动后,你应该能在 RViz 中看到从相机捕获的图像,以及检测到的 AprilTags 及其位置信息。

为了查看检测到的原始标签数据,可以运行以下命令,订阅并打印 /tag_detections 话题:

rostopic echo /tag_detections

这将显示检测到的 AprilTag 数据,包括标签的 ID、位置、姿态等信息,通常以 geometry_msgs/PoseStamped 消息格式呈现。

3.  给相机添加噪声

学习目标

在本示例中,我们将:

  • 简要介绍如何为传感器图像添加增强(augmentation)。

  • 发布带有噪声的图像数据。

1. 在一个终端中,运行以下命令来启动带有噪声增强的相机脚本:

./python.sh standalone_examples/api/omni.isaac.ros_bridge/camera_noise.py

当场景加载完成后,你应该会看到视口中的一个仓库场景,它会逆时针旋转。

2. 启动 RViz 并查看图像数据

在一个新的终端中,source ROS 环境并运行 RViz:

3. 在 RViz 中添加图像显示窗口

  1. 在 RViz 窗口的左下角点击 Add,打开弹出的窗口。

  2. By display type 选项卡下选择 Image,然后点击 OK

此时,RViz 窗口中会出现一个新的图像显示窗口,并且在 Display 菜单中会有一个标记为 Image 的菜单项。你可以将该图像窗口拖动到一个合适的位置。

4.配置图像显示话题

展开 Image 菜单,并将 Image Topic 设置为 /rgb_augmented。这时,你应该能在 RViz 中看到 Isaac Sim 中稍微带噪声的图像版本。

5. 代码解释

1. 设置相机路径

首先,我们设置一个相机在我们想要捕获数据的渲染产品上。可以使用 API 来设置视口中的相机,或者使用更底层的 API,直接操作渲染产品的 prim(这会直接影响渲染设置)。这两种方法都可以达到相同的目的。为了演示,我们使用 set_camera_prim_path,因为我们已经在处理渲染产品的路径。

# 获取当前视口的渲染产品路径
render_product_path = get_active_viewport().get_render_product_path()
# 使用渲染产品路径设置相机路径
set_camera_prim_path(render_product_path, CAMERA_STAGE_PATH)

2. 定义图像增强

在传感器中有几种方式来定义增强(augmentation)。增强可以通过不同的方式实现,常见的有:

  • C++ OmniGraph 节点

  • Python OmniGraph 节点

  • omni.warp 核心

  • numpy 核心

接下来,我们用 numpyomni.warp 核心来定义一个简单的噪声函数。为了简化,这里没有做颜色值的越界检查。

GPU 噪声核心(使用 omni.warp
# GPU 噪声核,用于生成高斯噪声
@wp.kernel
def image_gaussian_noise_warp(data_in: wp.array(dtype=wp.uint8, ndim=3),  # 输入数据(图像)data_out: wp.array(dtype=wp.uint8, ndim=3), # 输出数据(带噪声的图像)seed: int,  # 随机种子sigma: float = 25.0,  # 噪声强度(标准差)
):i, j = wp.tid()state = wp.rand_init(seed, wp.tid())# 为每个像素通道添加高斯噪声data_out[i, j, 0] = wp.uint8(wp.int32(data_in[i, j, 0]) + wp.int32(sigma * wp.randn(state)))data_out[i, j, 1] = wp.uint8(wp.int32(data_in[i, j, 1]) + wp.int32(sigma * wp.randn(state)))data_out[i, j, 2] = wp.uint8(wp.int32(data_in[i, j, 2]) + wp.int32(sigma * wp.randn(state)))
CPU 噪声核心(使用 numpy):
# CPU 噪声核,用于生成高斯噪声
def image_gaussian_noise_np(data_in: np.ndarray, seed: int, sigma: float = 25.0):np.random.seed(seed)# 通过 numpy 为输入图像添加高斯噪声return data_in + sigma * np.random.randn(*data_in.shape)

3. 定义图像增强操作

我们使用 rep.Augmentation.from_function() 来定义一个图像增强操作。在这个例子中,我们增强的是图像的输出,将 IsaacConvertRGBAToRGB 注释器的结果(将 RGBA 转换为 RGB)与噪声增强结合起来。

# 获取 RGB 数据的渲染变量名
rv_rgb = omni.syntheticdata.SyntheticData.convert_sensor_type_to_rendervar(sd.SensorType.Rgb.name)
# 获取 RGBA 到 RGB 的转换注释器
rgba_to_rgb_annotator = f"{rv_rgb}IsaacConvertRGBAToRGB"# 注册新的增强注释器,添加噪声
rep.annotators.register(name="rgb_gaussian_noise",  # 增强的名称annotator=rep.annotators.augment_compose(source_annotator=rgba_to_rgb_annotator,  # 使用已有的 RGBA 到 RGB 转换注释器augmentations=[rep.Augmentation.from_function(image_gaussian_noise_warp, seed=1234, sigma=25)],  # 使用噪声增强),
)

Augmentation.from_function()

  • 这是用来从函数创建一个增强操作的方式,image_gaussian_noise_warpimage_gaussian_noise_np 就是传递的增强函数。

  • seed 参数用于初始化随机数生成器,以确保噪声可以重复生成。它还与节点标识符结合,生成唯一的种子值。

4. 使用增强注释器并将其附加到 ROS 发布器

最终,我们替换现有的 IsaacConvertRGBAToRGB 注释器,使用新的带噪声的 rgb_gaussian_noise 注释器。然后,我们初始化 ROS 发布器并将其附加到渲染产品路径上,以开始捕获并发布数据。

# 替换现有的 IsaacConvertRGBAToRGB 注释器,使用带噪声的 rgb_gaussian_noise 注释器
writer = rep.writers.get(f"{rv_rgb}" + "ROS1PublishImage")
writer.annotators[0] = "rgb_gaussian_noise"
writer.initialize(topicName="rgb_augmented", frameId="sim_camera")
writer.attach([render_product_path])  # 附加到渲染产品路径

4. 发布相机数据

为了开始本教程,我们首先设置一个包含 omni.isaac.sensor.Camera 对象的环境。运行以下代码会加载一个简单的仓库环境,并在场景中放置一个相机。

运行以下脚本:

import carb
from isaacsim import SimulationApp
import sysBACKGROUND_STAGE_PATH = "/background"
BACKGROUND_USD_PATH = "/Isaac/Environments/Simple_Warehouse/warehouse_with_forklifts.usd"CONFIG = {"renderer": "RayTracedLighting", "headless": False}simulation_app = SimulationApp(CONFIG)import omni
import numpy as np
import omni.graph.core as og
import omni.replicator.core as rep
import omni.syntheticdata._syntheticdata as sd
from omni.isaac.core import SimulationContext
from omni.isaac.core.utils import stage, extensions, nucleus
from omni.isaac.sensor import Camera
import omni.isaac.core.utils.numpy.rotations as rot_utils
from omni.isaac.core.utils.prims import is_prim_path_valid
from omni.isaac.core_nodes.scripts.utils import set_target_prims# 启用 ROS 桥接扩展
extensions.enable_extension("omni.isaac.ros_bridge")simulation_app.update()# 检查 rosmaster 节点是否正在运行
import rosgraphif not rosgraph.is_master_online():carb.log_error("Please run roscore before executing this script")simulation_app.close()exit()simulation_context = SimulationContext(stage_units_in_meters=1.0)# 查找 Isaac Sim 资产文件夹并加载环境和机器人场景
assets_root_path = nucleus.get_assets_root_path()if assets_root_path is None:carb.log_error("Could not find Isaac Sim assets folder")simulation_app.close()sys.exit()# 加载环境
stage.add_reference_to_stage(assets_root_path + BACKGROUND_USD_PATH, BACKGROUND_STAGE_PATH)###### 相机辅助函数 ######### 这里应该粘贴教程中的函数
def publish_camera_tf(camera: Camera):camera_prim = camera.prim_pathif not is_prim_path_valid(camera_prim):raise ValueError(f"Camera path '{camera_prim}' is invalid.")try:# Generate the camera_frame_id. OmniActionGraph will use the last part of# the full camera prim path as the frame name, so we will extract it here# and use it for the pointcloud frame_id.camera_frame_id=camera_prim.split("/")[-1]# Generate an action graph associated with camera TF publishing.ros_camera_graph_path = "/CameraTFActionGraph"# If a camera graph is not found, create a new one.if not is_prim_path_valid(ros_camera_graph_path):(ros_camera_graph, _, _, _) = og.Controller.edit({"graph_path": ros_camera_graph_path,"evaluator_name": "execution","pipeline_stage": og.GraphPipelineStage.GRAPH_PIPELINE_STAGE_SIMULATION,},{og.Controller.Keys.CREATE_NODES: [("OnTick", "omni.graph.action.OnTick"),("IsaacClock", "omni.isaac.core_nodes.IsaacReadSimulationTime"),("RosPublisher", "omni.isaac.ros_bridge.ROS1PublishClock"),],og.Controller.Keys.CONNECT: [("OnTick.outputs:tick", "RosPublisher.inputs:execIn"),("IsaacClock.outputs:simulationTime", "RosPublisher.inputs:timeStamp"),]})# Generate 2 nodes associated with each camera: TF from world to ROS camera convention, and world frame.og.Controller.edit(ros_camera_graph_path,{og.Controller.Keys.CREATE_NODES: [("PublishTF_"+camera_frame_id, "omni.isaac.ros_bridge.ROS1PublishTransformTree"),("PublishRawTF_"+camera_frame_id+"_world", "omni.isaac.ros_bridge.ROS1PublishRawTransformTree"),],og.Controller.Keys.SET_VALUES: [("PublishTF_"+camera_frame_id+".inputs:topicName", "/tf"),# Note if topic_name is changed to something else besides "/tf",# it will not be captured by the ROS tf broadcaster.("PublishRawTF_"+camera_frame_id+"_world.inputs:topicName", "/tf"),("PublishRawTF_"+camera_frame_id+"_world.inputs:parentFrameId", camera_frame_id),("PublishRawTF_"+camera_frame_id+"_world.inputs:childFrameId", camera_frame_id+"_world"),# Static transform from ROS camera convention to world (+Z up, +X forward) convention:("PublishRawTF_"+camera_frame_id+"_world.inputs:rotation", [0.5, -0.5, 0.5, 0.5]),],og.Controller.Keys.CONNECT: [(ros_camera_graph_path+"/OnTick.outputs:tick","PublishTF_"+camera_frame_id+".inputs:execIn"),(ros_camera_graph_path+"/OnTick.outputs:tick","PublishRawTF_"+camera_frame_id+"_world.inputs:execIn"),(ros_camera_graph_path+"/IsaacClock.outputs:simulationTime","PublishTF_"+camera_frame_id+".inputs:timeStamp"),(ros_camera_graph_path+"/IsaacClock.outputs:simulationTime","PublishRawTF_"+camera_frame_id+"_world.inputs:timeStamp"),],},)except Exception as e:print(e)# Add target prims for the USD pose. All other frames are static.set_target_prims(primPath=ros_camera_graph_path+"/PublishTF_"+camera_frame_id,inputName="inputs:targetPrims",targetPrimPaths=[camera_prim],)returndef publish_camera_info(camera: Camera, freq):# The following code will link the camera's render product and publish the data to the specified topic name.render_product = camera._render_product_pathstep_size = int(60/freq)topic_name = camera.name+"_camera_info"queue_size = 1node_namespace = ""frame_id = camera.prim_path.split("/")[-1] # This matches what the TF tree is publishing.stereo_offset = [0.0, 0.0]writer = rep.writers.get("ROS1PublishCameraInfo")writer.initialize(frameId=frame_id,nodeNamespace=node_namespace,queueSize=queue_size,topicName=topic_name,stereoOffset=stereo_offset,)writer.attach([render_product])gate_path = omni.syntheticdata.SyntheticData._get_node_path("PostProcessDispatch" + "IsaacSimulationGate", render_product)# Set step input of the Isaac Simulation Gate nodes upstream of ROS publishers to control their execution rateog.Controller.attribute(gate_path + ".inputs:step").set(step_size)returndef publish_pointcloud_from_depth(camera: Camera, freq):# The following code will link the camera's render product and publish the data to the specified topic name.render_product = camera._render_product_pathstep_size = int(60/freq)topic_name = camera.name+"_pointcloud" # Set topic name to the camera's namequeue_size = 1node_namespace = ""frame_id = camera.prim_path.split("/")[-1] # This matches what the TF tree is publishing.# Note, this pointcloud publisher will simply convert the Depth image to a pointcloud using the Camera intrinsics.# This pointcloud generation method does not support semantic labelled objects.rv = omni.syntheticdata.SyntheticData.convert_sensor_type_to_rendervar(sd.SensorType.DistanceToImagePlane.name)writer = rep.writers.get(rv + "ROS1PublishPointCloud")writer.initialize(frameId=frame_id,nodeNamespace=node_namespace,queueSize=queue_size,topicName=topic_name)writer.attach([render_product])# Set step input of the Isaac Simulation Gate nodes upstream of ROS publishers to control their execution rategate_path = omni.syntheticdata.SyntheticData._get_node_path(rv + "IsaacSimulationGate", render_product)og.Controller.attribute(gate_path + ".inputs:step").set(step_size)returndef publish_depth(camera: Camera, freq):# The following code will link the camera's render product and publish the data to the specified topic name.render_product = camera._render_product_pathstep_size = int(60/freq)topic_name = camera.name+"_depth"queue_size = 1node_namespace = ""frame_id = camera.prim_path.split("/")[-1] # This matches what the TF tree is publishing.rv = omni.syntheticdata.SyntheticData.convert_sensor_type_to_rendervar(sd.SensorType.DistanceToImagePlane.name)writer = rep.writers.get(rv + "ROS1PublishImage")writer.initialize(frameId=frame_id,nodeNamespace=node_namespace,queueSize=queue_size,topicName=topic_name)writer.attach([render_product])# Set step input of the Isaac Simulation Gate nodes upstream of ROS publishers to control their execution rategate_path = omni.syntheticdata.SyntheticData._get_node_path(rv + "IsaacSimulationGate", render_product)og.Controller.attribute(gate_path + ".inputs:step").set(step_size)returndef publish_rgb(camera: Camera, freq):# The following code will link the camera's render product and publish the data to the specified topic name.render_product = camera._render_product_pathstep_size = int(60/freq)topic_name = camera.name+"_rgb"queue_size = 1node_namespace = ""frame_id = camera.prim_path.split("/")[-1] # This matches what the TF tree is publishing.rv = omni.syntheticdata.SyntheticData.convert_sensor_type_to_rendervar(sd.SensorType.Rgb.name)writer = rep.writers.get(rv + "ROS1PublishImage")writer.initialize(frameId=frame_id,nodeNamespace=node_namespace,queueSize=queue_size,topicName=topic_name)writer.attach([render_product])# Set step input of the Isaac Simulation Gate nodes upstream of ROS publishers to control their execution rategate_path = omni.syntheticdata.SyntheticData._get_node_path(rv + "IsaacSimulationGate", render_product)og.Controller.attribute(gate_path + ".inputs:step").set(step_size)return#################################################################### 创建相机实例。注意,Camera 类接受位置和方向的世界轴约定。
camera = Camera(prim_path="/World/floating_camera",position=np.array([-3.11, -1.87, 1.0]),frequency=20,resolution=(256, 256),orientation=rot_utils.euler_angles_to_quats(np.array([0, 0, 0]), degrees=True),
)camera.initialize()simulation_app.update()
camera.initialize()############### 调用相机发布函数 ################ 调用发布器函数。
# 确保你已经粘贴了上面定义的辅助函数,并取消注释以下行再运行。
approx_freq = 30publish_camera_tf(camera)
publish_camera_info(camera, approx_freq)
publish_rgb(camera, approx_freq)
publish_depth(camera, approx_freq)
publish_pointcloud_from_depth(camera, approx_freq)##################################################################### 初始化物理引擎
simulation_context.initialize_physics()# 开始仿真
simulation_context.play()while simulation_app.is_running():simulation_context.step(render=True)simulation_context.stop()
simulation_app.close()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/92501.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/92501.shtml
英文地址,请注明出处:http://en.pswp.cn/bicheng/92501.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Kafka + 时间轮 + 数据库实现延迟队列方案

Kafka 原生不支持延迟队列功能。而RabbitMQ、RocketMQ及Redis等其他消息队列原生支持延迟队列。 RabbitMQ RocketMQ Redis 实现方式 通过插件实现&#xff0c;消息进入延迟队列后根据配置时间过滤转发。 原生支持&#xff0c;发送消息时设置延迟级别&#xff0c;定时任务处…

力扣 hot100 Day69

287. 寻找重复数 给定一个包含 n 1 个整数的数组 nums &#xff0c;其数字都在 [1, n] 范围内&#xff08;包括 1 和 n&#xff09;&#xff0c;可知至少存在一个重复的整数。 假设 nums 只有 一个重复的整数 &#xff0c;返回 这个重复的数 。 你设计的解决方案必须 不修改…

Android 的CameraX的使用(配置,预览,拍照,图像分析,录视频)

Android Studio 版本号:2024.1.2 CameraX是Jetpack系列中的一个库,它基于Camera2 API构建,但提供了更高层次的抽象。 CameraX 三大核心用例: Preview预览 ,ImageCapture拍照和 VideoCapture录视频 一、创建项目,进行环境配置 CameraX 需要一些属于 Java 8 的方法,因此…

【机器学习深度学习】微调训练数据质量

目录 前言 一、为什么数据质量评估很重要 二、数据质量评估的核心维度 三、数据质量的可量化维度&#xff08;必须要测的指标&#xff09; 四、多答案、多类型数据的取舍与优化 场景 A&#xff1a;一个问题有多个相似回答 场景 B&#xff1a;多个类型数据&#xff0c;每…

从DeepSeek-V3到Kimi K2,大型语言模型架构对比

文章目录 摘要 **稀疏化与专家系统** **注意力机制优化** **归一化与稳定性设计** 模型架构对比详析 DeepSeek-V3 vs Llama 4 Maverick Qwen3 vs SmolLM3 Kimi 2的突破 1 DeepSeek V3/R1 1.1 多头潜在注意力(MLA) 1.2 混合专家系统(MoE) 1.3 DeepSeek 总结 2 OLMo 2 2.1 归…

Unity笔记(二)——Time、Vector3、位置位移、角度、旋转、缩放、看向

写在前面写本系列的目的(自用)是回顾已经学过的知识、记录新学习的知识或是记录心得理解&#xff0c;方便自己以后快速复习&#xff0c;减少遗忘。这里只有部分语法知识。五、Time时间相关1、时间缩放比例概念&#xff1a;可以通过UnityEngine.Time类的timeScale属性控制游戏时…

vue+vite项目中怎么定义一个环境变量可以在开发环境和生产环境使用不同的值,并且可以在vue页面和index.html通用。

首先我们需要下载一个插件vite-plugin-html然后再项目最外层和index.html同级目录下新建.env.development和.env.production两个项目并且定义你想要的环境变量名:注意要以VITE_开头VITE_APP_MAP_TOKEN1233444然后vite.config.js文件import { defineConfig,loadEnv } from vite…

Python-深度学习--2信息熵,条件熵(ID3决策树),KL散度

一、信息熵&#xff08;Entropy&#xff09;的计算与应用信息熵用于衡量一个概率分布的不确定性&#xff0c;值越大表示分布越分散&#xff08;不确定性越高&#xff09;。1. 数学定义对于离散概率分布 P&#xff0c;信息熵公式为&#xff1a;&#xff08;通常以 2 为底单位是比…

国产化Word处理控件Spire.Doc教程:Python提取Word文档中的文本、图片、表格等

在现代办公场景中&#xff0c;Word文档已成为信息存储与交流的重要载体&#xff0c;承载着关键的业务数据、结构化表格、可视化图表以及协作批注等重要内容。面对日益增长的文档处理需求&#xff0c;传统的人工操作方式已难以满足效率与准确性的双重标准。采用Python实现Word文…

Spring IOC 原理

Spring IoC&#xff08;控制反转&#xff09;是Spring框架的核心机制&#xff0c;其原理是通过容器管理对象生命周期和依赖关系&#xff0c;实现解耦。 1. 控制反转&#xff08;IoC&#xff09;核心思想 传统模式&#xff1a;对象主动创建依赖&#xff08;如new Service()&…

VSCode:基础使用 / 使用积累

官网 Visual Studio Code - Code Editing. Redefined 记录一、更新依赖 尝试删除yarn.lock文件 记录二、“解决冲突”的方式变了 更新后&#xff0c;“解决冲突”的方式变了&#xff0c;有的时候能选中两者&#xff0c;有的时候不能 现在又更新了&#xff0c;回复到了原来…

tcp 确认应答和超时时间

1. 确认应答之间的时间&#xff08;RTT&#xff09;这是指 从发送方发送数据到接收方返回确认&#xff08;ACK&#xff09;之间的时间。它反映的是数据传输的 往返延迟。例如&#xff0c;发送方发送一个数据包&#xff0c;接收方收到后&#xff0c;回传一个确认包&#xff08;A…

图的应用-最短路径

最短路径的典型用途&#xff1a;交通网络的问题——从甲地到乙地之间是否有公路连通&#xff1f;在有多条通路的情况下&#xff0c;哪一条路最短&#xff1f;交通网络用有向网来表示&#xff1a;顶点——表示地点&#xff0c;弧——表示两个地点有路连通&#xff0c;弧上的权值…

【qt5_study】1.Hello world

模板 作为初学者我们选择第一个Application(Qt)和 Qt Widgets Application,所谓的模板就是 Qt为了方便开发程序,在新建工程时可以让用户基于一种模板来编写程序,包括 cpp文件, ui文件都已经快速的创建,而不用用户手动创建这些文件。 基类 这里默认选择的基类为 QMainWin…

项目构想|文生图小程序

Date: August 4, 2025项目介绍 &#x1f44b;&#xff0c;我们通过 Vibe Coding 做一个文字生成图片的小程序。 我们会从需求分析、技术选型、UI设计、项目构筑到最后打包&#xff0c;一路尝试 Vibe Coding 实现。 创建项目 创建文件夹&#xff1a;ai-pic-mini-app 采用 Git 进…

TiDB/MongoDB/Taosdb存储引擎概览

数据库类型存储引擎数据结构源码位置tidbRockDBLSM树https://github.com/facebook/rocksdbmongodbWiredTigerB 树/LSM树https://github.com/wiredtiger/wiredtigerTDengineTSDBBRINhttps://github.com/taosdata/TDengine 1、tidb存储引擎概览 LSM树数据结构描述LSM树(Log Str…

qt窗口--01

文章目录qt窗口--01窗口概览菜单栏工具栏状态栏浮动窗口子窗口对话框model结语很高兴和大家见面&#xff0c;给生活加点impetus&#xff01;&#xff01;开启今天的编程之路&#xff01;&#xff01; 作者&#xff1a;٩( ‘ω’ )و260 我的专栏&#xff1a;qt&#xff0c;Li…

Neo4j 社区版 Mac 安装教程

最近用到了nebulagraph图数据库做金融反欺诈项目&#xff0c;虽然nebula属于分布式架构&#xff0c;但依然感觉nebula使用不太顺手&#xff0c;这里顺便研究一下neo4j这款数据库如何&#xff0c;这里先从安装开始&#xff1f; 一、 准备工作 确认 Java 版本要求&#xff1a; N…

Android Studio(2025.1.2)Gemini Agent 使用指南

Android Studio&#xff08;2025.1.2&#xff09;Gemini Agent 使用指南 文章目录Android Studio&#xff08;2025.1.2&#xff09;Gemini Agent 使用指南1. 什么是 Gemini Agent&#xff1f;2. 如何启用和配置 Gemini Agent2.1 获取 API Key2.2 在 Android Studio 中配置3. 实…

计算机视觉--opencv(代码详细教程)

在计算机视觉的广袤领域中&#xff0c;OpenCV 是一座极为关键的里程碑。无论是在前沿的学术研究&#xff0c;还是在蓬勃发展的工业界&#xff0c;OpenCV 凭借其强大的功能与高效的性能&#xff0c;为开发者提供了丰富的图像处理和计算机视觉算法&#xff0c;助力无数项目落地。…