【 rbx1翻译 第七章、控制移动基座】第八节、使用里程计进行往返运动

2023-05-16

7.8 Out and Back Using Odometry (使用里程计进行往返运动)

现在,我们了解了里程表信息是如何在ROS中表示的,我们可以更精确地在往返过程中移动机器人。 下一个脚本将监视/ odom和/ base_link坐标系之间的转换报中的机器人的位置和方向,而不是根据时间和速度来猜测距离和角度。
Now that we understand how odometry information is represented in ROS, we can be more precise about moving our robot on an out-and-back course. Rather than guessing distances and angles based on time and speed, our next script will monitor the robot’s position and orientation as reported by the transform between the /odom and /base_link frames.

在rbx1_nav / nodes目录中,新文件为odom_out_and_back.py。 在查看代码之前,让我们比较一下模拟器和真实机器人之间的结果。
The new file is called odom_out_and_back.py in the rbx1_nav/nodes directory. Before looking at the code, let’s compare the results between the simulator and a real robot.

7.8.1 Odometry-Based Out and Back in the ArbotiX Simulator (在ArbotiX Simulator中基于里程表的往返运动)

如果您已经在运行模拟机器人,请先用Ctrl-C终止模拟,以便我们从头开始测量里程。 然后再次启动模拟的机器人,运行RViz,然后运行odom_out_and_back.py脚本,如下所示:
If you already have a simulated robot running, first Ctrl-C out of the simulation so we can start the odometry readings from scratch. Then bring up the simulated robot again, run RViz , then run the odom_out_and_back.py script as follows:

roslaunch rbx1_bringup fake_turtlebot.launch
rosrun rviz rviz -d `rospack find rbx1_nav`/sim.rviz
rosrun rbx1_nav odom_out_and_back.py

一个经典的结果如下所示:
A typical result is shown below:
在这里插入图片描述如您所见,在没有物理环境影响的理想模拟器中使用里程计可以产生基本上完美的结果。 这应该不足为奇。 那么,当我们在真实的机器人上尝试时会发生什么呢?
As you can see, using odometry in an ideal simulator without physics produces basically perfect results. This should not be terribly surprising. So what happens when we try it on a real robot?

7.8.2 Odometry-Based Out and Back Using a Real Robot (使用真正的机器人进行基于里程表的往返运动)

如果您有TurtleBot或其他与ROS兼容的机器人,则可以在现实世界中尝试基于里程表的往返脚本。
If you have a TurtleBot or other ROS-compatible robot, you can try the odometry based out-and-back script in the real world.

首先,请确保您终止所有正在运行的仿真。 然后启动机器人的启动文件。 对于TurtleBot,您可以运行:
First make sure you terminate any running simulations. Then bring up your robot’s startup launch file(s). For a TurtleBot you would run:

roslaunch rbx1_bringup turtlebot_minimal_create.launch

(或者,如果您已经创建了一个启动文件来存储校准参数,则可以使用自己的启动文件。)
(Or use your own launch file if you have created one to store your calibration parameters.)

确保您的机器人有足够的工作空间-距离机器人至少1.5米,两侧至少一米。
Make sure your robot has plenty of room to work in—at least 1.5 meters ahead of it and a meter on either side.

如果您使用的是TurtleBot,我们还将运行odom_ekf.py脚本(包含在rbx1_bringup软件包中),以便我们可以在RViz中看到TurtleBot的组合里程表坐标系。 如果您不使用TurtleBot,则可以跳过此步骤。 此启动文件应在TurtleBot的笔记本电脑上运行:
If you are using a TurtleBot, we will also run the odom_ekf.py script (included in the rbx1_bringup package) so we can see the TurtleBot’s combined odometry frame in RViz . You can skip this if you are not using a TurtleBot. This launch file should be run on the TurtleBot’s laptop:

roslaunch rbx1_bringup odom_ekf.launch

如果您已经从上一个测试运行了RViz,则只需取消选中Odometry显示并选中Odometry EKF显示,然后跳过以下步骤。
If you already have RViz running from the previous test, you can simply un-check the Odometry display and check the Odometry EKF display, then skip the following step.

