当前位置: 首页 > 编程日记 > 正文

Gazebo构建小车模型并通过ROS控制

Gazebo构建小车模型并通过ROS控制

  • 介绍
  • 编写车子的URDF文件
  • 编写控制小车移动的插件(与ROS交互)
  • 结尾

介绍

突然想试试Gazebo这款仿真软件,因为它可以让你在任何时候都有机器人玩。但Gazebo的机制也比较复杂,所以还是先学习一下如何搭一个简单的小车,并通过ROS平台完成对小车的控制。

编写车子的URDF文件

这里是跟着《ROS机器人开发》书中的介绍一步步来的,对详细过程有兴趣的朋友去看一下。为了方便,直接把代码和注释都写在一起,但运行时要注意的是:URDF文件里不要有中文注释:

<!--URDF文件的注释方法,即XML语法的注释,但不能使用中文注释-->
<!--但是这个urdf只能用于在rviz中展示机器人模型,要想在gazebo中显示,需要将urdf换成sdf格式。好在开发者提供了专门的转换命令,用户只需要在urdf文件中添加一些额外的标签,如:gazebo与rviz对应的link颜色设置代码不同,所以要对urdf中material块加入gazebo标签,这些标签放在</robot>之前就行-->
<?xml version='1.0'?>
<!--这里给整个完整的机器人进行命名,整个机器人就相当于C++中的类对象。机器人的零件link,零件间关系joint相当于类成员以及成员间关系-->
<robot name="dd_robot"><!--定义一个机器人对象,整个<robot>代码块对应一个机器人模型--><link name="base_link"><!--base_link是特殊的link,之后机器人所有包含的link都会基于这个base_link来定义--><visual><!--设置某个link的显示效果(即在rviz等软件中的显示效果),如它的坐标、几何属性(用什么几何形状表示)--><!--这里没声明visual name则默认base_link--><origin xyz="0.0 0.0 0.0"  rpy="0.0 0.0 0.0"/><!--link的方向和坐标(link中心的坐标)属性(origin)--><geometry><!--link的几何属性--> <box size="0.5 0.5 0.25" /><!--用一个box来表示该link,设置box的长宽高--></geometry><!--设置这个link的颜色,如果下一个visual没有设置其他颜色,则整个link都使用这个颜色--><!--一旦制定了某个名称的material,则这个名称的material可以复用,即在其他visual块中调用<material name="xxx"/>即可--><material name="blue"><color rgba="0.0 0.5 1.0 1.0"/></material></visual><!--为每个可视化元件添加碰撞属性,以便让gazebo知道各个元件的具体边界位置要将visual和collision属性分开写,它们一个是视觉属性,一个是碰撞属性--><collision><origin xyz="0.0 0.0 0.0" rpy="0.0 0.0 0.0"/><geometry><box size="0.5 0.5 0.25"/></geometry></collision><!--一般collision和visual块中的几何属性是一样的,因为一个物体外表要和它的形体相一致--><!--inertial块代表link的惯性、运动学特性,它是模型在gazebo中能够显示的重要元素。每有一个geometry就需要有一个inertial--><inertial><mass value="5"/><!--mass的值是某个link的重量,单位时千克--><inertia ixx="0.13" ixy="0.0" ixz="0.0" iyy="0.21" iyz="0.0" izz="0.13"/><!--inertia为3x3的转动惯量矩阵框架,inertia要根据link实际使用的geometry内容而定,可以去网站上找到相关计算公式--></inertial><!--一个link块中可以添加多个visual块,相当于这个link由代码块中所有visual组成。同个link中的所有visual是个整体,它们的运动是一致的--><visual name="caster"><origin xyz="0.2 0.0 -0.125" rpy="0.0 0.0 0.0"/><geometry><sphere radius="0.05"/></geometry></visual><collision><origin xyz="0.2 0.0 -0.125" rpy="0.0 0.0 0.0"/><geometry><sphere radius="0.05"/></geometry></collision></link><!--右边轮子的link,编写思路和上面的一样--><link name="right_wheel"><visual><!--轮子的中心坐标可以设置为0,0,0,最终轮子的位置是会根据使用的joint确定--><origin xyz="0.0 -0.0 0.0" rpy="1.570795 0.0 0.0"/><geometry><cylinder length="0.1" radius="0.2"/></geometry><!--设置link的颜色--><material name="black"><color rgba="0.05 0.05 0.05 1.0"/></material></visual><collision><origin xyz="0.0 0.0 0.0" rpy="1.570795 0.0 0.0"/><geometry><cylinder length="0.1" radius="0.2"/></geometry></collision></link><!--连接右边轮子和底座两个links的关节joint--><joint name="join_right_wheel" type="continuous"><!--设置joint名称和类型。这里使用连续类型的关节--><!--设置关节所连接的对象,一般一个关节连接两个对象:父子两个对象。对象名称就是之前定义的那些link的名称--><parent link="base_link"/><!--设置父对象--><child link="right_wheel"/><!--设置子对象--><!--下面设定的joint的中心是子对象与父对象间的相对位移。之前设定的子对象link的中心坐标也是在这个joint对应的相对位移的基础上确定好的--><origin xyz="0.0 -0.30 0.0" rpy="0.0 0.0 0.0"/><!--设置joint的方向之类的位置信息--><axis xyz="0.0 1.0 0.0"/><!--因为连续型关节能围绕一个轴旋转,所以这里要设置这个关节能绕哪个轴旋转--></joint><!--设置左边轮子,和右边轮子的思路一样--><link name="left_wheel"><!--左轮的一些物理属性可以和右边轮子一样--><visual><origin xyz="0.0 0.0 0.0" rpy="1.570795 0.0 0.0"/><geometry><cylinder length="0.1" radius="0.2"/></geometry><!--设置这个visual的颜色。由于之前定义了一个名为black的material,所以这里可以直接调用这个颜色--><material name="black"/></visual><collision><origin xyz="0.0 0.0 0.0" rpy="1.570795 0.0 0.0"/><geometry><cylinder length="0.1" radius="0.2"/></geometry></collision></link><!--连接右边轮子和底座两个links的关节joint,和之前思路一样--><joint name="join_left_wheel" type="continuous"><parent link="base_link"/><child link="left_wheel"/><origin xyz="0.0 -0.3 0.0" rpy="0.0 0.0 0.0"/><axis xyz="0.0 1.0 0.0"/></joint><!--给urdf文件加入gazebo标签,主要是加入对urdf中material中颜色的gazebo标签--><gazebo reference="base_link"><!--指明这个标签时针对base_link对象的--><material>Gazebo/Blue</material><!--将指定对象的颜色属性转换成gazebo能够呈现的颜色,也就是所谓的gazebo标签。因为之前设置的URDF中的颜色代码在Gazebo中无法显示。这和Gazebo的显示颜色的机制有关--></gazebo><gazebo reference="right_wheel"><material>Gazebo/Black</material></gazebo><gazebo reference="left_wheel"><material>Gazebo/Black</material></gazebo><!--其余的代码都可以直接转成sdf格式以供gazebo使用,不用添加标签--><!--这三个标签最好写在每个link结束后面。这里为了统一注释,所以写在了一起-->
</robot>

