17自由度人形机器人实现行走功能

1. 功能说明

     本文示例将实现R307样机17自由度人形机器人行走的功能。该项目利用探索者平台制作,其驱动系统采用伺服电机。

2. 仿人形机器人结构设计

     人型机器人是一种旨在模仿人类外观和行为的机器人(robot),尤其特指具有和人类相似肌体的种类。常见一个包含完整四肢和头部运动的机器人需要17个自由度,每条腿有5个自由度;两条手臂共6个自由度,每条手臂3个自由度;头部1个自由度,全部一共17个自由度。

     串联人形机构:串联人形仿生机器人是由多个 舵机关节模组 组合而成的,类似于多个串联机械臂组装而成。

3. 仿人形机器人运动算法

      人形机器人行走主要依靠腿部的运动,同时可以通过甩臂等动作调整平衡姿态,所以人形机器人的步态规划主要看腿部各关节的协调,下面给大家列一个10自由度人形双足机器人的前进步态:

      这里为了方便分析,将双足简化成如下图所示,其中每条腿包含一个两自由度的髋关节,共两个自由度A和B,A左右摆动、B为前后摆动;一个自由度的膝关节C,为前后摆动;两个自由度的踝关节D和E,D为前后摆动、E为左右摆动。

      正面图:第一步通过左右倾斜让左腿脱离地面,注意保持上半身的水平。调整A/A1、E/E1:

      侧面图:第二步左腿抬起,右腿回到初始位置。调整B、C、D:

      侧面图:第三步右腿向前弯曲,使身体前倾,让左脚落地,为下一步右腿迈步做准备:

      正面图:第四步通过左右倾斜让左腿脱离地面,注意保持上半身的水平。调整A/A1、E/E1(注意这一步之前左脚落地后绷直):

      侧面图:第五步右腿抬起,左腿回到初始位置。调整B1、C1、D1:

      侧面图:第六步左腿向前弯曲,使身体前倾,让右脚脚落地,为下一步左腿迈步做准备:

      提示:在上面的步态描述中所画的图都以每一步最全面的角度为准,所以大家不要在意视图,注意步态。

4. 电子硬件

本实验中采用了以下硬件:

主控板

Basra主控板(兼容Arduino Uno)

扩展板

Bigfish2.1扩展板

SH-ST步进电机扩展板
电池7.4V锂电池

电路连接:

1~17号舵机接线如下:

D1、D2、D3、D4、D7、D8、D9、D18、D19、D20、D21、D23、D24、D25、D26、D27、D5

5. 功能实现

上位机:Controller 1.0

下位机编程环境:Arduino 1.8.19

5.1示例程序

下面提供一个17自由度人形机器人行走前进的参考例程(_17servo_human.ino),将参考例程下载到主控板中:

/*------------------------------------------------------------------------------------

  版权说明:Copyright 2023 Robottime(Beijing) Technology Co., Ltd. All Rights Reserved.

           Distributed under MIT license.See file LICENSE for detail or copy at

           https://opensource.org/licenses/MIT

           by 机器谱 2023-04-14 https://www.robotway.com/

  ------------------------------*/

#include <Arduino.h>        //要用到的函数库

#include <avr/pgmspace.h>

#include "Config.h"

#include <Tlc5940.h>

#include <tlc_servos.h>

/* 此程序包含四个动作组,如有需要可自行添加,需修改处有注释,按注释修改

*

* act_num:定义动作组数量

* frequency:定义舵机转动频率

* servo_num:定义舵机数量

* servo_speed:定义舵机速度,单位毫秒

* action_delay:定义动作组每行动作执行的动作间隔,单位微秒

* actChangeDelay:定义不同动作组执行时的切换时间间隔,单位毫秒

*/

#define act_num 6

#define frequency 10

#define servo_num 17

#define servo_speed 4

#define action_delay 10

#define actChangeDelay 1000


/*

* 动作组定义,可自行添加动作组,名称可修改,此处为 4 个动作组

*/

#define action_move 0

#define action_left 1

#define action_right 2

#define action_back 3

#define action_dance 4

#define action_init 5


/*

* servo_pin:定义舵机引脚,按顺序从小到大定义,引脚号应从 1 开始

* actPwmNum:定义动作组数组的长度

*/

