强化学习环境 - robogym - 学习 - 3

news2024/11/16 13:29:55

强化学习环境 - robogym - 学习 - 3

文章目录

  • 强化学习环境 - robogym - 学习 - 3
    • 项目地址
    • 为什么选择 robogym
    • Observation - 观测信息
    • Action - 动作信息
    • Initialization - 初始状态设置

项目地址

https://github.com/openai/robogym

为什么选择 robogym

  1. 自己的项目需要做一些机械臂 table-top 级的多任务操作

  2. robogym 基于 mujoco 搭建,构建了一个仿真机械臂桌面物体操作(pick-place、stack、rearrange)场景

  3. robogym 的例程效果看,支持多个相机示教,包括眼在手上和眼在手外,可以获取多视角视觉信息

  4. robogym 的物体支持 YCB 数据集格式

主要是这些原因,当然,看官方 readme.md 文档,它还有其他不错的功能。

国内主流社区对 robogym 的介绍比较少,所以选择写一些文档记录一下,作为参考。

Observation - 观测信息

robogym 的观测一般通过 obs = env.reset() 返回即可得到。爬源码可得到 obs 是一个字典。

把字典的键排序按照值的方法进行了简答的分类,可以得到:仿真环境的 obs 字典是通过:self.mujoco_simulationrobot_obsself._goalself._goal_info_dictnp.array 四个变量得到的。

obs = {
    		# 读取 self.mujoco_simulation 内部的方法返回作为值
            "obj_pos": self.mujoco_simulation.get_object_pos(),
            "obj_rel_pos": self.mujoco_simulation.get_object_rel_pos(),
            "obj_vel_pos": self.mujoco_simulation.get_object_vel_pos(),
            "obj_rot": self.mujoco_simulation.get_object_rot(),
            "obj_vel_rot": self.mujoco_simulation.get_object_vel_rot(),
    		"qpos": self.mujoco_simulation.qpos,
    		"obj_gripper_contact": self.mujoco_simulation.get_object_gripper_contact(),
            "obj_bbox_size": self.mujoco_simulation.get_object_bounding_box_sizes(),
            "obj_colors": self.mujoco_simulation.get_object_colors(),
    
    		# 在代码上面实例化了
    		# robot_obs = self.mujoco_simulation.robot.observe()
    		# 这个实例,这部分的键对应的值就是 robot_obs 的方法
            "robot_joint_pos": robot_obs.joint_positions(),
            "gripper_pos": robot_obs.tcp_xyz(),
            "gripper_velp": robot_obs.tcp_vel(),
            "gripper_controls": robot_obs.gripper_controls(),
            "gripper_qpos": robot_obs.gripper_qpos(),
            "gripper_vel": robot_obs.gripper_vel(),
    		"tcp_force": robot_obs.tcp_force(),
            "tcp_torque": robot_obs.tcp_torque(),
    
            # self._goal 从源码来看就是每个物体重排列的位置。
    		
            "qpos_goal": self._goal["qpos_goal"].copy(),
            "goal_obj_pos": self._goal["obj_pos"].copy(),
            "goal_obj_rot": self._goal["obj_rot"].copy(),
            "rel_goal_obj_pos": self._goal_info_dict["rel_goal_obj_pos"].copy(),
            "rel_goal_obj_rot": self._goal_info_dict["rel_goal_obj_rot"].copy(),
            
    		"is_goal_achieved": np.array([self._is_goal_achieved], np.int32),
            "safety_stop": np.array([robot_obs.is_in_safety_stop()]),
            
        }

这里列出了每个键对应的含义。