这串代码是使用 VSCode 写的,因为 VSCode 里面有个专门的 URDF 插件,可以帮你补全代码啥的,挺实用的。根据这个代码我们就构建了一个拥有三个轮子的小车。然后用下面的 launch 文件( launch 文件中可以写中文注释)打开rviz,将小车模型在rviz中显示。

<launch<!--在通过命令行启动launch文件时要提供那些参数,也可以设置这些参数的默认值--><arg name="model" /><arg name="gui" default="False" /><!--这个launch将在ROS中的参数管理平台中发布这些可以查看、使用的参数--><!--robot_description是最重要的!!他应该是能够告诉 Rviz 应该读取显示哪个URDF文件--><param name="robot_description" textfile="$(find ros_robotics)/urdf/$(arg model)" /><param name="use_gui" value="$(arg gui)"/><!--use_gui表示是否打开一个可以控制整个模型中所有joint的gui界面--><!--这个launch要启动3个node节点: joint_state_publisher, robot_state_publisher and rviz--><!--下面启动node的方法其实是系统自动在命令窗口中分别用rosrun命令启动各个node,以最后的node代码块为例,它对应的启动命令是:rosrun pkg(rviz) node(rviz) args(各个参数) required(意义不太清楚)  代码块中的name有着其他含义--><!--这段node代码块的含义:从pkg对应的功能包中,启动名称为type对应值的节点,并将启动的阶段在ROS平台中的名称设为name的对应值--><!--joint_state_publisher将urdf中的关节信息发布出去,从而帮助rviz等软件根据关节来显示各个link和机器人模型--><node name="joint_state_publisher"pkg="joint_state_publisher"type="joint_state_publisher" /><!--robot_state_publisher会将机器人行动后的信息发布出去,帮助tf功能包确定机器人当前的状态,从何在模拟软件中显示--><node name="robot_state_publisher"pkg="robot_state_publisher"type="robot_state_publisher" /><!--这段node块复杂一点:一开始的代码和之前的意义一样,即启动rviz。之后设置rviz启动时的所有参数args,和required(意义不明)urdf.rviz是rviz软件的可读文件,它保存了上一次rviz退出时的状态,之后启动rviz时,通过读取这个urdf.rviz可以恢复先前的状态,并配置好rviz的参数--><node name="rviz" pkg="rviz" type="rviz" args="-d $(find ros_robotics)/urdf.rviz" required="true" />
</launch>