如果尚未启动RViz,请立即使用nav_ekf配置文件在你的工作站上运行它。 该文件只是预选择了 /odom_ekf话题,以显示组合的里程表数据:
If RViz is not already up, run it now on your workstation with the nav_ekf config file. This file simply pre-selects the / odom_ekf topic for displaying the combined odometry data:

rosrun rviz rviz -d `rospack find rbx1_nav`/nav_ekf.rviz

最后,像在模拟中一样,启动基于里程表的往返脚本。您可以在工作站 或 使用SSH登陆后的机器人计算机上运行以下命令:
Finally, launch the odometry-based out-and-back script just like we did in simulation. You can run the following command either on your workstation or on the robot’s laptop after logging in with ssh :

rosrun rbx1_nav odom_out_and_back.py

这是在地毯上操作时我自己的TurtleBot的结果:
Here is the result for my own TurtleBot when operating on a low-ply carpet:
在这里插入图片描述
从图片中可以看到,结果比定时往返的情况要好得多。 实际上,在现实世界中的结果甚至比RViz中显示的还要好。 (请记住,RViz中的里程计箭头不会与机器人在现实世界中的实际位置和方向完全对齐。)在此特定运行中,机器人最终距起始位置不到1厘米,只有几厘米偏离正确方向的角度。 当然,要获得甚至如此好的结果,您将需要花费一些时间,如前所述,仔细校准机器人的里程计。
As you can see from the picture, the result is much better than the timed out-and-back case. In fact, in the real world, the result was even better than shown in RViz . (Remember that the odometry arrows in RViz won’t line up exactly with the actual position and orientation of the robot in the real world.) In this particular run, the robot ended up less than 1 cm from the starting position and only a few degrees away from the correct orientation. Of course, to get results even this good, you will need to spend some time carefully calibrating your robot’s odometry as described earlier.

7.8.3 The Odometry-Based Out-and-Back Script (基于Odometry的往返脚本)

现在,这是完整的基于里程表的往返脚本。 脚本中的注释应该使脚本的意思表达已经很明确了。在列出所有代码后,我们将对关键代码行进行更详细地描述。
Here now is the full odometry-based out-and-back script. The embedded comments should make the script fairly self-explanatory but we will describe the key lines in greater detail following the listing.

源链接: odom_out_and_back.py
Link to source: odom_out_and_back.py

#!/usr/bin/env python

""" odom_out_and_back.py - Version 1.1 2013-12-20

    A basic demo of using the /odom topic to move a robot a given distance
    or rotate through a given angle.

    Created for the Pi Robot Project: http://www.pirobot.org
    Copyright (c) 2012 Patrick Goebel.  All rights reserved.

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.5
    
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details at:
    
    http://www.gnu.org/licenses/gpl.html
      
"""

import rospy
from geometry_msgs.msg import Twist, Point, Quaternion
import tf
from rbx1_nav.transform_utils import quat_to_angle, normalize_angle
from math import radians, copysign, sqrt, pow, pi

