LeGO LOAM坐标系问题的自我思考

LeGO LOAM坐标系问题的自我思考

  • 总体思考流程
  • IMU坐标系
  • LeGO LOAM代码分析
    • 代码
  • 对于IMU输出测量值的integration积分过程
  • 欧拉角的旋转矩阵
    • VeloToStartIMU()函数
    • TransformToStartIMU(PointType *p)

总体思考流程

第一页
请添加图片描述第二页
请添加图片描述第三页
请添加图片描述

IMU坐标系

在LeGO LOAM中IMU坐标系的形式采用前(x)-左(y)-上(z)的形式,IMU坐标系同时可以表示为载体坐标系(body frame)世界坐标系表示的形式采用左(x)-上(y)-前(z)的形式,世界坐标系也可以称为world系世界坐标系作为一种固定的坐标系,而IMU坐标系作为一种非固定坐标系

下图展示为两种坐标系的表示形式:
(下图展示的坐标系为IMU坐标系)
在这里插入图片描述
(下图展示的坐标系为世界坐标系)
在这里插入图片描述
坐标系在实体汽车上的表示:
在这里插入图片描述

LeGO LOAM代码分析

代码

void imuHandler(const sensor_msgs::Imu::ConstPtr& imuIn){double roll, pitch, yaw;tf::Quaternion orientation;tf::quaternionMsgToTF(imuIn->orientation, orientation);tf::Matrix3x3(orientation).getRPY(roll, pitch, yaw);float accX = imuIn->linear_acceleration.y - sin(roll) * cos(pitch) * 9.81;float accY = imuIn->linear_acceleration.z - cos(roll) * cos(pitch) * 9.81;float accZ = imuIn->linear_acceleration.x + sin(pitch) * 9.81;imuPointerLast = (imuPointerLast + 1) % imuQueLength;imuTime[imuPointerLast] = imuIn->header.stamp.toSec();imuRoll[imuPointerLast] = roll;imuPitch[imuPointerLast] = pitch;imuYaw[imuPointerLast] = yaw;imuAccX[imuPointerLast] = accX;imuAccY[imuPointerLast] = accY;imuAccZ[imuPointerLast] = accZ;imuAngularVeloX[imuPointerLast] = imuIn->angular_velocity.x;imuAngularVeloY[imuPointerLast] = imuIn->angular_velocity.y;imuAngularVeloZ[imuPointerLast] = imuIn->angular_velocity.z;AccumulateIMUShiftAndRotation();}

上述代码为消除IMU测量的加速度数据受到重力加速度的影响(重力加速度存在于world坐标系)

  1. 因为IMU坐标系与world坐标系是不对齐的,所以,下面这三行代码的用途如下:
#输出的为在IMU与world坐标系一致朝向的IMU坐标系下的新IMU坐标系下的加速度 测量数据值float accX = imuIn->linear_acceleration.y - sin(roll) * cos(pitch) * 9.81;float accY = imuIn->linear_acceleration.z - cos(roll) * cos(pitch) * 9.81;float accZ = imuIn->linear_acceleration.x + sin(pitch) * 9.81;

将重力加速度转到IMU坐标系,然后执行消除重力的影响:涉及的公式如下
在这里插入图片描述在这里插入图片描述在这里插入图片描述
同时因为IMU坐标系与world坐标系不对齐,所以第二部将X->y,Y->z,Z->x实则是考虑一个新的IMU坐标系,使得这个新的IMU坐标与world坐标系能够在朝向上一致!!!(但是需要区分的是此时新的IMU坐标系和world坐标系只是朝向一致,但是他们并不是同一个坐标系!!!)
在这里插入图片描述

  1. 但是对于imu坐标系表示为前x->左y->上z新的IMU坐标系(IMU’)表示为左x->上y->前z,所以 最终得到的accX,accY,accZ分别经过imu到IMU’的坐标系的变换,(所以需要经历的变换为如下图所示:)
    在这里插入图片描述

对于IMU输出测量值的integration积分过程

因为accX,accY,accZ对应的都是IMU表示的新的坐标系(IMU’)下的测量数据值,因为IMU到world坐标系下的旋转满足yaw-pitch-roll旋转,同时是内旋,满足右乘,所以最终满足的公式为:
在这里插入图片描述

// rollfloat x1 = cos(roll) * accX - sin(roll) * accY;float y1 = sin(roll) * accX + cos(roll) * accY;float z1 = accZ;//z