int servo_pin[servo_num] = {1, 2, 3, 4, 5, 7, 8, 9, 18, 19, 20, 21, 23, 24, 25, 26, 27};

int actPwmNum[act_num] = {};


//中间数组

float value_pre[servo_num] = {};

float value_cur[servo_num] = {};

int count_input = 0;

boolean _b = false;


/**************+++++++++++动作组数组,请将转换后的动作组数据粘贴到相应的动作组中+++++++***************************/

//这个动作组没有添加动作,可以自己添加机器人动作

const PROGMEM int actionInit[] = {

};


//actionMove[]该动作组包括了机器人的一些简单的动作,包括转头、下蹲、踮脚、左右摇晃、骑马舞、扎马步等动作。

const PROGMEM int actionMove[] = {

1411,2300,1522,1344,1522,544,1433,1456,1456,1433,1078,1500,1500,1367,1767,1367,1411,

1411,2300,1522,1344,1522,544,1433,1456,1456,1433,1078,1500,1500,1367,1767,1367,1411,

1411,2300,1522,1344,1522,544,1433,1456,1322,1433,1078,1500,1456,1367,1767,1367,1411,

1411,2300,1522,1344,1522,544,1433,1456,1456,1433,1078,1500,1500,1367,1767,1367,1411,

922,1856,1522,1344,1522,1833,767,1456,1322,1433,1078,1500,1456,1367,1767,1367,1411,

1411,2300,1522,1344,1522,544,1433,1456,1456,1433,1078,1500,1500,1367,1767,1367,1411,

1411,2300,1522,1344,1522,522,1411,1456,1544,1439,1078,1500,1656,1367,1767,1367,1411,

1411,2300,1522,1344,1522,544,1433,1456,1456,1433,1078,1500,1500,1367,1767,1367,1411,

2056,900,1522,1344,1522,1011,1878,1456,1544,1439,1078,1500,1656,1367,1767,1367,1411,

1411,2300,1522,1344,1522,544,1411,1456,1456,1439,1078,1500,1500,1367,1767,1367,1411,

656,2100,1522,1344,1522,633,1922,1456,1456,1439,1078,1500,1500,1367,1767,1367,1411,

1411,1989,856,1344,1522,633,1922,1456,1367,1439,1078,1500,1500,1367,1767,1367,1411,

656,2100,1522,1344,1522,633,1922,1456,1456,1439,1078,1500,1500,1367,1767,1367,1411,

656,2100,1522,1344,2078,767,1389,1456,1478,1439,1078,1500,1656,1367,1767,1367,1411,

656,2100,1522,1344,1522,633,1922,1456,1456,1439,1078,1500,1500,1367,1767,1367,1411,

1411,2300,1522,1344,1522,544,1433,1456,1456,1433,1078,1500,1500,1367,1767,1367,1411,

1411,2300,1522,1344,1522,544,1433,1456,1456,1433,1078,1500,1500,1367,1767,1367,1411,

1411,2300,1522,1344,1522,544,1433,1456,1322,1433,1078,1500,1456,1367,1767,1367,1411,

1411,2300,1522,1344,1522,544,1433,1456,1456,1433,1078,1500,1500,1367,1767,1367,1411,

922,1856,1522,1344,1522,1833,767,1456,1322,1433,1078,1500,1456,1367,1767,1367,1411,

1411,2300,1522,1344,1522,544,1433,1456,1456,1433,1078,1500,1500,1367,1767,1367,1411,

1411,2300,1522,1344,1522,522,1411,1456,1544,1439,1078,1500,1656,1367,1767,1367,1411,

1411,2300,1522,1344,1522,544,1433,1456,1456,1433,1078,1500,1500,1367,1767,1367,1411,

2056,900,1522,1344,1522,1011,1878,1456,1544,1439,1078,1500,1656,1367,1767,1367,1411,

1411,2300,1522,1344,1522,544,1411,1456,1456,1439,1078,1500,1500,1367,1767,1367,1411,

656,2100,1522,1344,1522,633,1922,1456,1456,1439,1078,1500,1500,1367,1767,1367,1411,

1411,1989,856,1344,1522,633,1922,1456,1367,1439,1078,1500,1500,1367,1767,1367,1411,

656,2100,1522,1344,1522,633,1922,1456,1456,1439,1078,1500,1500,1367,1767,1367,1411,

656,2100,1522,1344,2078,767,1389,1456,1478,1439,1078,1500,1656,1367,1767,1367,1411,

656,2100,1522,1344,1522,633,1922,1456,1456,1439,1078,1500,1500,1367,1767,1367,1411,

1411,2300,1522,1344,1522,523,1322,1456,1456,1433,1078,1500,1500,1367,1767,1367,1411,

1411,2300,1522,1344,1522,523,1322,1456,1456,1433,1078,1500,1500,1367,1767,1367,1411,

1411,2300,1522,1344,1522,523,1322,1500,1589,1452,1078,1500,1688,1367,1767,1367,1411,

1411,2300,1967,1344,1944,523,1322,1500,1589,1452,1078,1500,1567,1367,1678,1233,1411,

1411,2300,1700,1344,1700,523,1322,1456,1456,1452,1078,1500,1544,1367,1678,1233,1411,

1411,2300,1522,1344,1522,523,1322,1433,1144,1452,1078,1500,1389,1367,1678,1233,1353,

1411,2300,967,1344,967,523,1322,1390,1456,1452,1144,1633,1389,1389,1767,1367,1353,

1411,2300,1322,1344,1344,523,1322,1456,1483,1433,1144,1633,1500,1389,1767,1367,1411,

1411,2300,1522,1344,1522,523,1322,1485,1601,1433,1144,1633,1678,1389,1767,1367,1435,

1411,2300,2122,1344,1967,523,1322,1493,1601,1433,1078,1500,1589,1418,1589,1078,1435,

1411,2300,1767,1344,1700,523,1322,1456,1456,1433,1078,1500,1478,1415,1589,1078,1436,

1411,2300,1522,1344,1522,523,1322,1455,1313,1433,1078,1500,1389,1388,1589,1065,1402,

1411,2300,922,1344,856,523,1322,1455,1389,1433,1161,1656,1389,1389,1767,1376,1402,

1411,2300,1344,1344,1278,523,1322,1456,1456,1433,1161,1656,1500,1389,1767,1376,1411,

};