observation 键名每个键的意义
object_posGet position for all objects.
object_rel_posGet position for all objects relative to the gripper position.
object_vel_posGet position velocity for all objects relative to tooltip velocity.
object_rotGet rotation in euler angles for all objects.
object_vel_rotGet rotation velocity for all objects.
robot_joint_posArray of joint angles (one for each joint).
gripper_posTooltip position in the Cartesian coordinate space.
gripper_velpTooltip velocity in the Cartesian coordinate space.
gripper_controlsGripper’s linear target position.
gripper_qposGripper joint positions.
gripper_velGripper joint velocities.
qposCopy of full sim qpos including 3D-position and 4D-quaternion.
qpos_goalCopy of full sim goal qpos including 3D-position and 4D-quaternion.
goal_obj_posGet current-goal positions for all objects.
goal_obj_rotGet current-goal rotations in euler angles for all objects.
is_goal_achievedReturn if current goal is achieved.
rel_goal_obj_posGet current-goal positions for all objects relative to the gripper position.
rel_goal_obj_rotGet current-goal rotations for all objects relative to the gripper position.
obj_gripper_contactA numpy array of shape [num objects, len(other_geom_ids)], in which each value is binary, 1 meaning having contact and 0 no contact.
obj_bbox_sizeReturns the bounding box for one objects as a tuple of (positive, half size), where both positive and half size are np.array of shape (3,).
obj_colorsThis logic works, assuming only assign a single color to one object.
safety_stopTrue if the arm is in a safety stop, False otherwise.
tcp_forceTCP force in world coordinates.
tcp_torqueTCP torque in world coordinates.

根据自己的项目,选择:

  • object_posobject_rot ,代表了每个物体的位置和姿态;
  • gripper_posgripper_controls ,代表了机械臂的位置和张开闭合程度;
  • goal_obj_posgoal_obj_rot ,代表了每个物体的目标位置和目标姿态。

需要精简一下观测的信息,有三种思路:

  1. 爬源码,把不必要的观测信息直接注释掉;

    【注意】 一些项目中会在 observation 生成后再对里面的键做处理,这样做会导致一些bug!!

  2. 利用 Open AI Gym 的 FilterObservation() 这个类过滤掉不想要的键;

  3. 自己写一个函数,把不必要的键过滤掉;

    【注意】 .reset().step() 的返回都需要进行这样的操作!!

这里我选择自己写一个函数。

# create a small util to filter the observation
def filter_obs(raw_obs: dict, name_list: list) -> dict:
    result = {}
    for name in name_list:
        result[name] = copy.copy(raw_obs[name])
    return result

最后的代码如下。选择 pprint.pprint() 进行输出可以更加格式化。

import copy
import pprint
from robogym.envs.rearrange.ycb import make_env


# create a small util to filter the observation
def filter_obs(raw_obs: dict, name_list: list) -> dict:
    result = {}
    for name in name_list:
        result[name] = copy.copy(raw_obs[name])
    return result


# Create an environment with the default number of objects: 5
env = make_env(
    parameters={
        'simulation_params': {
            'num_objects': 3,
            'max_num_objects': 8,
        }
    }
)

# Reset to randomly generate an environment with `num_objects: 3`
obs = env.reset()
obs = filter_obs(obs, ["obj_pos", "obj_rot", "gripper_pos", "gripper_controls", "goal_obj_pos", "goal_obj_rot"])
pprint.pprint(obs)

while True:
    a = env.action_space.sample()
    next_obs, reward, done, info = env.step(a)
    next_obs = filter_obs(next_obs, ["obj_pos", "obj_rot", "gripper_pos", "gripper_controls", "goal_obj_pos", "goal_obj_rot"])
    pprint.pprint(next_obs)
    env.render()

得到结果:

