Gazebo仿真环境下的强化学习实现

在这里插入图片描述

Gazebo仿真环境下的强化学习实现

主体源码参照《Goal-Driven Autonomous Exploration Through Deep Reinforcement Learning》

文章目录

  • Gazebo仿真环境下的强化学习实现
    • 1. 源码拉取
    • 2. 强化学习实现
      • 2.1 环境
      • 2.2 动作空间
      • 2.3 状态空间
      • 2.4 奖励空间
      • 2.5 TD3训练
    • 3. 总结

1. 源码拉取

git clone https://github.com/reiniscimurs/DRL-robot-navigation

笔者采用其强化学习方法,但是对于仿真环境以及机器人模型仍然用自己的包,源码中采用了与论文强相关的用法

2. 强化学习实现

2.1 环境

源码:

class GazeboEnv:"""Superclass for all Gazebo environments."""def __init__(self, launchfile, environment_dim):self.environment_dim = environment_dimself.odom_x = 0self.odom_y = 0self.goal_x = 1self.goal_y = 0.0self.upper = 5.0self.lower = -5.0self.velodyne_data = np.ones(self.environment_dim) * 10self.last_odom = Noneself.set_self_state = ModelState()self.set_self_state.model_name = "r1"self.set_self_state.pose.position.x = 0.0self.set_self_state.pose.position.y = 0.0self.set_self_state.pose.position.z = 0.0self.set_self_state.pose.orientation.x = 0.0self.set_self_state.pose.orientation.y = 0.0self.set_self_state.pose.orientation.z = 0.0self.set_self_state.pose.orientation.w = 1.0self.gaps = [[-np.pi / 2 - 0.03, -np.pi / 2 + np.pi / self.environment_dim]]for m in range(self.environment_dim - 1):self.gaps.append([self.gaps[m][1], self.gaps[m][1] + np.pi / self.environment_dim])self.gaps[-1][-1] += 0.03port = "11311"subprocess.Popen(["roscore", "-p", port])print("Roscore launched!")# Launch the simulation with the given launchfile namerospy.init_node("gym", anonymous=True)if launchfile.startswith("/"):fullpath = launchfileelse:fullpath = os.path.join(os.path.dirname(__file__), "assets", launchfile)if not path.exists(fullpath):raise IOError("File " + fullpath + " does not exist")subprocess.Popen(["roslaunch", "-p", port, fullpath])print("Gazebo launched!")# Set up the ROS publishers and subscribersself.vel_pub = rospy.Publisher("/r1/cmd_vel", Twist, queue_size=1)self.set_state = rospy.Publisher("gazebo/set_model_state", ModelState, queue_size=10)self.unpause = rospy.ServiceProxy("/gazebo/unpause_physics", Empty)self.pause = rospy.ServiceProxy("/gazebo/pause_physics", Empty)self.reset_proxy = rospy.ServiceProxy("/gazebo/reset_world", Empty)self.publisher = rospy.Publisher("goal_point", MarkerArray, queue_size=3)self.publisher2 = rospy.Publisher("linear_velocity", MarkerArray, queue_size=1)self.publisher3 = rospy.Publisher("angular_velocity", MarkerArray, queue_size=1)self.velodyne = rospy.Subscriber("/velodyne_points", PointCloud2, self.velodyne_callback, queue_size=1)self.odom = rospy.Subscriber("/r1/odom", Odometry, self.odom_callback, queue_size=1)

强化学习中环境用于产生状态输入,并通过智能体的动作产生新的状态,在类中设定了目标和里程计的私有域,代表了自己当前的目标点和位姿信息。
初始化方法中设置了若干发布者和订阅者
/gazebo/unpause_physics 用于在Gazebo仿真环境中取消暂停物理模拟。当Gazebo仿真环境处于暂停状态时,物理模拟会停止,仿真中的物体将不再移动或交互。通过调用 /gazebo/unpause_physics 服务,你可以使仿真环境恢复到正常运行状态,允许物理模拟继续进行。
/gazebo/pause_physics 是一个ROS服务,用于在Gazebo仿真环境中暂停物理模拟。通过调用 /gazebo/pause_physics 服务,你可以将仿真环境的物理模拟暂停,这将导致仿真中的物体停止运动,仿真时间暂停。
注意,在初始化方法中可以看出,roslaunch也是通过程序启动,节点一并启动(在本机有Anaconda的情况下会有麻烦)