直接用 roslaunch 命令执行该launch文件,显示效果:
在这里插入图片描述
 第一次执行可能要调一下Rviz,先点左边窗口的Add按钮,找到RobotModel和TF,然后将Fixed Frame设定为base_link即可。
 其实也可以用Gazebo显示,只要稍微修改一下就行,这就看个人的习惯了。这个小车模型可以直接在 Gazebo 中用Model Edit 搭建。相比于写代码,图形化的搭建方式可能会更方便些。具体搭建方法大家可以参考这篇文章。

编写控制小车移动的插件(与ROS交互)

这个小车和常见的 turtlebot 不能说是一模一样,但也可以说是毫无关系。不过好在Gazebo中有很多现成的插件和模型,我们可以自行选择添加,编写小车代码只是为了帮助加深对 Gazebo 的理解。因为只是初步学习Gazebo仿真,所以我只做了控制小车移动的代码。为了方便直接把代码和注释写在一起:

#include <gazebo/gazebo.hh>//主要这个头文件,包含 Gazebo 中的大部分对象
#include <gazebo/physics/physics.hh>
#include <gazebo/transport/transport.hh>
#include <gazebo/msgs/msgs.hh>
#include <thread>
//ROS 要用到的所用到的头文件
#include <ros/ros.h>
#include <ros/callback_queue.h>
#include <ros/subscribe_options.h>
//ROS 的消息文件
#include <std_msgs/Float32.h>
//所有 Gazebo 插件都要在 Gazebo 的命名空间下创建。Gazebo 是之前头文件中已有的命名空间。
namespace gazebo
{/// \brief A plugin to control car motion.//可以把插件看作是C++中的类class PositionPlugin : public ModelPlugin//定义插件的类名,该类继承 ModelPlugin{/// \brief Constructor 类对象构造函数,在gazebo中创建该插件时会执行一次public: PositionPlugin() {//一些测试代码,显示插件已经被构建了std::cout<<"Motion Plugin"<<std::endl;}/// \brief 在该插件被加载进模型中时,gazebo会运行一次 Load 函数/// \param[in] _model A pointer to the model that this plugin is attached to.///  _model 指针参数会指向该插件所在的模型对象/// \param[in] _sdf A pointer to the plugin's SDF element./// _sdf指针指向插件对应的sdf元素。这种一般是指向world文件中编写的插件的 SDF 代码。public: void Load(physics::ModelPtr _model, sdf::ElementPtr _sdf){std::cout<<"Starting Load"<<std::endl;this->model = _model;std::cerr << "\n The model's name is [" <<_model->GetScopedName() << "]\n";std::string car_name_ori="Hello";//不好意思,这里把名字取的太随意了,可以自行修改(T T)// Initialize ros, if it has not already bee initialized.if (!ros::isInitialized()){int argc = 0;char **argv = NULL;ros::init(argc, argv, car_name_ori + "_" + "node",ros::init_options::NoSigintHandler);}// 根据之前定义的名字,创建ROS节点this->rosNode.reset(new ros::NodeHandle(car_name_ori + "_" + "Handle"));// 创建一个ROS中的topicros::SubscribeOptions so =//create 函数创造使用相应信息数据类型的topicros::SubscribeOptions::create<std_msgs::Float32>("/" + this->model->GetName() + "/" + car_name_ori + "/pos_cmd",//topic的名称1,//topic在通道内保存信息的数量个数boost::bind(&PositionPlugin::OnRosMsg, this, _1),//该topic对应的回调函数ros::VoidPtr(), &this->rosQueue);//该topic的数据队列是用户自定义的,所以要将自己创建的 CallbackQueue 对象传递过去(引用传递)this->rosSub = this->rosNode->subscribe(so);//看到这里朋友们可以发现,该话题的创建方式和 ROS 教程中不同。上述这种方式最主要的点在于用户要自行给定topic的队列控制函数,即rosQueue。用户要在函数中控制topic多久处理一次队列中的信息。//将控制topic队列的函数放进新的线程中,这样才能使topic正常工作。this->rosQueueThread =std::thread(std::bind(&PositionPlugin::QueueThread, this));//将设置模型速度的函数和仿真世界刷新函数绑定,这样才能有效改变模型速度(不断试错发现的)this->updateConnection = event::Events::ConnectWorldUpdateBegin(std::bind(&PositionPlugin::OnUpdate, this));}/// \brief Handle an incoming message from ROS上述topic对应的回调函数/// \param[in] _msg A float value that is used to control the carpublic: void OnRosMsg(const std_msgs::Float32ConstPtr &_msg){//std::cout<<"I can hear you "<<std::endl;this->vel=_msg->data;sleep(1);//加入这个会让小车只运动一秒this->vel=0;}public:void OnUpdate(){	this->model->SetLinearVel(ignition::math::Vector3d(this->vel, 0, 0));//设置模型的线速度//this->model->SetAngularVel(ignition::math::Vector3d(this->vel, 0, 0));//设置模型的角速度//设置速度的函数要和仿真世界刷新函数共同执行,放在ROS回调函数中无效。}/// \brief ROS helper function that processes messagesprivate: void QueueThread()//这个函数是每多少timeout时间处理一次存储在topic通道中的信息。这个函数和之前的创建topic的代码要配套使用,否则topic会无法工作{static const double timeout = 0.01;while (this->rosNode->ok()){this->rosQueue.callAvailable(ros::WallDuration(timeout));//因为topic创建的方式比较特殊,故要设置数据队列处理数据的时间间隔!!!!!!}}/// \brief Pointer to the model.private: physics::ModelPtr model;/// \brief A node use for ROS transportprivate: std::unique_ptr<ros::NodeHandle> rosNode;/// \brief A ROS subscriberprivate: ros::Subscriber rosSub;/// \brief A ROS callbackqueue that helps process messagesprivate: ros::CallbackQueue rosQueue;/// \brief A thread the keeps running the rosQueueprivate: std::thread rosQueueThread;private: double vel;//速度变量private: event::ConnectionPtr updateConnection;};// Tell Gazebo about this plugin, so that Gazebo can call Load on this plugin. GZ_REGISTER_MODEL_PLUGIN(PositionPlugin)//这部分一定要有,这样才能让 gazebo 知道这是个插件
} // namespace gazebo