{'goal_obj_pos': array([[1.39363232, 0.86174547, 0.51221652],
       [1.57460708, 0.70375038, 0.50919097],
       [1.20793525, 0.8834796 , 0.49350575],
       [0.        , 0.        , 0.        ],
       [0.        , 0.        , 0.        ],
       [0.        , 0.        , 0.        ],
       [0.        , 0.        , 0.        ],
       [0.        , 0.        , 0.        ]]),
 'goal_obj_rot': array([[ 0.        ,  0.        , -1.79725862],
       [ 0.        ,  0.        , -1.13518178],
       [ 0.        ,  0.        , -2.40479252],
       [ 0.        ,  0.        ,  0.        ],
       [ 0.        ,  0.        ,  0.        ],
       [ 0.        ,  0.        ,  0.        ],
       [ 0.        ,  0.        ,  0.        ],
       [ 0.        ,  0.        ,  0.        ]]),
 'gripper_controls': array([0.]),
 'gripper_pos': array([1.23887261, 0.43994768, 0.68622718]),
 'obj_pos': array([[1.59604171, 0.81327296, 0.51217642],
       [1.57460711, 0.41286039, 0.50922118],
       [1.40990736, 0.64130153, 0.49354594],
       [0.        , 0.        , 0.        ],
       [0.        , 0.        , 0.        ],
       [0.        , 0.        , 0.        ],
       [0.        , 0.        , 0.        ],
       [0.        , 0.        , 0.        ]]),
 'obj_rot': array([[-8.89659174e-05, -7.47313090e-05, -1.79530140e+00],
       [-3.00692282e-06,  4.73572520e-06, -1.13518163e+00],
       [-4.85122664e-02, -4.51887581e-02, -2.40575071e+00],
       [ 0.00000000e+00,  0.00000000e+00,  0.00000000e+00],
       [ 0.00000000e+00,  0.00000000e+00,  0.00000000e+00],
       [ 0.00000000e+00,  0.00000000e+00,  0.00000000e+00],
       [ 0.00000000e+00,  0.00000000e+00,  0.00000000e+00],
       [ 0.00000000e+00,  0.00000000e+00,  0.00000000e+00]])}

为什么 'goal_obj_rot' 这部分只有第三个元素有数值,前面两个没数值?

原因是这是用 rpy 格式描述姿态的。这三个元素依次表示roll 、 pitch 和 yaw 角。如下图所示。

111

而 table-top 级的物体都是“平躺”的,所以默认 yaw 角有姿态。

在上述打印出来的字典可以看到,当忽略很小的小数(-3.00692282e-06)时,目标姿态和当前物体姿态差别不大,这说明在当前环境中,只需要机械臂做细致的平移就行。

Action - 动作信息

robogym 的动作空间比较特殊:它通过一层 wrapper 把原本 [ − 1 , 1 ] [-1,1] [1,1] 数值的动作空间给离散化了:在 ~/robogym/robogym/wrappers/utils.py 里面 DiscretizeActionWrapper 把奖励值做了封装,通过离散数值索引一个列表 [-1. -0.8 -0.6 -0.4 -0.2 0. 0.2 0.4 0.6 0.8 1. ] ,获得机械臂TCP末端的偏移量,前面三维度分别是 xyz,后面两个维度是姿态角,最后一个维度是夹爪的开闭(但是测试效果是夹爪开闭似乎无效,可能是因为这是 rearrange 环境,对物体的操作更多是“push”而不是“pick-and-place”)。

【注意】在这样的默认包装下,保持机械臂末端位姿不动的动作向量是:a = np.asarray([5, 5, 5, 5, 5, 5]) 可以设置一个全局参数保存这个动作向量。

【注意】a = np.asarray([0, 0, 0, 0, 0, 0]) 不是静止的向量,相反,它是偏移最大的动作向量!

Initialization - 初始状态设置

好的初始状态既能完成更好的实验,也能在做成视频的时候更美观些。对于机械臂 rearrange 环境,设置初始状态的函数是在 ~/robogym/robogym/envs/rearrange/common/base.py 文件里面 RearrangeEnv 类的 _randomize_robot_initial_position() 函数中。函数中是通过设置末端TCP的初始位姿来进行状态初始化的。

action = self.action_space.sample()
if self.parameters.n_random_initial_steps < 1:
    return
for _ in range(self.parameters.n_random_initial_steps):
    self._set_action(action)
    self.mujoco_simulation.step()
self._set_action(action * 0.0)
for _ in range(100):
    # calling set_action each tick is necessary 
    # for the robot to reach stability with relative actions
    self._set_action(action * 0.0)
    self.mujoco_simulation.step()