//这个动作组没有添加动作,可以自己添加机器人动作

const PROGMEM int actionLeft[] = {

};


//这个动作组没有添加动作,可以自己添加机器人动作

const PROGMEM int actionRight[] = {

};


//这个动作组没有添加动作,可以自己添加机器人动作

const PROGMEM int actionBack[] = {

};


//actionDance[]该动作组是机器人的行走步态动作组

const PROGMEM int actionDance[] = {

1411,2300,1344,1344,1278,523,1322,1456,1456,1433,1161,1656,1500,1389,1767,1376,1411,

1411,2300,1522,1344,1522,523,1322,1485,1601,1433,1144,1633,1678,1389,1767,1367,1435,

1411,2300,2122,1344,1967,523,1322,1493,1601,1433,1078,1500,1589,1418,1589,1078,1435,

1411,2300,1767,1344,1700,523,1322,1456,1456,1433,1078,1500,1478,1415,1589,1078,1436,

1411,2300,1522,1344,1522,523,1322,1455,1313,1433,1078,1500,1389,1388,1589,1065,1402,

1411,2300,922,1344,856,523,1322,1455,1389,1433,1161,1656,1389,1389,1767,1376,1402,

1411,2300,1344,1344,1278,523,1322,1456,1456,1433,1161,1656,1500,1389,1767,1376,1411,

};


/**************************+++++---------分割线--------++++++*******************************************************/


//动作组数组长度获取函数,增加动作组时需要按如下格式添加:actPwmNum[增加的动作组序号] = sizeof(增加的动作组名称) / sizeof(增加的动作组名称[0]);

void act_length()

{

  actPwmNum[0] = (sizeof(actionMove) / sizeof(actionMove[0]))/servo_num;

  actPwmNum[1] = (sizeof(actionLeft) / sizeof(actionLeft[0]))/servo_num;

  actPwmNum[2] = (sizeof(actionRight) / sizeof(actionRight[0]))/servo_num;

  actPwmNum[3] = (sizeof(actionBack) / sizeof(actionBack[0]))/servo_num;

  actPwmNum[4] = (sizeof(actionDance) / sizeof(actionDance[0]))/servo_num;

  actPwmNum[5] = (sizeof(actionInit) / sizeof(actionInit[0]))/servo_num;


  for(int i=0;i<act_num;i++)

  {

    Serial.println(actPwmNum[i]);   //打印出每个动作组中各有多少个动作(也就是打印出每个动作组中有几行动作)

  }

  delay(2000);


}