2.2 动作空间

由发布者可以看出强化学习的策略的动作空间
linear_velocity:输出线速度
angular_velocity:输出角速度

2.3 状态空间

如图,作者的强化学习架构为
在这里插入图片描述其输入空间为24维向量,其中,180度扫描的激光点进行了20等分,选取每个等分区域的最小值作为显著性代表值,剩下的4维为与目标的距离、与目标的转角差、机器人的线速度、机器人的角速度

distance = np.linalg.norm([self.odom_x - self.goal_x, self.odom_y - self.goal_y])
theta = beta - angleif theta > np.pi:theta = np.pi - thetatheta = -np.pi - thetaif theta < -np.pi:theta = -np.pi - thetatheta = np.pi - theta
vel_cmd = Twist()vel_cmd.linear.x = action[0]vel_cmd.angular.z = action[1]
robot_state = [distance, theta, action[0], action[1]]
    def velodyne_callback(self, v):data = list(pc2.read_points(v, skip_nans=False, field_names=("x", "y", "z")))self.velodyne_data = np.ones(self.environment_dim) * 10for i in range(len(data)):if data[i][2] > -0.2:dot = data[i][0] * 1 + data[i][1] * 0mag1 = math.sqrt(math.pow(data[i][0], 2) + math.pow(data[i][1], 2))mag2 = math.sqrt(math.pow(1, 2) + math.pow(0, 2))beta = math.acos(dot / (mag1 * mag2)) * np.sign(data[i][1])dist = math.sqrt(data[i][0] ** 2 + data[i][1] ** 2 + data[i][2] ** 2)for j in range(len(self.gaps)):if self.gaps[j][0] <= beta < self.gaps[j][1]:self.velodyne_data[j] = min(self.velodyne_data[j], dist)break

2.4 奖励空间

在每一步仿真后都会计算奖励,奖励的准则为到达目标加200分,碰撞-100分,再根据角速度和线速度以及显著性的最小激光点进行动态调整,引导机器人

    def step(self, action):...reward = self.get_reward(target, collision, action, min_laser)return state, reward, done, targetdef get_reward(target, collision, action, min_laser):if target:return 100.0elif collision:return -100.0else:r3 = lambda x: 1 - x if x < 1 else 0.0return action[0] / 2 - abs(action[1]) / 2 - r3(min_laser) / 2   

2.5 TD3训练

采用Actor-Critic的方法进行训练,训练为常规的强化学习架构,本文按照读者有强化学习基础行进,重要的是输入的参数,要定义好维度问题。