print(self.mujoco_simulation.get_qpos('robot0:arm_joint_angles'))

里面用到了这个类中实例过的mujoco接口 mujoco_simulation 。这里的mujoco接口保留了大量 mujoco-py 的方法,可以爬源码看到都有哪些函数方法可以调用。

class SimulationInterface:
    """
    Base class for domain-specific simulation interfaces tied to particular XML.

    Goal is to transform code interfacing with generic `MjSim` that looks like that:

    hand_angles = sim.data.qpos[hand_angle_idx]
    cube_pos = sim.data.qpos[cube_pos_idx]
    sim.model.actuator_gainprm[actuator_idx] = actuator_kps
    sim.model.actuator_biasprm[actuator_idx] = actuator_kps

    Into more high-level and domain-specific version:

    hand_angles = sim.hand.get_angles()
    cube_pos = sim.get_cube_pos()
    sim.set_actuator_kp(actuator_kps)

    Etc.

    This is a base class that just exposes a few generic utilities to help the subclasses
    implement the abovementioned functionality. By convention, the subclasses should be named
    <Something>Simulation.
    """

    __slots__ = [
        "sim",
        "qpos_idxs",
        "qvel_idxs",
        "synchronization_points",
        "_mujoco_viewer",
    ]

    def __init__(self, sim: MjSim):
        self.sim = sim

        self.qpos_idxs: Dict[str, List[int]] = {}
        self.qvel_idxs: Dict[str, List[int]] = {}

        self.synchronization_points = []  # type: ignore

        self._mujoco_viewer = None

    @property
    def mj_sim(self):
        """ MuJoCo simulation object - alias to make it clearer """
        return self.sim

    @property
    def mujoco_viewer(self):
        """
        Get a nicely-interactive version of the mujoco viewer
        """
        if self._mujoco_viewer is None:
            # Inline import since this is only relevant on platforms
            # which have GLFW support.
            from mujoco_py.mjviewer import MjViewer  # noqa

            self._mujoco_viewer = MjViewer(self.sim)

        return self._mujoco_viewer

    def enable_pid(self):
        """ Enable our custom PID controller code for the actuators with 'user' type """
        cymj.set_pid_control(self.sim.model, self.sim.data)

    ########################################################################################
    # SUBCLASS REGISTRATION
    def register_joint_group(self, group_name, prefix):
        """ Finds and collect joint ids for given joint name prefix or a list of prefixes. """
        if isinstance(prefix, str):
            self.qpos_idxs[group_name] = joint_qpos_ids_from_prefix(
                self.sim.model, prefix
            )
            self.qvel_idxs[group_name] = joint_qvel_ids_from_prefix(
                self.sim.model, prefix
            )
        elif isinstance(prefix, list):
            self.qpos_idxs[group_name] = list(
                it.chain.from_iterable(
                    joint_qpos_ids_from_prefix(self.sim.model, p) for p in prefix
                )
            )
            self.qvel_idxs[group_name] = list(
                it.chain.from_iterable(
                    joint_qvel_ids_from_prefix(self.sim.model, p) for p in prefix
                )
            )

    def register_joint_group_by_name(self, group_name, name):
        """ Finds and collect joint ids for given joint name or list of names. """
        if isinstance(name, str):
            self.qpos_idxs[group_name] = joint_qpos_ids(self.sim.model, name)
            self.qvel_idxs[group_name] = joint_qvel_ids(self.sim.model, name)
        elif isinstance(name, list):
            self.qpos_idxs[group_name] = list(
                it.chain.from_iterable(joint_qpos_ids(self.sim.model, n) for n in name)
            )
            self.qvel_idxs[group_name] = list(
                it.chain.from_iterable(joint_qvel_ids(self.sim.model, n) for n in name)
            )

    ########################################################################################
    # GET DATA OUT OF SIM
    def get_qpos(self, group_name):
        """ Gets qpos for a particular group. """
        return self.sim.data.qpos[self.qpos_idxs[group_name]]

    def get_qpos_dict(self, group_names):
        """ Gets qpos dictionary for multiple groups. """
        return {k: self.get_qpos(k) for k in group_names}

    def get_qvel(self, group_name):
        """ Gets qvel for a particular group. """
        return self.sim.data.qvel[self.qvel_idxs[group_name]]

    def get_qvel_dict(self, group_names):
        """ Gets qpos dictionary for multiple groups. """
        return {k: self.get_qvel(k) for k in group_names}

    @property
    def qpos(self):
        """ Returns. copy of full sim qpos. """
        return self.sim.data.qpos.copy()

    @property
    def qvel(self):
        """ Returns copy of full sim qvel. """
        return self.sim.data.qvel.copy()

    def get_state(self) -> MjSimState:
        return self.sim.get_state()

    ########################################################################################
    # SET DATA IN SIM
    def set_qpos(self, group_name, value):
        """ Sets qpos for a given group. """
        self.sim.data.qpos[self.qpos_idxs[group_name]] = value

    def set_qvel(self, group_name, value):
        """ Sets qpos for a given group. """
        self.sim.data.qvel[self.qvel_idxs[group_name]] = value

    def add_qpos(self, group_name, value):
        """ Sets qpos for a given group. """
        self.sim.data.qpos[self.qpos_idxs[group_name]] += value

    def set_state(self, state: MjSimState):
        self.sim.set_state(state)

    ########################################################################################
    # INTERFACE TO UNDERLYING SIM
    def step(self, with_udd=True):
        """
        Advances the simulation by calling ``mj_step``.

        If ``qpos`` or ``qvel`` have been modified directly, the user is required to call
        :meth:`.forward` before :meth:`.step` if their ``udd_callback`` requires access to MuJoCo
        state set during the forward dynamics.
        """
        self.sim.step(with_udd=with_udd)
        self.sim.forward()

        # To potentially communicate with other processes
        for point in self.synchronization_points:
            point.synchronize()

    def reset(self):
        """
        Resets the simulation data and clears buffers.
        """
        self.sim.reset()

    def set_constants(self):
        """
        Sets the derived constants of the mujoco simulation.
        """
        self.sim.set_constants()

    def forward(self):
        """
        Computes the forward kinematics. Calls ``mj_forward`` internally.
        """
        self.sim.forward()

    def render(
        self,
        width=None,
        height=None,
        *,
        camera_name=None,
        depth=False,
        mode="offscreen",
        device_id=-1
    ):
        """
        Renders view from a camera and returns image as an `numpy.ndarray`.

        Args:
        - width (int): desired image width.
        - height (int): desired image height.
        - camera_name (str): name of camera in model. If None, the free
            camera will be used.
        - depth (bool): if True, also return depth buffer
        - device (int): device to use for rendering (only for GPU-backed
            rendering).

        Returns:
        - rgb (uint8 array): image buffer from camera
        - depth (float array): depth buffer from camera (only returned
            if depth=True)
        """
        return self.sim.render(
            width=width,
            height=height,
            camera_name=camera_name,
            depth=depth,
            mode=mode,
            device_id=device_id,
        )

    ########################################################################################
    # PROPERTIES
    @property
    def n_substeps(self):
        """ Number of substeps in the mujoco sim """
        return self.sim.nsubsteps