//map映射函数

long map_servo(long x, long in_min, long in_max, long out_min, long out_max)

{

  return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;

}


//PWM 转换为舵机角度的函数,增加动作组时需要修改

void vlaue2angle(int p, int act)

{

  switch(act)

  {

    case 0:   value_cur[p] = map_servo(pgm_read_word_near(actionMove + p + servo_num * count_input), 500, 2500, 0, 180);   break;

    case 1:   value_cur[p] = map_servo(pgm_read_word_near(actionLeft + p + servo_num * count_input), 500, 2500, 0, 180);   break;

    case 2:   value_cur[p] = map_servo(pgm_read_word_near(actionRight + p + servo_num * count_input), 500, 2500, 0, 180);   break;

    case 3:   value_cur[p] = map_servo(pgm_read_word_near(actionBack + p + servo_num * count_input), 500, 2500, 0, 180);   break;

    case 4:   value_cur[p] = map_servo(pgm_read_word_near(actionDance + p + servo_num * count_input), 500, 2500, 0, 180); break;

    case 5:   value_cur[p] = map_servo(pgm_read_word_near(actionInit + p + servo_num * count_input), 500, 2500, 0, 180); break;

    default: break;

  }

}


//舵机初始化函数(初始化舵机动作),动作组第一行为舵机初始化值

void servo_init(int act, int num)

{   

  if(!_b)

  {

    for(int i=0;i<servo_num;i++)

    {

      vlaue2angle(i, act);

      tlc_setServo(servo_pin[i], value_cur[i]);

      value_pre[i] = value_cur[i];

    }

    Tlc.update();

  }  

  num == 1 ? _b = true : _b = false;

}


//舵机移动函数,参数: act:动作组宏定义名称 ;num:动作组执行的次数,num > 0 ;

void servo_move(int act, int num)

{  

  float value_delta[servo_num] = {};

  float in_value[servo_num] = {};

 

  servo_init(act, num);

 

  for(int i=0;i< num * actPwmNum[act];i++)

  {

    count_input++;

   

    if(count_input == actPwmNum[act])

    {

      count_input = 0;

      continue;

    }

   

    for(int i=0;i<servo_num;i++)

    {

      vlaue2angle(i, act);

      in_value[i] = value_pre[i];

      value_delta[i] = (value_cur[i] - value_pre[i]) / frequency;

    }

   

    for(int i=0;i<frequency;i++)

    {

      for(int k=0;k<servo_num;k++)

      {

        in_value[k] += value_delta[k];  

        value_pre[k] = in_value[k];

      }     

      for(int j=0;j<servo_num;j++)

      {       

        tlc_setServo(servo_pin[j], in_value[j]);

        delay(servo_speed);

      }

      Tlc.update();

    }

  }

}

/********************************************************-------分割线--------****************************************************/

//初始化函数

void setup() {

  Serial.begin(9600);     //开启串口通信,波特率9600

  Tlc.init(0);

  tlc_initServos();

  act_length();  

  delay(action_delay);

}


//主函数

void loop()

{

    servo_move(action_move, 1);   //执行action_move动作组(左右摇,踮脚,扎马步等动作)

    delay(actChangeDelay);

    while(1){

     servo_move(action_dance, 1);   //while(1){...动作...}一直执行括号中的动作(即机器人行走)

      };

}

5.2 调试

       双击打开Controller 1.0.exe。将波特率与串口设置好,同时留下1、2、3、4、5、7、8、9、18、19、20、21、23、24、25、26、27几个舵机串口,调试舵机角度。具体操作步骤可参考 【U002】如何驱动模拟舵机-Controller 1.0b软件的使用

      将几个舵机的角度调试好并记录下来,将调试好的舵机角度写到对应例程(_17servo_human.ino)中的位置;下图所示是角度,大家可尝试自己更改角度值使其动作看起来更流畅。