class OutAndBack():
    def __init__(self):
        # Give the node a name
        rospy.init_node('out_and_back', anonymous=False)

        # Set rospy to execute a shutdown function when exiting       
        rospy.on_shutdown(self.shutdown)

        # Publisher to control the robot's speed
        self.cmd_vel = rospy.Publisher('/cmd_vel', Twist, queue_size=5)
        
        # How fast will we update the robot's movement?
        rate = 20
        
        # Set the equivalent ROS rate variable
        r = rospy.Rate(rate)
        
        # Set the forward linear speed to 0.15 meters per second 
        linear_speed = 0.15
        
        # Set the travel distance in meters
        goal_distance = 1.0

        # Set the rotation speed in radians per second
        angular_speed = 0.5
        
        # Set the angular tolerance in degrees converted to radians [tolerance:公差]
        angular_tolerance = radians(1.0)
        
        # Set the rotation angle to Pi radians (180 degrees)
        goal_angle = pi

        # Initialize the tf listener
        self.tf_listener = tf.TransformListener()
        
        # Give tf some time to fill its buffer
        rospy.sleep(2)
        
        # Set the odom frame
        self.odom_frame = '/odom'
        
        # Find out if the robot uses /base_link or /base_footprint
        try:
            self.tf_listener.waitForTransform(self.odom_frame, '/base_footprint', rospy.Time(), rospy.Duration(1.0))
            self.base_frame = '/base_footprint'
        except (tf.Exception, tf.ConnectivityException, tf.LookupException):
            try:
                self.tf_listener.waitForTransform(self.odom_frame, '/base_link', rospy.Time(), rospy.Duration(1.0))
                self.base_frame = '/base_link'
            except (tf.Exception, tf.ConnectivityException, tf.LookupException):
                rospy.loginfo("Cannot find transform between /odom and /base_link or /base_footprint")
                rospy.signal_shutdown("tf Exception")  
        
        # Initialize the position variable as a Point type
        position = Point()
            
        # Loop once for each leg of the trip
        for i in range(2):
            # Initialize the movement command
            move_cmd = Twist()
            
            # Set the movement command to forward motion
            move_cmd.linear.x = linear_speed
            
            # Get the starting position values     
            (position, rotation) = self.get_odom()
                        
            x_start = position.x
            y_start = position.y
            
            # Keep track of the distance traveled
            distance = 0
            
            # Enter the loop to move along a side
            while distance < goal_distance and not rospy.is_shutdown():
                # Publish the Twist message and sleep 1 cycle         
                self.cmd_vel.publish(move_cmd)
                
                r.sleep()
        
                # Get the current position
                (position, rotation) = self.get_odom()
                
                # Compute the Euclidean distance from the start
                distance = sqrt(pow((position.x - x_start), 2) + 
                                pow((position.y - y_start), 2))

            # Stop the robot before the rotation
            move_cmd = Twist()
            self.cmd_vel.publish(move_cmd)
            rospy.sleep(1)
            
            # Set the movement command to a rotation
            move_cmd.angular.z = angular_speed
            
            # Track the last angle measured
            last_angle = rotation
            
            # Track how far we have turned
            turn_angle = 0
            
            while abs(turn_angle + angular_tolerance) < abs(goal_angle) and not rospy.is_shutdown():
                # Publish the Twist message and sleep 1 cycle         
                self.cmd_vel.publish(move_cmd)
                r.sleep()
                
                # Get the current rotation
                (position, rotation) = self.get_odom()
                
                # Compute the amount of rotation since the last loop
                delta_angle = normalize_angle(rotation - last_angle)
                
                # Add to the running total
                turn_angle += delta_angle
                last_angle = rotation
                
            # Stop the robot before the next leg
            move_cmd = Twist()
            self.cmd_vel.publish(move_cmd)
            rospy.sleep(1)
            
        # Stop the robot for good
        self.cmd_vel.publish(Twist())
        
    def get_odom(self):
        # Get the current transform between the odom and base frames
        try:
            (trans, rot)  = self.tf_listener.lookupTransform(self.odom_frame, self.base_frame, rospy.Time(0))
        except (tf.Exception, tf.ConnectivityException, tf.LookupException):
            rospy.loginfo("TF Exception")
            return

        return (Point(*trans), quat_to_angle(Quaternion(*rot)))
        
    def shutdown(self):
        # Always stop the robot when shutting down the node.
        rospy.loginfo("Stopping the robot...")
        self.cmd_vel.publish(Twist())
        rospy.sleep(1)
 
if __name__ == '__main__':
    try:
        OutAndBack()
    except:
        rospy.loginfo("Out-and-Back node terminated.")

现在让我们看一下脚本中的关键行。
Let’s now look at the key lines in the script.

from geometry_msgs.msg import Twist, Point, Quaternion
import tf
from rbx1_nav.transform_utils import quat_to_angle, normalize_angle

我们将需要geometry_msgs包中的Twist,Point和Quaternion数据类型。 我们还将需要tf库来监视/ odom和/ base_link(或/ base_footprint)坐标系之间的转换。 transform_utils库是一个小模块,您可以在rbx1_nav / src / rbx1_nav目录中找到,并且包含从TurtleBot软件包中借来的一些便捷功能。 函数quat_to_angle将四元数转换为欧拉角(偏航角),而normalize_angle函数则消除180度和-180度之间以及0度和360度之间的歧义。
We will need the Twist , Point and Quaternion data types from the geometry_msgs package. We will also need the tf library to monitor the transformation between the /odom and /base_link (or /base_footprint ) frames. The transform_utils library is a small module that you can find in the rbx1_nav/src/rbx1_nav directory and contains a couple of handy functions borrowed from the TurtleBot package. The function quat_to_angle converts a quaternion to an Euler angle (yaw) while the normalize_angle function removes the ambiguity between 180 and -180 degrees as well as 0 and 360 degrees.