在这里,我主要通过单步调试,实现一个关节角的初始化。具体做法是:注释掉上面初始化状态的代码,写入自己的代码:

from math import pi

print(self.mujoco_simulation.qpos_idxs.keys())
self.mujoco_simulation.set_qpos('robot0:arm_joint_angles',np.asarray([1.5 * 0.5 * pi, -0.5 * pi, 1.5 * 0.5 * pi,-1.74529567, -4.18881842, 2.35619837]))

self.mujoco_simulation.step()

结果现实,代码可以运行。效果如下:

222

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

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

相关文章

04.数据解析之css选择器

1、常见数据类型 结构化的数据是指可以使用关系型数据库表示和存储&#xff0c;表现为二维形式的数据。一般特点是&#xff1a;数据以行为单位&#xff0c;一行数据表示一个实体的信息&#xff0c;每一行数据的属性是相同的。 1、1 结构化数据 ​ 结构化的数据是指可以使用关…

策略模式与模板方法结合案例

一、背景 上周在迁移项目MQ工程的时候&#xff0c;重新Review代码&#xff0c;发现有一段代码综合使用了策略模式和模板方法&#xff0c;下面讲解一下具体场景应用的思路。 二、模板方法 策略模式前段时间有一个关于库存具体案例&#xff0c;详见 库存管理与策略模式。 模板…