为了让 Gazebo 直接同时加载小车模型和编写的插件,这里推荐写一个 world 文件:

<?xml version="1.0" ?>
<sdf version="1.6"><world name="motion_world"><!-- 给world导入环境光模型 --><include><uri>model://sun</uri></include><!-- 地面 --><include><uri>model://ground_plane</uri></include><!-- A testing model --><model name='dd_robot'><include><uri>model://dd_robot</uri></include><!-- Attach the plugin to this model --><plugin name="motion_controller" filename="libmotion_controller.so"></plugin></model></world>
</sdf>

然后用gazebo world文件命令运行这个文件。提一嘴,在执行命令前,我们要先把之前的小车 URDF 文件变成Gazebo 可用的SDF文件。方法很简单,直接执行这个命令即可gz sdf -p urdf文件 > sdf文件。我们还需要为这个 SDF 文件配套写一个 config 文件(介绍文件),内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<model><name>dd_robot</name><version>1.0</version><sdf version="1.4">dd_robot.sdf</sdf><description>My Car.</description>
</model>

然后我们把转换好的 SDF 文件和 config 文件打包到一个叫 dd_robot 文件夹中,并将文件夹放进 ~/.gazebo/models/ 目录下。只有这样,在执行world文件时,Gazebo 才能找到你的模型文件,因为 Gazebo 是有默认模型搜索路径的(也可以修改GAZEBO_MODEL_PATH环境变量,不过我没试过)。然后先在一个命令窗口执行roscore,并在另一个窗口运行 world 文件。最后再在新的窗口向对应的topic发布命令:rostopic pub topicname 信息类型 信息,即左边窗口的操作:
在这里插入图片描述
图一、小车的原始位置。
在这里插入图片描述
图二、控制小车以0.2m/s的速度移动1s钟(这在代码中有写)

