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

强化学习环境 - 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 actionsself._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_kpssim.model.actuator_biasprm[actuator_idx] = actuator_kpsInto 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 subclassesimplement 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 = simself.qpos_idxs: Dict[str, List[int]] = {}self.qvel_idxs: Dict[str, List[int]] = {}self.synchronization_points = []  # type: ignoreself._mujoco_viewer = None@propertydef mj_sim(self):""" MuJoCo simulation object - alias to make it clearer """return self.sim@propertydef 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  # noqaself._mujoco_viewer = MjViewer(self.sim)return self._mujoco_viewerdef 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 REGISTRATIONdef 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 SIMdef 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}@propertydef qpos(self):""" Returns. copy of full sim qpos. """return self.sim.data.qpos.copy()@propertydef 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 SIMdef set_qpos(self, group_name, value):""" Sets qpos for a given group. """self.sim.data.qpos[self.qpos_idxs[group_name]] = valuedef set_qvel(self, group_name, value):""" Sets qpos for a given group. """self.sim.data.qvel[self.qvel_idxs[group_name]] = valuedef add_qpos(self, group_name, value):""" Sets qpos for a given group. """self.sim.data.qpos[self.qpos_idxs[group_name]] += valuedef set_state(self, state: MjSimState):self.sim.set_state(state)######################################################################################### INTERFACE TO UNDERLYING SIMdef 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 MuJoCostate set during the forward dynamics."""self.sim.step(with_udd=with_udd)self.sim.forward()# To potentially communicate with other processesfor 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 freecamera will be used.- depth (bool): if True, also return depth buffer- device (int): device to use for rendering (only for GPU-backedrendering).Returns:- rgb (uint8 array): image buffer from camera- depth (float array): depth buffer from camera (only returnedif depth=True)"""return self.sim.render(width=width,height=height,camera_name=camera_name,depth=depth,mode=mode,device_id=device_id,)######################################################################################### PROPERTIES@propertydef n_substeps(self):""" Number of substeps in the mujoco sim """return self.sim.nsubsteps

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