# Set the angular tolerance in degrees converted to radians
angular_tolerance = radians(2.5)

在这里,我们定义了旋转的angular_tolerance。 原因是使用真正的机器人很容易使旋转过度,甚至微小的角度误差也可能使机器人远离下一个位置。 根据经验,发现约2.5度的公差是可以接受的结果。
Here we define an angular_tolerance for rotations. The reason is that it is very easy to overshoot the rotation with a real robot and even a slight angular error can send the robot far away from the next location. Empirically it was found that a tolerance of about 2.5 degrees gives acceptable results.

# Initialize the tf listener
self.tf_listener = tf.TransformListener()

# Give tf some time to fill its buffer
rospy.sleep(2)

# Set the odom frame
self.odom_frame = '/odom'

# Find out if the robot uses /base_link or /base_footprint
try:
	self.tf_listener.waitForTransform(self.odom_frame,'/base_footprint', rospy.Time(),rospy.Duration(1.0))
	self.base_frame = '/base_footprint'
except (tf.Exception, tf.ConnectivityException, tf.LookupException):
	try:
		self.tf_listener.waitForTransform(self.odom_frame,'/base_link', rospy.Time(), rospy.Duration(1.0))
		self.base_frame = '/base_link'
	except (tf.Exception, tf.ConnectivityException,tf.LookupException):
		rospy.loginfo("Cannot find transform between /odom and /base_link or /base_footprint")
		rospy.signal_shutdown("tf Exception")

接下来,我们创建一个TransformListener对象来监视坐标系转换。 请注意,tf需要一点时间来填充监听器的缓冲区,因此我们添加了一个rospy.sleep(2)调用。 要获取机器人的位置和方向,我们需要在/ odom框架与TurtleBot使用的/ base_footprint框架或Pi Robot和Maxwell使用的/ base_link框架之间进行转换。 首先,我们测试/ base_footprint框架,如果找不到,我们测试/ base_link框架。 结果存储在self.base_frame变量中,以便稍后在脚本中使用。
Next we create a TransformListener object to monitor frame transforms. Note that tf needs a little time to fill up the listener’s buffer so we add a call to rospy.sleep(2) . To obtain the robot’s position and orientation, we need the transform between the /odom frame and either the /base_footprint frame as used by the TurtleBot or the /base_link frame as used by Pi Robot and Maxwell. First we test for the /base_footprint frame and if we don’t find it, we test for the / base_link frame. The result is stored in the self.base_frame variable to be used later in the script.

for i in range(2):
	# Initialize the movement command
	move_cmd = Twist()

与定时往返脚本一样,我们将行程分成两部分执行,每一部分都是:首先将机器人向前移动1米,然后将其旋转180度。
As with the timed out-and-back script, we loop through the two legs of the trip: first moving the robot 1 meter forward, then rotating it 180 degrees.

	(position, rotation) = self.get_odom()
	x_start = position.x
	y_start = position.y

在每部分的起点,我们使用get_odom()函数记录起点和方向。 接下来让我们看一下,以便我们了解其工作原理。
At the start of each leg, we record the starting position and orientation using the get_odom() function. Let’s look at that next so we understand how it works.

def get_odom(self):
	# Get the current transform between the odom and base frames
	try:
		(trans, rot) = self.tf_listener.lookupTransform(self.odom_frame,self.base_frame, rospy.Time(0))
	except (tf.Exception, tf.ConnectivityException, tf.LookupException):
		rospy.loginfo("TF Exception")
		return
	return (Point(*trans), quat_to_angle(Quaternion(*rot)))

get_odom()函数首先使用tf_listener对象查找里程表和基础坐标系之间的当前转换。 如果查找有问题,我们将抛出异常。 否则,返回平移的Point表示和旋转的四元数表示。 trans和rot变量前面的*是Python的用于将数字列表传递给函数的符号,我们在这里使用它是因为trans是x,y和z坐标的列表,而rot是x,y, z和w四元数分量。
The get_odom() function first uses the tf_listener object to look up the current transform between the odometry and base frames. If there is a problem with the lookup, we throw an exception. Otherwise, we return a Point representation of the translation and a Quaternion representation of the rotation. The * in front of the trans and rot variables is Python’s notation for passing a list of numbers to a function and we use it here since trans is a list of x, y, and z coordinates while rot is a list of x, y, z and w quaternion components.