结尾

在调试的过程中发现Gazebo还是很好玩的,不过它的机制很复杂,还常常报些搞不懂的错(毕竟新手)。虽然Gazebo的模型库中就有很多已经构建好的模型,但尝试自己动手搭建未尝不是件很刺激的事(也是件烦躁的事)。好了,对Gazebo的初步学习到此结束,之后还有很长的路要走,比如给模型加入纹理啥的。

相关文章:

【杂项】SVN服务器的本地搭建和使用

转载于:https://www.cnblogs.com/haizhibin1989/p/6939025.html

编译vim-8.2并配置jedi-vim插件

目录 一、背景 二、编译vim-8.2 三、配置jedi-vim插件 3.1、安装插件vundle 3.2、用vundle安装jedi-vim插件 一、背景 CentOS 7.9上已经安装了anaconda&#xff0c;python3.7的虚拟环境webenv。现在编译安装vim-8.2&#xff0c;使之支持python3&#xff08;yum装包是不支…

group by总结(还有having)

先在MySQL数据库里创建一个表&#xff0c;并添加几条数据用于测试&#xff1a; create table fruit(name varchar(4),address varchar(12),type_name varchar(6) )insert into fruit values (香蕉,广西,大香蕉); insert into fruit values (苹果,山东,红富士); insert into fr…

PHP数组基本的操作方法

1、数组操作的基本函数 数组的键和值&#xff1a;  array_values($arr);获得数组的值  array_keys($arr);获得数组的键名  array_flip($arr);数组中的值与键名互换&#xff08;如果有重复前面的会被后面的覆盖&#xff09;  in_array("apple",$arr);在数组中…

linux kafka进程挂了 自动重启

使用crontab&#xff0c;定时监控 kafka进程&#xff0c;发现挂了后重启。 shell脚本如下&#xff1a; #!/bin/sh source /etc/profile proc_dir"/data/kafka" # 程序目录 proc_name"kafka.Kafka" …

Towards Real-time Semantic RGB-D SLAM in Dynamic Environments(动态语义SLAM)

动态环境下的实时语义SLAM简介摘要系统流程实验结果总结简介 在ICRA 2021上看到这样一篇论文&#xff1a;Towards Real-time Semantic RGB-D SLAM in Dynamic Environments&#xff0c;发现它也是使用的语义网络基于深度图的多视图几何方法来去除图片中的动态对象的。这一方法和…

gpupdate /force 遇报错解决过程

windows server 2008 修改策略后&#xff0c;需要更新。在cmd中执行 gpupdate /force&#xff0c;遇到报错。报错内容为 The processing of Group Policy failed. Windows attempted to read the file \\<domain.name>\SysVol\<domain.name>\Policies\{xxxxxxxx-xx…

pytorch学习——torch.cat和torch.stack的区别

合并tensors torch.cat 沿着特定维数连接一系列张量。torch.stack 沿新维度连接一系列张量。 torch.cat 在给定维度中连接给定的 seq 个张量序列。 所有张量必须具有相同的形状&#xff08;连接维度除外&#xff09;或为空。 torch.cat(tensors, dim0, *, outNone) → Tens…

Docker将容器制作成镜像并提交到远程仓库