智能银行卡明细筛选与统计,轻松掌握账户总花销!

作为现代生活的重要组成部分&#xff0c;银行卡成为了我们日常消费和收入的主要途径。但是&#xff0c;当我们需要了解自己的银行卡账户的总花销时&#xff0c;繁琐的明细筛选和统计工作常常让人头疼。现在&#xff0c;让我们向您推荐一款智能银行卡明细筛选与统计工具&#xf…

基于SpringBoot的学生选课系统

基于SpringBoot的学生选课系统的设计与实现&#xff0c;前后端分离 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringBootMyBatisVue工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 前台主页 登录界面 管理员界面 教师界面 学生界面 摘要 学生选课系统…

halcon 数字识别

文章目录 素材交互选取区域阈值分割特征提取识别字符显示全部代码 素材 dev_get_window(WindowHandle) **读取图像 read_image(Image,C:/Users/Augustine/Desktop/1.png) **把图像转正&#xff0c;镜像方式 mirror_image(Image,ImageMirror,row) mirror_image(ImageMirror,Imag…

Python 无废话-基础知识面向对象编程详解

类定义 如何理解万物皆对象&#xff1f; 生活中一些事物&#xff0c;动物&#xff08;可爱的小狗、调皮的小猫&#xff09;、交通工具&#xff08;比亚迪U8汽车、飞机&#xff09;、人&#xff08;学生、教师&#xff09;…… 这些对象都有着独特或共性的属性和方法来描述其…

Android:实现Camera前后双摄

效果展示 一.概述 本博文讲解如何实现手机前后两颗摄像头同时预览并显示 我之前博文《OpenGLES&#xff1a;GLSurfaceView实现Android Camera预览》对单颗摄像头预览做过详细讲解&#xff0c;而前后双摄实现原理其实也并不复杂&#xff0c;粗糙点说就是把单摄像头预览流程写两…

Pytorch之MobileNetV3图像分类

&#x1f482; 个人主页:风间琉璃&#x1f91f; 版权: 本文由【风间琉璃】原创、在CSDN首发、需要转载请联系博主&#x1f4ac; 如果文章对你有帮助、欢迎关注、点赞、收藏(一键三连)和订阅专栏哦 前言 由于传统卷积神经网络&#xff0c; 内存需求大、 运算量大导致无法在移动…

多线程JUC

文章目录 多线程一.什么是多线程二.多线程的两个概念三.线程的实现方式四.常见的成员方法五.线程安全的问题六.死锁七.生产者和消费者 多线程 一.什么是多线程 进程:是程序的基本执行实体 理解:每一个运行的软件就是一个进程 线程:是操做系统能够进行运算调度的最小单位,它…

Halcon 从基础到精通-02- 开发基于HALCON的应用

HALCON的应用通过HDevelop应用来构建原型。HDevelop的开发主要有3种形式。 Start from Scratch: 手动通过脚本&#xff0c;把HDevelop的代码转化为一般的编程语言。如&#xff0c;上一节提到&#xff0c;其实&#xff0c;每个operators,也许并不一样&#xff0c;需要依据HALC…

开发工具箱 —— it-tools