在这里插入图片描述

// pitchfloat x2 = x1;//xfloat y2 = cos(pitch) * y1 - sin(pitch) * z1;float z2 = sin(pitch) * y1 + cos(pitch) * z1;

在这里插入图片描述

//yawaccX = cos(yaw) * x2 + sin(yaw) * z2;accY = y2;//yaccZ = -sin(yaw) * x2 + cos(yaw) * z2;

在这里插入图片描述
IMU坐标系转为机器人坐标系(左X(pitch)->上Y(yaw)->前Z(roll)),需要按照转换后的坐标系进行欧拉角的旋转yaw->pitch->roll的内旋右乘->表示为先✖roll(Z)->再✖pitch(x)->再✖yaw(Y)

    void AccumulateIMUShiftAndRotation(){float roll = imuRoll[imuPointerLast];float pitch = imuPitch[imuPointerLast];float yaw = imuYaw[imuPointerLast];float accX = imuAccX[imuPointerLast];float accY = imuAccY[imuPointerLast];float accZ = imuAccZ[imuPointerLast];
//将新的坐标系IMU'数据通过YAW->PITCH->ROLL转到world坐标系
// roll zfloat x1 = cos(roll) * accX - sin(roll) * accY;float y1 = sin(roll) * accX + cos(roll) * accY;float z1 = accZ;//z
//pitch xfloat x2 = x1;//xfloat y2 = cos(pitch) * y1 - sin(pitch) * z1;float z2 = sin(pitch) * y1 + cos(pitch) * z1;
//yaw yaccX = cos(yaw) * x2 + sin(yaw) * z2;accY = y2;//yaccZ = -sin(yaw) * x2 + cos(yaw) * z2;int imuPointerBack = (imuPointerLast + imuQueLength - 1) % imuQueLength;double timeDiff = imuTime[imuPointerLast] - imuTime[imuPointerBack];if (timeDiff < scanPeriod) {
// 最终得到的 Shift | Velo | AngularRotation均表示为world坐标系下的数值imuShiftX[imuPointerLast] = imuShiftX[imuPointerBack] + imuVeloX[imuPointerBack] * timeDiff + accX * timeDiff * timeDiff / 2;imuShiftY[imuPointerLast] = imuShiftY[imuPointerBack] + imuVeloY[imuPointerBack] * timeDiff + accY * timeDiff * timeDiff / 2;imuShiftZ[imuPointerLast] = imuShiftZ[imuPointerBack] + imuVeloZ[imuPointerBack] * timeDiff + accZ * timeDiff * timeDiff / 2;imuVeloX[imuPointerLast] = imuVeloX[imuPointerBack] + accX * timeDiff;imuVeloY[imuPointerLast] = imuVeloY[imuPointerBack] + accY * timeDiff;imuVeloZ[imuPointerLast] = imuVeloZ[imuPointerBack] + accZ * timeDiff;imuAngularRotationX[imuPointerLast] = imuAngularRotationX[imuPointerBack] + imuAngularVeloX[imuPointerBack] * timeDiff;imuAngularRotationY[imuPointerLast] = imuAngularRotationY[imuPointerBack] + imuAngularVeloY[imuPointerBack] * timeDiff;imuAngularRotationZ[imuPointerLast] = imuAngularRotationZ[imuPointerBack] + imuAngularVeloZ[imuPointerBack] * timeDiff;}}

其最终得到的速度,偏移以及旋转的积分数据值表示的为在world坐标系下的数据

欧拉角的旋转矩阵

在adjustDistortion对点云数据执行运动去畸变的过程是这样的,首先将lidar点云同样与IMU数据统一的跟world坐标系同指向的新的lidar’坐标系(用来与world坐标系的朝向对齐):执行如下代码的变换:

point.x = segmentedCloud->points[i].y;point.y = segmentedCloud->points[i].z;point.z = segmentedCloud->points[i].x;

然后,找到针对此刻点云对应的IMU数据信息,如果是第一帧,则不需要旋转到IMU对应的初始时刻 但是对于在scanperiod的时间间隔内,lidar360度旋转,非第一帧对应的初始时刻的IMU数据,则需要转换到初始时刻的IMU数据坐标系下也就是涉及的两个函数VeloToStartIMU()函数和TransformToStartIMU(point)函数

void adjustDistortion(){bool halfPassed = false;int cloudSize = segmentedCloud->points.size();PointType point;for (int i = 0; i < cloudSize; i++) {point.x = segmentedCloud->points[i].y;point.y = segmentedCloud->points[i].z;point.z = segmentedCloud->points[i].x;float ori = -atan2(point.x, point.z);if (!halfPassed) {if (ori < segInfo.startOrientation - M_PI / 2)ori += 2 * M_PI;else if (ori > segInfo.startOrientation + M_PI * 3 / 2)ori -= 2 * M_PI;if (ori - segInfo.startOrientation > M_PI)halfPassed = true;}else {ori += 2 * M_PI;if (ori < segInfo.endOrientation - M_PI * 3 / 2)ori += 2 * M_PI;else if (ori > segInfo.endOrientation + M_PI / 2)ori -= 2 * M_PI;}float relTime = (ori - segInfo.startOrientation) / segInfo.orientationDiff;point.intensity = int(segmentedCloud->points[i].intensity) + scanPeriod * relTime;if (imuPointerLast >= 0) {//have imu datafloat pointTime = relTime * scanPeriod;imuPointerFront = imuPointerLastIteration;while (imuPointerFront != imuPointerLast) {if (timeScanCur + pointTime < imuTime[imuPointerFront]) {break;}imuPointerFront = (imuPointerFront + 1) % imuQueLength;}//find the imuPointerFront (imu time ) > current scan timeif (timeScanCur + pointTime > imuTime[imuPointerFront]) {//no imu dataimuRollCur = imuRoll[imuPointerFront];//imu data coverageimuPitchCur = imuPitch[imuPointerFront];imuYawCur = imuYaw[imuPointerFront];imuVeloXCur = imuVeloX[imuPointerFront];imuVeloYCur = imuVeloY[imuPointerFront];imuVeloZCur = imuVeloZ[imuPointerFront];imuShiftXCur = imuShiftX[imuPointerFront];imuShiftYCur = imuShiftY[imuPointerFront];imuShiftZCur = imuShiftZ[imuPointerFront];   } else {int imuPointerBack = (imuPointerFront + imuQueLength - 1) % imuQueLength;//0-1 % imuQueLength xfloat ratioFront = (timeScanCur + pointTime - imuTime[imuPointerBack]) / (imuTime[imuPointerFront] - imuTime[imuPointerBack]);float ratioBack = (imuTime[imuPointerFront] - timeScanCur - pointTime) / (imuTime[imuPointerFront] - imuTime[imuPointerBack]);imuRollCur = imuRoll[imuPointerFront] * ratioFront + imuRoll[imuPointerBack] * ratioBack;imuPitchCur = imuPitch[imuPointerFront] * ratioFront + imuPitch[imuPointerBack] * ratioBack;if (imuYaw[imuPointerFront] - imuYaw[imuPointerBack] > M_PI) {imuYawCur = imuYaw[imuPointerFront] * ratioFront + (imuYaw[imuPointerBack] + 2 * M_PI) * ratioBack;} else if (imuYaw[imuPointerFront] - imuYaw[imuPointerBack] < -M_PI) {imuYawCur = imuYaw[imuPointerFront] * ratioFront + (imuYaw[imuPointerBack] - 2 * M_PI) * ratioBack;} else {imuYawCur = imuYaw[imuPointerFront] * ratioFront + imuYaw[imuPointerBack] * ratioBack;}imuVeloXCur = imuVeloX[imuPointerFront] * ratioFront + imuVeloX[imuPointerBack] * ratioBack;imuVeloYCur = imuVeloY[imuPointerFront] * ratioFront + imuVeloY[imuPointerBack] * ratioBack;imuVeloZCur = imuVeloZ[imuPointerFront] * ratioFront + imuVeloZ[imuPointerBack] * ratioBack;imuShiftXCur = imuShiftX[imuPointerFront] * ratioFront + imuShiftX[imuPointerBack] * ratioBack;imuShiftYCur = imuShiftY[imuPointerFront] * ratioFront + imuShiftY[imuPointerBack] * ratioBack;imuShiftZCur = imuShiftZ[imuPointerFront] * ratioFront + imuShiftZ[imuPointerBack] * ratioBack;}if (i == 0) {//first point cloud initializationimuRollStart = imuRollCur;imuPitchStart = imuPitchCur;imuYawStart = imuYawCur;imuVeloXStart = imuVeloXCur;imuVeloYStart = imuVeloYCur;imuVeloZStart = imuVeloZCur;imuShiftXStart = imuShiftXCur;imuShiftYStart = imuShiftYCur;imuShiftZStart = imuShiftZCur;if (timeScanCur + pointTime > imuTime[imuPointerFront]) {imuAngularRotationXCur = imuAngularRotationX[imuPointerFront];imuAngularRotationYCur = imuAngularRotationY[imuPointerFront];imuAngularRotationZCur = imuAngularRotationZ[imuPointerFront];}else{int imuPointerBack = (imuPointerFront + imuQueLength - 1) % imuQueLength;float ratioFront = (timeScanCur + pointTime - imuTime[imuPointerBack]) / (imuTime[imuPointerFront] - imuTime[imuPointerBack]);float ratioBack = (imuTime[imuPointerFront] - timeScanCur - pointTime) / (imuTime[imuPointerFront] - imuTime[imuPointerBack]);imuAngularRotationXCur = imuAngularRotationX[imuPointerFront] * ratioFront + imuAngularRotationX[imuPointerBack] * ratioBack;imuAngularRotationYCur = imuAngularRotationY[imuPointerFront] * ratioFront + imuAngularRotationY[imuPointerBack] * ratioBack;imuAngularRotationZCur = imuAngularRotationZ[imuPointerFront] * ratioFront + imuAngularRotationZ[imuPointerBack] * ratioBack;}imuAngularFromStartX = imuAngularRotationXCur - imuAngularRotationXLast;imuAngularFromStartY = imuAngularRotationYCur - imuAngularRotationYLast;imuAngularFromStartZ = imuAngularRotationZCur - imuAngularRotationZLast;imuAngularRotationXLast = imuAngularRotationXCur;imuAngularRotationYLast = imuAngularRotationYCur;imuAngularRotationZLast = imuAngularRotationZCur;updateImuRollPitchYawStartSinCos();} else {VeloToStartIMU();TransformToStartIMU(&point);}}segmentedCloud->points[i] = point;}imuPointerLastIteration = imuPointerLast;}

VeloToStartIMU()函数

==因为对应的velocity数据是在world坐标系下的,所以imuVeloFromStartXCur存在的坐标系也是world坐标系下的,因此,如果要转到start坐标系,需要先转移到IMU坐标系,然后在转移到start imu的坐标系 ==
**world坐标系到IMU坐标系的变换满足roll (Z)->pitch(X) ->yaw(Y) ,得到的变换如下图所示: **
请添加图片描述

    void VeloToStartIMU(){imuVeloFromStartXCur = imuVeloXCur - imuVeloXStart;//current time to start timeimuVeloFromStartYCur = imuVeloYCur - imuVeloYStart;imuVeloFromStartZCur = imuVeloZCur - imuVeloZStart;
//新的坐标系Y为yaw ->yaw的转置float x1 = cosImuYawStart * imuVeloFromStartXCur - sinImuYawStart * imuVeloFromStartZCur;float y1 = imuVeloFromStartYCur;float z1 = sinImuYawStart * imuVeloFromStartXCur + cosImuYawStart * imuVeloFromStartZCur;
//新的坐标系X为pitch->X的转置float x2 = x1;float y2 = cosImuPitchStart * y1 + sinImuPitchStart * z1;float z2 = -sinImuPitchStart * y1 + cosImuPitchStart * z1;
//新的坐标系Z为roll ->Z的转置imuVeloFromStartXCur = cosImuRollStart * x2 + sinImuRollStart * y2;imuVeloFromStartYCur = -sinImuRollStart * x2 + cosImuRollStart * y2;imuVeloFromStartZCur = z2;}

TransformToStartIMU(PointType *p)

函数首先通过yaw(Y)->pitch(X)->roll(Z)的右乘转到world坐标系,然后再进行world 到 start imu的转换(YawT)->(PitchT)->(RollT)因为是固定坐标系的旋转所以执行的乘法为左乘(Y->X->Z)最终得到变换的结果

    void TransformToStartIMU(PointType *p){float x1 = cos(imuRollCur) * p->x - sin(imuRollCur) * p->y;float y1 = sin(imuRollCur) * p->x + cos(imuRollCur) * p->y;float z1 = p->z;float x2 = x1;float y2 = cos(imuPitchCur) * y1 - sin(imuPitchCur) * z1;float z2 = sin(imuPitchCur) * y1 + cos(imuPitchCur) * z1;float x3 = cos(imuYawCur) * x2 + sin(imuYawCur) * z2;float y3 = y2;float z3 = -sin(imuYawCur) * x2 + cos(imuYawCur) * z2;float x4 = cosImuYawStart * x3 - sinImuYawStart * z3;float y4 = y3;float z4 = sinImuYawStart * x3 + cosImuYawStart * z3;float x5 = x4;float y5 = cosImuPitchStart * y4 + sinImuPitchStart * z4;float z5 = -sinImuPitchStart * y4 + cosImuPitchStart * z4;p->x = cosImuRollStart * x5 + sinImuRollStart * y5 + imuShiftFromStartXCur;p->y = -sinImuRollStart * x5 + cosImuRollStart * y5 + imuShiftFromStartYCur;p->z = z5 + imuShiftFromStartZCur;}

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

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

相关文章

基于VMware的ubuntu与vscode建立ssh连接

1.首先安装openssh服务 sudo apt update sudo apt install openssh-server -y 2.启动并检查ssh服务状态 到这里可以按q退出 之后输入命令 &#xff1a; ip a 红色挡住的部分就是我们要的地址&#xff0c;这里就不展示了哈 3.配置vscode 打开vscode 搜索并安装&#xff1a;…

牛客网 除2!(详解)c++

题目链接&#xff1a;除2&#xff01; 1.题目解析 1&#xff1a;想让数组所有数之和尽可能小&#xff0c;肯定有个想法&#xff0c;就是我每次选数组中偶数的时候&#xff0c;我必定挑一个最大的&#xff0c;因为我挑一个最大的出来&#xff0c;把它变成一半&#xff0c;这个时…

Upscayl-官方开源免费图像AI增强软件

upscayl 链接&#xff1a;https://pan.xunlei.com/s/VOI0Szqe0fCwSSUSS8zRqKf7A1?pwdhefi#

C++并发编程指南08

以下是经过优化排版后的5.3节内容&#xff0c;详细解释了C中的同步操作和强制排序机制。每个部分都有详细的注释和结构化展示。 文章目录 5.3 同步操作和强制排序假设场景示例代码 5.3.1 同步发生 (Synchronizes-with)基本思想 5.3.2 先行发生 (Happens-before)单线程环境多线程…

7.攻防世界fileclude

题目描述 进入题目页面如下 看到题目提示应该为文件包含漏洞 解释上述代码 // 输出提示信息&#xff1a;错误的方式&#xff01; WRONG WAY! <?php // 包含名为 "flag.php" 的文件&#xff0c;通常这个文件里可能包含重要的敏感信息&#xff0c;如 flag inclu…

Manacher 最长回文子串

方法&#xff1a;求字符串的 #include<bits/stdc.h> using namespace std; using lllong long; const int N1e69; char s[N]; int p[N];int main() {cin>>s1;int nstrlen(s1);s[0]^;s[2*n2]$; for(int i2*n1;i>1;i--){s[i](i&1)?#:s[i>>1];//右移表示…

5.4.2 结构化设计方法+结构化程序设计方法

文章目录 结构化设计方法结构化程序设计方法 结构化设计方法 结构化设计是将通过结构化分析得到的数据流图转换成软件体系结构。可用使用结构图描述结构化设计&#xff0c;结构图由模块、数据和调用组成。模块是指有功能&#xff0c;且可通过模块名调用的程序语句。其内部特征包…

ArkTS语言介绍

文章目录 一、基本知识声明类型运算符语句函数函数声明可选参数Rest参数返回类型函数的作用域函数调用函数类型箭头函数(又名Lambda函数)闭包函数重载类字段方法构造函数可见性修饰符对象字面量抽象类接口接口属性接口继承抽象类和接口泛型类型和函数泛型类和接口泛型约束泛型…

【2025年最新版】Java JDK安装、环境配置教程 (图文非常详细)

文章目录 【2025年最新版】Java JDK安装、环境配置教程 &#xff08;图文非常详细&#xff09;1. JDK介绍2. 下载 JDK3. 安装 JDK4. 配置环境变量5. 验证安装6. 创建并测试简单的 Java 程序6.1 创建 Java 程序&#xff1a;6.2 编译和运行程序&#xff1a;6.3 在显示或更改文件的…

71.在 Vue 3 中使用 OpenLayers 实现按住 Shift 拖拽、旋转和缩放效果

前言 在前端开发中&#xff0c;地图功能是一个常见的需求。OpenLayers 是一个强大的开源地图库&#xff0c;支持多种地图源和交互操作。本文将介绍如何在 Vue 3 中集成 OpenLayers&#xff0c;并实现按住 Shift 键拖拽、旋转和缩放地图的效果。 实现效果 按住 Shift 键&#…

【数据结构】_复杂度

目录 1. 算法效率 2. 时间复杂度 2.1 时间复杂度概念 2.2 准确的时间复杂度函数式 2.3 大O渐进表示法 2.4 时间复杂度的常见量级 2.5 时间复杂度示例 3. 空间复杂度 3.1 空间复杂度概念 3.2 空间复杂度示例 1. 算法效率 一般情况下&#xff0c;衡量一个算法的好坏是…

十分钟快速上手 markdown

前言 本人利用寒假期间&#xff0c;将自己所学的markdown的知识&#xff0c;以及将自己常用的一些操作和注意事项记录下来&#xff0c;希望能够帮助大家 一、markdown是什么 Markdown 是一种轻量级标记语言&#xff0c;说白了就是可以让你利用最简单的语法达到最好的排版效果…

一文讲解Java中的ArrayList和LinkedList

ArrayList和LinkedList有什么区别&#xff1f; ArrayList 是基于数组实现的&#xff0c;LinkedList 是基于链表实现的。 二者用途有什么不同&#xff1f; 多数情况下&#xff0c;ArrayList更利于查找&#xff0c;LinkedList更利于增删 由于 ArrayList 是基于数组实现的&#…

Python 梯度下降法(五):Adam Optimize

文章目录 Python 梯度下降法&#xff08;五&#xff09;&#xff1a;Adam Optimize一、数学原理1.1 介绍1.2 符号说明1.3 实现流程 二、代码实现2.1 函数代码2.2 总代码2.3 遇到的问题2.4 算法优化 三、优缺点3.1 优点3.2 缺点 四、相关链接 Python 梯度下降法&#xff08;五&a…

【上篇】-分两篇步骤介绍-如何用topview生成和自定义数字人-关于AI的使用和应用-如何生成数字人-优雅草卓伊凡-如何生成AI数字人

【上篇】-分两篇步骤介绍-如何用topview生成和自定义数字人-关于AI的使用和应用-如何生成数字人-优雅草卓伊凡-如何生成AI数字人 背景 AI数字人有很多应用目前&#xff0c;本文做如何生成数字人&#xff0c;因为后续就连我们公司自己也会有很多关于AI数字人的使用&#xff0c…

MapReduce简单应用(一)——WordCount

目录 1. 执行过程1.1 分割1.2 Map1.3 Combine1.4 Reduce 2. 代码和结果2.1 pom.xml中依赖配置2.2 工具类util2.3 WordCount2.4 结果 参考 1. 执行过程 假设WordCount的两个输入文本text1.txt和text2.txt如下。 Hello World Bye WorldHello Hadoop Bye Hadoop1.1 分割 将每个文…

tensorboard的基本使用及案例

TensorBoard 是一个可视化工具&#xff0c;用于展示机器学习模型的训练过程和结果。以下是 TensorBoard 的基本使用方法及一些案例。 基本使用 安装 安装 TensorBoard&#xff1a; pip install tensorboard 如果使用 PyTorch&#xff0c;还需要安装 torch 和 torchvision&…

【ArcGIS遇上Python】批量提取多波段影像至单个波段

本案例基于ArcGIS python,将landsat影像的7个波段影像数据,批量提取至单个波段。 相关阅读:【ArcGIS微课1000例】0141:提取多波段影像中的单个波段 文章目录 一、数据准备二、效果比对二、python批处理1. 编写python代码2. 运行代码一、数据准备 实验数据及完整的python位…

吴恩达深度学习——超参数调试

内容来自https://www.bilibili.com/video/BV1FT4y1E74V&#xff0c;仅为本人学习所用。 文章目录 超参数调试调试选择范围 Batch归一化公式整合 Softmax 超参数调试 调试 目前学习的一些超参数有学习率 α \alpha α&#xff08;最重要&#xff09;、动量梯度下降法 β \bet…

Alibaba开发规范_编程规约之命名风格

文章目录 命名风格的基本原则1. 命名不能以下划线或美元符号开始或结束2. 严禁使用拼音与英文混合或直接使用中文3. 类名使用 UpperCamelCase 风格&#xff0c;但以下情形例外&#xff1a;DO / BO / DTO / VO / AO / PO / UID 等4. 方法名、参数名、成员变量、局部变量使用 low…