提示:17自由度人形机器人行走调试并不只是通过程序去调整步态和舵机角度,还涉及到重心的调整,重心可以通过编程调整,也可以通过调整结构实现。

6. 资料内容

①行走-例程源代码

②行走-样机3D文件

③Controller1.0b资料包

资料内容详见:17自由度人形机器人-行走

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MySQL备份和恢复

文章目录 一、库的备份和恢复1.库的备份2.库的恢复 二、表的备份和恢复1.表的备份2.表的恢复 备份数据&#xff0c;其实就是生成一个 sql 文件&#xff0c;把创建数据库、创建表、插入数据等各种 SQL 语句都装载到这个文件中。恢复数据&#xff0c;其实就是按顺序执行 sql 文件…

抖音营销策略:新手如何利用抖音提高品牌曝光度

随着短规频平台的兴起&#xff0c;抖音作为其中的校佼者&#xff0c;已经成为了众多用户和企业的营销利器。但是&#xff0c;对于抖音新手而言&#xff0c;如何在这个平台上快速提升影响力呢?下面不若与众就为大家分享几个实用的方法。 一、关注抖音热门话题和潮流 抖音平台上…

算法记录lday4 LinkedList链表交换 删除倒数N个点 环形链表

今日任务 ● 24. 两两交换链表中的节点 ● 19.删除链表的倒数第N个节点 ● 面试题 02.07. 链表相交 ● 142.环形链表II 两两交换链表中的节点 题目描述 Given a linked list, swap every two adjacent nodes and return its head. You must solve the problem without modi…

错题汇总03

1.以下对二维数组a进行正确初始化的语句是 A int a[2][]{{0,1,2},{3,4,5}} B int a[][3]{{0,1,2},{3,4,5}} C int a[2][4]{{0,1,2},{3,4},{5}}; D int a[][3]{{0,,2},{},{3,4,5}} A数组列不能省略 C数组越界 D数组初始化每一行必须连续初始化 2.能把函数处理结果的二个数据…

存储资源调优技术——SmartDedupe智能数据重删、SmartCompression智能数据压缩技术

目录 SmartDedupe智能数据重删技术 SmartCompression智能数据压缩技术 SmartDedupe智能数据重删技术 基本概念 智能数据重删技术 是一种数据缩减技术&#xff0c;通过删除存储系统中的冗余数据块 减少数据占用的物理存储容量&#xff0c;节省存储空间&#xff08;会降低性能&a…

【Java笔试强训 13】

&#x1f389;&#x1f389;&#x1f389;点进来你就是我的人了博主主页&#xff1a;&#x1f648;&#x1f648;&#x1f648;戳一戳,欢迎大佬指点! 欢迎志同道合的朋友一起加油喔&#x1f93a;&#x1f93a;&#x1f93a; 目录 一、选择题 二、编程题 &#x1f525;参数解析…

【YOLO系列】YOLOv7论文超详细解读(翻译 +学习笔记)

前言 终于读到传说中的YOLOv7了~≖‿≖✧ 这篇是在美团的v6出来不到一个月就高调登场&#xff0c;作者还是我们熟悉的AB大神&#xff08;对&#xff0c;就是v4那个&#xff09;&#xff0c;读起来又是“熟悉”的感觉&#xff08;贯穿了我的整个五一假期&#xff08;╯&#x…

Qt第一天:创建Qt项目

方式一&#xff1a;使用向导创建 打开Qt Creator 界面选择 New Project或者选择菜单栏 【文件】-【新建文件或项目】菜单项 弹出New Project对话框&#xff0c;选择Qt Widgets Application 选择【Choose】按钮&#xff0c;弹出如下对话框 设置项目名称和路径&#xff0c;按照…

软件测试:测试一个网站

一、软件测试的原则 1、软件测试应尽早执行&#xff0c;并贯穿于整个软件生命周期 2、软件测试应追溯需求 3、测试应由第三方来构造 4、穷举测试是不可能的,要遵循 Good-enough 原则 5、必须确定预期输出&#xff08;或结果&#xff09; 6、必须彻底检查每个测试结果 7、…

CH32V307V-EVT-R1 简单上手入门