现在回到脚本的主要部分:
Now back to the main part of the script:

# Keep track of the distance traveled
distance = 0
# Enter the loop to move along a side
while distance < goal_distance and not rospy.is_shutdown():
	# Publish the Twist message and sleep 1 cycle
	self.cmd_vel.publish(move_cmd)
	r.sleep()
	# Get the current position
	(position, rotation) = self.get_odom()
	# Compute the Euclidean distance from the start
	distance = sqrt(pow((position.x - x_start), 2) + pow((position.y - y_start), 2))

这只是我们向前移动机器人直到机器人走过1.0米距离的循环。
This is just our loop to move the robot forward until we have gone 1.0 meters.

# Track how far we have turned
turn_angle = 0
while abs(turn_angle + angular_tolerance) < abs(goal_angle) and not rospy.is_shutdown():
	# Publish the Twist message and sleep for 1 cycle
	self.cmd_vel.publish(move_cmd)
	r.sleep()
	# Get the current rotation
	(position, rotation) = self.get_odom()
	# Compute the amount of rotation since the last loop
	delta_angle = normalize_angle(rotation - last_angle)
	# Add to the running total
	turn_angle += delta_angle
	last_angle = rotation

这是我们在脚本开头附近设置的在允许的角度公差内旋转180度的循环。
And this is our loop for rotating through 180 degrees within the angular tolerance we set near the beginning of the script.

7.8.4 The /odom Topic versus the /odom Frame ( /odom话题与 /odom坐标系)

读者可能想知道为什么我们在之前的脚本中使用TransformListener来访问里程表信息,而不是仅订阅/ odom话题。 原因是/ odom主题上发布的数据并不总是完整的。 例如,TurtleBot使用单轴陀螺仪来提供对机器人旋转的额外估计。 通过robot_pose_ekf节点(在TurtleBot启动文件中启动)将其与车轮编码器的数据相结合,以获得比单独使用任何一个源更好的旋转估计。
The reader may be wondering why we used a TransformListener in the previous script to access odometry information rather than just subscribing to the /odom topic. The reason is that the data published on the /odom topic is not always the full story. For example, the TurtleBot uses a single-axis gyro to provide an additional estimate of the robot’s rotation. This is combined with the data from the wheel encoders by the robot_pose_ekf node (which is started in the TurtleBot launch file) to get a better estimate of rotation than either source alone.

但是,robot_pose_ekf节点不会将其数据发布回 /odom话题(/odom话题是为车轮编码器数据保留的。) 反而,将其发布在/ odom_combined话题上。 此外,数据不是作为Odometry消息发布,而是作为PoseWithCovarianceStamped消息发布。 但是,它确实发布了我们所需的从/ odom坐标系到/ base_link(或/ base_footprint)坐标系转换的信息。 因此,使用tf监视/ odom和/ base_link(或/ base_footprint)坐标系之间的转换通常比依赖/ odom消息话题更加安全。
However, the robot_pose_ekf node does not publish its data back on the /odom topic which is reserved for the wheel encoder data. Instead, it publishes it on the /odom_combined topic. Furthermore, the data is published not as an Odometry message but as a PoseWithCovarianceStamped message. It does however, publish a transform from the /odom frame to the /base_link (or /base_footprint ) frame which provides the information we need. As a result, it is generally safer to use tf to monitor the transformation between the /odom and /base_link (or /base_footprint ) frames than to rely on the /odom message topic.