文章目录 开发工具箱 —— it-tools安装访问效果 开发工具箱 —— it-tools 安装 docker 安装教程&#xff1a;在 CentOs7 中安装宝塔面板和 Docker&#xff08;包括MySQL&#xff0c;Redis&#xff09; docker 安装命令 docker run -d --name it-tools --restart unless-st…

[unity]保存文件的路径设置

序 比如&#xff0c;序列化了一个数组&#xff0c;保存到磁盘上。 原来的路径是"D://test.bin"&#xff0c;能跑&#xff0c;但是有点问题&#xff1a;序列化出来的文件和原项目离的太远&#xff0c;不好管理。 要是能保存到unity工程的文件夹里就好了。这个路径该…

c#设计模式-行为型模式 之 责任链模式

&#x1f680;简介 又名职责链模式&#xff0c;为了避免请求发送者与多个请求处理者耦合在一起&#xff0c;将所有请求的处理者通过前一对 象记住其下一个对象的引用而连成一条链&#xff1b;当有请求发生时&#xff0c;可将请求沿着这条链传递&#xff0c;直到有对象处理它为…

学员自述:上位机编程培训经历

、大家好&#xff0c;我是华山编程培训中心的学员 之前是从事PLC编程工作的&#xff0c;在C#语言这一块是零基础&#xff0c;之前也尝试过自学&#xff0c;但对于类啊继承啊堆栈这些基本的概念始终是无法理解&#xff0c;直到看到华山培训的视频&#xff0c;并参与朱老师的直播…

番外--命令操作

------------- task00: 00&#xff1a;常用文件目录类命令1-18.&#xff08;pwd&#xff1b; cd&#xff1b;ls&#xff1b; more&#xff1b;less&#xff1b;head&#xff1b;tail&#xff1b; mkdir&#xff1b;rmdir&#xff1b;cp&#xff1b;mv&#xff1b;rm&#xff1b…

pandas 笔记:asfreq

1 方法介绍 asfreq 是一个在 Pandas 时间序列数据分析中常用的方法。这个方法主要用于改变时间序列的频率。asfreq 可以帮助我们将一个时间序列从一个频率转换为另一个频率 2 基本用法 DataFrame.asfreq(freq, methodNone, howNone, normalizeFalse, fill_valueNone)3 参数说…

实验室超声波(提取)萃取技术有哪些实际的应用?

梵英超声(fanyingsonic)实验室超声波清洗机 超声波具有“空化现象”&#xff0c;“机械振动”以及“热效应”等特性。“空化现象”可产生瞬间几千个压力&#xff0c;使提取介质的微小气泡压缩、爆裂、破碎被提取原料和细胞壁&#xff0c;加速天然药用成分的溶出&#xff0c;“机…

微服务技术栈-Docker应用部署

文章目录 前言一、数据卷二、Docker 应用部署1、MySQL部署2、Tomcat部署3、Nginx部署4、Redis部署5、Kafka部署 总结 前言 之前文章讲到过&#xff0c;docker运行程序的过程就是去仓库把镜像拉到本地&#xff0c;然后用一条命令把镜像运行起来变成容器&#xff0c;接下来我们将…

虫情测报灯——一种农业虫情防治工具

KH-CQPest虫情测报灯是一种农业虫情防治工具&#xff0c;它可以通过光源或药物诱虫的方式&#xff0c;吸引害虫撞击撞击屏&#xff0c;通过远红外自动处理技术&#xff0c;无公害杀死害虫的同时保存害虫标本&#xff0c;利用高像素的摄像头拍照、农业四情测报平台识别害虫&…

简单两步实现离线部署ChatGPT,ChatGPT平替版,无需GPU离线搭建ChatGPT

文末附主程序安装包和大模型参数文件~ 演示效果如下图所示&#xff1a; 一、使用方法 软件主要分为两个部分&#xff1a;GPT4ALL软件主体&#xff08;主程序&#xff09;模型参数&#xff08;离线模型&#xff09;&#xff0c;如果使用API Key的话则不需要下载模型参数。 可以…