import os
import timeimport numpy as np
import torch
import torch.nn as nn
import torch.nn.functional as F
from numpy import inf
from torch.utils.tensorboard import SummaryWriterfrom replay_buffer import ReplayBuffer
from velodyne_env import GazeboEnvdef evaluate(network, epoch, eval_episodes=10):avg_reward = 0.0col = 0for _ in range(eval_episodes):count = 0state = env.reset()done = Falsewhile not done and count < 501:action = network.get_action(np.array(state))a_in = [(action[0] + 1) / 2, action[1]]state, reward, done, _ = env.step(a_in)avg_reward += rewardcount += 1if reward < -90:col += 1avg_reward /= eval_episodesavg_col = col / eval_episodesprint("..............................................")print("Average Reward over %i Evaluation Episodes, Epoch %i: %f, %f"% (eval_episodes, epoch, avg_reward, avg_col))print("..............................................")return avg_rewardclass Actor(nn.Module):def __init__(self, state_dim, action_dim):super(Actor, self).__init__()self.layer_1 = nn.Linear(state_dim, 800)self.layer_2 = nn.Linear(800, 600)self.layer_3 = nn.Linear(600, action_dim)self.tanh = nn.Tanh()def forward(self, s):s = F.relu(self.layer_1(s))s = F.relu(self.layer_2(s))a = self.tanh(self.layer_3(s))return aclass Critic(nn.Module):def __init__(self, state_dim, action_dim):super(Critic, self).__init__()self.layer_1 = nn.Linear(state_dim, 800)self.layer_2_s = nn.Linear(800, 600)self.layer_2_a = nn.Linear(action_dim, 600)self.layer_3 = nn.Linear(600, 1)self.layer_4 = nn.Linear(state_dim, 800)self.layer_5_s = nn.Linear(800, 600)self.layer_5_a = nn.Linear(action_dim, 600)self.layer_6 = nn.Linear(600, 1)def forward(self, s, a):s1 = F.relu(self.layer_1(s))self.layer_2_s(s1)self.layer_2_a(a)s11 = torch.mm(s1, self.layer_2_s.weight.data.t())s12 = torch.mm(a, self.layer_2_a.weight.data.t())s1 = F.relu(s11 + s12 + self.layer_2_a.bias.data)q1 = self.layer_3(s1)s2 = F.relu(self.layer_4(s))self.layer_5_s(s2)self.layer_5_a(a)s21 = torch.mm(s2, self.layer_5_s.weight.data.t())s22 = torch.mm(a, self.layer_5_a.weight.data.t())s2 = F.relu(s21 + s22 + self.layer_5_a.bias.data)q2 = self.layer_6(s2)return q1, q2# TD3 network
class TD3(object):def __init__(self, state_dim, action_dim, max_action):# Initialize the Actor networkself.actor = Actor(state_dim, action_dim).to(device)self.actor_target = Actor(state_dim, action_dim).to(device)self.actor_target.load_state_dict(self.actor.state_dict())self.actor_optimizer = torch.optim.Adam(self.actor.parameters())# Initialize the Critic networksself.critic = Critic(state_dim, action_dim).to(device)self.critic_target = Critic(state_dim, action_dim).to(device)self.critic_target.load_state_dict(self.critic.state_dict())self.critic_optimizer = torch.optim.Adam(self.critic.parameters())self.max_action = max_actionself.writer = SummaryWriter()self.iter_count = 0def get_action(self, state):# Function to get the action from the actorstate = torch.Tensor(state.reshape(1, -1)).to(device)return self.actor(state).cpu().data.numpy().flatten()# training cycledef train(self,replay_buffer,iterations,batch_size=100,discount=1,tau=0.005,policy_noise=0.2,  # discount=0.99noise_clip=0.5,policy_freq=2,):av_Q = 0max_Q = -infav_loss = 0for it in range(iterations):# sample a batch from the replay buffer(batch_states,batch_actions,batch_rewards,batch_dones,batch_next_states,) = replay_buffer.sample_batch(batch_size)state = torch.Tensor(batch_states).to(device)next_state = torch.Tensor(batch_next_states).to(device)action = torch.Tensor(batch_actions).to(device)reward = torch.Tensor(batch_rewards).to(device)done = torch.Tensor(batch_dones).to(device)# Obtain the estimated action from the next state by using the actor-targetnext_action = self.actor_target(next_state)# Add noise to the actionnoise = torch.Tensor(batch_actions).data.normal_(0, policy_noise).to(device)noise = noise.clamp(-noise_clip, noise_clip)next_action = (next_action + noise).clamp(-self.max_action, self.max_action)# Calculate the Q values from the critic-target network for the next state-action pairtarget_Q1, target_Q2 = self.critic_target(next_state, next_action)# Select the minimal Q value from the 2 calculated valuestarget_Q = torch.min(target_Q1, target_Q2)av_Q += torch.mean(target_Q)max_Q = max(max_Q, torch.max(target_Q))# Calculate the final Q value from the target network parameters by using Bellman equationtarget_Q = reward + ((1 - done) * discount * target_Q).detach()# Get the Q values of the basis networks with the current parameterscurrent_Q1, current_Q2 = self.critic(state, action)# Calculate the loss between the current Q value and the target Q valueloss = F.mse_loss(current_Q1, target_Q) + F.mse_loss(current_Q2, target_Q)# Perform the gradient descentself.critic_optimizer.zero_grad()loss.backward()self.critic_optimizer.step()if it % policy_freq == 0:# Maximize the actor output value by performing gradient descent on negative Q values# (essentially perform gradient ascent)actor_grad, _ = self.critic(state, self.actor(state))actor_grad = -actor_grad.mean()self.actor_optimizer.zero_grad()actor_grad.backward()self.actor_optimizer.step()# Use soft update to update the actor-target network parameters by# infusing small amount of current parametersfor param, target_param in zip(self.actor.parameters(), self.actor_target.parameters()):target_param.data.copy_(tau * param.data + (1 - tau) * target_param.data)# Use soft update to update the critic-target network parameters by infusing# small amount of current parametersfor param, target_param in zip(self.critic.parameters(), self.critic_target.parameters()):target_param.data.copy_(tau * param.data + (1 - tau) * target_param.data)av_loss += lossself.iter_count += 1# Write new values for tensorboardself.writer.add_scalar("loss", av_loss / iterations, self.iter_count)self.writer.add_scalar("Av. Q", av_Q / iterations, self.iter_count)self.writer.add_scalar("Max. Q", max_Q, self.iter_count)def save(self, filename, directory):torch.save(self.actor.state_dict(), "%s/%s_actor.pth" % (directory, filename))torch.save(self.critic.state_dict(), "%s/%s_critic.pth" % (directory, filename))def load(self, filename, directory):self.actor.load_state_dict(torch.load("%s/%s_actor.pth" % (directory, filename)))self.critic.load_state_dict(torch.load("%s/%s_critic.pth" % (directory, filename)))# Set the parameters for the implementation
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")  # cuda or cpu
seed = 0  # Random seed number
eval_freq = 5e3  # After how many steps to perform the evaluation
max_ep = 500  # maximum number of steps per episode
eval_ep = 10  # number of episodes for evaluation
max_timesteps = 5e6  # Maximum number of steps to perform
expl_noise = 1  # Initial exploration noise starting value in range [expl_min ... 1]
expl_decay_steps = (500000  # Number of steps over which the initial exploration noise will decay over
)
expl_min = 0.1  # Exploration noise after the decay in range [0...expl_noise]
batch_size = 40  # Size of the mini-batch
discount = 0.99999  # Discount factor to calculate the discounted future reward (should be close to 1)
tau = 0.005  # Soft target update variable (should be close to 0)
policy_noise = 0.2  # Added noise for exploration
noise_clip = 0.5  # Maximum clamping values of the noise
policy_freq = 2  # Frequency of Actor network updates
buffer_size = 1e6  # Maximum size of the buffer
file_name = "TD3_velodyne"  # name of the file to store the policy
save_model = True  # Weather to save the model or not
load_model = False  # Weather to load a stored model
random_near_obstacle = True  # To take random actions near obstacles or not# Create the network storage folders
if not os.path.exists("./results"):os.makedirs("./results")
if save_model and not os.path.exists("./pytorch_models"):os.makedirs("./pytorch_models")# Create the training environment
environment_dim = 20
robot_dim = 4
env = GazeboEnv("multi_robot_scenario.launch", environment_dim)
time.sleep(5)
torch.manual_seed(seed)
np.random.seed(seed)
state_dim = environment_dim + robot_dim
action_dim = 2
max_action = 1# Create the network
network = TD3(state_dim, action_dim, max_action)
# Create a replay buffer
replay_buffer = ReplayBuffer(buffer_size, seed)
if load_model:try:network.load(file_name, "./pytorch_models")except:print("Could not load the stored model parameters, initializing training with random parameters")# Create evaluation data store
evaluations = []timestep = 0
timesteps_since_eval = 0
episode_num = 0
done = True
epoch = 1count_rand_actions = 0
random_action = []# Begin the training loop
while timestep < max_timesteps:# On termination of episodeif done:if timestep != 0:network.train(replay_buffer,episode_timesteps,batch_size,discount,tau,policy_noise,noise_clip,policy_freq,)if timesteps_since_eval >= eval_freq:print("Validating")timesteps_since_eval %= eval_freqevaluations.append(evaluate(network=network, epoch=epoch, eval_episodes=eval_ep))network.save(file_name, directory="./pytorch_models")np.save("./results/%s" % (file_name), evaluations)epoch += 1state = env.reset()done = Falseepisode_reward = 0episode_timesteps = 0episode_num += 1# add some exploration noiseif expl_noise > expl_min:expl_noise = expl_noise - ((1 - expl_min) / expl_decay_steps)action = network.get_action(np.array(state))action = (action + np.random.normal(0, expl_noise, size=action_dim)).clip(-max_action, max_action)# If the robot is facing an obstacle, randomly force it to take a consistent random action.# This is done to increase exploration in situations near obstacles.# Training can also be performed without itif random_near_obstacle:if (np.random.uniform(0, 1) > 0.85and min(state[4:-8]) < 0.6and count_rand_actions < 1):count_rand_actions = np.random.randint(8, 15)random_action = np.random.uniform(-1, 1, 2)if count_rand_actions > 0:count_rand_actions -= 1action = random_actionaction[0] = -1# Update action to fall in range [0,1] for linear velocity and [-1,1] for angular velocitya_in = [(action[0] + 1) / 2, action[1]]next_state, reward, done, target = env.step(a_in)done_bool = 0 if episode_timesteps + 1 == max_ep else int(done)done = 1 if episode_timesteps + 1 == max_ep else int(done)episode_reward += reward# Save the tuple in replay bufferreplay_buffer.add(state, action, reward, done_bool, next_state)# Update the countersstate = next_stateepisode_timesteps += 1timestep += 1timesteps_since_eval += 1# After the training is done, evaluate the network and save it
evaluations.append(evaluate(network=network, epoch=epoch, eval_episodes=eval_ep))
if save_model:network.save("%s" % file_name, directory="./models")
np.save("./results/%s" % file_name, evaluations)