在rbx1_bringup / nodes目录中,您将找到一个名为odom_ekf.py的节点,该节点将/ odom_combined话题上的PoseWithCovarianceStamped消息以Odometry类型消息重新发布在/ odom_ekf话题上。 这样做是为了使我们可以在RViz中同时查看/ odom和/ odom_ekf主题,以将TurtleBot的基于车轮的里程表与包含陀螺仪数据的组合里程表进行比较。
In the rbx1_bringup/nodes directory you will find a node called odom_ekf.py that republishes the PoseWithCovarianceStamped message found on the /odom_combined topic as an Odometry type message on the topic called /odom_ekf . This is done only so we can view both the /odom and /odom_ekf topics in RViz to compare the TurtleBot’s wheel-based odometry with the combined odometry that includes the gyro data.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【 rbx1翻译 第七章、控制移动基座】第八节、使用里程计进行往返运动 的相关文章

  • 【RealSense】L515学习记录

    Intel RealSense SDK 2 0的安装 1 注册服务器的公钥 sudo apt key adv keyserver keyserver ubuntu com recv key F6E65AC044F831AC80A06380C
  • 【YOLOv5】记录YOLOv5的学习过程

    以下记录的是Ubuntu20 04版本 xff0c 其他Ubuntu版本也相差不大 一 安装pytorch GPU版本 显卡驱动 CUDA cuDNN 下载pytorch GPU版本 xff1a 最新版本链接 xff1a Start Loc
  • 【Kinect】Ubuntu20.04 安装Azure Kinect Sensor

    本文主要记录Ubuntu20 04 安装Azure Kinect Sensor SDK Azure Kinect 人体跟踪 SDK官网 xff1a https learn microsoft com zh cn azure Kinect d
  • 【ORB_SLAM】Ubuntu20.04 配置ORB_SLAM3

    本文主要记录基于Ubuntu20 04环境下 xff0c 对普通的ORB SLAM3和稠密版本的ORB SLAM3进行环境的配置 一 配置ORB SLAM3 lt 普通版本 gt 1 安装ROS开发环境 这里采用鱼香ros的一键安装 xff
  • 【工具】记录安装Zsh

    本文主要记录下安装Zsh的过程 xff0c 方便后续换设备安装 xff01 与大家共同学习 xff01 xff08 Ubuntu 20 04 xff09 安装zsh sudo apt install zsh 2 下载oh my zsh 并安
  • 【Ubuntu】记录Ubuntu缺少启动项问题

    今天突然发现自己装的Ubuntu没有启动项 xff0c 也就是没有那个EFI分区 xff0c 人都麻了 xff01 原因是先把装Ubuntu的固态拿了出来 xff0c 再装的win11 xff0c 结果win11可以用了 xff0c Ubu
  • 【SLAM学习】基于Pangolin绘制运动轨迹

    Pangolin库 是一个轻量级的跨平台视图控制库 xff0c 主要用于可视化 交互和调试三维数据 该库提供了一系列图形界面工具 xff0c 包括窗口 OpenGL渲染器 3D相机 图像显示等 xff0c 可以方便地进行三维数据可视化和交互
  • Groovy学习-IO/文件操作

    读取文件 读取文本文件并打印每一行文本 new File 39 39 39 a txt 39 eachLine line gt println line eachLine方法是Groovy为File类自动添加的方法 xff0c 同时提供多个
  • linux---线程池种类以及实现(固定数量)

    线程池是什么 一堆固定的数量的或者有最大数量限制的线程 43 任务队列 gt 用于我们并发处理请求 xff0c 避免了大量频繁的线程的创建和销毁的事件成本 xff0c 同时避免了峰值压力带来瞬间大量线程被创建资源耗尽 xff0c 程序奔溃的
  • 什么是线程池?为什么使用线程池?

    1 什么是线程池 xff1f 线程池和数据库连接池非常类似 xff0c 可以统一管理和维护线程 xff0c 减少没有必要的开销 2 为什么要使用线程池 xff1f 因为频繁的开启线程或者停止线程 xff0c 线程需要重新从cpu从就绪状态调
  • Java实现List按条件分成多个子List

    一 业务场景 相信很多开发的小伙伴都有遇到过需要对表按特定条件进行查询 xff0c 然后再进行归类 xff0c 比如 xff1a 对员工表进行检索 xff0c 然后分别按他们所在的部门进行归类 xff0c 一般的做法都是按部门唯一标识 xf
  • MySQL生成随机姓名

    CREATE DEFINER 61 96 root 96 64 96 localhost 96 FUNCTION 96 rand name 96 n int RETURNS varchar 16 CHARSET utf8 begin 初始化
  • RabbitMQ的安装教程

    本文介绍RabbitMQ在Linxu上的安装教程 一 下载相关安装包 相应的安装包可以从官网上 xff08 https www rabbitmq com xff09 进行下载 xff0c 也可以从我的网盘上下载 蓝奏云地址 xff1a ht
  • SpringBoot实现广州健康通疫苗预约提醒

    一 前言 终于轮到了打第二针疫苗的时候 xff0c 无奈每次打开 广州健康通 或 粤康通 小程序 xff0c 每次都是被预约完的状态 xff0c 广州人口众多 xff0c 说不定有很多人一直守在小程序前等着放号 xff0c 所以这篇文章就诞
  • 搭建SFTP服务器实现文件上传

    1 前言 最近一直在做数据迁移接口的开发 xff0c 涉及到大文件的远程下载与上传 xff0c 其实倒没有什么原理可言 xff0c 无非就是两台机器互连之后 xff0c 获得文件流然后进行传输 xff0c 不过在这过程也遇到过一些小坑 xf
  • SpringBoot整合RabbitMQ实现五种消息模型

    一 什么是消息队列 xff1f 消息 xff0c 可以理解为两个应用之间传递的数据 xff0c 数据可以是基本数据类型 xff0c 也可以是对象等 消息队列 xff0c 则是容器 xff0c 生产者产生的消息存放在这个容器里面 MQ的整个过
  • SpringBoot整合CXF框架实现Webservice服务端

    1 前言 近期接手一个10多年的老项目 xff0c 敲重点 xff0c 10多年 xff01 xff01 xff01 就是最纯粹的servlet技术 xff0c 貌似是从2008年运维到现在 xff0c 老项目终究会有被淘汰的这一天 xff
  • Windows下切换不同版本JDK

    1 前言 从四月份重新入职新公司以来 xff0c 主要负责两个项目的开发 xff0c 一个是10多年前的项目 xff0c 一个是2019年开始开发的项目 xff0c 这两个项目依赖于不同版本的JDK xff0c 一个是JDK6 xff0c
  • css实现圆形div旋转,如“已预约”效果

    lt DOCTYPE html gt lt html gt lt head gt lt meta charset 61 34 utf 8 34 gt lt title gt lt title gt lt head gt lt style g
  • c++---类和对象(六大默认成员函数)

    类中默认的六个成员函数构造函数析构函数拷贝构造函数赋值操作符重载取地址和const取地址操作符重载const成员函数 1 类中默认的六个成员函数 首先看看下面代码 class A int main A a return 0 这个代码并没有报