Docker将容器制作成镜像并提交到远程仓库 步骤如下 先在dockerhub上创建一个自己的用户https://hub.docker.com/。或者在阿里云也可以。 2. 然后先创建一个空的镜像名。 3. 在终端上登录。 4. 这里有一个容器ID为fe08a32503b1。想把它制作成镜像以备后期自己用。 5. 将容器制作…

关于子业之间相互取得元素或者方法

1.跳转是将页面name带过去 例子&#xff1a; url&#xff1a;"login.jsp?windowName"window.name; 传递参数到子页面 &#xff0c;使得子页面能够通过名字返回数据 2.获取跳转到页面 window.top.frames[0].frames["${param.windowName}"].document转载于:…

windows 2008 (非R2)使用批处理文件调整组策略过程记录

2021年12月8日&#xff0c;对windows server 2008 &#xff08;不是 windows server 2008 R2&#xff09; 调整组策略。其中有一部分&#xff0c;无法通过图形界面&#xff08;gpedit.msc&#xff09;进行&#xff0c;只能在cmd用命令行执行。执行时遇到如下报错。 猜想是由于中…

【Leetcode】 刷题之路1(python)

leetcode 刷题之路1&#xff08;python&#xff09; 看到有大佬总结了一些相关题目&#xff0c;想着先刷一类。 1.两数之和15.三数之和16.最接近的三数之和11.盛最多的水18.四数之和454.四数相加II 1. 两数之和给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你…

MySQL数据库中的内置函数

SQL函数分为单行函数和多行函数&#xff1a; 单行函数: 红色标注的为重点。 … … … …字符串函数: … … … … … … … … … … 1.length() 存储长度 … … … … … … … … … … 2.char_length() 字符个数 … … … … … … … … … … 3.concat()首尾相连 … ……

elasticsearch从入门到出门-01windows上安装使用

elasticsearch 1、安装JDK&#xff0c;至少1.8.0_73以上版本&#xff0c;java -version2、下载和解压缩Elasticsearch安装包&#xff0c;目录结构3、启动Elasticsearch&#xff1a;bin\elasticsearch.bat&#xff0c;es本身特点之一就是开箱即用&#xff0c;如果是中小型应…

读django文档——Managing static files (e.g. images, JavaScript, CSS)

在上一篇读django文档——nginx uwsgi 部署django项目_苦行僧的妖孽日常-CSDN博客 部署django项目后&#xff0c;发现在runserver时都能正常部署的 static 文件都没有生效。查看文档解决该问题&#xff0c;记录这一过程。 If you use django.contrib.staticfiles as explaine…

pytorch中tensor.mul()和mm()和matmul()

tensor.mul tensor.mul和tensor * tensor 都是将矩阵的对应位置的元素相乘&#xff0c;因此要求维度相同&#xff0c;点乘torch.mul(input, other, *, outNone) → Tensor 参数&#xff1a; input (Tensor) – the input tensor. other (Tensor or Number) torch.mul(input, …

python学习笔记 day44 数据库三范式

参考自 https://www.cnblogs.com/wangfengming/articles/7929118.html 1. 数据库三范式概念&#xff1a; 为了建立减少冗余&#xff0c;结构合理的数据库&#xff0c;涉及数据库时必须要遵守一定的规则&#xff0c;在关系数据库中&#xff0c;这种规则就成为范式&#xff0c;范…

行内标签(最常用的:a标签、img标签、span标签)

a 标签&#xff1a; 功能&#xff1a; 从一个页面跳转到其他页面&#xff0c;或者是当前页面的其他位置。 属性&#xff1a; href &#xff1a;指定跳转的目标路径。 值可以是一个外部网站的地址&#xff1b;也可以是一个内部网页的地址 target: _self 默认值&#xff0c;在当…

SAP HR模块配置假期日历和缺勤类型

目录 一、配置假期日历 二、配置缺勤信息类型 2.1、定义缺勤类型 2.2、定义缺勤的计算规则 2.3、分配缺勤计算规则到缺勤类型 一、配置假期日历 SAP的HR模块中&#xff0c;业务顾问在实施的时候一般会配置未来10年的假期日历&#xff0c;到期后再进行配置。 延长假期日…

表格(table、tr、th、td、colspan、rowspan)