from math import piprint(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.mzph.cn/news/97783.shtml

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

相关文章

微信小程序使用路由传参和传对象的方法

近期在做微信小程序开发&#xff0c;在页面跳转时&#xff0c;需要携带参数到下一个页面&#xff0c;尤其是将对象传入页面。为了方便重温&#xff0c;特此记录。 路由传字符串参数 原始页面 传递字符串参数比较简单。路由跳转有两种方式&#xff0c;一种是通过navigator组件…

企业AI工程化之路:如何实现高效、低成本、高质量的落地?

MLOps工程实践 概述面临挑战目的内容简介读者对象专家推荐目录 写在末尾&#xff1a; 主页传送门&#xff1a;&#x1f4c0; 传送 概述 作为计算机科学的一个重要领域&#xff0c;机器学习也是目前人工智能领域非常活跃的分支之一。机器学习通过分析海量数据、总结规律&#x…

Flask实现注册登录模块

&#x1f64c;秋名山码民的主页 &#x1f602;oi退役选手&#xff0c;Java、大数据、单片机、IoT均有所涉猎&#xff0c;热爱技术&#xff0c;技术无罪 &#x1f389;欢迎关注&#x1f50e;点赞&#x1f44d;收藏⭐️留言&#x1f4dd; 获取源码&#xff0c;添加WX 目录 前言1.…

机器学习之SGD, Batch, and Mini Batch的简单介绍

文章目录 总述SGD(Stochastic Gradient Descent)(随机梯度下降&#xff09;Batch &#xff08;批量&#xff09;mini Batch (迷你批量&#xff09; 总述 SGD, Batch, and Mini Batch是可用于神经网络的监督学习计算权重更新的方案&#xff0c;即∆wij。 SGD(Stochastic Gradi…

el-tree中插入图标并且带提示信息

<template><div class"left"><!-- default-expanded-keys 默认展开 --><!-- expand-on-click-node 只有点击箭头才会展开树 --><el-tree :data"list" :props"defaultProps" node-click"handleNodeClick" :…

c语言进阶部分详解(详细解析字符串常用函数,并进行模拟实现(下))

上篇文章介绍了一些常用的字符串函数&#xff0c;大家可以跳转过去浏览一下&#xff1a;c语言进阶部分详解&#xff08;详细解析字符串常用函数&#xff0c;并进行模拟实现&#xff08;上&#xff09;&#xff09;_总之就是非常唔姆的博客-CSDN博客 今天接着来介绍一些&#x…

Linux防火墙之--SNAT和DNAT

1.SNAT是什么 SNAT又称源地址转换。源地址转换是内网地址向外访问时&#xff0c;发起访问的内网ip地址转换为指定的ip地址&#xff08;可指定具体的服务以及相应的端口或端口范围&#xff09;&#xff0c;这可以使内网中使用保留ip地址的主机访问外部网络&#xff0c;即内网的多…

腾讯云轻量和CVM有啥区别?怎么选择服务器配置?

腾讯云轻量服务器和云服务器有什么区别&#xff1f;为什么轻量应用服务器价格便宜&#xff1f;是因为轻量服务器CPU内存性能比云服务器CVM性能差吗&#xff1f;轻量应用服务器适合中小企业或个人开发者搭建企业官网、博客论坛、微信小程序或开发测试环境&#xff0c;云服务器CV…

TDengine OSS 与 qStudio 实现无缝协同,革新数据分析和管理方式

在数字化转型如火如荼的当下&#xff0c;海量爆发的时序数据处理成为转型成功的关键因素之一。为了帮助社区用户更好地进行数据分析和管理&#xff0c;丰富可视化解决方案的多样性&#xff0c;我们将开源的时序数据库&#xff08;Time Series Database&#xff09; TDengine OS…

一文看懂光模块的工作原理

你们好&#xff0c;我的网工朋友 光模块有很多类别&#xff0c;是我们经常要用到的PHY层器件。虽然封装&#xff0c;速率&#xff0c;传输距离有所不同&#xff0c;但是其内部组成基本是一致的。 以太网交换机常用的光模块有SFP&#xff0c;GBIC&#xff0c;XFP&#xff0c;X…

运行软件找不到mfc140u.dll怎么解决,mfc140u.dll是什么文件

"找不到 mfc140u.dll"是一条错误信息&#xff0c;表示您的计算机上缺少一个名为 mfc140u.dll 的动态链接库&#xff08;DLL&#xff09;文件。这个文件通常与 Microsoft Visual C Redistributable 相关。Mfc140u.dll 是 Microsoft 基础类库&#xff08;MFC&#xff0…

GD32F103x 定时器

1. 定时器的基本介绍 STM32的定时器主要分为三种&#xff1a;高级定时器、通用定时器、基本定时器。 即&#xff1a;高级定时器具有捕获/比较通道和互补输出&#xff0c;死区时间&#xff0c;通用定时器只有捕获/比较通道&#xff0c;基本定时器没有以上两者。 1. 基本定时…

【深度学习】UNIT-DDPM核心讲解

文章目录 大致介绍&#xff1a;扩散损失&#xff1a;转换损失&#xff1a;循环一致性损失&#xff1a;推理过程&#xff1a;优缺点&#xff1a; 参考文章&#xff1a; https://blog.csdn.net/ssshyeong/article/details/127210086 这篇文章对整个文章 UNIT-DDPM: UNpaired Imag…

Python为Excel中每一个单元格计算其在多个文件中的平均值

本文介绍基于Python语言&#xff0c;对大量不同的Excel文件加以跨文件、逐单元格平均值计算的方法。 首先&#xff0c;我们来明确一下本文的具体需求。现有一个文件夹&#xff0c;其中有如下所示的大量Excel文件&#xff0c;我们这里就以.csv文件为例来介绍。其中&#xff0c;每…

网工内推 | IT高级运维工程师,周末双休,包吃包住,14-20k

01 深圳朗特智能控制股份有限公司 招聘岗位&#xff1a;IT高级运维工程师 职责描述&#xff1a; 1、对集团网络基础架构的建设、运维、安全制定相关标准和准则&#xff1b; 2、负责集团数据中心、核心设备、信息安全的管理和运维&#xff1b; 3、执行网络、服务器、核心交换机…

21.6 CSS 弹性布局

1. 弹性盒子 CSS弹性盒子(Flexbox)是一种布局模型, 用于创建灵活的, 自适应的网页布局. 它的目的是在不同屏幕尺寸和设备上实现一致的布局效果.引入弹性盒布局模型的目的是提供一种更加有效的方式来对一个容器中的子元素进行排列, 对齐和分配空白空间.弹性容器通过设置display…

深入理解强化学习——强化学习的基础知识

分类目录&#xff1a;《深入理解强化学习》总目录 在机器学习领域&#xff0c;有一类任务和人的选择很相似&#xff0c;即序贯决策&#xff08;Sequential Decision Making&#xff09;任务。决策和预测任务不同&#xff0c;决策往往会带来“后果”&#xff0c;因此决策者需要为…

华硕平板k013me176cx线刷方法

1.下载adb刷机工具, 或者刷机精灵 2.下载刷机rom包 华硕asus k013 me176cx rom固件刷机包-CSDN博客 3.平板进入刷机界面 进入方法参考&#xff1a; ASUS (k013) ME176CX不进入系统恢复出厂设置的方法-CSDN博客 4.解压ME176C-CN-3_2_23_182.zip&#xff0c;把UL-K013-CN-3.2.…

竞赛选题 机器学习股票大数据量化分析与预测系统 - python 竞赛选题

文章目录 0 前言1 课题背景2 实现效果UI界面设计web预测界面RSRS选股界面 3 软件架构4 工具介绍Flask框架MySQL数据库LSTM 5 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 机器学习股票大数据量化分析与预测系统 该项目较为新颖&am…

动态内存管理函数(malloc,calloc,realloc,free)

动态内存函数 1.1malloc和free C语言提供了一个动态内存开辟的函数&#xff1a; void* malloc (size_t size); 这个函数向内存申请一块连续可用的空间&#xff0c;并返回指向这块空间的指针。 如果开辟成功&#xff0c;则返回一个指向开辟好空间的指针。如果开辟失败&#…