随机推荐

  • 微服务系列--nacos注册中心与服务发现

    1 前言 终究还是到了更新关于微服务相关博客的时候了 xff0c 经过挺长一段时间微服务的自主学习 xff0c 现在不敢说自己熟悉微服务 xff0c 但我也能略知一二 微服务嘛 xff0c 其实入门之后便会发现 xff0c 其实关于微服务相
  • 微服务系列--Ribbon负载均衡

    1 前言 这篇文章接上一篇文章进行开发 xff0c 上一篇整合完了Nacos xff0c 这篇来整合Ribbon Ribbon不属于SpringCloud Alibaba的东西 xff0c 而是基于Netflix Ribbon实现的 可以让
  • Centos7安装Jenkins

    将Jenkins存储库添加到yum repos xff0c 并安装Jenkins sudo wget O etc yum repos d jenkins repo http pkg jenkins ci org redhat jenkins
  • Jenkins自动化部署SpringBoot项目

    首先需要安装所需的两个插件 xff0c Maven Integration plugin 和 Publish Over SSH 在 系统配置 xff0c 将服务器信息配置到jenkins xff0c 我用的是腾讯云服务器 xff0c 所以将
  • 优雅关闭SpringBoot项目-接口方式

    前言 一般在服务器重新部署SpringBoot项目 xff0c 无非就是用kill 9暴力停止进程 xff0c 但会造成很多数据问题 xff0c 如果遇到一些耗时或者正在处理交易类的业务时 xff0c 直接导致数据异常 xff0c 严重会导
  • Linux安装Jenkins

    前言 现在Jenkins的最新版本都需要基于JDK11以上才能够正常使用 xff0c 不然会出现各种插件安装不上的问题 又不想安装JDK11 xff0c 想继续用JDK8 xff0c 只能通过指定安装符合JDK8的Jenkins版本 PS
  • rosdep update出错解决办法(2021)

    ROS安装方法 xff1a ros安装后 xff0c 初始化时rosdep update出错解决办法 2021 06 30 初始化时rosdep update出错解决办法 2021年以前 xff0c 通过科学上网 手机开热点等方式 xff0
  • 0x0FA23729 (vcruntime140d.dll)处(位于 类和对象-封装.exe 中)引发的异常(已解决)

    运行程序的时候第42行 抛出异常 xff0c 但是我将该cpp文件放到别的解决方案下就不会出异常 include lt iostream gt include lt string gt using namespace std class P
  • Win10 摄像头:由于其配置信息(注册表中的)不完整或已损坏,Windows无法启动这个硬件设备.【未解决完全】

    问题描述 xff1a 刚刚重装完win10系统之后 xff0c 出现无法打开摄像头的问题 xff0c 解决方法 xff1a 通过修改注册表中得相关信息进行解决 首先打开设备管理器 xff0c 找到设备的类Guid记录下Guid 的值 如此处
  • 2021年总结与2022年展望

    一 工作和学习 通过调剂 xff0c 正式成为了一名研究生 xff0c 结束了自己两年的考研备考 xff0c 不知道是好还是坏 xff0c 看到周围朋友考的时候心里还是会有点失落感 在一家通信设备公司实习软件测试 xff0c 收获很多 xf
  • 计算机网络---网络基础(TCP/IP五层模型,数据的封装和分用)

    认识网络中常用的名词以及基本的概念熟悉OSI七层模型和TCP IP五层模型理解网络通信的数据传输流程 认识网络中常用的名词 ip地址 ip地址就是表示我们一台主机的因为数字不好记忆 xff0c 通常使用点分十进制表示IP xff0c 每条数
  • C语言简易TCP服务端程序

    C语言TCP服务端程序 文章目录 C语言TCP服务端程序项目介绍关键技术代码实现一请求一线程方式epoll方式实现多个客户端连接的TCP服务端程序epoll的水平触发和边缘触发 完整代码编译和启动使用NetAssist测试 项目介绍 本项目
  • C++使用gRPC实例

    什么是gRPC RPC 即远程过程调用协议 xff08 Remote Procedure Call Protocol xff09 xff0c 可以让我们像调用本地对象一样发起 远程调用 RPC 凭借其强大的治理功能 xff0c 成为解决分布
  • 复睿智行CC++开发实习面试

    线上面试 xff0c HR和一位技术的面试官 自我介绍 现在研究生学习的方向是什么 xff1f 我还去答区块链 xff0c 本来就半桶水 xff0c 还不如直接回答C C 43 43 后端这个方向 大数据分析这一块有做过吗 xff1f 我
  • 经纬恒润LinuxC++日常实习面经

    自我介绍 在学校成绩如何 xff0c 有没有获得奖学金 xff0c 考研的时间等等相关问题 能实习多久 xff0c 研究生研究的方向 你这个LinuxC 43 43 开发的学习是自学的吗 xff0c 怎样的自学途径 我 xff1a 看书 看
  • 集群聊天服务器项目(三)——负载均衡模块与跨服务器聊天

    负载均衡模块 为什么要加入负载均衡模块 原因是 xff1a 单台服务器并发量最多两三万 xff0c 不够大 负载均衡器 Nginx的用处或意义 xff08 面试题 xff09 把client请求按负载算法分发到具体业务服务器Chatserv
  • C++校招面试题

    C 43 43 static关键字的作用 xff08 从elf结构 链接的过程 xff09 答 xff1a static可以修饰全局变量 函数 局部变量 xff0c 这些符号在加了staitc后就只能在当前文件可见 xff0c 其他文件不可
  • make_shared知识点

    背景 普通创建shared ptr的方法如 xff1a shared ptr span class token operator lt span span class token keyword int span span class to
  • emplace方法原理剖析

    emplace back 和 push back 的差别 有一个类Test定义如下 span class token keyword class span span class token class name Test span span
  • 【 rbx1翻译 第七章、控制移动基座】第八节、使用里程计进行往返运动

    7 8 Out and Back Using Odometry 使用里程计进行往返运动 现在 xff0c 我们了解了里程表信息是如何在ROS中表示的 xff0c 我们可以更精确地在往返过程中移动机器人 下一个脚本将监视 odom和 base