3. 总结

实际上利用Gazebo进行强化学习无非是环境获取上的不同,Gazebo的环境控制需要使用ROS服务进行控制,状态可以通过Gazebo进行获取,同时某些必要数据需要从话题中获取,最重要的是组织获取 的数据(通过话题等)与控制Gazebo的仿真步骤之间的组合。
强化学习的手段与传统算法无异,强化学习方法最重要的是要确定动作空间、状态空间、奖励空间,这三个空间是work的前提。
在笔者自己的环境中,将获取里程计的话题以及获取激光点的数据替换成为了自己的本机的仿真环境匹配的话题。

 self.point_cloud = rospy.Subscriber("/scan", LaserScan, self.laser_callback, queue_size=1)self.odom = rospy.Subscriber("/odom", Odometry, self.odom_callback, queue_size=1)self.frontiers_sub = rospy.Subscriber("/frontiers", Marker, self.frontiers, queue_size=1)self.center_frontiers_sub = rospy.Subscriber("/center_frontiers", Marker, self.center_frontiers, queue_size=1)

与Gazebo仿真环境相关的话题有很多,用于在ROS中与仿真环境进行通信和交互。以下是一些常见的与Gazebo相关的话题以及它们的作用:

/gazebo/model_states:这个话题发布了所有仿真中模型的状态信息,包括它们的位置、姿态、线速度、角速度等。