文章目录 〇、前言一、开发板展示以及介绍二、开发环境配置与搭建2.1 IDE 介绍2.2 IDE 环境搭建2.3 IDE 配置2.3.1 语言切换&#xff08;汉化&#xff1f;不存在的&#xff09; 三、初次烧录与体验四、简单总结与心得&#x1f517; 链接直达 〇、前言 运气不错&#xff0c;前几…

Baklib推荐:关于建设企业知识管理的有效方法

随着信息化和互联网技术的不断发展&#xff0c;企业面临着海量的信息和知识&#xff0c;如何有效地管理和利用这些信息和知识已经成为了企业发展的关键问题之一。企业知识管理是指企业利用信息技术手段&#xff0c;对企业内部的知识进行系统化、集成化、共享化管理&#xff0c;…

4D毫米波雷达聚类检测和追踪

代码&#xff1a;https://github.com/Xiao-Hu-Z/RaderDetectionAndTracking 代码正在写&#xff0c;实时更新&#xff01; 流程 4D雷达毫米波聚类跟踪流程如下图&#xff1a; 预处理主要包括标定、坐标转换和动静分离。 标定使用水平仪、角反&#xff0c;采集数据分析&…

fastai2 实现SSD

https://github.com/search?qfastaissd 有几个值得参考的代码&#xff0c;好好学习。 GitHub - Samjoel3101/SSD-Object-Detection: I am working on a SSD Object Detector using fastai and pytorch fastai2实现的SSD&#xff0c;终于找到了code。https://github.com/sidrav…

【NLP实战】基于Bert和双向LSTM的情感分类【上篇】

文章目录 前言简介数据获取与提取数据清洗读取数据&#xff0c;查看数据清洗训练集观察数据分布去除空数据去除重复数据关于去除停用词关于特殊符号储存清洗后的数据集 清洗测试集观察数据分布去除空数据去除重复数据(并储存) 清洗验证集观察数据分布去除空行去除重复数据(并储…

16.基于主从博弈理论的共享储能与综合能源微网优化运行研究

说明书 MATLAB代码&#xff1a;基于主从博弈理论的共享储能与综合能源微网优化运行研究 关键词&#xff1a;主从博弈 共享储能 综合能源微网 优化调度 参考文档&#xff1a;《基于主从博弈理论的共享储能与综合能源微网优化运行研究》完全复现 仿真平台&#xff1a;MATLAB …

图解项目管理必备十大管理模型

请点击↑关注、收藏&#xff0c;本博客免费为你获取精彩知识分享&#xff01;有惊喜哟&#xff01;&#xff01; 心智模型 心智模型是根深蒂固存在于人们心中&#xff0c;影响人们如何理解这个世界&#xff08;包括我们自己、他人、组织和整个世界&#xff09;&#xff0c;以及…

pytest - Getting Start

前言 项目开发中有很多的功能&#xff0c;通常开发人员需要对自己编写的代码进行自测&#xff0c;除了借助postman等工具进行测试外&#xff0c;还需要编写单元测试对开发的代码进行测试&#xff0c;通过单元测试来判断代码是否能够实现需求&#xff0c;本文介绍的pytest模块是…

Android APK 反编译后重新打包并签名

APKTool&#xff1a; Apktool 是一个逆向android非常有用的工具&#xff0c;可以用来反编译apk文件&#xff0c;并且能在修改部分资源文件后&#xff0c;重新打包成一个新的apk。 下载连接&#xff1a;http://ibotpeaches.github.io/Apktool/install/ 下载之后文件夹非常清爽&…

ChatGPT会颠覆SEO内容创作吗

近几年 AI 的发展日新月异。除了搜索算法本身大规模应用人工智能&#xff0c;我也一直关注着 AI 用于写作的进展。 上篇关于 Google 有用内容更新的帖子还在说&#xff0c;高质量内容创作是 SEO 最难的事之一&#xff0c;对某些网站来说&#xff0c;如果能有工具帮助&#xff…

Mysql 日志

目录 0 课程视频 1 错误日志 -> 默认开启 1.1 查看变量 show variables like %log_error%; 1.2 文件位置 /var/log -> mysqld.log 1.3 指令语法 2 二进制日志 -> 修改数据和数据库结构的日志 2.1 记录原则 2.1.1 记录 数据库创建语句 和 增删改查 2.1.2 不记…