表格一&#xff1a; <!DOCTYPE html> <html> <head><meta charset"UTF-8"><title></title><style>table{width: 720px;/*设置表格水平宽度为720px*/margin: 0 auto;/*使表格水平居中*/border: 1px solid black;/*设置边框…

Java基础概念性的知识总结

属于个人的所学的知识总结&#xff0c;不是全面的 1.JDK、JRE和JVM三者的区别 01.JDK&#xff1a;(Java Development ToolKit)Java开发工具包&#xff0c;是整个Java的核心。包括了Java的运行环境、JRE、一堆Java工具和Java基础的类库。 02.JRE&#xff1a;(Java Runtime Envir…

vue里的数据

背景&#xff1a; 一个项目完工在即&#xff0c;鉴于此&#xff0c;前端使用了vue&#xff0c;写下此栏&#xff0c;以供日后翻阅&#xff0c; 会涉及到我所运用到的vue相关知识&#xff0c;需要一定的js基础。 默认vue的single-file-components&#xff08;单文件组件开发&…

【Leetcode】刷题之路2(python)

哈希映射类题目&#xff08;简单题小试牛刀啦bhn&#xff09; 242.有效的字母异位词349.两个数组的交集1002.查找常用字符202.快乐数383.赎金信 242. 有效的字母异位词 用python的Counter类太绝了&#xff01;&#xff01;&#xff01; 一行代码解决问题&#xff0c;这道题实…

ORA-01113 file 1 needs media recovery

启动数据库时报错。ORA-01113 datafile1需要恢复。 rman执行恢复。恢复后尝试打开数据库&#xff0c;看结果 rman target / recover datafile 1; alter database open; 反复上述过程&#xff0c;直到所有数据文件恢复。 recover datafile 1; …… recover datafile 13; 如果…

大数据批量导入,解决办法,实践从定时从 sqlserver 批量同步数据到 mySql

c#代码&#xff0c;批量导入数据代码 public class MySql_Target : ZFCommon.DataAccesser.Base.DABase{public MySql_Target(){this.InitDataAccesser(ZFCommon.DataAccesser.DatabaseType.MySql, ReadConfig.TargetConnection);}///大批量数据插入,返回成功插入行数 /// <…

【目标检测】yolo系列:从yolov1到yolov5之YOLOv5训练自己数据集(v6.0)

一、源码下载及requirments 源码下载地址&#xff1a;https://github.com/ultralytics/yolov5 &#xff08;持续更新中&#xff09; 本人所用环境如下&#xff1a; pytorch&#xff1a;1.8&#xff08;因为cuda版本用了pytorch1.8&#xff09; cuda&#xff1a;10.1 Python&am…

CSS之常用选择器(元素、id、类、通配选择器)

<!DOCTYPE html> <html><head><meta charset"UTF-8"><title></title><style>/*1、元素选择器作用&#xff1a;根据标签名来选中指定的元素语法&#xff1a;标签名{}例子&#xff1a;p{} h1{} div{}*//*p{color: red;}*/…

Java中 实体类 VO、 PO、DO、DTO、 BO、 QO、DAO、POJO的概念

PO(persistant object) 持久对象 在 o/r 映射的时候出现的概念&#xff0c;如果没有 o/r 映射&#xff0c;没有这个概念存在了。通常对应数据模型 ( 数据库 ), 本身还有部分业务逻辑的处理。可以看成是与数据库中的表相映射的 java 对象。最简单的 PO 就是对应数据库中某个表中…

SAP有用的NOTE(持续更新)

目录 2421240 - Portal is not loaded on Chrome 56 or higher. 66971 - Supported SAP GUI platforms 66971 - Supported SAP GUI platforms 1999880 - FAQ: SAP HANA System Replication 2250144 - FAQ: SAP HANA Secure User Store 2222200 - FAQ: SAP HANA Network …

【目标检测】yolo系列:从yolov1到yolov5之YOLOv1详解及复现

检测器通常能够被分为两类&#xff0c;一类是two-stage检测器&#xff0c;最具代表的为faster R-CNN&#xff1b;另一类是one-stage检测器&#xff0c;包括YOLO&#xff0c;SSD等。一般来说&#xff0c;two-stage检测器具有高定位和识别准确性&#xff0c;而one-stage则有速度上…