/gazebo/link_states:类似于 /gazebo/model_states,但是发布了模型的每个链接的状态信息,适用于多链接模型。

/gazebo/set_model_state:这是一个用于设置模型状态的话题。通过向该话题发送消息,你可以控制模型的位置、姿态等属性。

/gazebo/set_link_state:类似于 /gazebo/set_model_state,但用于设置链接的状态,允许你更精细地控制模型的不同部分。

/gazebo/unpause_physics/gazebo/pause_physics:这些话题用于控制仿真的暂停和继续。通过向 /gazebo/unpause_physics 发送请求,可以取消暂停仿真物理模拟,而通过向 /gazebo/pause_physics 发送请求,可以将仿真暂停。

/gazebo/reset_world/gazebo/reset_simulation:这些话题用于重置仿真环境。 /gazebo/reset_world 用于重置仿真世界的状态,而 /gazebo/reset_simulation 用于重置仿真整个仿真会话的状态。

/gazebo/delete_model:通过向这个话题发送消息,你可以请求删除指定名称的模型,从仿真环境中移除它。

/gazebo/spawn_sdf_model/gazebo/spawn_urdf_model:这些话题用于在仿真环境中生成新的SDF或URDF模型。通过向这些话题发送消息,你可以在仿真环境中动态生成模型。

/gazebo/apply_body_wrench:这个话题用于对仿真环境中的物体施加力或扭矩,以模拟外部力或操作。

/gazebo/camera/*:用于模拟相机传感器,例如 /gazebo/camera/image 可以获取相机的图像数据。

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

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

相关文章

简述SpringMVC

一、典型的Servlet JSP JavaBean UserServlet看作业务逻辑处理&#xff08;Controller&#xff09;User看作模型&#xff08;Model&#xff09;user.jsp看作渲染&#xff08;View&#xff09; 二、高级MVC 由DispatcherServlet对请求统一处理 三、SpringMVC MVC与Spr…

springboot实战(四)之整合mybatis-plus

目录 环境&#xff1a; 准备&#xff1a; 开始&#xff1a; 1.创建表t_user 2.项目添加依赖 3.配置 1.配置mysql链接信息 2.在启动类配置mapper扫描路径 4.创建实体类 5.创建mapper 6.测试 环境&#xff1a; jdk&#xff1a;1.8 springboot版本&#xff1a;2.7.15…

面试题-React(七):React组件通信

在React开发中&#xff0c;组件通信是一个核心概念&#xff0c;它使得不同组件能够协同工作&#xff0c;实现更复杂的交互和数据传递。常见的组件通信方式&#xff1a;父传子和子传父 一、父传子通信方式 父组件向子组件传递数据是React中最常见的一种通信方式。这种方式适用…

VMware tools的安装以及按钮灰色的解决方法

VMware tools的安装 ** 注意&#xff1a;** 新版本的 VMware 会自动安装的 VMware tools&#xff0c;如何测试 VMware tools 呢&#xff1f;在Windows 系统里复制一段话&#xff0c;能粘贴到 Ubuntu 系统里终端里&#xff0c;说明 VMware tools 已经安装了。 没有安装的请参考…

问道管理:暂停交易!港交所最新宣布,北向资金也受影响!大涨超180%

今日上午A股商场全体涨跌互现&#xff0c;煤炭板块涨幅居前。新股方面也体现较好&#xff0c;有一只新股盘中一度暴涨超越180%。 别的&#xff0c;飓风“苏拉”对股市也产生了影响。港交所最新公告称&#xff0c;因为八号飓风信号现正收效&#xff0c;今日&#xff08;星期五&…

抢先体验|乐鑫推出 ESP32-S3-BOX-3 新一代开源 AIoT 开发套件

乐鑫科技 (688018.SH) 非常高兴地宣布其开发套件阵容的最新成员 ESP32-S3-BOX-3。这款完全开源的 AIoT 应用开发套件搭载乐鑫高性能 ESP32-S3 AI SoC&#xff0c;旨在突破传统开发板&#xff0c;成为新一代开发工具的引领者。 【乐鑫新品抢先体验】ESP32-S3-BOX-3 新一代开源 A…

代码随想录刷题笔记 (python版本) 持续更新.....

代码随想录刷题笔记总结: https://www.programmercarl.com/ 个人学习笔记 如有错误欢迎指正交流1. 数组 1.1 理论基础 详细介绍:https://www.programmercarl.com/%E6%95%B0%E7%BB%84%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.html 数组下标都是从0开始的。数组内存空间的地址是…

jmeter单接口和多接口测试

最近接触到了多接口串联&#xff0c;接口串联的技术会在其他帖子有说明&#xff0c;其核心技术点就是通过正则表达式和变量来实现接口的关联。目前为止呢笔者用到的地方还只有一个&#xff0c;就是关于session保持的时候。但是看到很多资料都说测试过程中经常遇到b接口需要用a接…

jvm 新生代的区域划分

虚拟机将内存分为一块较大的 Eden 空间和两块较小的 Survivor 空间&#xff0c;每次分配内存只使用 Eden 和其中一块 Survivor。发生垃圾收集时&#xff0c;将 Eden 和 Survivor 中仍然存活的对象一次性复制到另外一块 Survivor 空间上&#xff0c;然后直接清理掉 Eden 和已用过…

【学习笔记】计算机视觉对比学习综述

计算机视觉对比学习综述 前言百花齐放InstDiscInvaSpreadCPCCMC CV双雄MoCoSimCLRMoCo v2SimCLR v2SwAV 不用负样本BYOLSimSiam TransformerMoCo v3DINO 总结参考链接 前言 本篇对比学习综述内容来自于沐神对比学习串讲视频以及其中所提到的论文和博客&#xff0c;对应的链接详…

Scikit-Learn 和深度学习怎么选择

大家好&#xff0c;今天我们要聊聊一个机器学习的话题&#xff1a;Scikit-Learn 和深度学习&#xff0c;到底哪一个更适合解决你的问题&#xff1f;我们先来看看这两种技术的异同点&#xff0c;然后再讲讲如何在实际问题中做出选择。 1. Scikit-Learn 与深度学习&#xff1a;谁…

java+springboot+mysql校园跑腿管理系统

项目介绍&#xff1a; 使用javaspringbootmysql开发的校园跑腿管理系统&#xff0c;系统包含超级管理员&#xff0c;系统管理员、用户角色&#xff0c;功能如下&#xff1a; 超级管理员&#xff1a;管理员管理&#xff1b;用户管理&#xff08;充值&#xff09;&#xff1b;任…

C++面试题(叁)---操作系统篇

目录 操作系统篇 1 Linux中查看进程运行状态的指令、查看内存使用情况的指令、 tar解压文件的参数。 2 文件权限怎么修改 3 说说常用的Linux命令 4 说说如何以root权限运行某个程序。 5 说说软链接和硬链接的区别。 6 说说静态库和动态库怎么制作及如何使用&#xff0c;区…

自动化实时在线静电监控系统的构成

自动化实时在线静电监控系统是一种帮助企业监测和管理静电问题的技术解决方案。静电在许多工业和商业环境中都是一个潜在的风险和生产问题。通过使用这样的监控系统&#xff0c;企业可以及时发现并采取对策来预防或减轻可能的静电问题。 该系统通常由以下组成部分构成&#xf…

三、定长内存池

三、定长内存池 我们知道申请内存使用的是malloc&#xff0c;malloc其实就是一个通用的大众货&#xff0c;什么场景下都可以使用&#xff0c;而什么场景下都可以用就意味着什么场景下都不会有很高的性能&#xff0c;下面我们就先来设计一个定长内存池作为一个开胃菜&#xff0…

linux字符串处理

目录 1. C 截取字符串,截取两个子串中间的字符串linux串口AT指令 2. 获取该字符串后面的字符串用 strstr() 函数查找需要提取的特定字符串&#xff0c;然后通过指针运算获取该字符串后面的字符串用 strtok() 函数分割字符串&#xff0c;找到需要提取的特定字符串后&#xff0c;…

简单使用_matlab生成数据帧

文章目录 生成数据帧参考 生成数据帧 代码如下&#xff0c;代码很简单&#xff0c;有几点要注意&#xff0c; 较高版本的MATLAB中支持0x的写法使用bitand进行位运算使用strcat函数进行字符串拼接时&#xff0c;如果需要插入空格&#xff0c;要使用双引号 cmd_ay(1) 0x33; …

硬件性能评估指标-DMIPS、MFLOPS、MAC、TOPS

硬件性能评估指标-DMIPS、MFLOPS、MAC、TOPS DMIPS&#xff08;Dhrystone Million Instructions Per Second&#xff09;&#xff1a; DMIPS用于衡量计算机系统的整体指令执行性能&#xff0c;通常关注整数操作。它基于Dhrystone基准测试来计算&#xff0c;该测试主要包含整数运…

需求管理系统大盘点,谁能问鼎行业王者宝座?

“需求管理系统有哪些&#xff1f;这些品牌引领行业新风潮&#xff1a;Zoho Projects、SAP SuccessFactors、Oracle NetSuite、Microsoft Dynamics 365、Infor CloudSuite、JDA Software。” 需求管理系统是一种专门用于收集、分析和跟踪客户需求的工具&#xff0c;可以帮助企业…

总线:特性、分类、性能指标、系统总线的结构、总线仲裁、总线定时、总线标准

总线&#xff08;Bus&#xff09;&#xff0c;是一组为各功能部件之间进行信息传送的公共线路。 总线的特性&#xff1a; 机械特性&#xff08;物理特性&#xff09;&#xff1a;尺寸、形状、引脚数、排列顺序。电气特性&#xff1a;每根信号线上的信号传输方向、表示信号有效…