0%

简介

  • Git常见的语法知识

git bundle 命令 详解

git bundle 命令用于将 Git 仓库的所有对象(commit、tree、blob等)打包成一个二进制文件,这个文件可以在不连接到中央仓库的情况下传递给其他人,并且可以克隆该仓库。这在离线环境或网络较差的情况下非常有用。

以下是 git bundle 命令的基本语法和一些常见用法:

1
2
3
4
5
6
7
8
9
10
11
# 创建一个包含所有分支的 bundle 文件
git bundle create repo.bundle --all

# 创建一个包含指定分支的 bundle 文件
git bundle create repo.bundle branch1 branch2

# 创建一个指定范围的 bundle 文件(从某个 commit 到另一个 commit)
git bundle create repo.bundle <start-commit>..<end-commit>

# 从 bundle 文件中提取对象到本地仓库
git clone repo.bundle new-repo

这里是一些命令的详细解释:

  • git bundle create: 创建一个 bundle 文件。后面的参数是要包含的分支或 commit 的范围。
  • repo.bundle: bundle 文件的名称。你可以自定义文件名。
  • --all: 包含所有分支。
  • branch1 branch2: 包含指定的分支。
  • <start-commit>..<end-commit>: 包含指定范围内的 commit。

一旦你创建了 bundle 文件,你可以将它传递给其他人,他们可以通过克隆该 bundle 文件来获取整个仓库的历史。例如,他们可以使用以下命令:

1
git clone repo.bundle new-repo

需要注意的是,git bundle 不包含远程仓库的引用,因此在使用 bundle 文件进行克隆时,你将得到一个没有远程跟踪分支的本地仓库。如果需要获取远程跟踪分支,可以使用 git fetch 命令。

1
2
cd new-repo
git fetch origin refs/heads/*:refs/remotes/origin/*

这样,你就可以在新的本地仓库中获取与远程仓库相同的分支。

git config 详解

git config 是 Git 版本控制系统中用于配置和管理 Git 仓库的命令。通过 git config 命令,你可以设置和获取 Git 仓库的各种配置选项,包括全局配置和仓库级配置。

git config 命令有三个不同的级别:全局、仓库和本地。这些级别决定了配置选项的作用范围。

以下是 git config 命令的一些常用选项和使用方法:

  1. 获取配置值:使用 git config <key> 命令获取特定配置选项的值。例如,要获取用户的姓名配置,可以使用 git config user.name

  2. 设置配置值:使用 git config <key> <value> 命令设置特定配置选项的值。例如,要设置用户的姓名配置,可以使用 git config user.name "Your Name"

  3. 全局配置:使用 git config --global 命令来设置全局配置选项。全局配置选项将应用于当前用户的所有 Git 仓库。例如,使用 git config --global user.name "Your Name" 来设置全局用户姓名。

  4. 仓库配置:在 Git 仓库的根目录下,使用 git config 命令来设置仓库配置选项。这些配置选项将仅应用于当前仓库。例如,使用 git config user.email "your@example.com" 来设置仓库的用户邮箱。

  5. 本地配置:对于某个特定的 Git 命令,你可以通过在命令后添加 --local 参数,将配置选项设置为本地级别。例如,使用 git config --local core.ignorecase true 来设置当前仓库的忽略文件大小写的配置。

  6. 列出配置:使用 git config --list 命令列出当前仓库的所有配置选项及其对应的值。添加 --global 参数可以列出全局配置选项。

  7. 编辑配置文件:使用 git config --edit 命令打开 Git 配置文件进行手动编辑。对于全局配置,会打开用户主目录下的 .gitconfig 文件,对于仓库配置,会打开仓库目录下的 .git/config 文件。

这些是 git config 命令的一些常见用法和选项。通过适当配置 Git,你可以定制化和优化你的版本控制工作流程。


git config 常用选项

下面是一些常用的 git config 命令选项:

  1. 用户信息

    • user.name:设置用户的姓名。
    • user.email:设置用户的电子邮件地址。
    • 例如:git config --global user.name "Your Name"
  2. 文本编辑器

    • core.editor:设置用于 Git 提交消息的文本编辑器。
    • 例如:git config --global core.editor "vim"
  3. 自动换行

    • core.autocrlf:控制换行符的处理方式。
      • true:在提交时自动将换行符转换为 CRLF,检出时转换为 LF(适用于 Windows 系统)。
      • input:在提交时将换行符转换为 LF,检出时不做转换(适用于 macOS 和 Linux 系统)。
      • false:保持换行符不变。
    • 例如:git config --global core.autocrlf true
  4. 忽略文件

    • core.excludesfile:指定一个全局的忽略文件,用于列出不应受版本控制的文件和目录。
    • 例如:git config --global core.excludesfile ~/.gitignore_global
  5. 分支合并策略

    • merge.tool:设置用于解决合并冲突的工具。
    • 例如:git config --global merge.tool kdiff3
  6. 查看提交历史

    • alias.log:设置自定义的 git log 命令别名。
    • 例如:git config --global alias.log "log --oneline --decorate"
  7. 远程仓库

    • remote.origin.url:设置远程仓库的 URL。
    • branch.<branchname>.remote:设置分支与远程仓库的关联。
    • 例如:git config remote.origin.url "https://github.com/username/repo.git"

这些是一些常用的 git config 命令选项,你可以根据自己的需求进行配置。使用 --global 参数将选项设置为全局级别,省略该参数则为当前仓库级别的配置。

git tag 标签的使用

标签(tag)相关的常用命令

  • git tag 查看标签
  • git tag <tag-name> 创建命名标签
  • git tag -a <tag-name> -m <message> 添加一个注解标签
  • git tag <tag-name> <commit-id> -a -m <message> 给过去提交记录创建标签
  • git push origin <tag-name> 推送标签到远程仓库
  • git push origin --tags 推送全部标签
  • git pull origin --tags 远程拉取标签
  • git tag -d <tag-name> 删除本地标签
  • git push origin :refs/tags/<tag-name> 删除远程标签

git remote

  • git remote:用于管理远程仓库
  • git remote:不带参数时可以查看远程仓库名称
  • git remote -v : 可以查看远程仓库名称和网址
  • git remote add 仓库名 仓库地址 : 添加远程仓库,同时设置远程仓库的名字
  • git remote rm origin : 删除名字为origin的远程仓库

git branch

  • git branch : 可以查看本地仓库的分支情况

  • git branch 分支名 : 创建分支

  • git checkout 分支名 : 切换到指定分支

    • 两个命令可以合成一个命令:git checkout -b 分支名 ,相当于创建分支后切换到新建分支
  • git branch -d 分支名 : 删除某个分支

  • git merge 分支名 : 合并某个分支到现在所处的分支

  • git branch -r : 查看远程仓库的分支情况

  • git branch -a : 查看所有分支的情况,即本地分支和远程分支(上面的部分是本地分支,下面红色的部分是远程的分支)

  • 远程分支的创建不能通过git branch进行,而是在git push的时候默认执行

  • 分支重命名:git branch -m oldname newname

git push

  • git push <远程主机名> <本地分支名> : <远程分支名>

    • 分支的推送顺序写法是:<来源地>:<目的地>
  • 远程分支的删除也不能使用git branch , 同样采用git push

    • git push <远程主机名> --delete <删除的分支名>
    • 或者:git push <远程主机名> : <远程分支名> ,省略了本地分支名相当于推送了一个空的本地分支到远程分支上,就相当于删除了远程分支

git fetch

  • git fetch这个命令用于取回远程仓库上的更新到本地仓库,默认是取回远程仓库上的所有更新,
  • 如果要取回执行分支上的内容,可以使用git fetch <远程仓库> <分支名>。这样取回的分支是不会影响本地仓库中的代码,通常用于查看他人进程,取回远程分支之后,可以在远程分支的基础上创建新的分支,也可以将远程分支和本地分支合并:git merge origin/dev or git rebase origin/dev : 表示将当前分支与远程分支合并

简介

  • Eigen 库常用的编程技巧

eigen3 两个矩阵相乘 示例详解

Eigen是一个C++模板库,用于线性代数操作,包括矩阵相乘。Eigen的3.x版本中提供了一个简洁而强大的矩阵相乘接口,用于进行矩阵乘法运算。下面是一个简单的示例,展示如何在Eigen中进行两个矩阵的相乘。

首先,确保你已经安装了Eigen库,并且包含了适当的头文件。通常,你需要在代码中包含类似这样的头文件:

1
#include <Eigen/Dense>

然后,你可以使用Eigen库来执行矩阵相乘操作。以下是一个示例代码,假设你已经创建了两个矩阵 A 和 B,并且想要计算它们的乘积 C。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <iostream>
#include <Eigen/Dense>

int main() {
// 创建矩阵 A 和 B
Eigen::MatrixXd A(3, 3); // 3x3 矩阵
Eigen::MatrixXd B(3, 3); // 3x3 矩阵

// 初始化矩阵 A 和 B
A << 1, 2, 3,
4, 5, 6,
7, 8, 9;

B << 9, 8, 7,
6, 5, 4,
3, 2, 1;

// 计算矩阵相乘 C = A * B
Eigen::MatrixXd C = A * B;

// 打印结果
std::cout << "Matrix A:\n" << A << std::endl;
std::cout << "Matrix B:\n" << B << std::endl;
std::cout << "Matrix C (A * B):\n" << C << std::endl;

return 0;
}

在这个示例中,我们首先创建了两个3x3的矩阵 A 和 B,并使用<<操作符初始化它们。然后,我们使用*运算符将矩阵 A 和 B 相乘,将结果存储在矩阵 C 中。

最后,我们打印了矩阵 A、B 和 C 的值。你会看到矩阵 C 包含了矩阵 A 和 B 的乘积。

这只是一个简单的示例,展示了如何在Eigen中进行矩阵相乘操作。Eigen提供了丰富的线性代数功能,包括各种矩阵运算和分解,使其成为处理线性代数问题的强大工具。

Eigen::Vector3d 获取元素值

在Eigen C++库中,Eigen::Vector3d 是一个表示三维向量的类。要获取Eigen::Vector3d 对象的元素值,你可以使用operator[]或者成员函数x(), y()z()。下面是一些示例代码:

  1. 使用 operator[]

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #include <Eigen/Dense>

    int main() {
    Eigen::Vector3d v(1.0, 2.0, 3.0);

    double x = v[0]; // 获取第一个元素
    double y = v[1]; // 获取第二个元素
    double z = v[2]; // 获取第三个元素

    return 0;
    }
  2. 使用成员函数 x(), y()z()

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #include <Eigen/Dense>

    int main() {
    Eigen::Vector3d v(1.0, 2.0, 3.0);

    double x = v.x(); // 获取第一个元素
    double y = v.y(); // 获取第二个元素
    double z = v.z(); // 获取第三个元素

    return 0;
    }

两种方法都可以用来获取向量的元素值。选择哪种方法取决于你的偏好和代码的上下文。使用 operator[] 更类似于访问普通的数组,而使用成员函数则更加直观,因为它们使用了更具描述性的名称。

Eigen::Vector3f 示例

以下是一个简单的示例,演示了如何使用Eigen库中的Eigen::Vector3f来执行向量计算操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <iostream>
#include <Eigen/Dense>

int main()
{
// 声明两个三维浮点数向量
Eigen::Vector3f v1(1.0, 2.0, 3.0);
Eigen::Vector3f v2(4.0, 5.0, 6.0);

// 向量加法
Eigen::Vector3f sum = v1 + v2;

// 向量点积
float dotProduct = v1.dot(v2);

// 向量叉积
Eigen::Vector3f crossProduct = v1.cross(v2);

// 打印结果
std::cout << "v1: " << v1.transpose() << std::endl;
std::cout << "v2: " << v2.transpose() << std::endl;
std::cout << "Sum: " << sum.transpose() << std::endl;
std::cout << "Dot product: " << dotProduct << std::endl;
std::cout << "Cross product: " << crossProduct.transpose() << std::endl;

return 0;
}

在这个示例中,我们首先包含了Eigen库的头文件,并声明了两个三维浮点数向量 v1v2。然后,我们执行了向量加法、点积和叉积操作,并输出了结果。

请确保您已经正确安装了Eigen库,并且能够通过编译器访问该库。在实际应用中,您可以使用g++或其他支持C++的编译器来编译和运行这段示例代码。

简介

  • Eigen 第三方库基础知识
  • Eigen,仅包含头文件即可

eigen3 Eigen::MatrixBaseEigen::Vector3d::normalized()函数 详解

Eigen::MatrixBase<Eigen::Vector3d>::normalized() 函数用于返回一个单位向量,即输入向量的归一化版本。这个函数返回一个新的向量,该向量具有与原始向量相同的方向,但长度为1。

下面是一些关键的详解:

1
Eigen::MatrixBase<Eigen::Vector3d>::normalized()
  • 返回类型: 返回类型是 Eigen::MatrixBase<Derived>,其中 Derived 表示输入矩阵或向量的派生类类型。

  • 用途: normalized() 函数用于将向量归一化,即将其缩放为单位长度。

  • 注意事项:

    • 如果输入向量的长度为零,则 normalized() 会产生一个未定义的结果。
    • 对于零向量,normalized() 返回与原始向量相同的零向量。
    • normalized() 函数不会修改原始向量,而是返回一个新的归一化向量。
  • 示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #include <iostream>
    #include <Eigen/Dense>

    int main() {
    Eigen::Vector3d v(1.0, 2.0, 3.0);
    Eigen::Vector3d normalized_v = v.normalized();

    std::cout << "Original Vector: " << v << std::endl;
    std::cout << "Normalized Vector: " << normalized_v << std::endl;

    return 0;
    }

    这个示例中,normalized_v 将包含 v 的单位向量。

总的来说,normalized() 函数在Eigen库中是用于向量归一化的方便方法。归一化是在计算机图形学、机器学习和其他领域中经常使用的操作,它确保向量的长度为1,并保持原始向量的方向。

Eigen::Isometry3d 类 详解

Eigen::Isometry3d 是Eigen库中的一个类,用于表示三维空间中的等距变换(Isometry Transformation),也称为刚体变换(Rigid Transformation)。等距变换包括平移和旋转,通常用于表示物体在三维空间中的姿态和位置。

以下是关于 Eigen::Isometry3d 类的详细信息:

构造函数

1
Eigen::Isometry3d transform = Eigen::Isometry3d::Identity();

构造函数用于创建一个等距变换,通常初始化为单位等距变换,表示物体的初始位置和姿态。

成员函数

  1. translation()
    返回等距变换的平移部分,它是一个三维向量表示平移的位移。

  2. translation()(重载):
    设置等距变换的平移部分。

  3. rotation()
    返回等距变换的旋转部分,它是一个Eigen::Matrix3d表示旋转矩阵。

  4. matrix()
    返回等距变换的矩阵表示,是一个Eigen::Matrix4d矩阵。

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
#include <Eigen/Geometry>

int main() {
// 创建等距变换,表示平移(1, 2, 3)并绕X轴旋转45度
Eigen::Isometry3d transform = Eigen::Isometry3d::Identity();
transform.translation() = Eigen::Vector3d(1.0, 2.0, 3.0);
transform.rotate(Eigen::AngleAxisd(M_PI / 4.0, Eigen::Vector3d::UnitX()));

// 获取平移部分和旋转部分
Eigen::Vector3d translation = transform.translation();
Eigen::Matrix3d rotation = transform.rotation();

// 输出结果
std::cout << "平移部分:" << translation.transpose() << std::endl;
std::cout << "旋转部分:" << std::endl << rotation << std::endl;

// 获取等距变换的矩阵表示
Eigen::Matrix4d transform_matrix = transform.matrix();
std::cout << "等距变换矩阵:" << std::endl << transform_matrix << std::endl;

return 0;
}

在上述示例中,我们创建了一个等距变换对象,并使用成员函数设置其平移部分和旋转部分。然后,我们分别获取了平移部分和旋转部分,并输出了等距变换的矩阵表示。

Eigen::Isometry3d 类是Eigen库中用于表示三维等距变换的重要工具。它允许您方便地表示和操作物体在三维空间中的姿态和位置,这在机器人学、计算机图形学和仿真等领域中非常有用。

Eigen::AngleAxisd 类 详解

Eigen::AngleAxisd 是Eigen库中的一个类,用于表示轴角(Axis-Angle)形式的旋转。轴角表示是一种用于描述三维空间中的旋转的常见方式,它包括一个旋转轴和一个旋转角度。该类位于Eigen库的Eigen/Geometry模块中。

以下是关于 Eigen::AngleAxisd 类的详细信息:

构造函数

1
Eigen::AngleAxisd(const Scalar& angle, const Vector3d& axis)
  • angle:旋转角度,以弧度表示。
  • axis:旋转轴的单位向量。

构造函数用于创建一个轴角表示的旋转,指定旋转角度和旋转轴。

成员函数

  1. angle()
    返回轴角表示中的旋转角度(以弧度表示)。

  2. axis()
    返回轴角表示中的旋转轴,它是一个单位向量。

  3. toRotationMatrix()
    将轴角表示转换为旋转矩阵(Eigen::Matrix3d),这个矩阵可以用于执行坐标变换。

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
#include <Eigen/Geometry>

int main() {
// 创建轴角表示的旋转(绕X轴旋转45度)
Eigen::AngleAxisd rotation(M_PI / 4.0, Eigen::Vector3d::UnitX());

// 获取旋转角度和旋转轴
double angle = rotation.angle();
Eigen::Vector3d axis = rotation.axis();

// 输出结果
std::cout << "旋转角度 (弧度): " << angle << std::endl;
std::cout << "旋转轴: " << axis.transpose() << std::endl;

// 将轴角表示转换为旋转矩阵
Eigen::Matrix3d rotation_matrix = rotation.toRotationMatrix();
std::cout << "旋转矩阵:" << std::endl << rotation_matrix << std::endl;

return 0;
}

在上述示例中,我们创建了一个轴角表示的旋转对象,并使用成员函数获取旋转角度和旋转轴。然后,我们使用 toRotationMatrix() 函数将轴角表示转换为旋转矩阵。

Eigen::AngleAxisd 类是Eigen库中用于处理轴角旋转的重要工具,它使您能够方便地表示和操作旋转信息。您可以使用旋转矩阵来执行坐标变换,或将其与其他旋转进行组合。这对于机器人学、计算机图形学和仿真等领域非常有用。

Eigen::Matrix3d 数据结构 详解

Eigen::Matrix3d 是Eigen库中的一个数据结构,表示一个3x3的矩阵,其中d表示矩阵元素的数据类型为double。Eigen库是一个用于线性代数操作的C++库,提供了高性能的矩阵和向量运算,特别适用于数学和科学计算。

Eigen::Matrix3d 可以用来表示各种线性代数和几何学中的3x3矩阵,如旋转矩阵、变换矩阵、协方差矩阵等。这个数据结构在计算机图形学、机器人学、物理模拟等领域中经常被使用。

以下是一些关于Eigen::Matrix3d的详细信息和常见操作:

  1. 构造函数:您可以使用多种构造函数创建Eigen::Matrix3d对象。例如:

    1
    2
    Eigen::Matrix3d mat1; // 默认构造函数,创建零矩阵
    Eigen::Matrix3d mat2(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0); // 从给定的元素创建矩阵
  2. 元素访问:您可以通过行和列索引来访问矩阵的元素。Eigen库支持使用(i, j)ij索引方式,其中(i, j)表示第i行、第j列的元素,ij从0开始。

    1
    2
    double element = mat2(1, 2); // 访问第2行第3列的元素
    double element_row_col = mat2.row(1)[2]; // 也可以使用行和列的方式访问
  3. 矩阵运算:您可以对Eigen::Matrix3d对象执行各种矩阵运算,如矩阵加法、矩阵乘法、矩阵转置等。Eigen库提供了丰富的运算符重载和成员函数来进行这些操作。

    1
    2
    3
    Eigen::Matrix3d result = mat1 + mat2; // 矩阵加法
    Eigen::Matrix3d product = mat1 * mat2; // 矩阵乘法
    Eigen::Matrix3d transposed = mat1.transpose(); // 矩阵转置
  4. 单位矩阵:您可以使用Eigen::Matrix3d::Identity()来创建一个单位矩阵。

    1
    Eigen::Matrix3d identity = Eigen::Matrix3d::Identity();
  5. 行和列操作:Eigen库提供了许多操作来处理矩阵的行和列,如获取行、列、设置行、列等。

    1
    2
    3
    Eigen::Vector3d row_vector = mat2.row(1); // 获取第2行
    Eigen::Vector3d col_vector = mat2.col(2); // 获取第3列
    mat2.row(0) = Eigen::Vector3d(10.0, 20.0, 30.0); // 设置第1行的值
  6. 其他操作:Eigen库还提供了许多其他操作,如求逆、行列式计算、特征值分解等。

Eigen::Matrix3d 是Eigen库中一个非常有用的数据结构,用于表示和处理3x3矩阵数据。您可以使用它来执行各种线性代数和几何计算。Eigen库还支持其他矩阵大小的数据结构,如Eigen::Matrix4dEigen::MatrixXd(动态大小矩阵)等,以满足不同的需求。

Eigen::Vector3d 数据结构 详解

Eigen::Vector3d 是Eigen库中的一个数据结构,表示三维向量,其中d表示向量元素的数据类型为double。Eigen库是一个用于线性代数操作的C++库,提供了高性能的矩阵和向量运算,特别适用于数学和科学计算。

Eigen::Vector3d 表示一个包含三个double类型元素的向量,通常用于表示三维空间中的位置、方向或其他三维向量数据。这个数据结构在机器人学、计算机图形学、物理模拟等领域中经常被使用。

以下是一些关于Eigen::Vector3d的详细信息和常见操作:

  1. 构造函数:您可以使用多种构造函数创建Eigen::Vector3d对象。例如:

    1
    2
    Eigen::Vector3d v1;           // 默认构造函数,创建零向量 (0, 0, 0)
    Eigen::Vector3d v2(1.0, 2.0, 3.0); // 从给定的元素创建向量
  2. 元素访问:您可以通过下标或成员函数来访问向量的元素。例如:

    1
    2
    3
    4
    5
    6
    7
    8
    double x = v2[0]; // 访问第一个元素(x坐标)
    double y = v2[1]; // 访问第二个元素(y坐标)
    double z = v2[2]; // 访问第三个元素(z坐标)

    // 或者使用成员函数
    double x = v2.x();
    double y = v2.y();
    double z = v2.z();
  3. 向量运算:您可以对Eigen::Vector3d对象执行各种向量运算,如加法、减法、点积、叉积等。Eigen库提供了丰富的运算符重载和成员函数来进行这些操作。

    1
    2
    3
    4
    Eigen::Vector3d result = v1 + v2; // 向量加法
    Eigen::Vector3d diff = v1 - v2; // 向量减法
    double dot_product = v1.dot(v2); // 点积
    Eigen::Vector3d cross_product = v1.cross(v2); // 叉积
  4. 归一化:您可以使用成员函数将向量归一化为单位向量。

    1
    v2.normalize(); // 归一化v2为单位向量
  5. 长度和距离:您可以使用成员函数计算向量的长度(模)或两个点之间的距离。

    1
    2
    double length = v2.norm(); // 向量的长度
    double distance = (v1 - v2).norm(); // 两个点之间的距离
  6. 其他操作:Eigen库提供了许多其他操作,如向量的投影、反射、角度计算等。

Eigen::Vector3d 是Eigen库中一个非常有用的数据结构,用于表示和处理三维向量数据。您可以使用它来执行各种线性代数和几何计算。注意,Eigen库支持其他数据类型的向量,如Eigen::Vector3ffloat类型元素)和Eigen::Vector3iint类型元素)等,以满足不同的需求。

Eigen::Vector3f 详解

在C++中,Eigen是一个开源的线性代数库,用于高效地进行矩阵和向量计算。Eigen::Vector3f是Eigen库中表示三维浮点数向量的数据类型。

下面是对Eigen::Vector3f的详细解释:

  1. Eigen库
    Eigen是一个C++模板库,专注于线性代数运算。它提供了各种矩阵和向量操作,包括基本的线性代数运算、矩阵分解、特征值计算等。Eigen的设计目标是高性能和表达力,适用于各种科学计算和工程应用。

  2. Eigen::Vector3f
    Eigen::Vector3f是Eigen库中的一个模板类,表示一个三维浮点数向量。这个向量类包含了三个浮点数字段,分别表示向量的 x、y 和 z 分量。

    1
    2
    Eigen::Vector3f v;  // 声明一个三维浮点数向量
    v << 1.0, 2.0, 3.0; // 设置向量的 x、y 和 z 分量

    在Eigen中,向量和矩阵都是模板类,它们提供了许多重载的操作符和函数,使得线性代数运算变得方便和高效。

    使用Eigen::Vector3f时,您可以执行向量加法、减法、点积、叉积、标量乘法等操作,以及其他线性代数运算。例如:

    1
    2
    3
    4
    5
    6
    Eigen::Vector3f v1(1.0, 2.0, 3.0);
    Eigen::Vector3f v2(4.0, 5.0, 6.0);

    Eigen::Vector3f sum = v1 + v2;
    float dotProduct = v1.dot(v2);
    Eigen::Vector3f crossProduct = v1.cross(v2);

    此外,Eigen还提供了丰富的线性代数函数,使您能够执行向量的归一化、取模、求距离、求角度等操作。

总之,Eigen::Vector3f是Eigen库中用于表示三维浮点数向量的类型。它是Eigen库在处理线性代数运算时的基本构建块之一,方便高效地进行各种向量计算和分析。

Eigen 是什么

Eigen是一个用于线性代数运算的C++模板库。它提供了许多用于向量、矩阵、数组和其他线性代数对象的数学运算和操作。Eigen是一个开源库,具有高性能和易用性的特点,广泛用于科学计算、图形学、机器学习和机器人等领域。

以下是Eigen库的一些特点:

  1. 高性能:Eigen通过使用表达式模板技术和编译时优化,能够生成高效的代码,提供快速的数值计算。

  2. 简洁易用:Eigen提供了简洁的API,使得进行线性代数运算变得直观和易于理解。它支持类似于数学符号的语法,使得代码更加清晰和可读。

  3. 丰富的功能:Eigen提供了广泛的线性代数运算功能,包括矩阵和向量的基本运算(如加法、乘法、转置等)、线性方程求解、特征值计算、奇异值分解、矩阵分解等。

  4. 跨平台支持:Eigen是一个纯头文件库,没有外部依赖,可以方便地在不同的操作系统和编译器上使用。

  5. 可扩展性:Eigen支持自定义类型和运算,可以与现有的代码和数据结构集成,并方便地扩展功能。

Eigen的语法和用法类似于数学符号,使得编写线性代数相关的代码更加直观和易于维护。它被广泛应用于科学计算、机器学习、计算机图形学等领域,是C++中进行线性代数运算的常用工具库之一。

总结来说,Eigen是一个高性能、易用且功能丰富的C++线性代数库,用于进行矩阵、向量和其他线性代数对象的数学运算。


Eigen 详解

Eigen是一个C++模板库,用于进行线性代数运算和数值计算。它提供了丰富的线性代数功能,包括矩阵和向量的基本运算、线性方程求解、特征值计算、奇异值分解、矩阵分解等。以下是Eigen库的一些详细解释:

  1. 数据结构:Eigen库通过模板类来定义不同类型的线性代数对象,如矩阵(Matrix)、向量(Vector)、数组(Array)等。这些对象可以具有不同的维度和数据类型,如动态大小或静态大小的矩阵。

  2. 数学运算:Eigen提供了大量的数学运算操作符和函数,使得进行线性代数运算变得方便和直观。例如,你可以使用运算符进行矩阵和向量的加法、减法、乘法和除法操作,还可以进行转置、逆矩阵、点积、叉积等运算。

  3. 线性方程求解:Eigen提供了多种方法来求解线性方程组,包括常规的LU分解、QR分解、Cholesky分解等。你可以使用这些方法来解决线性方程组、最小二乘问题和最小化问题等。

  4. 特征值和奇异值计算:Eigen支持计算矩阵的特征值和特征向量,以及奇异值分解。这些计算对于矩阵的分析和特征提取非常有用。

  5. 矩阵分解:Eigen提供了多种矩阵分解的方法,如LU分解、QR分解、Cholesky分解等。这些分解方法可以用于解决矩阵方程、计算矩阵的逆等问题。

  6. 数值计算性能:Eigen通过使用表达式模板技术和编译时优化,生成高效的代码,提供了出色的数值计算性能。它能够自动进行向量化和并行化处理,以充分利用现代计算机的硬件特性。

  7. 跨平台支持:Eigen是一个纯头文件库,没有外部依赖,可以在不同的操作系统和编译器上进行使用。它与标准的C++语法和库相容,易于集成到现有的C++项目中。

Eigen是一个广泛应用于科学计算、机器学习、计算机图形学等领域的工具库。它提供了强大的线性代数功能和高性能的数值计算能力,使得进行复杂的数学运算变得更加简单和高效。

如果你需要更详细的信息和示例代码,可以参考Eigen官方文档和示例。


Eigen 官网

Eigen的官方网站是:https://eigen.tuxfamily.org/

在Eigen官网上,你可以找到关于Eigen库的详细文档、示例代码、教程和其他资源。以下是一些在Eigen官网上可以找到的主要内容:

  1. 文档:Eigen官网提供了全面的文档,包括用户手册、快速入门指南、API参考等。文档详细介绍了Eigen库的各个方面,包括使用方法、功能特性、使用示例等。

  2. 示例代码:Eigen官网提供了大量的示例代码,涵盖了各种线性代数运算和数值计算的常见用法。这些示例代码可以帮助你快速上手并理解Eigen库的使用方法。

  3. 教程:Eigen官网上提供了一些教程和指南,帮助你深入了解Eigen库的内部机制和高级功能。这些教程涵盖了Eigen的设计原理、性能优化技巧、高级数学运算等方面的内容。

  4. 下载和安装:Eigen官网提供了源代码的下载链接和安装指南。你可以根据自己的需要下载适合的版本,并按照安装指南进行配置和编译。

  5. 社区和支持:Eigen官网上有用户论坛和邮件列表,你可以在这里与其他用户交流经验、提问问题和寻求帮助。此外,官方网站还提供了联系开发团队的方式,以便于反馈bug、提供反馈和建议等。

通过Eigen官方网站,你可以获取关于Eigen库的最新信息、更新、支持和社区交流。如果你对Eigen库有兴趣或需要使用它进行线性代数运算和数值计算,官方网站是一个很好的起点。

请注意,由于网站内容可能会有更新,建议你访问Eigen官方网站以获取最新的信息和资源。


Eigen 示例

以下是一个简单的示例,展示了Eigen库的基本用法和一些常见的线性代数运算:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <iostream>
#include <Eigen/Dense>

int main() {
// 创建矩阵
Eigen::Matrix3f A;
A << 1, 2, 3,
4, 5, 6,
7, 8, 9;

// 创建向量
Eigen::Vector3f b(1, 2, 3);

// 解线性方程 Ax = b
Eigen::Vector3f x = A.lu().solve(b);

// 输出结果
std::cout << "Solution:\n" << x << std::endl;

// 计算特征值和特征向量
Eigen::SelfAdjointEigenSolver<Eigen::Matrix3f> eigensolver(A);
if (eigensolver.info() != Eigen::Success) {
std::cout << "Failed to compute eigenvalues!" << std::endl;
return 1;
}
std::cout << "Eigenvalues:\n" << eigensolver.eigenvalues() << std::endl;
std::cout << "Eigenvectors:\n" << eigensolver.eigenvectors() << std::endl;

return 0;
}

在这个示例中,我们首先创建了一个3x3的矩阵A和一个3维向量b。然后,使用A.lu().solve(b)求解线性方程Ax = b,得到解x。我们输出了解x的值。

接下来,我们使用Eigen库的SelfAdjointEigenSolver来计算矩阵A的特征值和特征向量。通过eigensolver.eigenvalues()和eigensolver.eigenvectors(),我们分别获取了特征值和特征向量,并将它们输出到控制台。

请确保在使用这个示例之前,已经正确安装了Eigen库,并将其包含路径配置正确。

这只是Eigen库的一个简单示例,Eigen库还提供了许多其他功能和操作,如矩阵乘法、逆矩阵、奇异值分解等。你可以在Eigen的官方文档和示例中找到更多详细的用法和示例代码。


Eigen 安装第三方库

在Linux系统上安装Eigen库可以按照以下步骤进行操作:

  1. 打开终端,并确保你的系统已经安装了C++编译器和CMake工具。

  2. 下载Eigen库的源代码。你可以从Eigen的官方网站(https://eigen.tuxfamily.org/)下载最新版本的源代码压缩包,或者使用Git进行克隆。

    例如,使用Git进行克隆:

    1
    git clone https://gitlab.com/libeigen/eigen.git
  3. 进入Eigen源代码的目录:

    1
    cd eigen
  4. 创建一个用于构建Eigen库的目录,并进入该目录:

    1
    mkdir build && cd build
  5. 运行CMake命令生成构建文件:

    1
    cmake ..
  6. 使用make命令进行编译:

    1
    make
  7. (可选)运行make install命令将库安装到系统目录中:

    1
    sudo make install

    注意:执行make install命令可能需要root权限。

现在,你已经成功在Linux系统上安装了Eigen库。你可以在自己的C++项目中包含Eigen的头文件,并链接Eigen库进行使用。

例如,在你的C++源文件中,使用以下方式包含Eigen的头文件:

1
#include <Eigen/Dense>

然后,你就可以使用Eigen库提供的各种功能进行线性代数运算和数值计算了。

请注意,安装过程中的具体命令可能会因系统环境和Eigen库的版本而有所不同。建议在安装过程中仔细阅读Eigen的文档,并按照其中的指导进行操作。

另外,如果你使用的是特定的Linux发行版,也可以尝试通过包管理器安装Eigen库。例如,使用apt包管理器安装Eigen:

1
sudo apt-get install libeigen3-dev

这将自动安装Eigen库及其相关的开发文件到系统中,使你能够在C++项目中直接使用Eigen库。

头文件

在使用Eigen库时,你可以根据需要包含不同的头文件。以下是一些常用的Eigen头文件:

  1. Eigen/Dense:包含了Eigen库的核心功能,如矩阵、向量和数组的定义和运算符重载。

  2. Eigen/Core:提供了Eigen库的基本功能和类型定义,是Eigen/Dense头文件的核心部分。

  3. Eigen/Eigenvalues:包含了计算矩阵特征值和特征向量的功能。

  4. Eigen/SVD:提供了奇异值分解(Singular Value Decomposition,SVD)的功能。

  5. Eigen/QR:提供了QR分解的功能。

  6. Eigen/LU:提供了LU分解的功能。

  7. Eigen/Cholesky:提供了Cholesky分解的功能。

  8. Eigen/Geometry:包含了用于几何计算的功能,如旋转矩阵、变换矩阵等。

这只是一小部分常用的Eigen头文件。根据你的具体需求,你可能还需要包含其他特定的头文件。Eigen库的头文件结构清晰,你可以根据你的具体使用情况选择包含适当的头文件。

例如,在你的C++源文件中,你可以按照以下方式包含Eigen库的头文件:

1
2
3
4
#include <Eigen/Dense>          // 包含核心功能
#include <Eigen/Eigenvalues> // 计算特征值和特征向量
#include <Eigen/SVD> // 奇异值分解
#include <Eigen/QR> // QR分解

请注意,在包含Eigen库的头文件之前,确保你已经正确安装并配置了Eigen库。同时,根据你的操作系统和安装方式,可能需要调整头文件的路径。

希望这些信息能帮助你使用Eigen库进行C++编程!

简介

  • Git的理论基础知识

Git工作流程

  1. 克隆Git资源作为工作目录
  2. 在克隆的资源上添加或者修改文件
  3. 如果其他人修改了,你可以更新资源
  4. 在提交前查看修改
  5. 提交修改
  6. 在修改完成后,如果发现错误,可以撤回提交并再次修改并提交

基本概念:工作区,暂存区和版本库

  • 工作区:就是在电脑里能够看到的目录
  • 暂存区:英文叫stage或index,一般放在.git目录下的index文件中,所以把暂存区有时也叫做索引(index)
  • 版本库:工作区有一个隐藏目录.git,这个不算工作区,而是git的版本库
  1. 当对工作区修改(或新增)的文件执行 git add 命令时,暂存区的目录树被更新,同时工作区修改(或新增)的文件内容被写入到对象库中的一个新的对象中,而该对象的ID被记录在暂存区的文件索引中
  2. 当执行提交操作时 git commit 时,暂存区的目录树写到版本库(对象库)中,master分支会做相应的更新,即master只想的目录树就是提交时暂存区的目录树.

Git官方手册

Git的三种状态:已提交(committed), 已修改(modified)和已暂存(staged)

  • 已修改:表示修改了文件,但还没有保存到数据库中
  • 已暂存:表示对一个已修改文件的当前版本做了标记,使之包含在下次提交的快照中
  • 已提交:表示数据已经安全地保存在本地数据库中

这会让Git项目拥有三个三阶段:工作区, 暂存区和Git目录

  • 工作区:是对项目的某个版本独立提取出来的内容,这些从Git仓库的压缩数据中提取出来的文件,放在磁盘上进行使用或修改
  • 暂存区:是一个文件,保存了下次将要提交的文件列表信息,一般在Git仓库目录中.按照Git的术语叫做”索引”,不过一般说法还是叫”暂存区”
  • Git仓库目录:是Git用来保存项目的元数据和对象数据库的地方.这是Git中最重要的部分,从其他计算机克隆仓库时,复制的就是这里的数据.

基本的Git工作流程

  1. 在工作区中修改文件
  2. 将想要下次提交的更改 选择性地暂存,这样只会将更改的部分添加到暂存区
  3. 提交更新,找到暂存区的文件,将快照永久性存储到Git目录

.gitignore 文件

  • In the project, it does not need to save all of the files. And the .gitignore file is used to save the folders which do not need to save.
  • 在工程中,并不是所有文件都需要保存到版本库中。在Git工作区的根目录下创建一个特殊的.gitignore文件,把要忽略的文件名填进去,Git就会自动忽略这些文件或目录
  • 匹配规则
    • 空格不匹配任意文件,可作为分隔符,可用反斜杠转义
    • 开头的文件标识注释,可以使用反斜杠进行转义
    • / 结束的模式只匹配文件夹以及在该文件夹路径下的内容,但是不匹配该文件
    • / 开始的模式匹配项目和目录
    • ? 通用匹配单个字符
    • * 通用匹配零个或多个字符
    • [] 通用匹配单个字符列表

工作流

  1. working directory:持有实际文件
  2. Index:类似于一个缓冲区与,临时保存文件的改动
  3. HEAD:指向最后一次提交的结果

添加与提交

  1. 把文件添加到暂存区: git add <filename>
  2. 提交改动信息: git commit -m "代码提交信息". (至此,改动已经提交到了HEAD,但是还没有到远端仓库)
  3. 推送改动: git push origin master(master 换成想要推送的分支)

简介

  • github 平台使用

使用https

  • 清除所有的git配置

    • sudo aptitude purge git
  • 在github生成token,它具有访问项目的权限

  • 安装gh工具

    • sudo apt install gh
  • 配置个人信息

    • gh auth login
    • username:
    • token
  • git使用https

git clone 出错

  • 今天克隆GitHub仓库中的项目时,执行git clone git://github.com/alibaba/Tangram-Android.git却失败报错:
    1
    2
    Cloning into 'Tangram-Android'...
    fatal: unable to access 'http://github.com/alibaba/Tangram-Android.git/': OpenSSL SSL_read: Connection was reset, errno 10054
  • 解决方法,需要执行以下两个步骤:
    • 输入git config –global http.sslVerify “false”,解除SSL验证;
    • 将地址https://改为git://,避开SSL验证。

git连接到github远程仓库,并提交代码至远程仓库

  • 设置用户名和邮箱

    • git config --global user.name "elliot53"
    • git config --global user.email "1604244855@qq.com"
  • 查看配置的用户名和邮箱

    • git config user.name
    • git config user.email
  • 生成SSH Key密钥

    • ssh-keygen -t rsa -C "1604244855@qq.com"
    • 连续按下三次回车,密钥会在第一次回车的时候,输出密钥文件将要保存的位置
  • 获取SSH Key密钥

    • cat /root/.ssh/rsa.pub
    • 选中并复制全部密钥(ssh-rsa开始,一直到.com结束)
  • 配置github密钥

    • 打开github-settings
    • 选择SSH and GPG keys
    • 点击New SSH key
    • 填入title和key
  • 在本地仓库配置远程仓库地址,本地仓库链接远程仓库

    • 复制远程仓库的ssh地址
    • git remote add origin_ssh ssh@github.com/elliot53/notes.git
  • 测试链接是否成功

    • ssh -T git@github.com
  • 脚本

    1
    2
    3
    4
    5
    6
    7
    8
    git config --global user.name "elliot53"
    git config --global user.email "1604244855@qq.com"
    git config user.name
    git config user.email
    ssh-keygen -t rsa -C "1604244855@qq.com"
    cat ~/.ssh/id_rsa.pub
    git remote add origin_ssh ssh@github.com/elliot53/notes.git
    ssh -T git@github.com

什么是GitHub Actions

  • 一个简单的需求,是在仓库出现更改时自动更新构建与部署博客。其实,监视仓库并在由改动时自动执行一系列动作是非常广泛的需求。软件开发工作中,经常需要对新添加的代码随时进行测试,或者进行部署,都是通过这样的自动化流程实现的。

  • 实际上,这类服务还有个专业名词: 持续集成(Continuous Intergration)/持续部署(Continuous Deploy),简称CI/CD

  • 此前,最广泛使用的CI服务当属于Travis CI;现在GitHub也推出了自家的CI服务GitHub Actions。

  • 当仓库收到新的更新(push)时,GitHub会根据仓库中.github/workflows文件夹下的YAML配置文件启动CI流程

简介

  • Git常见的使用技巧

写了很多代码,发现写错了分支怎么办

  • 未提交的情况下

    • git add . (把所有改动暂存)
    • git stash (把暂存的文件提交到git的暂存栈)
    • git checkout 本该提交代码的分支
    • git stash pop (将暂存栈中的代码放出来)
  • 至于是继续改还是提交就随你了

  • 已提交的情况下

    • git checkout 不该提交代码提交了代码的分支
    • git reset HEAD~1 (最近一次提交放回暂存区, 并取消此次提交)
    • git stash (把暂存的文件提交到git的暂存栈)
    • git checkout 该提交代码的分支
    • git stash pop
  • 下面一顿操作随你猛了,等你把代码提交到了正确的分支后,再次切到刚刚错的分支

git 迭代拉取子项目

在 Git 中,如果你有一个父项目,而该项目包含了子项目,你可能希望在父项目中拉取或更新这些子项目。这种情况下,通常会使用 Git 的子模块(submodule)功能。子模块允许你在一个 Git 仓库中引用另一个仓库。

要拉取或更新子项目,可以按照以下步骤进行:

  1. 添加子模块:如果尚未添加子模块,可以使用以下命令将子模块添加到父项目中:

    1
    git submodule add <URL-of-submodule-repository> <path-to-store-submodule>

    例如:

    1
    git submodule add https://github.com/example/submodule.git path/to/submodule
  2. 初始化子模块:在克隆父项目后,子模块目录中可能还没有子模块的文件。要初始化子模块,可以运行:

    1
    git submodule init
  3. 更新子模块:一旦子模块被添加并初始化,你可以使用以下命令更新子模块到父项目所引用的特定版本:

    1
    git submodule update --remote

    这会将每个子模块更新到它们在父项目中所引用的最新提交。

记住,当你拉取父项目时,子模块不会自动更新。你需要显式运行 git submodule update --remote 来更新子模块。

这些是用于在 Git 中迭代拉取子项目的基本步骤。

git 仅检查指定项目 忽略子项目

在Git中,如果你想仅检查指定项目而忽略子项目,你可以使用.gitignore文件来指定哪些文件或目录应该被忽略。在.gitignore中,你可以列出你希望忽略的文件或目录的模式。

以下是一些建议:

  1. 创建.gitignore文件: 在你的项目根目录下创建一个名为.gitignore的文件。

  2. 编辑.gitignore文件: 打开.gitignore文件并添加你希望忽略的文件或目录的模式。如果你想忽略所有子项目,你可以使用通配符(如/*)来匹配所有直接子目录。例如:

    1
    2
    /*
    !/指定项目/

    这将忽略根目录下的所有内容,但允许指定项目目录被追踪。

  3. 将.gitignore文件添加到版本控制: 确保将.gitignore文件添加到Git版本控制中,这样其他人克隆你的仓库时也会遵循这些规则。

    1
    2
    git add .gitignore
    git commit -m "Add .gitignore to ignore subprojects"
  4. 更新.gitignore: 如果在项目的后续开发中需要调整忽略规则,只需更新.gitignore文件并提交更改即可。

请记住,.gitignore文件中的模式是相对于.gitignore所在目录的相对路径的。确保你的规则符合你的项目结构。

git config 查看默认编辑器

要查看 Git 的默认文本编辑器,可以使用以下命令:

1
git config --global core.editor

上述命令将显示全局配置中设置的默认编辑器。如果没有设置默认编辑器,它将不会返回任何输出。

如果你在命令行中看到了输出,它将是你当前配置的默认编辑器的名称或路径。常见的编辑器包括 Vim、Emacs、Nano、Sublime Text、Visual Studio Code 等。

撤回本地修改

  • 放弃对本地已经修改,但是尚未提交的文件的修改,还原到其未修改前的状态
  • 命令
    • 撤回对所有已经修改,但是未提交的文件的修改,但不包括新增的文件
      • git checkout .
    • 撤回对指定文件的修改,[filename]为文件名
      • git checkout [filename]

git reset 回退项目版本

  • 可以回退到任意已经提交过的版本,已经add, commit但是没有push的文件也适用
  • 命令
    • git reset --hard [commit-hashcode]
  • 参数:
    • commit-hashcode 是某个commit的哈希值,可以适用git log查看
    • 因此,一般用法是先用git log 查看具体commit的哈希值,然后reset到那个版本

对于新增文件

  • 撤回本地修改和回退项目版本都不会对新增文件起作用。因为新增的文件是还未加到git的记录里面的,即属于未被tracked的状态,所以撤销修改和回退均对其不受影响。
  • 解决方法:
    • 直接手动删除文件即可

上游分支 upstream

  • upstream意为上游,即本地分支所对应的远程分支。

  • 一般,本地分支如果是从clone或者fetch得到的,都在远程库有一个upstream分支。

  • 设置upstream的方法有两种:

    • 在push的时候指定:git push --set-upstream origin my_remote_branch_name
    • 在新建分支的时候指定:git branch --set-upstream my_local_branch_name origin/my_remote_branch_name(错误)
  • 注:

    • 在运行git branch --set-upstream命令时,出现错误(git –version: 2.17.1)
    • fatal: the '--set-upstream' option is no longer supported. Please use '--track' or '--set-upstream-to' instead.
    • 设置方法:git branch --set-upstream-to=origin/<远程分支> <本地分支>
  • 实际上,上述命令,就是在修改本地的.git/config文件:

    1
    2
    3
    [branch "my_local_branch_name"]
    remote = origin
    merge = refs/heads/my_remote_branch_name
  • 取消分支上游

    • git branch --inset-upstream
  • 查看分支上游

    • git status
    • git checkout <分支>
    • git branch -vv
  • 设置完upstream后,就可以直接用 git push/pull 来拉取或推送相应的分支了。

直接拉取远程分支

  • 新建分支分支并切换到指定分支
    • git checkout -b dev origin/dev
    • git checkout -b 本地分支名 origin/远程分支名
  • 该命令可以将远程Git仓库里的指定分支拉取到本地,这样就在本地新建了一个dev分支,并和指定的远程分支origin/dev关联起来了。
  • 示例:
    • git checkout -b dev notes/dev : 切换指定远程分支

在本地使用指定提交id创建分支

  • 查看远程分支最新的commitSHA,例如:aa4339fbe90f68bc82901d976a7c11fe92179ef3

  • 使用命令直接从指定的commit新建分支:

    • git branch [branch-name] [commit-id]
    • git branch v1.x aa4339fbe90f68bc82901d976a7c11fe92179ef3

使用标签的方式

  • git clone [--branch tag-name/branch-name] <git-url> [dir] 下载并绑定指定分支或下载指定标签

使用流程

  • 在本地仓库创建标签,并推送到远程:

    • git tag -a v1.0 -m "create tag"
    • git push origin v1.0
  • 下载指定标签到本地:

    • git clone --branch v1.0 http://192.169.4.28/zjy/clean_code.git
  • 下载标签之后,出现的提示:

    • 你处于分离的HEAD状态。您可以环顾四周,进行实验性更改并提交它们,您可以放弃在此状态下所做的任何提交,而不会通过执行另一次签出影响任何分支。
    • 如果您想创建一个新的分支来保留您创建的提交,您可以(现在或以后)再次使用-b和chckout命令。

git同步项目进度方法

  • 创建三个分支:

    • master
    • dev
    • local
  • master分支:

    • 存放稳定版本的代码,在这个分支上的项目,所有的功能都是经过测试,不再改动的
    • 这个是对外发行的分支
  • dev分支

    • 存放正在开发的代码,在这个分支上的项目,可能正在新加功能,需要经过反复修改的,或者是同步的
    • 这个是面向所有开发者的
    • 所有开发者通过拉取这个分支的代码来同步项目开发的进程
  • local分支

    • 存放本地的项目的代码,在这个分支上的项目,随时都有可能修改
    • 这个是存放在本地,面向的是自己
    • 其作用是,自己开发的时候,都在这个本地分支上修改,需要推送到远程git上或者拉取远程git上最新的代码时,需要进行如下几步
      • 首先,将local分支的修改全部添加,并在本地提交
      • 其次,切换到本地的dev分支,然后拉取远程git上最新的dev分支
      • 最后,切换回local分支,将本地拉取到的最新的分支合并到local分支

git删除远程分支文件

  • git删除远程分支文件包括两种情况:
    • (1)仅仅删除远程分支文件,不删除本地的文件;
    • (2)删除远程分支文件的同时,删除本地的文件。

仅仅删除远程分支文件,不删除本地文件

  • 删除远程文件filename

    1
    2
    3
    git rm --cached filename
    git commit -m "delete remote file filename "
    git push -u origin master(此处是当前分支的名字)
  • 删除远程文件夹directoryname

    1
    2
    3
    git rm -r --cached directoryname
    git commit -m "delete remote directory directoryname "
    git push -u origin master(此处是当前分支的名字)

删除本地文件与远程分支文件

  • 删除文件filename

    1
    2
    3
    git rm filename
    git commit -m "delete file filename "
    git push -u origin master(此处是当前分支的名字)
  • 删除文件夹directoryname

    1
    2
    3
    git rm -r directoryname
    git commit -m "delete directory directoryname "
    git push -u origin master(此处是当前分支的名字)

git常见错误

fatal:refusing to merge unrelated histories

  • 在使用git pull命令拉取代码时出现这个错误
  • 原因:本地仓库和远程仓库实际上时独立的两个仓库
  • 解决方法:添加选项--allow-unrelated-histories解决问题
    • git pull zhuoer dev --allow-unrelated-histories

创建版本库

  • git clone <url> : 克隆远程版本库
  • git init : 初始化本地版本库

修改和提交

  • git status : 查看状态
  • git diff : 查看变更内容
  • git add . : 跟踪所有改动过的文件
  • git add <file> : 跟踪指定的文件
  • git mv <old> <new> : 文件改名
  • git rm <file> : 删除文件
  • git commit -m "commit message" : 提交所有更新过的文件
  • git commit --amend : 修改最后一次提交

查看提交历史

  • git log : 查看提交历史
  • git log -p <file> : 查看指定文件的提交历史
  • git blame <file> : 以列表方式查看指定文件的提交历史

撤销

  • git reset -- 0 1.9G 0% /sys/fs/cgroup /dev/mmcblk0p7 16G 12G 3.1G 79% /data HEAD : 撤销工作目录中所有未提交文件的修改内容
  • git checkout HEAD <file> : 撤销指定的未提交的修改内容
  • git revert <commit> : 取消指定的提交

分支与标签

  • git branch : 显示所有本地分支
  • git checkout <branch/tag> : 切换到指定分支或标签
  • git branch <new-branch> : 创建新分支
  • git branch -d <branch> : 删除本地分支
  • git tag : 列出所有本地标签
  • git tag <tagname> : 基于最新提交的创建标签
  • git tag -d <tagname> : 删除标签
  • git checkout -b dev notes/dev : 切换指定远程分支

合并和衍合

  • git merge <branch> : 合并指定分支到当前分支
  • git rebase <branch> : 衍合指定分支到当前分支

远程操作

  • git remote -v : 查看远程版本库信息
  • git remote show <remote> : 查看指定远程版本库信息
  • git remote add <remote> <url> : 添加远程版本库
  • git fetch <remote> : 从远程库获取代码
  • git pull <remote> <branch> : 下载代码及快速合并
  • git push <remote> <branch> : 上传代码及快速合并
  • git push <remote> :<branch/tag-name> : 删除远程分支或标签
  • git push --tags : 上传所有标签

拉取

  • git pull origin master
    • push : 将本地仓库与远程仓库合并
    • -u : 将本地仓库分支与远程仓库分支一起合并,就是说将master的分支也提交上去,这样就可以在远程仓库上看到在本地仓库的master中创建了多少分支。不加这个参数,只将当前的master与远程的合并,没有分支的历史纪录,也不能切换分支
    • origin : 远程仓库的意思,如果这个仓库是远程的,那么必须使用这个选项
    • master : 提交本地master分支仓库

递归克隆

  • git clone --recursive http://192.167.10.28/dagger/manager_node.git
  • recursive选项会递归克隆项目下的所有git项目

撤销 git add 并保留修改的方法

  • git reset --mixed – 撤销所有的已经add的文件
  • git reset HEAD . – 复制撤销某个文件或文件夹
  • git reset HEAD -filename – 另外,可以使用git status ,git会告诉可以通过哪一个命令来执行操作

git从历史上的某一次提交处建立分支

  • git log --oneline --all --graph --decorate
  • git branch dev 3be5879

远程仓库

  • git remote add <shortname> <url> : 添加一个新的远程Git仓库,同时指定一个方便使用的简写.

    • git remote add zhuoer http://192.167.10.28/dagger/zhuoer : 现在可以在命令行中使用字符串zhuoer来代替整个URL
  • git fetch <remote> : 从远程仓库中获得数据。这个命令会访问远程仓库,从中拉取所有还没有的数据。执行完成后,将会拥有那个远程仓库中所有分支的引用,可以随时合并或者查看。

  • 如果使用clone命令克隆了一个仓库,命令会自动将其添加为远程仓库并且默认以origin为简写。所以,git fetch origin会抓取克隆(或上一次抓取)后新推送的所有工作。

    • 注意:git fetch命令只会将数据下在到本地仓库,它并不会自动合并或者修改当前的工作,当准备好时,必须要手动将其合并入你的工作。
  • 如果当前分支设置了跟踪远程分支,那么可以使用git pull命令自动抓取后合并该远程分支到当前分支。

  • 默认情况下,git clone命令会自动设置本地master分支跟踪克隆的远程仓库的master分支(或其他名字的默认分支)。运行git pull通常会从最初克隆的服务器上抓取数据并自动尝试合并到当前所在的分支。)

推送到远程仓库

  • git push <remote> <branch>
    • 当你想要将master分支推送到origin服务器时(再次说明,克隆时通常会自动帮你设置好那两个名字),那么运行这个命令就可以将你所做的备份到服务器。

查看某个远程仓库

  • git remote show <remote>
    • 查看某一个远程仓库的更多信息
    • 它同样会列出远程仓库的URL与跟踪分支的信息。它告诉你正在处于master分支,并且如果运行git pull,就会抓取所有的远程引用,然后将远程master分支合并到本地master分支,
    • 它也会列出拉取到的所有远程引用。

远程仓库的重命名与移除

  • git remote rename

    • 修改一个远程仓库的简写名
    • 这个操作也会修改所有远程跟踪的分支名字
  • git remote remove或者git remote rm

    • 移除一个远程仓库
    • 一旦使用这种方式删除了一个远程仓库,那么所有和这个远程仓库相关的远程跟踪分支以及配置信息也会一起被删除。

打标签

  • git tag

    • 在Git中列出已有的标签
    • 按照通配符列出标签需要-l或者--list选项
    • 如果只想要完整的标签列表,那么运行git tag就会默认假定你想要一个列表,它会直接列出来
  • 创建标签,Git支持两种标签:轻量标签(lightweight)与附注标签(annotated)

    • 轻量标签很像一个不会改变的分支–它只是某个特定提交的引用
    • 附注标签是存储在Git数据库中的一个完整对象,它们是可以被校验的,其中包括打标签者的名字,电子邮件,地址,日期时间,此外还有一个标签信息,并且可以使用GNU Privacy Guard(GTG)签名并验证。
  • 通常会建议创建附注标签,这样可以拥有以上所有信息,但是如果只是想用一个临时的标签,或者因为某些原因不想要保存信息,那么也可以用轻量标签

  • 附注标签的创建: git tag -a v1.4 -m "my version 1.4"

    • -m : 指定了一条将会存储在标签中的信息。如果没有为附注标签指定一条信息,Git会启动编辑其要求你输入信息
  • 推送标签

    • git push origin v1.4
  • 轻量标签,本质上是将提交校验和存储到一个文件中–没有保存任何其他信息。

  • 创建轻量标签,不需要使用-a, -s, -m选项,只需要提供标签名字:git tag v1.4-lw

  • 后期打标签

    • 要在提交上打标签,需要在命令的末尾指定提交的校验和(或部分校验和)
    • git tag -a v1.2 9fcaw1
  • 删除标签

    • 删除本地仓库上的标签,可以使用命令git tag -d <tagname>
      • 注意:该命令并不会从任何远程仓库中移除这个标签,必须使用git push <remote>:refs/tags/<tagname>来更新远程仓库
      • 第一种变体是:git push <remote> :refs/tags/<tagname>,这种操作的含义是:将冒号前面的空值推送到远程标签名,从而高效地删除它
      • 第二种更加直观的删除远程标签的方式是:git push <remote> --delete <tagname>
  • 通过使用git show可以看到标签信息和与之对应的提交信息

Git别名

  • Git并不会在输入部分命令时自动推断出想要的命令。如果不想每次都输入完整的Git命令,可以通过git config文件来轻松地为每一个命令设置一个别名。
  • 例如:
    • git config --global alias.co checkout
    • git config --global alias.br branch
    • git config --global alias.ci commit
    • git config --global alias.st status
    • 这意味着,当要输入git commit时,只需要输入git ci
  • 在创建认为应该存在的命令时,这个技术会很有用。
    • 例如:为了解决取消暂存文件的易用性问题,可以向Git中添加取消暂存别名,git config --global alias.unstage 'reset HEAD --
    • 通常也会添加一个last命令:git config --global alias.last 'log -l HEAD。这样,可以很轻松地看到最后一次提交
  • Git只是简单地将别名替换为对应的命令。

Git分支

  • 几乎所有的版本控制系统都以某种形式支持分支。使用分支意味着可以把工作从开发主线上分离开来,以免影响开发主线。

  • Git保存的不是文件的变化或者差异,而是一系列不同时刻的快照。

  • Git的分支,其实质上仅仅是指向提交对象的可变指针。Git的默认分支名字是master,在多次提交操作之后,其实已经有一个指向最后哪个提交对象的master分支。master分支会在每次提交时自动向前移动。

    • Git的master分支并不是一个特殊分支。它跟其他分支完全没有区别。之所以几乎每一个仓库都有master分支,是因为git init命令默认创建它,并且大多数人都懒得去改动它
  • git branch testing : 创建分支testing,这会在当前所在的提交对象上创建一个指针。那么,Git又是怎么知道当前在哪一个分支上呢?

    • 也很简单,它有一个名为HEAD的特殊指针。它是一个指针,指向当前所在的本地分支(可以把HEAD想象为当前分支的别名)
    • 在本示例中,仍然在master分支上,因为git branch命令仅仅创建一个新分支,并不会自动切换到新分支中去
  • git log --decorate : 查看各个分支当前所指的对象

  • 分支切换:git checkout testing。如此以来,HEAD就指向testing分支了。

  • 由于Git的分支实质上仅是包含所指对象校验和(长度为40的SHA-1值字符串)的文件,所以它的创建和销毁都异常高效

远程分支

  • 远程引用是对远程仓库的引用(指针),包括分支,标签等。

  • 可以通过 git ls-remote <remote>来显示地获得远程引用的完整列表

  • 或者通过git remote show <remote>获得远程分支的更多信息

  • 更常见的做法是利用远程跟踪分支,远程跟踪分支是远程分支状态的引用,它们以<remote>/<branch>的形式命名

    • 例如:假设网络里由一个在git.ourcompany.com的Git服务器。如果从这里克隆,Git的clone命令会自动将其命名为origin,拉取它的所有数据,创建一个指向它的master分支的指针,并且在本地将其命名为origin/master。Git也会给你一个与originmaster分支在指向同一个地方的本地master分支,这样你就有工作的基础。
    • origin并无特殊含义。远程仓库名字origin与分支名字master一样,在Git中并没有任何特别的含义一样。同时,master是当你运行git init时默认的起始分支名字。如果你运行git clone -o booyah,那么默认的远程分支名字将会是booyah/master
  • git push <remote> <branch> : 推送到某个分支

  • 与给定的远程仓库同步数据,运行git fetch <remote>命令。

    • 示例:git fetch a311d
    • 这个命令查找a311d是哪一个服务器,从中抓取本地没有的数据,并且更新本地数据库,移动a311d/master指针到更新之后的位置。
  • git pull : 拉取

    • git fetch命令从服务器上抓取本地没有的数据时,它并不会修改工作目录中的内容,它只会获取数据然后让你自己合并
    • git pull命令在大多数情况下它的含义是一个git fetch紧接着一个git merge命令

如何避免每次输入密码

  • 如果正在使用HTTPS URL来推送,Git服务器会询问用户名与密码。默认情况下它会在终端中提示服务器是否允许你进行推送
  • 如果不想在每一个推送时都输入用户名与密码,可以设置一个credential cache。最简单的方式就是将其保存在内存中几分钟,可以简单地运行git config --global credential.helper cache来设置

跟踪分支

  • 从一个远程跟踪分支检出一个本地分支会自动创建所谓的“跟踪分支”(它跟踪的分支叫做“上游分支”)。
  • 跟踪分支是与远程分支有直接关系的本地分支。如果在一个跟踪分支上输入git pull,Git能够自动地识别去那个服务器上抓取,合并到哪个分支。
  • 当克隆一个仓库时,它通常会自动地创建一个跟踪origin/mastermaster分支。
  • 如果想设置其他的跟踪分支,或者是一个在其他远程仓库上的跟踪分支,简单的示例:git checkout -b <branch> <remote>/<branch>。这是一个十分常用的操作,所以Git提供了--track快捷方式
  • 如果想要将本地分支与远程分支设置为不同的名字,可以使用命令git checkout -b sf origin/serverfix

删除远程分支

  • 运行带有--delete选项的git push命令,用来删除一个远程分支,例如:git push zhuoer --delete docker-mqtt
  • 基本上这个命令做的只是从服务器上移除这个指针。Git服务器通常会保留数据一段时间直到垃圾回收运行,所以如果不小心删除掉了,通常是很容易恢复的。

Git 子模块

  • 使用场景:某个工作中的项目需要包含并使用另一个项目。也许是第三方库,或者独立开发的,用于多个父项目的库。现在问题是:把它们当作两个独立的项目,同时又想在一个项目中使用另一个

  • Git通过子模块来解决这个问题:子模块允许将一个Git仓库作为另一个Git仓库的子目录。它能够将另一个仓库克隆到自己的项目中,同时还可以保持提交的独立。

  • 将一个已存在的Git仓库添加为正在工作的仓库的自模块:git submodule add命令后加上想要跟踪的项目的相对或者绝对URL来添加新的子模块。

    • 默认情况下,子模块会将子项目放到一个与仓库同名的目录中,如果想放到其他地方,可以在命令结尾添加一个不同的路径。
  • .gitmodules配置文件,保存了项目URL与已经拉取的本地目录之间的映射

  • 我们首先将一个已存在的 Git 仓库添加为正在工作的仓库的子模块。 你可以通过在 git submodule add 命令后面加上想要跟踪的项目的相对或绝对 URL 来添加新的子模块。 在本例中,我们将会添加一个名为 “DbConnector” 的库。

    1
    2
    3
    4
    5
    6
    7
    $ git submodule add https://github.com/chaconinc/DbConnector
    Cloning into 'DbConnector'...
    remote: Counting objects: 11, done.
    remote: Compressing objects: 100% (10/10), done.
    remote: Total 11 (delta 0), reused 11 (delta 0)
    Unpacking objects: 100% (11/11), done.
    Checking connectivity... done.
  • 默认情况下,子模块会将子项目放到一个与仓库同名的目录中,本例中是 “DbConnector”。 如果你想要放到其他地方,那么可以在命令结尾添加一个不同的路径。

简介

  • JSON,指的是JavaScript对象表示法(JavaScript Object Notation)
  • JSON是轻量级的文本数据交换格式
  • JSON独立于语言,JSON使用Javascript语法来描述数据对象,但是JSON仍然独立于语言和平台。JSON解析器和JSON库支持许多种不同的编程语言。目前非常多的动态编程语言都支持JSON
  • JSON具有自我描述性,更容易理解

与XML相同之处

  • JSON和XML都用于接收Web服务端的数据
  • JSON是纯文本
  • JSON具有自我描述性(人类可读)
  • JSON具有层级结构(值中存在值)
  • JSON可通过JavaScript进行解析
  • JSON数据可使用AJAX进行传输

JSON语法规则

  • JSON语法是JavaScript对象表示语法的子集

  • 数据在名称/值对中

  • 数据由逗号,分隔

  • 使用斜杠\来转义字符

  • 大括号{}保存对象

  • 中括号[]保存数组,数组可以包含多个对象

  • JSON的两种结构

    • 对象:大括号{}保存的对象是一个无序的名称/值对集合。一个对象以左括号{开始,右括号}结束。每个键后跟一个冒号:,名称/值对使用逗号,分隔。
    • 数组:中括号[]保存的数组是值(value)的有序集合。一个数组以左中括号[开始,右中括号]结束,值之间使用逗号,分隔。值(value)可以是双引号括起来的字符串,数值,true, false, null, 对象或者数组,它们是可以嵌套的

JSON名称/值对

  • JSON数据的书写格式是:key:value
  • 名称/值对包括字段名称(在双引号中),后面写一个冒号,然后值:"name":"abc",等价于JavaScript语句:name = "abc"

C++处理JSON的开源库

在C++中,有多个流行的库可以用于处理JSON数据。以下是一些常用的C++ JSON处理库:

  1. RapidJSON: RapidJSON是一个高性能的JSON解析和生成库,提供了灵活的API和丰富的功能。它具有快速的解析速度和低内存占用,并支持DOM和SAX风格的API。

  2. jsoncpp: jsoncpp是一个简单易用的C++ JSON库,提供了方便的API用于解析和生成JSON数据。它支持将JSON数据与C++对象进行相互转换,并提供了灵活的配置选项。

  3. nlohmann/json: nlohmann/json是一个现代化的C++ JSON库,具有简单易用的API和高性能。它支持以类似于JavaScript的方式访问和操作JSON数据,并提供了方便的函数和操作符用于序列化和反序列化。

这些库都是开源库,可以从它们的官方网站或代码托管平台获取源代码和使用文档。你可以选择适合你项目需求和编程风格的库来处理JSON数据。

简介

  • 深入探讨三个流行的C++日志库: glog, log4cplug, spdlog
  • glog、log4cplus 和 spdlog,这三个日志库各有千秋,它们在性能、功能和易用性方面都有各自的优势
  • 探讨它们如何处理日志滚动、如何配置日志清理策略,以及如何实现自定义的日志管理策略

glog 日志库

  • glog,即Google Logging Library,是由Google开发的一款高效的日志库,广泛应用于C++项目中。它提供了丰富的日志记录功能,包括日志级别、条件日志、日志滚动等。

  • glog 是一个为了满足高性能需求而设计的日志库,它支持多线程环境,能够在不同的日志级别上打印信息,并且支持日志滚动。日志滚动是一种常见的日志管理策略,用于防止日志文件无限制地增长,占用过多的磁盘空间

  • glog 支持基于文件大小的日志滚动。当日志文件达到预设的大小限制时,glog 会自动将当前日志文件重命名为备份文件,并创建一个新的日志文件继续写入。这个过程是自动的,对程序运行无影响。

  • 虽然 glog 支持日志滚动,但它并不直接提供日志清理的功能。这意味着随着时间的推移,日志文件会不断累积,可能会占用大量的磁盘空间。为了解决这个问题,你可能需要依赖外部工具或者自己编写脚本来定期清理旧的日志文件。

  • 虽然 glog 本身不提供日志清理的功能,但你可以通过实现自定义的清理策略来管理日志文件。这通常涉及到文件系统操作,如检查文件的创建时间、大小等属性,然后根据你的清理策略删除旧的日志文件

log4cplus

  • log4cplus 是一个灵活且易于使用的日志库,它提供了丰富的日志记录功能,包括日志级别、日志格式化、日志滚动和日志清理等。它的设计哲学是使日志记录尽可能地简单而不失灵活性

  • log4cplus 提供了多种日志滚动策略,包括基于文件大小的滚动 (RollingFileAppender) 和基于时间的滚动 (DailyRollingFileAppender 和 TimeBasedRollingFileAppender)

  • RollingFileAppender 允许日志文件在达到指定大小时滚动。你可以配置 MaxFileSize 和 MaxBackupIndex 来控制日志文件的最大大小和备份文件的数量。

  • DailyRollingFileAppender 和 TimeBasedRollingFileAppender 提供了基于时间的日志滚动策略,允许你按照每天或者更精细的时间间隔来滚动日志文件。

  • log4cplus 的日志清理策略通常与日志滚动策略结合使用。通过配置 MaxBackupIndex,你可以限制保留的备份文件数量,从而实现基于文件个数的日志清理

  • 然而,log4cplus 不直接提供基于时间的日志清理策略。如果你需要根据日志文件的创建时间或最后修改时间来清理日志,你可能需要实现自定义的 Appender 或者使用外部工具

  • log4cplus 支持通过 XML 或 properties 文件来配置日志管理策略,这使得你可以在不修改代码的情况下调整日志行为

  • 如果 log4cplus 提供的日志管理策略不能满足你的需求,你可以通过继承 Appender 类来实现自定义的日志清理策略。

  • 你需要重写 append() 方法,在这里实现你的日志清理逻辑。例如,你可以检查日志文件的创建时间或大小,并在达到一定条件时删除旧的日志文件

spdlog

  • spdlog 是一个快速、轻量级的日志库,它支持多线程、异步日志记录。它的设计哲学是“快速和简单”,旨在提供一个直观而强大的日志记录工具
  • spdlog 提供了多种日志滚动策略,包括按大小滚动和按时间滚动。
  • 这种滚动策略会在日志文件达到一定大小时滚动日志。你可以配置 max_size 和 max_files 来控制日志文件的最大总大小和保留的日志文件的最大数量。
  • 这种滚动策略会在每天的某个特定时间滚动日志。你可以配置 rotation_hour 和 rotation_minute 来决定每天滚动日志的时间。
  • spdlog 的配置通常是通过代码进行的,你需要在代码中创建和配置 Logger 和 Sink。
  • 虽然 spdlog 提供了一些内置的滚动策略,但你也可以实现自己的 Sink 来实现自定义的清理策略

比较和总结 (Comparison and Conclusion)

性能比较 (Performance Comparison)

  • 在性能方面,spdlog 通常被认为是最快的,因为它是为高性能而设计的,支持异步日志记录。glog 和 log4cplus 的性能也不错,但通常略低于 spdlog

  • glog:虽然 glog 提供了丰富的功能和灵活的配置,但这也使得它在性能上有所牺牲。特别是在高并发的环境下,glog 的性能可能会受到影响。

  • log4cplus:log4cplus 提供了更丰富的功能,包括多种 Appender 和 Layout,但这也意味着更多的性能开销。尽管如此,对于大多数应用来说,这种性能差异是可以接受的。

  • spdlog:spdlog 是专为高性能设计的,支持异步日志记录,能够在高并发环境下提供极高的日志记录性能。

功能比较 (Feature Comparison)

  • 在功能方面,log4cplus 提供了最丰富的特性,包括多种 Appender、Layout 和日志滚动策略。glog 和 spdlog 在功能上略有不足,但仍然能满足大多数日志记录需求。

  • glog:提供基本的日志记录功能,支持按大小滚动日志,但在日志清理和滚动策略方面略显不足。

  • log4cplus:提供最丰富的功能和配置选项,支持多种日志滚动和清理策略,是功能最全面的选择。

  • spdlog:虽然在功能上不如 log4cplus 丰富,但 spdlog 提供了高性能的异步日志记录功能,非常适合性能敏感的应用。

使用场景建议 (Usage Scenario Recommendations)

  • glog:适用于需要简单、高效日志记录的场景,特别是在 Google 的生态系统中。
  • log4cplus:适用于需要丰富功能和灵活配置的企业级应用,尤其是在需要复杂日志管理策略的场景。
  • spdlog:适用于性能敏感、需要高速日志记录的应用,如游戏、高频交易等。

总结 (Conclusion)

  • 选择合适的日志库对于确保应用程序的稳定性和性能至关重要。glog、log4cplus 和 spdlog 都是优秀的 C++ 日志库,各有其优势和应用场景。通过本文的比较和分析,希望读者能够根据自己的具体需求,做出明智的选择。

简介

  • ethercat的理论基础知识

EtherCAT

  • EtherCATEthernet for Control Automation Technolog的简称,是一个实时控制的开放标准。

  • ETG, EtherCAT技术小组,该组织是Beckhoff为支持和推广EtherCAT而成立的。ETG网站是关于EtherCAT的信息来源。

EtherCAT xenomai 安装

  • notes/PDF/EtherCAT(ubuntu18.04,linux4.9.38,xenomai3.1,igh1.52)配置完整流程.docx
  • pdf文档配置menuconfig时步骤不完整,坑!!!
  • 另一个地址:https://www.icode9.com/content-3-916631.html

固定RxPDOs

  • notes/PDF/AP系列驱动器+EtherCAT+手册V1.0.pdf -- P12

  • **对于CSP(循环同步位置)**0x6060的操作方式=8:

    • 接收PDO 4 : 0x1700
      • 0x6040 – 控制字
      • 0x607A – 轨迹目标位置
      • 0x60B1 – 速度偏移
      • 0x60B2 – 转矩偏移
  • 对于CSV(循环同步速度)0x6060的操作模式=9:

    • 接收PDO 5:0x1701
      • 0x6040 – 控制字
      • 0x60FF – 目标速度
      • 0x60B2 – 转矩偏移量
  • 对于CST(循环同步转矩)0x6060的操作方式=10:

    • 接收PDO 6:0x1702
      • 0x6040 – 控制字
      • 0x60FF – 目标速度
      • 0x60B2 – 转矩偏移量

固定TxPDO

  • 发送PDO 5:0x1B00
    • 0x6041 – 16 – 状态字
    • 0x6064 – 32 – 实际电机位置
    • 0x60F4 – 32 – 位置循环错误(跟随错误)
    • 0x606C – 32 – 实际电机速度
    • 0x6077 – 16 – 转矩实际值

请求主站

  • 用户程序通过ecrt_request_master请求主站设备,该函数调用ecrt_request_master_err(),取得master设备,并执行ec_master_enter_operation_phase()函数

  • 请求主站设备完成后,开始创建数据域,调用ecrt_master_create_domain()

  • 创建数据域成功后,分别完成对各从站设备的配置,配置内容包括:PDO映射,SM配置,FFMU配置和DC配置

  • 用户程序调用的入口是ecrt.h和相关的库文件,通过ioctl以驱动的形式实现,与master文件夹中的部分函数稍有区别

从站配置

  • 从站配置是应用层通过ecrt_master_slave_config()函数添加到主站的config链表中

PDO

  • 过程数据对象(Process Data Object, PDO),是用来传输实时数据的,提供对设备应用对象的直接访问通道,它用来传输实时短帧数据,具有较高的优先权。

  • PDO传输的数据必须少于或等于8个字节,PDOCAN报文数据域中每个字节都用作数据传输,因此,在应用层上不包含传输控制信息,报文利用率极高。

  • PDO通信是基于生产者/消费者的通讯模式,每个PDO有一个唯一的标识符且可以通过一个节点发送,但有多个节点可以接收。PDO的接收不需要消费者确认。

    • 由生产者发送的PDO称为发送PDO(TPDO)
    • 由消费者接收的PDO称为接收PDO(RPDO)
  • 每个PDO在对象字典中由两个对象描述: 通信参数和映射参数

    • PDO通信参数指明使用哪个COB-ID,传输类型,禁用时间和定时时间
    • PDO映射参数用于设定PDO报文中的数据的映射关系,确定要传输的数据在CAN报文数据域中的定位。该参数允许PDO的生产者和消费者知道正在传输什么信息,而不需要在CAN报文中增加额外的协议控制信息,使传输的效率达到最高。一个PDO最多可以映射64个对象
  • PDO通讯具有三种出发模式:内部事件驱动或内部定时器触发,同步触发,远程请求触发

    • 内部事件驱动或内部定时触发。通讯由某一事件触发。例如数字I/O口状态改变,超过预先设定的值,定时器中断等都会触发节点发送一个PDO。这种模式可使总线负载达到最小,在相对低的波特率下获得比较高的通讯特性。
    • 同步触发。同步触发PDO是指CANopen节点收到由管理节点发出的同步报文(同步对象Sync)之后,根据触发报文条件向总线发出PDO报文。同步传输又分为周期性和非周期性。周期性是指CANopen节点收到一定数量的同步报文之后才开始发送;非周期性PDO是指PDO触发条件成立之后,当收到下一个同步对象后马上发送PDO
    • 远程请求触发。PDO消费者可以给PDO生产者发送远程PDO请求,相应PDO生产者将对远程帧作出相应,向总线上发送相应的PDO数据。
  • PDO通讯时的触发模式由PDO通信参数中的传输类型来确定,传输类型是一个8位无符号整数,这个传输类型值的大小与PDO触发方式的对应关系

  • 主站和从站PDO通信的机制

    • PDO的基本概念及其在对象字典中的索引,在主站和从战采用PDO通信方式时,思路是 – 先配置主站的PDO的通信参数(COB-ID,数据传输类型),再配置从站的通信参数与主站一致,这样就建立了主站与从站的PDO通信的关系。然后再通过字典配置主站PDO映射参数,配置完成后从主站就可以通过PDO通信传输数据。
  • PDO传输的“总指挥”就是对象字典。PDO发送什么数据,接收什么数据,什么时候发送和接收,发送和接收的数据都放在哪儿,都是由对象字典配置。

CAN

  • CAN是控制器局域网络(Controller Area Network, CAN)的简称,是由以研发和生产汽车电子产品著称的德国BOSCH公司开发的,并最终称为国际标准,是国际上应用最广泛的现场总线之一

EtherCAT 使用与解析–关于ethercat应用层使用

  • url – https://blog.csdn.net/lswdcyy/article/details/105441470

  • 下载ethercat源码并且安装好之后,测试ethercat使用可以遵循以下步骤

  • 开启ethercat系统 – sudo /etc/init.d/ethercat start

    • 执行这一步需要确保一点 – 按照ethercat源码中的README指导将一些需要的文件复制以及创建软连接到/opt/init.d/ethercat以及/opt/sysconfig/ethercat两个文件,前者是系统启动文件,后者是系统配置文件
    • 系统配置文件,是一份变量定义文件,在系统启动脚本中执行,定义两类变量,一个是主站MAC地址(MASTER0_DEVICE),一个是使用的模块驱动名称(DEVICE_MODULES)
  • 开启系统后,要在应用层进行对主站模块的使用,本质上是通过开启/dev/EtherCAT字符设备,而后基于ioctl方式调用内核主站模块各种功能

    • 开启系统后,用户主要需要进行从站配置与PDO映射,域操作功能,然后就可以进行PDO交换了
    • 主站程序运行在内核空间,应用层需要一种方式实现对内核调用。通过打开主站创建的字符设备/dev/EtherCAT就是这个作用
    • 主要用到的函数
      • ec_master_t *ecrt_request_master(unsigned int master_index);
        • 负责打开字符设备文件,传入参数为使用主站索引(使用/etc/init.d/ethercat开启系统的时候可以一次性传入多个MAC地址从而开启多个主站,不同主站创建不同的字符设备,例如/dev/EtherCAT0, /dev/EtherCAT1...),
        • 而这个索引就是用于开启对应的字符设备,从而使用不同的主站,使用open接口打开,然后返回文件描述符,该文件描述符用于ioctl调用对应主站功能。另外在申请到主站后就不再允许进行总线的重新扫描,固化了主站连接的从站链表,而且设置从站状态当前申请状态为PREOP
      • ec_domain_t *ecrt_master_create_domain(ec_master_t* master);
        • 负责创建域,domainPDO映射有密切联系,在激活的位置详谈
        • 这个函数具体内容就是直接在内核空间中创建一块ec_domain空间并且将该空间连接到主站domain链表尾部
      • ec_slave_config_t *ecrt_master_slave_config(ec_master_t* master, uint16_t alias, uint16_t position, uint32_t vendor_id, uint32_t product_code);
        • 从站配置函数
        • 主站模块中的从站链表,它们之间的关系为:从站配置是应用层通过ecrt_master_slave_config()函数添加到主站的configs链表中的,而从站链表slaves则是通过ethercat主站状态机通过扫描ethercat总线得到的,两者的共同之处在于从站配置过程的alias, position, VID, PID,这些在主站扫描到的从站链表中都是有一份参数的,当应用层设置配置和主站扫描到从站信息相匹配的时候,那就将从站与从站配置相联系(这时候会将主站扫描的SII信息关于sync关联的PDO信息复制到从站配置中,也就是默认PDO配置);这样,就可以通过从站配置寻找到主站模块中从站配置信息,进而获取到从站信息。
      • int ecrt_slave_config_reg_pdo_entry(ec_slave_config_t *sc, uint16_t index, uint8_t subindex, ec_domain_t *domain, unsigned int *bit position);
        • 从站配置PDO函数
        • 需要注意的一点 – 在主站正式激活之前,所有配置PDO相关的其实并没有相对应的空间申请操作,一切都是进行的计算,计算PDO需要多大空间,计算domains的逻辑位置,计算FMMU的逻辑位置,计算PDO的逻辑位置,直到主站正式激活,主站会根据自身已经申请的域链表domains,获取所有域所需要的空间大小,而后对每个域进行逻辑地址分配,每个域中再对每个FMMU进行逻辑地址分配。
        • 接口参数
          • uint16_t index – 对象字典索引
          • uint8_t subindex – 对象字典子索引
          • ec_domain_t *domain – 使用的域
          • unsigned int* bit_position – 一个Byte中的偏移量,当PDO映射逻辑地址不是完整的Byte时有用
        • 首先,通过从站应用层配置索引可以获取到主站的从站配置链表中对应的从站配置,而后根据配置目标domain的索引获取到主站的domains链表对应的域,这样就可以实现应用层的从站配置和domain切换到主站对应的从站配置和domain,然后进行pdo映射操作。
        • 每次进行PDO映射的时候,并不是只对设置的一个对象进行处理,而是直接将整个sync关联的PDO都进行批次化处理。所以,本质上来讲,PDO配置映射就是确定PDO的逻辑地址位置
      • int ecrt_master_activate(ec_master_t *master);
        • 函数为正式激活的函数
        • 主站注册的domains链表整体大小计算;经过PDO注册映射之后,对主站中关联的每个domains都是相互独立的,并且每个domains都只是一个计算得到的值,其实并没有需要的空间申请,因此在主站激活的时候会将全部domians需要的空间进行统一申请。具体申请到的PDO映射逻辑空间存放在字符设备打开文件的priv指针处,关于字符设备的file->priv在字符设备打开eccdev_open的时候进行指定。然后按照主站连接的domains链表顺序对每个domian起始地址进行设置:主要是domain的逻辑起始地址,domain的大小,以及domain中的FMMU的逻辑地址重新设置,最终,domain和FMMU的逻辑起始地址都是在主站全部domains环境下的逻辑起始地址。为了进行PDO映射,在主站激活过程中还对每个domain需要的子报文进行空间申请。在计算子报文需要个数的时候,各个domain计算各自需要的子报文需要,这样就可以满足不同domain的PDO交换周期是可以单独设置的;在domain计算自己需要的子报文个数的时候,计算是以FMMU为一个基本单位进行计算的,每个子报文可承载的数据大小为1486Byte,然后根据一个子报文中FMMU的输入输出情况设置子报文类型,也就是EC_DATAGRAM_LRD类型子报文,EC_DATAGRAM_LRR类型子报文以及EC_DATAGRAM_LRW类型子报文。然后将这些子报文添加到domain的datagram_pairs链表中。当然,整体过程中,domain映射空间和子报文使用的数据空间都是同一段空间。
        • 完成主站的domains域空间处理,之后就停止主站的空闲阶段线程(等待空间阶段线程退出)
        • 开启主站的操作阶段线程,该线程和空闲阶段线程相比不同之处–在于将主站子报文队列组合发送移动到用户手中进行处理
      • uint8_t *ecrt_domain_data(ec_domain_t *domain);
        • 返回domain在逻辑空间的逻辑地址
      • void ecrt_domain_queue(ec_domain_t *domain);
        • 将对应domain空间使用的子报文排列到主站子报文发送链表中
      • void ecrt_master_send(ec_master_t *master);
        • 将主站的子报文发送链表的子报文进行发送,在发送过程中,默认的会将从站状态机子报文和主站状态机子报文进行排队发送

ecrt.h头文件接口

  • ecrt_master_receive()

    • 功能:从硬件获取接收到的帧并处理数据报。通过调用中断服务例程查询网络设备接收到的帧。提取收到的数据报并将结果发送到队列中的数据报对象。接收到的数据报和超时的数据报将被标记并退出队列
    • 函数原型:void ecrt_master_receive(ec_master_t* master);
    • 参数:masterethercat主机
    • 返回值:无
  • ecrt_domain_process()

    • 功能:确定域数据报的状态。评估接收到的数据报的工作计数器,并在必要时输出统计信息。必须在ecrt_master_receive()接收域数据报之后调用此函数,以便ecrt_domain_state()返回上一次进程数据交换的结果。
    • 函数原型:void ecrt_domain_process(ec_domain_t *domain);
    • 参数:domain – 域
    • 返回值:无
  • EC_READ_U16()

    • 功能:宏函数,计算整数数据,同样还有EC_READ_U32()
  • EC_WRITE_U16()

    • 功能:宏函数,将整型数据写入内存。内存大小是ecrt_slave_config_create_sdo_request()的参数。
  • ecrt_master_sync_reference_clock()

    • 功能:将DC参考时钟偏移补偿数据报排队发送,参考时钟将上次取消ecrt_master_application_time()提供的应用程序时间同步
    • 函数原型:void ecrt_master_sync_reference_clock(ec_master_t *master)
    • 参数:masterethercat主机
    • 返回值:无
  • ecrt_master_sync_slave_clocks()

    • 功能:将DC时钟偏移补偿数据报排队发送,所有的子时钟与基准时钟同步
    • 函数原型:void ecrt_master_sync_slave_clocks(ec_master_t* master);
    • 参数:masterethercat主机
    • 返回值:无
  • ecrt_domain_queue()

    • 功能:将主数据报队列中的所有域数据报排队。调用此函数可标记域的数据报以便在ecrt_master_send()的下一次调用
    • 函数原型:void ecrt_domain_queue(ec_domain_t* domain);
    • 参数:domain – 域
    • 返回值:无
  • ecrt_master_send()

    • 功能:发送队列中的所有数据报。该方法接收所有排队等待传输的数据报,将他们放入帧中,并将他们传递给以太网设备进行发送
    • 函数原型:void ecrt_master_send(ec_master_t* master);
    • 参数:masterethercat主机
    • 返回值:无
  • ecrt_master_application_time()

    • 功能:设置应用程序时间。在使用分布式时钟操作从机时,主机必须知道应用程序的时间。时间不是由主机本身增加的,因此必须循环调用此方法
    • 函数原型:void ecrt_master_application_time(ec_master_t* master, uint64_t app_time);
    • 参数:masterethercat主机;app_time – 应用时间
    • 返回值:无
  • ecrt_release_master()

    • 功能:释放请求的ethercat主机
    • 函数原型:void ecrt_release_master(ec_master_t* master);
    • 参数:masterethercat主机
    • 返回值:无

关于PDO映射

  • https://www.codeleading.com/article/95113301360/#:~:text=%E5%BD%93%E7%84%B6%E5%8F%A6%E5%A4%96%E4%B8%80%E7%A7%8D%E5%B0%B1%E6%98%AF%E4%BD%BF%E7%94%A8ecrt_slave_config_pdos,%28%29%E5%87%BD%E6%95%B0%E5%AF%B9%E4%BB%8E%E7%AB%99%E9%85%8D%E7%BD%AE%E8%BF%9B%E8%A1%8C%E8%AE%BE%E7%BD%AE%EF%BC%8C%E8%AF%A5%E5%87%BD%E6%95%B0%E4%BC%9A%E5%B0%86%E5%8E%9F%E6%9C%ACSII%E5%A4%8D%E5%88%B6%E5%88%B0%E7%9A%84%E4%BB%8E%E7%AB%99%E9%85%8D%E7%BD%AE%E4%B8%AD%E7%9A%84sync%E8%BF%9B%E8%A1%8C%E6%B8%85%E9%99%A4%EF%BC%8C%E8%80%8C%E5%90%8E%E4%BE%9D%E6%8D%AE%E6%96%B0%E7%9A%84%E9%85%8D%E7%BD%AE%E8%BF%9B%E8%A1%8C%E8%AE%BE%E7%BD%AE%EF%BC%9A%E9%9C%80%E8%A6%81%E4%BD%BF%E7%94%A8%E7%9A%84%E9%85%8D%E7%BD%AE%E7%BB%93%E6%9E%84%E5%A6%82%E4%B8%8B%EF%BC%9A

  • 对于PDO映射,首先它是已经有了一个sync中关联PDO的链表的前提下才进行的PDO映射。

  • 使用ecrt_slave_config_pdos()函数进行PDO的在sync中的配置

    • 之所以有这样一个步骤,是因为主站状态部分,主站状态机在扫描SII信息时会提取TxPDORxPDO到从站的同步管理器(SII信息中有PDO和sync相关的信息);然后再使用ecrt_master_slave_config()进行函数配置的时候会将对应从站的sync相关的PDO(master->slaves->sync)复制到从站配置部分,这样即使不去人为的配置同步管理器和PDO的映射关系,也没有什么影响
  • ecrt_slave_config_pdos()

    • 函数对从站配置进行设置,会将原本SII复制到从站配置中的sync进行清除,而后依据新的配置进行设置,(目的就是为了对从站同步管理器的自定义设置)
    • 需要使用到的参数分别是sync, pdo, pdo_entry结构体,三者关系是sync索引PDOPDO索引PDO_entry
    • 从站如何获取PDO配置,可以使用sudo ethercat cstruct命令进行该信息的提取
    • 针对每个ec_sync_info_t输入结构数组进行PDO映射处理,分为三个层次
      • sync层次 – sync层次主要配置同步管理器的方向和看门狗设置
      • PDO层次 – 处理PDO的时候需要两个过程,一个是对之前的PDO配置进行清除,另一个是将自定义配置的PDO设置到从站配置的同步管理器链表中,这个过程还会查询之前的默认配置,将之前PDO中的PDO_entry复制到PDO
  • 以上两种PDO配置并不冲突,可以理解为前者是从站的默认配置,后者是用户为了个性化自定义配置(有无均可,只不过自定义的化可能会有冗余信息)

主站和从站

  • 参考:
    • https://blog.csdn.net/qq923433160/article/details/83781812

  • 主站的实现可采用嵌入式和PC机两种方式,均需配备标准以太网MAC控制器,传输介质可使用100BASE-TX规范的5类UTP线缆。

  • EtherCAT从站设备除了具备通信功能外,还需具备对从站设备的控制功能。常见的从站设备有I/O端子、伺服设备、微处理器等。

  • EtherCAT主站运行需具备以下几个基本功能:

    • 读取从站设备描述XML文件并对其进行解析,获取其中配置参数
    • 捕获和发送EtherCAT数据帧,完成EtherCAT子报文解析、打包等
    • 管理从站设备状态,运行状态机,完成主从站状态机设置和维护
    • 可进行非周期性数据通信,完成系统参数配置,处理通讯过程中突发事件
    • 实现周期性过程数据通信,实现数据实时交换,实时监控从站状态,从站反馈 信号实时处理等功能。

控制卡

  • 参考:
    • https://www.cnblogs.com/cariohu/p/15508175.html

控制卡分类

  • 控制器或者控制卡的性能主要取决于控制算法,不同厂家控制卡的性能差别可能非常大。

  • 目前常见工业应用中比较高端的有以色列ACS,美国Aerotech,这是属于第一梯队的,其他国外的流行品牌还有elmo、PMAC、Galil、欧姆龙等。国内的有固高、雷赛、正运动、柏楚等,与国外产品相比仍然有一定差距,但也在不断突破。

  • 根据控制器传递命令给驱动器的方式,可以分为:总线型、模拟量型、PWM型、脉冲型控制卡。

  • 目前,总线型控制卡是最主流的,各大厂家的口号都是一网到底,这个网就是指的总线,就是通过一根总线把所有模块都接上去,确实方便。其他三种类型控制卡也有各自的特色,所以都并行存在于主流市场

总线控制卡

  • 常见的总线接口有,EtherCAT、CAN、Modbus、Profinet、EPA、SERCOS-Ⅲ等。

  • 总线有这么多种,他们之间是否有联系,又有哪些区别呢?这是我们学习总线之前需要搞清楚的问题,不然总是会心里没底,或者是错误的把总线混搭一起,这些是新手的必经之路。

  • 要想搞清楚不同总线之间的区别与联系,我们就得从总线通讯的组成或者是框架去看

    • 通讯的概念出现的很早,早期的电话电报就是一种通讯方式,但工业上的通讯应用都是OSI七层模型。OSI(open system interconnect)即开放系统的互连,这个是二十世纪七十年代的产物,当时就是为了解决各系统之间通讯的问题。
    • OSI七层模型图,从模型中我们可以看到,通讯最终是转化为比特流发送出去,我们说的通讯速率就是比特流的速率,比如百兆网络100Mbit/s。比特流的传输载体是物理层,是我们看的见摸得着的线缆以及接口芯片等。
    • 物理层往上是数据链路层,数据链路层的职责是负责将具体的数据转化成比特流,然后通过物理层的硬件发送。可以简单理解为,硬件的编码与解码,比如要发送数字8,那么数字8的比特流高低电平是怎样的;当收到一串比特流后,应该转换为哪个数字,这个就靠数据链路层完成的,数据链路层也是硬件。
    • 数据链路层再往上,还有五层。这五层都有一个特点,他们都是软件层,是运行在处理器上的软件代码,这五层完成数据报的解析,编组,归类,最终到显示。
  • 当我们用因特网看视频时,这些层就在周而复始发送请求,解析数据,并最终刷新到显示界面。这五层搞起来确实有点复杂,有些时候其实是不需要的,比如我们知道数据的具体含义,我们就不需要再去分组整理数量,直接使用即可,工业通讯应用正是符合这个特点。

  • 尤其是针对运动控制或者过程控制总线,层太多不仅没用,反而会增加成本,并且运动控制或者过程控制这种专用总线上数据的含义都是严格一一对应的,不需各种分组分段解析啥的。所以,将五层压缩为一层,叫应用层。

  • 物理层,数据链路层,应用层都有各自的功能,三层功能没有重叠部分。

  • 发送工作流程是当数据到达后应用层后把数据放到对应的存储区,数据需要发送时到对应区域取出数据,交给数据链路层,比特流经物理层发送出去;

  • 接收工作流程就是反过来,物理层上的比特流被数据链路层解析为正确的数值,放到对应的存储区域,应用层需要数据的时候取走数据即可。

  • 所以,运动控制或者过程控制总线,这种专用总线都是三层模型,三层模型的功能:

    • 应用层:搬运数据,完成控制功能
    • 数据链路层:承上启下,生成比特流,以及解析比特流
    • 物理层:比特流传输载体
  • 当我们接触或者学习新的总线时,主要是搞清楚总线的框架,即这三层的情况是怎样的。只有搞清楚了这三层,你才不会被各种新鲜名词所吓倒,你才不会去随便混搭总线。搞清楚了总线通讯模型后,我们看下当前最火的两个总线,EtherCAT和CAN总线。

  • 为什么EtherCAT和CAN总线这么火?

CAN总线

  • 首先,是CAN总线起步早,博世公司1986年推出,当时主要是面向汽车行业。注意这里我说的是CAN总线,不是CANOPEN总线,CANOPEN只是基于CAN总线的应用层协议,汽车行业基于CAN总线的应用层协议是J1939。经过汽车行业的多年应用,大家发现这个总线的优点很多,速度快,1Mbit在现在看确实不快,但在那个年代还是非常牛的;有COB-ID,有仲裁机制,高优先级的数据可以先传输,低优先级是数据后发送,排队的数据在总线空闲的时候会自动发送,无需人为干预;差分传输,数据传输可靠性高;理论上可以在总线上挂任意多节点;成本低,几块钱的MCU就自带CAN控制器,现在一般同时支持CAN2.0A和2.0B。

  • 既然CAN总线有这么多优点,那就得充分利用上,紧接着有个组织叫CIA(CAN in Automation)起草了基于CANopen的设备及通讯子协议定义DS 301(Draft Standard 301),也就是我们经常说的301协定。DS301只是CANopen的一个基础规范,具体到细分领域有,I/O模组的DS401,运动控制的DS402。讲到这里就出现了我们期盼已久的CANopen协议,之所以火就是因为起步早,又赶上了电机运动控制的蓬勃发展时期,靠谱好用,便宜,易上手。其实基于CAN总线的应用层协议还有北美船舶行业通讯协议,广州周立功公司的iCAN,但这个两个协议都不在运动控制系统中出现。其实协议就是这么简单,你也可以基于CAN总线创立自己的协议,只要有人用,你就很了不起。

  • 这里简单讲下CANopen DS402的相关知识,方便我们后面的理解。DS402里面有一些概念,对象字典,Node-ID,COB-ID,SDO,PDO,NMT,Heartbeat,状态机,Master,Slave,我们都简单介绍下。

    • DS402中规定网络中各设备是主从关系,即Master-Slave模式,原则上只能有一个Master,负责整个网络的管理。其实CAN总线上的都是节点,没有主从的概念,主从的概念是在DS402中规定的,这一点我们要清楚。
    • 对象字典我们可以理解为寄存器表,只不过DS402已经规定了这个寄存器表的组织结构,包括一部分地址必须给协议使用,如0x6040,0x6041这些都是规定好的。有了对象字典我们就知道每个对象代表的是什么意思,每个厂家都按这个去设计。传输数据的时候我们得知道这个是哪个从站设备的数据,就需要有个Node-ID,简单说就是设备的编号。
    • 假如不同设备同时要传输同样对象字典的数据,那我们该怎样区分呢?这个时候就有COB-ID,COB-ID是对应的编码加上Node-ID,如0x600表示SDO读,对应节点1组合后的COB-ID就是0x600+0x01=0x601,节点2则为0x602,以此类推。这样我们就可以通过COB-ID来直接操作数据了,而无需关心是哪个节点的,如果数据同时需要发送,那么总线的仲裁机制就会起作用,COB-ID越小的优先级越高,优先发送,等待的数据在前面的数据发送完之后会自动重发。
  • 数据的传输分为两种

    • 一种是SDO,就是有问才有答,查询一次回复一次,类似服务生一样。
    • 另一种是PDO,叫过程数据,提前配置好了数据的传输方式后数据就会自动上传,如可以设置数据的最小间隔时间,同步、异步、RTR等。
  • SDO和PDO都是为了传输数据,但PDO传输的是过程数据,更精简,传输数据的效率会更高,如循环同步模式肯定是PDO传输数据

  • NMT是网络管理的意思,主站负责管理整个网络,如各节点的状态切换等。

  • 状态机是控制节点切换的,如在非使能状态到使能状态应该怎么响应,这个是状态机管理的。

  • 最后一个是Hearbeat,当然也有NodeGuarding,这两个都是反馈节点的状态。当总线在工作的时候我们得知道节点是否还在线,Hearbeat就类似我们的心跳,间隔多长时间必须收到一次心跳,超出设定时间没收到心跳则表示该节点已死亡。

  • NodeGuarding是另外一种监测方式,它有主站和从站的互动,这是不同于Hearbeat的,就是主站要发命令给从站,从站也要回应命令,也是要求在规定的时间内,目前Hearbeat用的更多一些。

EtherCAT总线

  • EthterCAT的字面意思就是以太网自动化控制技术。简单点说就是基于以太网,完成自动化控制功能,但肯定与普通以太网还是有区别的。

  • 他们的传输介质是一样的,都是RJ45网口+网线,但EtherCAT网络的数据链路层芯片是专门设计的,其目的是为了提高总线的性能。比如,增加了DC同步单元,数据自动转发,还有FMMU单元,SM单元,详细的情况可以去查询相关资料。

  • DC同步单元的时钟都是ns为单位,可以满足非常高的同步要求,然后以太网的通讯速度又非常快,现在1000Mbit/s都已经不是事了,在每个传输周期可以有非常大量的数据交互。这些都是基于硬件的,做应用的人可以不用关心,我们还是讲讲上层协议。

  • 对硬件感兴趣的可以参考AX58100、ET1100芯片的数据手册,山东大学李正军教授的《EtherCAT工业以太网应用技术》非常不错,里面有详细的介绍,值得一看,这里就不展开讲了。

  • 基于EtherCAT总线的应用层协议有FoE、CoE、SoE、EoE、AoE、VoE,各个协议的具体描述如下表2-2:

    • FoE, File over EtherCAT – 在EtherCAT总线上传输文件的协议
    • CoE, CANopen over EtherCAT – 在EtherCAT总线上执行CANopen协议
    • SoE, SERCOS over EtherCAT – 在EtherCAT总线上执行SERCOS协议
    • EoE, Ethernet over EtherCAT – 在EtherCAT总线上执行Ethernet协议
    • AoE – 访问底层现场总线的从站设备的对象字典,如对连接到EtherCAT-CAN网关设备的CAN从站
    • VoE – 供应商自定义协议,基于邮箱
  • 这些都是运行在EhterCAT总线基础上的应用层协议,各个协议分管与自己相关的工作。

  • 我们现在常用的EtherCAT伺服驱动器,说白了就是把CANopen应用层协议搬到了EtherCAT总线之上。由于EhterCAT总线的高传输速度,所以这个时候可以有更高的控制信号频率,就会有更好的控制效果。

  • 讲到这里,我们可以发现,同样的协议可以在不同的总线上,同样的总线也可以用不同的协议。所以,当我们讨论总线的时候也要讨论总线的应用层协议,即我们前文提到的三层模型,只有三层模型都一样的系统才能完美对接。对总线就介绍这么多,原理都是一样的,其他总线可以按照这个方法学习,事半功倍。

  • 有了这样可靠性高,同步性好,控制频率可以很高的总线,现在控制指令的频率到8Khz已经不是问题了。控制卡的指令就可以很快很准的发送给总线上的驱动单元,最终达到好的控制效果。总线型控制系统的所有指令,位置反馈,指示状态,错误代码等等,都是由通讯来完成交互的,这一点和传统的控制方式有很大的区别。

驱动支持的各种模式详解

  • 早期非总线的驱动器一般是支持三个工作模式,位置模式,速度模式和电流模式,这个都比较简单,配置好模式,给对应的指令即可工作。

  • 这些模式一般都可以接收模拟量和PWM命令,位置模式还可以接收脉冲命令,这个就不展开讲了,参对应驱动的手册即可知道特定模式支持哪些类型的命令输入。这种驱动最大的缺点就是接线复杂,控制卡离驱动不能太远,还需要考虑控制线缆抗干扰,不利于分布式现场的情况。这种一般是应用于小型独立式设备,设备相对比较小,线缆不会太长,干扰问题比较好解决。

  • 随着总线型驱动器的出现,驱动器的工作模式增加了好几个。没有特殊说明的话,这里的总线指的是CAN总线和EtherCAT总线。

  • 基于这两个总线的驱动器一般都支持如表3-1所示的模式,当然还有PVT模式,IPM模式,但这些现在已经都不太常见了,有需要的可以查阅相关资料。

    • HM – 回零模式
    • PVM – 带规划的速度模式
    • PPM – 带规划的位置模式
    • CSP – 循环同步的位置模式
    • CSV – 循环同步的速度模式
    • CST – 循环同步的转矩模式
  • HM模式是回零模式,驱动器已经内置好了各种回零方式。如先找负限位再找index方式;用限位作为回零原点方式;碰到硬限位回零方式等等。这些回零方式的程序已经在驱动器内部实现好了,我们只需要配置好相关参数,启动回零即可,回零过程都是驱动器内部程序完成。同时,也有状态变量可以监控当前的回零状态,是否完成,是否有报错等。

  • PVM和PPM是带规划的速度和位置模式,规划的意思就是根据用户设定的加减速度去启动和停止运动。这个两个模式很简单,有点像非总线伺服驱动器的速度模式和位置模式,这里不详细介绍了。

  • 我们重点介绍下循环同步模式,循环同步的意思就是以一个固定的时间间隔,周而复始的发送数据和同步指令。为什么要搞这个玩法呢?PVM PPM不香吗?这是我们学习新知识前需要考虑的问题,搞清楚了背景,理解起来会更有帮助。

    • 我们先想下,控制卡+非总线伺服驱动器是怎样实现多轴同步的,是多个驱动的控制命令在同一个DSP中运算,这样时间上就不会有偏差,确保每次都是几乎同一时间把指令发送给驱动器。如果是多个DSP有各自控制的驱动器,这些驱动器之间做同步运动,比如插补,效果都会差于一个DSP内部轴同步的效果,除非你把多个DSP任一时刻都同步起来,同样的时间做同样的运算,这样也许会是一样的效果。
    • 而我们这里说的循环同步就是干这个事情,总线型驱动器与控制卡或者叫master之间的连接只有一条通讯线,无论这条通讯线是CAN总线的半双工,或是EtherCAT总线的全双工,再加100Mbit/s的带宽,数据传输总会有先后顺序,这个事实没法改变。假如总线上的所有驱动器都以收到指令数据的那一刻去执行指令,那么驱动器之间就无法很好同步了。
    • 那么应该怎么办呢?人是真的聪明,总会想办法去解决问题,天才的工程师提出了一个解决方案。所有驱动器都先收指令数据,但不要立马执行,等待一个命令再执行,这个就是同步命令,这样就完美的解决了总线上数据传输有先后顺序的问题。大家都是先把数据准备好,然后等待同步命令,这个就好比百米赛跑一样,大家都先准备好,等待发令枪再跑,这样就是公平的。至于最终跑的结果怎样看个人水平,驱动器最终执行的效果怎样也是看驱动器的性能,感觉这个启发真是源于生活,最终又服务于生活。
  • 讲完什么是循环同步后,我们看下循环同步的三个模式到底是啥。

  • 首先说CSP,循环同步的位置模式:

    • 这个模式接收的是控制卡下发的位置指令,但这个位置不是随便发的,需要根据位置轨迹解算为一个一个点,这个是需要上位机解算的。
    • 上位解算点的这个过程叫粗插,就是粗线条的给出一些点,这些点不是驱动伺服环路能直接使用的,驱动器在接收到这些点后需要再进行精插,最终变成伺服环路能直接执行的位置点。
    • 精插是相对于粗插来说的,精插是以伺服周期为基准时间单位,精细的将轨迹分成很多个位置点,形成一个位置表,每个伺服周期去这个表中取一个值执行即可。
    • 我们以一个T形加减速,有匀速过程的点到点运动为例来剖析CSP模式的细节。如图3-15,是一个点到点运动,位置—时间和速度—时间关系图,加速和减速阶段的轨迹是曲线,匀速阶段是直线。再看下位置图中的插值点,这些点之间的时间是均匀间隔的,每到一个时间点位置轨迹与时间轴围成一个面积,这个面积就是我们在CSP模式发送给驱动器的位置指令,随着时间的增加,这个面积会越来越大。
    • 只要这些插值点是均匀的,指令发送的时间是准确的,满足这两个条件的情况下,电机的转动必然是平滑的。这两个条件中的任何一个不满足,电机的转动都是会顿挫的。
    • 如果插值点不均匀,比如有的时候插值点是间隔10ms,有的时候插值点是20ms。最明显的结果就是电机运动不平滑,那么为什么会不平滑呢?我们知道位置轨迹连续则位置轨迹的导数或者叫曲线的曲率才不会有突变,位置轨迹导数对应着的是速度,速度不突变则电机运转平稳。如果我的插值点时间突然增加或者缩短,则必然会导致曲率突变,这是上位在解算轨迹点需要注意的问题。
    • 尤其是任意轨迹曲线,曲率的突变非常厉害,即使在均匀的插值情况下,电机运转可能都会抖动明显。所以,对任意曲线的插值,还有需要针对锐角以及曲率突变的点做优化,比如用圆弧过度锐角,或者降低运动速度。
    • 到这里我们对CSP的整个细节基本讲完了,在使用过程中,我们还需注意循环同步指令的周期以及指令到达是否准时。指令的周期不应过短,要让驱动器有精插的空间,比如驱动伺服环路400us,那么你就不要给低于400us的同步周期,当然很多驱动也不支持这么短的同步周期,即使支持也不要这样给。同步指令要有硬时性,或者实时性好,我们一般以us为单位,尽可能的准时,指令不准时同样会导致电机运动的时候顿挫严重,甚至驱动器报错。
    • 到这里我们讲完了整个CSP模式的要点,在使用CSP模式的时候如果电机运转不平滑,该怎样去找问题,这才是我们要关注的核心。看到这里应该有一种豁然开朗的感觉,就证明你完全理解了循环同步位置模式的精髓。
  • 讲完CSP模式,后面的CSV和CST模式就简单了,我们先看看CSV模式:

    • CSV是循环同步的速度模式,控制卡下发的是速度指令,这个速度指令和位置指令一样,也不是随便给的。需要对速度曲线进行插值,解算每个周期应该给驱动的速度指令,对位置轨迹求导数就是速度,也就有了速度曲线。
    • 同CSP一样,控制卡或者上位也只是粗插,伺服环路还会根据指令和周期的时间进行精插,最终就变成了伺服环路可以执行的指令。
    • 同样,CSV模式对指令的实时性要求同CSP一样,不准时的指令就会导致电机运转的时候顿挫,顿挫就是速度突变造成的,分析方法和CSP模式一样,这里不再赘述
  • 看完CSV,我们再看看CST:

    • 这个模式和前面两个的共同之处是都为循环同步模式,不同之处是CST模式的指令直接被伺服环路所用,中间没有精插的过程。由于这个不同,CST模式的指令实时性不好的时候我们也很难发现,因为CST模式对应的是电机的电流,电流对应的是电机的输出转矩,电流的突变就是转矩的突变。
    • 转矩的是突变对应三种情况:
      • 一种是电机输出转矩大于负载转矩,电机加速
      • 另一种是电机输出转矩等于负载转矩,电机还是静止;
      • 甚至是电机输出转矩小于负载转矩,电机被负载拖动,运动控制中这种一般很少
    • 指令实时性不好很难被发现,并不是说CST模式对指令实时性没有要求,既然叫循环同步模式,那就是有这个要求。
  • 总结下三个循环同步模式,循环同步模式的出现,使得我们对任意轨迹的指令规划变得非常方便,就是对曲线插值,获得各时刻应该下发的指令。它使我们更加靠近了伺服环路的工作原理,伺服环路其实也是一直在插,不断的解算各个伺服周期的命令,然后算法以读表的方式不断的读取各个周期的指令。

  • 讲到这里,整个驱动器的相关知识就介绍完了。简单总结就是,驱动器有硬件和固件两部分,硬件部分负责控制电机的换向,电流调节,反馈信号采集等;固件部分或者叫软件部分,则是通过硬件的各种反馈信号,周而复的运算,并将运算结果输出到硬件。其实整个伺服系统工作的过程,就是一个不断纠偏的过程,大了就小点,小了就大点,没有真正的静止,一直运动,只是在几个脉冲来回移动,这才是伺服系统的精髓,没有真正的静止。

EtherCAT 配置流程

  1. init master
  2. init slave
  3. init pdo
  4. init pdo_entry
  5. config pdo_entry
  6. config pdo
  7. config slave
  8. config master
  9. config sdo
  10. lock memory
  11. start master
  12. start slave

EtherCAT 通讯流程

  1. master receive
  2. slave receive
  3. pdo read update
  4. control strategy
  5. pdo write update
  6. master sync
  7. slave send
  8. master send

PDO

  • pdo 可以分为三级
    • SM(sync manager),每个SM可以同步多个 pdo
    • pdo,每个 pdo 包含多个 pdo entry
    • pdo entry,每个 pdo entry 对应一个 index 和 subindex

简介

  • 优化理论相关笔记

优化理论是什么

优化理论是数学的一个分支,研究如何找到最佳解决方案的方法,以满足特定的目标和约束条件。在优化问题中,通常需要在给定的一组可行解中找到最优解,使得某个目标函数取得最大值或最小值。

以下是优化理论的一些关键概念:

  1. 目标函数(Objective Function): 优化问题的目标是通过最小化或最大化一个目标函数来找到最佳解。目标函数通常表示为一组变量的函数。

  2. 约束条件(Constraint): 优化问题通常伴随一些约束条件,这些条件限制了变量的取值范围。优化的解决方案必须满足这些约束。

  3. 最优解(Optimal Solution): 最优解是在满足约束条件下,使目标函数取得最小值或最大值的解决方案。

  4. 局部最优解和全局最优解(Local Optimum and Global Optimum): 局部最优解是在某一邻域内为最优的解,而全局最优解是在整个解空间中为最优的解。

  5. 线性规划(Linear Programming): 一类优化问题,其中目标函数和约束条件都是线性的。线性规划在工程、经济学、运筹学等领域有广泛应用。

  6. 非线性优化(Nonlinear Optimization): 优化问题中目标函数或约束条件是非线性的。非线性优化方法用于解决这类问题,如牛顿法、梯度下降等。

  7. 整数规划(Integer Programming): 一类优化问题,其中变量被限制为整数值。整数规划在组合优化、资源分配等方面有应用。

  8. 凸优化(Convex Optimization): 一类特殊的优化问题,其中目标函数和约束条件都是凸函数。凸优化问题具有良好的性质,可以使用高效的算法求解。

  9. 多目标优化(Multi-objective Optimization): 在一个优化问题中有多个目标函数,需要找到一个平衡的解决方案。

  10. 全局优化(Global Optimization): 寻找整个解空间中的全局最优解,而不仅仅是局部最优解。

优化理论在工程、经济学、运筹学、机器学习等领域都有广泛应用,它提供了一系列方法来解决复杂的决策和设计问题。

简介

  • 平面几何相关笔记

平面几何教材

平面几何是几何学的一个分支,涉及二维空间内的点、线、面及其相互关系。以下是一些常见的平面几何教材,它们可能是针对不同年级和水平的学生:

  1. 《高中数学(必修):平面几何》 - 这是中国高中数学课程中常见的一本教材,涵盖了平面几何的基本概念、定理和解题方法。

  2. 《几何学原理》(Geometry: Euclid and Beyond)- 作者:Robin Hartshorne。这本书着重介绍了古典欧几里得几何,并深入讨论了几何学的一些高级主题,适合对几何学有深入兴趣的学生。

  3. 《平面几何学》(Plane Geometry)- 作者:George E. Martin。这本书通常作为大学本科阶段的平面几何学教材,内容涵盖了基本的几何学原理和证明方法。

  4. 《几何学》(Geometry)- 作者:David A. Brannan、Matthew F. Esplen、Jeremy J. Gray。这本书提供了一个广泛的几何学概述,适合高中或大学水平的学生,内容包括平面几何和立体几何。

  5. 《高中几何》(High School Geometry)- 作者:Jurgensen、Charles、Dolley。这是一本适用于高中学生的教材,涵盖了基本的平面几何概念和定理。

请注意,教材的选择可能会根据学生的年级、水平和教学要求而有所不同。建议查看学校或课程的具体教学大纲,以选择最适合的教材。

平面几何是什么

平面几何是几何学的一个分支,主要研究在一个平面上的几何关系和性质。在平面几何中,研究的对象包括点、直线、多边形、圆等在平面上的性质和相互关系。平面几何是欧几里德几何的一个主要组成部分,起源于古希腊的数学研究。

关键概念和主题包括:

  1. 点(Point): 平面上的位置,用坐标 ( (x, y) ) 表示。

  2. 直线(Line): 无数个点的集合,可以用方程或者参数方程表示。

  3. 线段(Segment): 直线上两个点之间的部分。

  4. 射线(Ray): 一条起始于一个点并延伸到无穷远的直线上的部分。

  5. 角(Angle): 由两条射线或线段的夹角形成,通常用度数或弧度来度量。

  6. 多边形(Polygon): 由一系列连续的线段组成的封闭图形,如三角形、四边形等。

  7. 圆(Circle): 平面上所有到圆心的距离都相等的点的集合。

平面几何的研究通常涉及基本的几何定理、公理和构造方法,以及通过这些基本概念推导出的各种性质。平面几何不仅是纯数学的一部分,而且在工程、建筑、计算机图形学等应用领域中有着广泛的应用。

数学 平面几何 法向量是什么

在平面几何中,一个平面的法向量是与该平面垂直的一个向量。法向量是描述平面方向和垂直性质的重要工具。

设平面的方程为 (ax + by + cz = d),其中 (a, b, c) 是平面的法向量的分量,而 (d) 是一个常数。法向量通常表示为
$$
\mathbf{N} = \langle a, b, c \rangle
$$

平面的法向量具有以下性质:

  1. 法向量与平面上的任意向量的点积为零,即
    $$
    \mathbf{N} \cdot \mathbf{V} = 0
    $$
    ,其中
    $$
    \mathbf{V}
    $$
    是平面上的一个向量。
  2. 法向量的方向与平面的法线方向一致。
  3. 法向量的长度表示平面到原点的距离,可以通过公式
    $$
    \frac{|d|}{\sqrt{a^2 + b^2 + c^2}}
    $$
    计算。

法向量在平面几何中有多种应用,包括判断两平面的关系、求解平面的交点、计算平面的夹角等。

简介

  • 微积分相关笔记

微积分是什么

微积分是数学的一个分支,研究函数的变化率和积分。它由微分学和积分学两部分组成,两者是互相联系的。微积分在自然科学、工程学、计算机科学等领域中有着广泛的应用。

以下是微积分的主要概念:

  1. 导数(Derivative): 导数表示函数在某一点的变化率,即函数在这一点的斜率。对于函数 (y = f(x)),其导数通常表示为 (f’(x)) 或 (\frac{dy}{dx})。

  2. 微分(Differential): 微分是导数的一种近似,它描述函数在某一点附近的局部线性变化。微分可以用于近似计算函数在某一点的变化。

  3. 积分(Integration): 积分是导数的逆运算,表示函数的累积变化量。对于函数 (y = f(x)),其积分通常表示为 (\int f(x) , dx),表示 (f(x)) 关于 (x) 的积累总和。

  4. 不定积分和定积分(Indefinite and Definite Integrals): 不定积分是对函数积分得到的结果,带有一个积分常数;定积分是对函数在一个区间上的积分,表示函数在该区间上的总变化。

  5. 微分方程(Differential Equations): 微分方程描述了一个或多个未知函数及其导数之间的关系,是许多科学和工程问题的数学模型。

  6. 链式法则、乘积法则和商法则(Chain Rule, Product Rule, Quotient Rule): 这些是导数计算中的常用规则,用于计算复合函数、乘积和商的导数。

  7. 定积分的应用(Applications of Definite Integrals): 定积分在计算面积、弧长、体积、质心等方面有着广泛的应用。

微积分为了解变化和量的累积提供了一种强大的工具,使得我们能够理解和分析函数的性质,并解决实际问题。

简介

  • 控制理论相关笔记

控制理论是什么

控制理论是研究如何设计并分析动态系统的一门工程和数学学科。它涉及系统的建模、分析、设计和优化,以便系统能够实现预期的性能和行为。控制理论广泛应用于自动化、机械工程、电气工程、航空航天、化工等领域。

以下是控制理论的一些关键概念:

  1. 系统(System): 一个可以被观测和操控的实体,可以是物理系统、电气系统、生物系统等。系统通常由一组相互关联的元件组成。

  2. 控制器(Controller): 控制器是一个用于调节系统行为的设备或算法。它通过对系统的输入进行调整,使系统输出达到期望的目标。

  3. 过程或系统的建模(System Modeling): 将实际系统抽象为数学模型,以便进行分析和设计。模型可以是线性或非线性的,时变或时不变的,连续或离散的,等等。

  4. 反馈控制(Feedback Control): 反馈控制是指通过测量系统输出并将这些信息反馈到控制器,从而调整系统输入,使系统保持在期望的状态。

  5. 开环和闭环控制(Open-Loop and Closed-Loop Control): 在开环控制中,系统的输出不直接影响控制器的输入;而在闭环控制中,系统的输出被用于调整控制器的输入。

  6. 稳定性分析(Stability Analysis): 研究系统是否在长时间内保持有限的响应。稳定性分析是控制系统设计中的一个重要步骤。

  7. 控制性能评估(Control Performance Evaluation): 衡量控制系统在不同操作条件下的性能,包括稳定性、灵敏度、鲁棒性等。

  8. 状态空间表示(State-Space Representation): 将系统的动态行为表示为一组状态变量和它们的导数的方程,通常采用矩阵形式。

  9. PID控制(Proportional-Integral-Derivative Control): 一种常见的控制策略,通过调整比例、积分和微分参数来实现系统的稳定性和性能。

  10. 鲁棒控制(Robust Control): 考虑系统参数变化和外部扰动时仍能保持良好性能的控制设计方法。

控制理论的目标是设计稳定、高性能、鲁棒的控制系统,以满足特定应用领域的需求。控制理论在自动化系统、飞行器、机器人、工业过程控制等方面有广泛的应用。

简介

  • 刚体运动学相关笔记

刚体运动学是什么

刚体运动学是研究刚体在空间中的运动和位置的学科。刚体是一个在运动过程中不发生形变的物体,即它的各个点在运动中相对位置不变。刚体运动学主要关注刚体的平动(直线运动)和转动(绕轴旋转)。

以下是刚体运动学的一些关键概念:

  1. 平动(Translation): 刚体的平动是指整个刚体保持平行于自身的情况下沿直线运动。平动的描述通常涉及到刚体的质心、速度和加速度。

  2. 转动(Rotation): 刚体的转动是指刚体绕轴旋转。转动的描述通常包括角度、角速度和角加速度。刚体的转动可以是绕固定轴或绕刚体自身的质心轴。

  3. 刚体的位姿(Pose): 描述刚体在空间中的位置和姿态。通常用平移矢量(描述位置)和旋转矩阵或四元数(描述姿态)来表示。

  4. 刚体的速度(Velocity): 描述刚体各点在运动中的速度。对于平动,速度是常矢量;对于转动,速度是角速度矢量。

  5. 刚体的加速度(Acceleration): 描述刚体各点在运动中的加速度。对于平动,加速度是常矢量;对于转动,加速度是角加速度矢量。

  6. 刚体的运动学方程(Equations of Motion): 这是一组描述刚体运动的方程,通常涉及刚体的位姿、速度和加速度。

  7. 刚体坐标系(Body-fixed Coordinate System): 用于描述刚体运动的坐标系,通常固定在刚体上。刚体坐标系的选择对于简化运动学方程很有帮助。

  8. 欧拉角(Euler Angles): 一种描述刚体旋转的方法,使用三个角度来表示刚体的姿态。

刚体运动学在机器人学、航空航天、机械工程、计算机图形学等领域都有着广泛的应用。在这些领域,研究刚体运动学有助于理解和控制物体在三维空间中的运动。

简介

  • ethercat常用函数

ethercat

1.1 启动,设置

  • ethercat都是在root用户下执行命令

  • 设置从站

    • ethercat alias -p 2 0:2
  • 启动ethercat

    • /etc/init.d/ethercat start
  • 查看状态

    • ethercat slv

1.2 调试命令

  • 查看从站状态码

    • ethercat upload -t int16 -p 0 0x603f 00
  • 查看从站位置:

    • ethercat upload -t int32 -p 0 0x6064 00

1.2 demo_webserver.c 分析

数据结构

ec_pdo_entry_info_t

  • 简介:PDO条目配置信息。这是ec_pdo_info_t中的entries字段的数据类型
  • 声明:
    1
    2
    3
    4
    5
    typedef struct {
    uint16_t index; /**< PDO entry index. */
    uint8_t subindex; /**< PDO entry subindex. */
    uint8_t bit_length; /**< Size of the PDO entry in bit. */
    } ec_pdo_entry_info_t;

ec_pdo_info_t

  • 简介:PDO配置信息。这是ec_sync_info_t中的pdos字段的数据类型
  • 声明:
    1
    2
    3
    4
    5
    typedef struct {
    uint16_t index; /**< PDO index. */
    unsigned int n_entries; /**< 要映射的entries PDO条目数 (0表示使用默认映射,这只能在从服务器处于总线配置时完成)*/
    ec_pdo_entry_info_t *entries;/**< 要映射的PDO项数组。可以是NULL,或者必须包含至少n_entries个值*/
    } ec_pdo_info_t;

ec_sync_info_t

  • 简介:同步管理器配置信息。这可以用于配置多个同步管理器,包括PDO分配和PDO映射。它被作为ecrt_slave_config_pdos()函数的输入参数使用
  • 声明:
    1
    2
    3
    4
    5
    6
    7
    typedef struct {
    uint8_t index; /**< 同步管理器索引。Sync manager index.Must be less than #EC_MAX_SYNC_MANAGERS for a valid sync manager,but can also be \a 0xff to mark the end of the list. */
    ec_direction_t dir; /**<同步管理器方向 */
    unsigned int n_pdos; /**< PDOs在pdos结构体数组中的数量 */
    ec_pdo_info_t *pdos; /**<带有要分配的pdo的数组。所包含的PDOs必须不少于n_pdos
    ec_watchdog_mode_t watchdog_mode; /**< 看门狗模式 */
    } ec_sync_info_t;

ec_master_t

  • 简介:主站

ecrt_master_state_t

  • 简介:主站状态,这个是用于函数ecrt_master_state()函数的输出参数
  • 声明:
    1
    2
    3
    4
    5
    typedef struct {
    unsigned int slaves_responding; // 所有Ethernet设备响应从站的总和
    unsigned int al_states : 4; // 所有从站的应用层状态。状态被编码在较低的4位。如果设置了一个比特位,就意味着至少有一个从站在主线上响应:Bit 0: \a INIT;Bit 1: \a PREOP;Bit 2: \a SAFEOP;Bit 3: \a OP */
    unsigned int link_up : 1; // true,如果至少有一个 Ethernet link是在线的,则为true
    } ec_master_state_t;

ec_slave_config_t

  • 简介:从站配置

ec_slave_config_state_t

  • 简介:从站配置状态。它用于函数ecrt_slave_config_state()的输出参数
  • 声明:
    1
    2
    3
    4
    5
    typedef struct {
    unsigned int online : 1; // 这个从站是在线的
    unsigned int operational : 1; // 这个从站通过指定配置进入OP状态
    unsigned int al_state : 4; // 应用层的从站状态:1: \a INIT;2: \a PREOP;4: \a SAFEOP;8: \a OP
    } ec_slave_config_state_t;

ec_domain_t

  • 简介:域

ec_wc_state_t

  • 简介:域工作计数器状态说明。这个是在ec_domain_state_t中使用
  • 声明:
    1
    2
    3
    4
    5
    typedef enum {
    EC_WC_ZERO = 0, // 没有交换注册的过程数据
    EC_WC_INCOMPLETE, // 交换了一些已注册的过程数据(部分过程数据)
    EC_WC_COMPLETE // 交换了所有已注册的过程数据
    } ec_wc_state_t;

ec_domain_state_t

  • 简介:域状态。它被作为函数ecrt_domain_state()的输出参数使用
  • 声明:
    1
    2
    3
    4
    5
    typedef struct {
    unsigned int working_counter; // 最后一个工作计数器的值
    ec_wc_state_t ws_state; // 工作计数器状态说明
    unsigned int redundancy_active; // 冗余链路正在使用
    } ec_domain_state_t;

ec_pdo_entry_reg_t

  • 简介:列出PDO条目批量注册的记录类型。此类型用于ecrt_domain_reg_pdo_entry_list()的数组参数。
  • 声明:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    typedef struct {
    uint16_t alias; // 从站别名地址
    uint16_t position; // 从站位置
    uint32_t vendor_id; // 从站供销商ID
    uint32_t product_code; // 从站产品码
    uint16_t index; // PDO条目索引
    uint8_t subindex; // PDO条目子索引
    unsigned int *offset; // 指向在进程数据中存储PDO条目(字节-)偏移量的变量的指针。
    unsigned int *bit_position; // 指向一个变量的指针,用于在\a偏移量内存储位位置(0-7)。可以为NULL,在这种情况下,如果PDO条目不字节对齐会引发错误
    } ec_pdo_entry_reg_t;

API

ecrt_master_create_domain

  • 简介:创建一个新的过程数据域。对于流程数据交换,至少需要一个流程数据域。这个方法创建一个新的过程数据域,并返回一个指向新域对象的指针。这个对象能够在循环操作中用于注册PDOs和交换PDOs
  • 声明:
    1
    ec_domain_t *ecrt_master_create_domain( ec_master_t *master);

ecrt_request_master

  • 简介:请求EtherCAT主机进行实时操作。
    • 在应用程序可以访问EtherCAT主机之前,它必须预留一个专用的主机。
    • 在用户空间,这是ecrt_open_master()ecrt_master_reserve()的方便函数。
    • 这个函数必须是应用程序使用EtherCAT时必须调用的第一个函数
    • 该函数以master的索引作为参数。第一个主节点的索引为0,第n个主节点的索引为n- 1。
    • 在加载master时,必须指定master的数量。
  • 声明:
    1
    ec_master_t *ecrt_request_master(unsigned int master_index);

ecrt_master_sdo_upload

  • 简介:执行SDO上传请求从从站读取数据。
    • 此请求由主状态机处理。
    • 他的方法会阻塞,直到请求被处理,并且不能在实时上下文中调用。
  • 声明:
    1
    int ecrt_master_sdo_upload(ec_master_t *master, uint16_t slave_position, uint16_t index, uint8_t subindex, uint8_t *target, size_t target_size, size_t *result_size, uint32_t *abort_code);
  • 参数:
    • master – EtherCAT主站
    • slave_position – 从站位置
    • index – SDO索引
    • subindex – SDO的子索引
    • target – 上传的目标缓冲区。
    • target_size – 目标缓冲区的大小
    • result_size – 已经上传的数据大小
    • abort_code – SDO上传的中止代码。
  • 返回值:
    • 成功 – 0
    • 失败 – < 0

ecrt_master_sdo_download

  • 简介:执行SDO下载请求,将数据写入从站。
    • 此请求由主状态机处理。
    • 他的方法会阻塞,直到请求被处理,并且不能在实时上下文中调用。
  • 声明:
    1
    int ecrt_master_sdo_download(ec_master_t *master, uint16_t slave_position, uint16_t index, uint8_t subindex, uint8_t *data, size_t data_size, uint32_t *abort_code);
  • 参数:
    • master – EtherCAT主站
    • slave_position – 从站位置
    • index – SDO索引
    • subindex – SDO的子索引
    • data – 要下载的数据缓冲区
    • data_size – 数据缓冲区大小
    • abort_code – SDO上传的中止代码。
  • 返回值:
    • 成功 – 0
    • 失败 – < 0

ecrt_domain_reg_pdo_entry_list

  • 简介:为一个域注册一堆PDO条目。此方法必须在ecrt_master_activate()之前在非实时上下文中调用。
  • 声明:
    1
    int ecrt_domain_reg_pdo_entry_list(ec_domain_t *domain, const ec_pdo_entry_reg_t *pdo_entry_regs);
  • 参数:
    • domain – 域
    • pdo_entry_regs – PDO注册数组。注册数组必须以一个空结构体结束,或者将\a索引字段设置为0 !
  • 返回值:
    • 成功 – 0
    • 失败 – 其他

ecrt_master_activate

  • 简介:完成配置阶段并为循环操作做准备。
    • 这个函数告诉主机配置阶段已经完成,将开始实时操作。
    • 该函数为域分配内部内存,并为域成员计算逻辑FMMU地址。
    • 它告诉主状态机现在要应用总线配置。
    • 调用此函数后,实时应用程序负责循环调用ecrt_master_send()ecrt_master_receive()以确保总线通信。
    • 在调用这个函数之前,由主线程负责,所以这些函数可能不会被调用!
    • 该方法本身分配内存,不应该在实时上下文中调用。
  • 声明:
    1
    int ecrt_master_activate(ec_master_t *master);
  • 参数:
    • master – EtherCAT 主站
  • 返回值:
    • 成功 – 0
    • 失败 – < 0

ecrt_domain_data

  • 简介:返回域的过程数据。
    • 在内核上下文中:
      • 如果使用ecrt_domain_external_memory()提供外部内存,则返回的指针将包含该内存的地址。
      • 否则它将指向内部分配的内存。
      • 在后一种情况下,在ecrt_master_activate()之前不能调用此方法。
    • 在用户空间上下文中:
      • 必须在ecrt_master_activate()之后调用此方法以获取映射的域进程数据内存。
  • 声明:uint8_t *ecrt_domain_data(ec_domain_t *domain);
  • 参数:
    • domain – 域
  • 返回值:
    • 返回指向过程数据内存区域的指针

ecrt_master_select_reference_clock

  • 简介:为分布式时钟选择参考时钟。如果这个方法没有被某个主时钟调用,或者从时钟配置指针为NULL,那么第一个具有DC功能的从时钟将提供参考时钟。
  • 声明:
    1
    int ecrt_master_select_reference_clock(ec_master_t *master, ec_slave_config_t *sc);
  • 参数:
    • master – EtherCAT 主站
    • sc – Slave的Slave配置要引用的Slave(或NULL)。
  • 返回值:
    • 成功 – 0
    • 失败 – 负数,错误码

ecrt_master_application_time

  • 简介:设置应用时间。在使用分布式时钟操作从服务器时,主服务器必须知道应用程序的时间。主程序本身不会增加时间,因此必须循环调用此方法。
    • 传递给该方法的时间用于计算从服务器的SYNC0/1中断的阶段。它应该经常在实时周期的同一点被调用。因此,建议在计算开始时调用它,以避免由于执行时间的变化而导致的偏差。
    • 该时间用于设置从机的系统时间偏移和循环操作开始时间寄存器,以及通过ecrt_master_sync_reference_clock()将DC参考时钟同步到应用程序时间。
    • 时间定义为从2000-01-01 00:00开始的纳秒。可以使用EC_TIMEVAL2NANO()宏来转换epoch时间,但这不是必需的,因为绝对值无关紧要
  • 声明:
    1
    void ecrt_master_application_time(ec_master_t *master, uint64_t app_time);
  • 参数:
    • master – EtherCAT 主站
    • app_time – 应用时间

ecrt_master_sync_reference_clock

  • 简介:将DC参考时钟漂移补偿数据报排队发送。参考时钟将被同步到由最后一次调用取消ecrt_master_application_time()提供的应用程序时间。
  • 声明:
    1
    void ecrt_master_sync_reference_clock(ec_master_t *master);
  • 参数:
    • master – EtherCAT 主站

ecrt_master_sync_slave_clocks

  • 简介:将DC时钟漂移补偿数据报排队发送。所有从时钟同步到参考时钟。
  • 声明:
    1
    void ecrt_master_sync_slave_clocks(ec_master_t *master);
  • 参数:
    • master – EtherCAT 主站

ecrt_release_master

  • 简介:释放一个请求的EtherCAT主机。
    • 在使用后,必须释放master,以便其他应用程序可以使用它。
    • 此方法释放所有已创建的数据结构。它不应该在实时上下文中调用。
    • 如果主站被激活,则内部调用ecrt_master_deactivate()
  • 声明:
    1
    void ecrt_release_master(ec_master_t *master);
  • 参数:
    • master – EtherCAT 主站

ecrt_master_receive

  • 简介:从硬件中获取接收到的帧并处理数据报。
    • 通过调用中断服务例程查询网络设备接收的帧。
    • 提取接收到的数据报,并将结果分派到队列中的数据报对象。
    • 接收到的数据报和超时的数据报将被标记,并退出队列
    • 必须在ecrt_master_activate()返回后由实时应用程序循环调用。
  • 声明:
    1
    void ecrt_master_receive(ec_master_t *master);

ecrt_domain_process

  • 简介:确定域的数据报的状态。
    • 计算接收到的数据报的工作计数器,并在必要时输出统计信息。
    • 这必须在ecrt_master_receive()接收域数据报之后调用,以便使ecrt_domain_state()返回最后一次进程数据交换的结果。
  • 声明:
    1
    void ecrt_domain_process(ec_domain_t *domain);

ecrt_domain_queue

  • 简介:(Re-)将所有域数据报放在主数据报队列中。调用此函数来标记域的数据报,以便在下一次调用ecrt_master_send()时进行交换
  • 声明:
    1
    void ecrt_domain_queue(ec_domain_t *domain);

ecrt_master_send

  • 简介:发送队列中的所有数据报。
    • 该方法获取所有已排队等待传输的数据报,将它们放入帧中,并将它们传递给以太网设备进行发送。
    • 必须在ecrt_master_activate()返回后由应用程序循环调用。
  • 声明:
    1
    void ecrt_master_send(ec_master_t *master);

ecrt_domain_state

  • 简介:读取域的状态。
    • 在给定的\a状态结构中存储域状态。
    • 利用该方法,可以实时监控过程数据交换情况。
  • 声明:
    1
    void ecrt_domain_state(const ec_domain_t *domain, ec_domain_state_t *state);
  • 参数:
    • domain – 域
    • state – 指向用于存储信息的状态对象的指针。

ecrt_master_state

  • 简介:读取当前主站的状态。
    • 在给定的\a状态结构中存储主站状态。
    • 此方法返回一个全局状态。对于冗余总线拓扑中特定于链路的状态,请使用ecrt_master_link_state()方法。
  • 声明:
    1
    void ecrt_master_state(const ec_master_t *master, ec_master_state_t *state);
  • 参数:
    • master – 主站
    • state – 指向用于存储信息的状态对象的指针

ecrt_slave_config_state

  • 简介:输出从站配置的状态。
    • 在给定的\a状态结构中存储状态信息。状态信息由主状态机更新,因此可能需要几个周期,直到它发生变化。
    • 如果需要实时监控进程数据交换的状态,则应该使用ecrt_domain_state()
  • 声明:
    1
    void ecrt_slave_config_state(const ec_slave_config_t *sc, ec_slave_config_state_t *state);
  • 参数:
    • sc – 从站配置
    • state – 需要写入的状态对象

ecrt_request_master

  • 简介:

    • ecrt_request_master() 是 EtherCAT 主站驱动库(EtherCAT Master Library)中的一个函数,用于请求 EtherCAT 主站的实例
  • 原型:

    1
    ec_master_t* ecrt_request_master(uint32_t master_id);
  • 参数:

    • master_id:一个无符号 32 位整数,表示所请求的 EtherCAT 主站的 ID
  • 返回值:

    • 成功时,返回 ec_master_t* 类型的指针,指向请求的 EtherCAT 主站实例。
    • 失败时,返回 NULL
  • 详解:

    • ecrt_request_master() 函数用于请求 EtherCAT 主站的实例,以便后续使用 EtherCAT Master Library 的其他函数进行 EtherCAT 网络的配置和操作。
    • 在调用 ecrt_request_master() 函数之前,需要确保 EtherCAT Master Library 已被正确初始化。
    • master_id 参数指定所请求的 EtherCAT 主站的 ID。在系统中存在多个 EtherCAT 主站时,可以使用不同的 ID 来区分它们。
    • 请求成功后,将返回指向请求的 EtherCAT 主站实例的指针。通过该指针,可以对 EtherCAT 主站进行配置、管理和操作。
    • 返回的 EtherCAT 主站实例指针将用作其他 EtherCAT Master Library 函数的参数,以标识要操作的 EtherCAT 主站。
  • 注:

    • 需要注意的是,ecrt_request_master() 函数只是请求 EtherCAT 主站实例的第一步。在使用 EtherCAT Master Library 进行 EtherCAT 网络的配置和操作之前,还需要使用其他函数进行更详细的初始化和配置,如 ecrt_master_open()、ecrt_master_activate() 等函数

ecrt_master_create_domain

  • 简介:

    • ecrt_master_create_domain() 是 EtherCAT 主站驱动库(EtherCAT Master Library)中的一个函数,用于创建 EtherCAT 主站的数据域(Domain)
  • 原型:

    1
    ec_domain_t* ecrt_master_create_domain(ec_master_t* master);
  • 参数:

    • master:指向已请求的 EtherCAT 主站实例的 ec_master_t* 类型指针
  • 返回值:

    • 成功时,返回 ec_domain_t* 类型的指针,指向创建的 EtherCAT 数据域(Domain)实例。
    • 失败时,返回 NULL
  • 详解:

    • ecrt_master_create_domain() 函数用于创建 EtherCAT 主站的数据域,用于管理 EtherCAT 从站设备的数据通信。
    • 在调用 ecrt_master_create_domain() 函数之前,需要先通过 ecrt_request_master() 函数请求 EtherCAT 主站的实例。
    • 参数 master 是指向已请求的 EtherCAT 主站实例的指针,用于指定创建数据域的主站。
    • 创建数据域后,可以使用其他 EtherCAT Master Library 函数来配置和管理数据域,如添加从站设备、映射对象字典、读取和写入数据等。
    • 返回的数据域实例指针将用作其他 EtherCAT Master Library 函数的参数,以标识要操作的数据域
  • 注:

    • 需要注意的是,ecrt_master_create_domain() 函数只是创建数据域的第一步。在使用数据域进行数据通信之前,还需要使用其他函数进行更详细的配置和映射,如 ecrt_domain_register()、ecrt_domain_queue() 等函数

ecrt_master_slave_config

  • 简介:

    • ecrt_master_slave_config() 是 EtherCAT 主站驱动库(EtherCAT Master Library)中的一个函数,用于配置 EtherCAT 主站中的从站设备
  • 原型:

    1
    ec_slave_config_t* ecrt_master_slave_config(ec_master_t* master, uint16_t alias, uint16_t position, uint32_t vendor_id, uint32_t product_code);
  • 参数:

    • master:指向已请求的 EtherCAT 主站实例的 ec_master_t* 类型指针。
    • alias:一个无符号 16 位整数,表示从站设备的别名(Alias)。
    • position:一个无符号 16 位整数,表示从站设备的位置(Position)。
    • vendor_id:一个无符号 32 位整数,表示从站设备的供应商 ID。
    • product_code:一个无符号 32 位整数,表示从站设备的产品码
  • 返回值:

    • 成功时,返回 ec_slave_config_t* 类型的指针,指向配置的从站设备实例。
    • 失败时,返回 NULL
  • 详解:

    • ecrt_master_slave_config() 函数用于配置 EtherCAT 主站中的从站设备。
    • 在调用 ecrt_master_slave_config() 函数之前,需要先通过 ecrt_request_master() 函数请求 EtherCAT 主站的实例。
    • 参数 master 是指向已请求的 EtherCAT 主站实例的指针,用于指定要配置的主站。
    • 参数 alias 和 position 是从站设备的别名和位置,用于唯一标识从站设备在 EtherCAT 网络中的位置。
    • 参数 vendor_id 和 product_code 是从站设备的供应商 ID 和产品码,用于识别特定的从站设备。
    • 配置从站设备后,可以使用其他 EtherCAT Master Library 函数来访问和操作该设备,如读取和写入从站设备的对象字典数据等。
    • 返回的从站设备实例指针将用作其他 EtherCAT Master Library 函数的参数,以标识要操作的从站设备
  • 注:

    • 需要注意的是,ecrt_master_slave_config() 函数只是配置从站设备的一部分。在配置从站设备后,还需要使用其他函数进行更详细的初始化和设置,如 ecrt_slave_config_pdos()、ecrt_slave_config_sdo() 等函数

ecrt_slave_config_pdos

  • 简介:

    • ecrt_slave_config_pdos() 是 EtherCAT 主站驱动库(EtherCAT Master Library)中的一个函数,用于配置从站设备的过程数据对象(Process Data Objects,PDOs)
  • 原型:

    1
    int ecrt_slave_config_pdos(ec_slave_config_t* config, int direction, const ec_pdo_entry_reg_t* entries);
  • 参数:

    • config:指向已配置的从站设备实例的 ec_slave_config_t* 类型指针。
    • direction:整数,表示 PDO 的方向。可以是以下值之一
      • EC_DIR_OUTPUT:表示输出 PDO。
      • EC_DIR_INPUT:表示输入 PDO
    • entries:指向 ec_pdo_entry_reg_t 结构的指针,定义了要配置的 PDO 条目
  • 返回值:

    • 成功时,返回 0。
    • 失败时,返回一个负数表示错误码。
  • 详解:

    • ecrt_slave_config_pdos() 函数用于配置从站设备的 PDOs,即定义输入和输出数据的结构和格式。
    • 在调用 ecrt_slave_config_pdos() 函数之前,需要先通过 ecrt_master_slave_config() 函数配置从站设备。
    • 参数 config 是指向已配置的从站设备实例的指针,用于指定要配置的从站设备。
    • 参数 direction 指定 PDO 的方向,可以是输出(发送给从站设备)或输入(从从站设备接收)。
    • 参数 entries 是指向 ec_pdo_entry_reg_t 结构的指针,用于定义要配置的 PDO 条目。
    • ec_pdo_entry_reg_t 结构定义了 PDO 条目的索引、子索引、数据类型、长度等信息,用于描述从站设备的数据结构。
    • 通过调用 ecrt_slave_config_pdos() 函数,可以将 PDO 条目注册到指定的方向上,并配置从站设备的数据通信
  • 注:

    • 需要注意的是,PDO 的配置涉及到更详细的数据结构和通信配置,如 PDO 映射、PDO 类型、PDO 数据长度等。具体的操作流程和函数使用方式应根据实际需求和 EtherCAT Master Library 的文档进行进一步的学习和了解

ecrt_domain_reg_pdo_entry_list

  • 简介:

    • ecrt_domain_reg_pdo_entry_list() 是 EtherCAT 主站驱动库(EtherCAT Master Library)中的一个函数,用于在数据域(Domain)中注册 PDO 条目列表
  • 原型:

    1
    int ecrt_domain_reg_pdo_entry_list(ec_domain_t* domain, const ec_pdo_entry_reg_t* entries);
  • 参数:

    • domain:指向已创建的数据域(Domain)实例的 ec_domain_t* 类型指针。
    • entries:指向 ec_pdo_entry_reg_t 结构的指针,定义了要注册的 PDO 条目列表
  • 返回值:

    • 成功时,返回 0。
    • 失败时,返回一个负数表示错误码
  • 说明:

    • ecrt_domain_reg_pdo_entry_list() 函数用于在数据域中注册 PDO 条目列表,将 PDO 条目与数据域进行关联。
    • 在调用 ecrt_domain_reg_pdo_entry_list() 函数之前,需要先通过 ecrt_master_create_domain() 函数创建数据域。
    • 参数 domain 是指向已创建的数据域实例的指针,用于指定要注册 PDO 条目的数据域。
    • 参数 entries 是指向 ec_pdo_entry_reg_t 结构的指针,定义了要注册的 PDO 条目列表。
    • ec_pdo_entry_reg_t 结构定义了 PDO 条目的索引、子索引、数据类型、长度等信息,用于描述从站设备的数据结构。
    • 通过调用 ecrt_domain_reg_pdo_entry_list() 函数,可以将 PDO 条目列表注册到指定的数据域中,以便进行数据通信
  • 注:

    • 需要注意的是,PDO 条目的注册与数据域的映射和通信相关。在注册 PDO 条目列表后,需要使用其他函数来配置和管理数据域,如 ecrt_domain_queue()、ecrt_domain_state() 等函数

ecrt_slave_config_dc

  • 简介:

    • ecrt_slave_config_dc() 是 EtherCAT 主站驱动库(EtherCAT Master Library)中的一个函数,用于配置从站设备的分布式时钟(Distributed Clock)
  • 原型:

    1
    int ecrt_slave_config_dc(ec_slave_config_t* config, uint32_t sync0_shift, uint32_t sync1_shift, uint32_t sync0_cycle_time, uint32_t sync1_cycle_time);
  • 参数:

    • config:指向已配置的从站设备实例的 ec_slave_config_t* 类型指针。
    • sync0_shift:一个无符号 32 位整数,表示 Sync 0 时钟的相位偏移。
    • sync1_shift:一个无符号 32 位整数,表示 Sync 1 时钟的相位偏移。
    • sync0_cycle_time:一个无符号 32 位整数,表示 Sync 0 时钟的周期时间。
    • sync1_cycle_time:一个无符号 32 位整数,表示 Sync 1 时钟的周期时间
  • 返回值:

    • 成功时,返回 0。
    • 失败时,返回一个负数表示错误码
  • 详解:

    • ecrt_slave_config_dc() 函数用于配置从站设备的分布式时钟,以便与 EtherCAT 网络的同步机制进行协调。
    • 在调用 ecrt_slave_config_dc() 函数之前,需要先通过 ecrt_master_slave_config() 函数配置从站设备。
    • 参数 config 是指向已配置的从站设备实例的指针,用于指定要配置的从站设备。
    • 参数 sync0_shift 和 sync1_shift 是用于同步时钟的相位偏移值,以微秒为单位。这些值决定了从站设备与主站之间的同步关系。
    • 参数 sync0_cycle_time 和 sync1_cycle_time 是 Sync 0 和 Sync 1 时钟的周期时间,以纳秒为单位。这些值决定了同步时钟的周期性。
    • 通过调用 ecrt_slave_config_dc() 函数,可以配置从站设备的分布式时钟参数,以确保从站设备在 EtherCAT 网络中的同步性能
  • 注:

    • 需要注意的是,分布式时钟的配置涉及到与 EtherCAT 网络的同步机制和时钟同步周期的相关设置

ecrt_master_activate

  • 简介

    • ecrt_master_activate() 是 EtherCAT 主站驱动库(EtherCAT Master Library)中的一个函数,用于激活 EtherCAT 主站。
  • 原型:

    1
    int ecrt_master_activate(ec_master_t* master);
  • 参数:

    • master:指向已请求的 EtherCAT 主站实例的 ec_master_t* 类型指针
  • 返回值:

    • 成功时,返回 0。
    • 失败时,返回一个负数表示错误码。
  • 详解:

    • ecrt_master_activate() 函数用于激活 EtherCAT 主站,启动 EtherCAT 网络通信。
    • 在调用 ecrt_master_activate() 函数之前,需要先通过 ecrt_request_master() 函数请求 EtherCAT 主站的实例,并完成主站的配置和初始化。
    • 参数 master 是指向已请求的 EtherCAT 主站实例的指针,用于指定要激活的主站。
    • 激活主站后,可以使用其他 EtherCAT Master Library 函数来访问和操作从站设备,如读取和写入从站设备的对象字典数据等。
    • 主站激活后,开始进行 EtherCAT 网络的实时通信,主站与从站设备之间进行数据交换和同步
  • 注:

    • 需要注意的是,激活主站是启动 EtherCAT 网络通信的关键步骤。在激活主站之前,需要确保主站的配置和初始化工作已经完成,并且从站设备已经正确配置和连接到 EtherCAT 网络

ecrt_domain_data

  • 简介:

    • ecrt_domain_data() 是 EtherCAT 主站驱动库(EtherCAT Master Library)中的一个函数,用于获取数据域(Domain)的数据缓冲区指针
  • 原型:

    1
    void* ecrt_domain_data(ec_domain_t* domain);
  • 参数:

    • domain:指向已创建的数据域(Domain)实例的 ec_domain_t* 类型指针
  • 返回值:

    • 返回 void* 类型的指针,指向数据域的数据缓冲区
  • 详解:

    • ecrt_domain_data() 函数用于获取数据域的数据缓冲区指针,以便读取和写入数据。
    • 在调用 ecrt_domain_data() 函数之前,需要先通过 ecrt_master_create_domain() 函数创建数据域。
    • 参数 domain 是指向已创建的数据域实例的指针,用于指定要获取数据的数据域。
    • 通过调用 ecrt_domain_data() 函数,可以获取数据域的数据缓冲区指针,从而进行数据的读取和写入。
    • 数据缓冲区的类型取决于数据域的配置,可以是一个数组或结构体,用于存储与从站设备进行通信的数据
  • 注:

    • 需要注意的是,数据域的数据缓冲区指针可以用于直接读取和写入数据,但在进行数据操作之前,需要确保 EtherCAT 主站已经激活并与从站设备进行通信

ecrt_release_master

  • 简介:

    • ecrt_release_master() 是 EtherCAT 主站驱动库(EtherCAT Master Library)中的一个函数,用于释放已分配的主站资源
  • 原型:

    1
    void ecrt_release_master(ec_master_t* master);
  • 参数:

    • master:指向已分配的 EtherCAT 主站实例的 ec_master_t* 类型指针
  • 详解:

    • ecrt_release_master() 函数用于释放已分配的 EtherCAT 主站资源。
    • 在使用 EtherCAT 主站进行通信时,需要先使用 ecrt_request_master() 函数来请求主站资源,并在使用完毕后调用 ecrt_release_master() 函数来释放这些资源。
    • 参数 master 是指向已分配的 EtherCAT 主站实例的指针,用于指定要释放的主站资源。
    • 调用 ecrt_release_master() 函数后,主站资源将被释放,该资源将可用于其他目的。
    • 在释放主站资源之前,应确保已完成所有与从站设备的通信和操作,并确保不再需要使用主站
  • 注:

    • 需要注意的是,在使用 EtherCAT 主站进行通信时,应始终遵循正确的初始化、配置、通信和释放资源的流程。确保按照 EtherCAT Master Library 的文档和指导进行正确的函数调用和顺序。

ecrt_master_application_time

  • 简介:

    • ecrt_master_application_time() 是 EtherCAT 主站驱动库(EtherCAT Master Library)中的一个函数,用于设置 EtherCAT 主站的应用程序时间
  • 原型:

    1
    2
    3
    #include <ethercat.h>

    int ecrt_master_application_time(uint64_t cycletime);
  • 参数:

    • cycletime:以纳秒为单位表示的 EtherCAT 主站的应用程序周期时间
  • 返回值:

    • 如果设置成功,返回 0。
    • 如果设置失败,返回一个负数,表示错误的原因
  • 详解:

    • ecrt_master_application_time() 函数用于设置 EtherCAT 主站的应用程序时间,即 EtherCAT 通信的周期时间。
    • 要使用 ecrt_master_application_time() 函数,需要包含头文件 <ethercat.h>。
    • cycletime 参数指定 EtherCAT 主站的应用程序周期时间,以纳秒为单位。它定义了 EtherCAT 网络中的数据交换周期。
    • 在 EtherCAT 网络中,所有从站设备都按照相同的应用程序周期时间进行通信。
    • 通过调用 ecrt_master_application_time() 函数,可以设置主站的应用程序周期时间,以确保从站设备之间的同步性。
    • 设置应用程序周期时间后,主站将按照该周期周期性地发送和接收数据,从而实现同步和通信。
    • 返回值为 0 表示设置成功,否则表示设置失败,可以根据返回值进行错误处理
  • 注:

    • 需要注意的是,使用 ecrt_master_application_time() 函数进行 EtherCAT 主站的应用程序时间设置时,需要确保对应的 EtherCAT 主站驱动库支持该功能,并且遵循相关的使用要求和限制

ecrt_master_receive

  • 简介:

    • ecrt_master_receive() 是 EtherCAT 主站驱动库(EtherCAT Master Library)中的一个函数,用于接收从站设备发送的数据
  • 原型:

    1
    2
    3
    #include <ethercat.h>

    int ecrt_master_receive(ec_master_t *master);
  • 参数:

    • master:指向 EtherCAT 主站的指针,表示要接收数据的主站
  • 返回值:

    • 如果接收数据成功,返回 0。
    • 如果接收数据失败,返回一个负数,表示错误的原因
  • 详解:

    • ecrt_master_receive() 函数用于从 EtherCAT 主站接收从站设备发送的数据。
    • 要使用 ecrt_master_receive() 函数,需要包含头文件 <ethercat.h>。
    • 通过调用 ecrt_master_receive() 函数,可以从主站接收数据,并将其存储在主站的内部数据结构中,以供后续处理和访问。
    • 接收的数据通常是从站设备发送的输入数据或状态信息。
    • ecrt_master_receive() 函数会阻塞当前线程,直到接收到数据或发生错误。
    • 返回值为 0 表示接收数据成功,否则表示接收数据失败,可以根据返回值进行错误处理
  • 注:

    • 需要注意的是,使用 ecrt_master_receive() 函数接收从站设备发送的数据时,需要确保 EtherCAT 主站驱动库已经成功初始化,并且在调用该函数之前已经进行了相关的配置和启动操作。具体的使用方法和注意事项,应该根据您所使用的 EtherCAT 主站驱动库的文档和示例进行适当的调整和使用。

ecrt_domain_process

  • 简介:

    • ecrt_domain_process() 是 EtherCAT 主站驱动库(EtherCAT Master Library)中的一个函数,用于处理 EtherCAT 领域(Domain)的数据
  • 原型:

    1
    2
    3
    #include <ethercat.h>

    int ecrt_domain_process(ec_domain_t *domain);
  • 参数:

    • domain:指向要处理的 EtherCAT 领域的指针。
  • 返回值:

    • 如果处理成功,返回 0。
    • 如果处理失败,返回一个负数,表示错误的原因。
  • 详解:

    • ecrt_domain_process() 函数用于处理 EtherCAT 领域中的数据,即实现从站设备的数据交换。
    • 要使用 ecrt_domain_process() 函数,需要包含头文件 <ethercat.h>。
    • 通过调用 ecrt_domain_process() 函数,可以将 EtherCAT 领域中的数据发送给从站设备,并从从站设备接收数据。
    • 在 EtherCAT 网络中,一个领域包含了一组 PDO(Process Data Object),每个 PDO 包含了从站设备的输入或输出数据。
    • 调用 ecrt_domain_process() 函数时,主站会将领域中的数据发送到各个从站设备,并等待从站设备发送响应数据。
    • ecrt_domain_process() 函数会阻塞当前线程,直到数据交换完成或发生错误。
    • 返回值为 0 表示处理成功,否则表示处理失败,可以根据返回值进行错误处理
  • 注:

    • 需要注意的是,使用 ecrt_domain_process() 函数处理 EtherCAT 领域的数据时,需要确保 EtherCAT 主站驱动库已经成功初始化,并且 EtherCAT 主站和从站设备已经正确配置和启动。具体的使用方法和注意事项,应该根据您所使用的 EtherCAT 主站驱动库的文档和示例进行适当的调整和使用。

ecrt_master_state

  • 简介:

    • ecrt_master_state() 是 EtherCAT 主站驱动库(EtherCAT Master Library)中的一个函数,用于获取 EtherCAT 主站的状态信息
  • 原型:

    1
    2
    3
    #include <ethercat.h>

    ec_master_state_t ecrt_master_state(ec_master_t *master);
  • 参数:

    • master:指向 EtherCAT 主站的指针,表示要获取状态信息的主站
  • 返回值:

    • ec_master_state_t 类型的值,表示 EtherCAT 主站的状态信息
  • 详解:

    • ecrt_master_state() 函数用于获取 EtherCAT 主站的状态信息,如主站是否启动、错误状态等。
    • 要使用 ecrt_master_state() 函数,需要包含头文件 <ethercat.h>。
    • 通过调用 ecrt_master_state() 函数,可以获取主站的当前状态信息。
    • 返回的 ec_master_state_t 类型的值包含了主站的各种状态信息,如启动状态、错误状态、从站数量等。
    • ec_master_state_t 是一个结构体,包含了以下成员变量:
      • int slaves_responding:应答的从站数量。
      • int al_states:AL 状态。
      • int link_up:链路是否连接。
      • int linking:链路状态。
      • int operational:主站是否进入操作状态。
      • int error_flag:错误标志。
      • int slave_states:从站状态
    • 您可以通过访问返回的 ec_master_state_t 结构体的成员变量来获取各个状态信息。
    • 使用 ecrt_master_state() 函数可以帮助您监控和了解 EtherCAT 主站的状态,以便进行适当的处理和错误处理
  • 注:

    • 需要注意的是,使用 ecrt_master_state() 函数获取 EtherCAT 主站状态信息时,需要确保 EtherCAT 主站驱动库已经成功初始化,并且主站已经正确配置和启动。具体的使用方法和注意事项,应根据您所使用的 EtherCAT 主站驱动库的文档和示例进行适当的调整和使用

ecrt_slave_config_state

  • 简介:

    • ecrt_slave_config_state() 是 EtherCAT 主站驱动库(EtherCAT Master Library)中的一个函数,用于获取 EtherCAT 从站配置对象的状态信息
  • 原型:

    1
    2
    3
    #include <ethercat.h>

    ec_slave_config_state_t ecrt_slave_config_state(ec_slave_config_t *slave_config);
  • 参数:

    • slave_config:指向 EtherCAT 从站配置对象的指针,表示要获取状态信息的从站配置对象
  • 返回值:

    • ec_slave_config_state_t 类型的值,表示 EtherCAT 从站配置对象的状态信息
  • 详解:

    • ecrt_slave_config_state() 函数用于获取 EtherCAT 从站配置对象的状态信息,如从站是否应答、错误状态等。
    • 要使用 ecrt_slave_config_state() 函数,需要包含头文件 <ethercat.h>。
    • 通过调用 ecrt_slave_config_state() 函数,可以获取从站配置对象的当前状态信息。
    • 返回的 ec_slave_config_state_t 类型的值包含了从站配置对象的各种状态信息,如从站是否应答、错误状态、应答延迟等。
    • ec_slave_config_state_t 是一个结构体,包含了以下成员变量:
      • int online:从站是否在线。
      • int operational:从站是否进入操作状态。
      • int al_state:从站的 AL 状态。
      • int state:从站的状态。
      • int error_flag:错误标志。
      • int response_delay:应答延迟
    • 您可以通过访问返回的 ec_slave_config_state_t 结构体的成员变量来获取各个状态信息。
    • 使用 ecrt_slave_config_state() 函数可以帮助您监控和了解 EtherCAT 从站配置对象的状态,以便进行适当的处理和错误处理
  • 注:

    • 需要注意的是,使用 ecrt_slave_config_state() 函数获取 EtherCAT 从站配置对象状态信息时,需要确保 EtherCAT 主站驱动库已经成功初始化,并且相关的从站配置对象已经正确配置和启动。具体的使用方法和注意事项,应根据您所使用的 EtherCAT 主站驱动库的文档和示例进行适当的调整和使用

ecrt_master_sync_reference_clock

  • 简介:

    • ecrt_master_sync_reference_clock() 是 EtherCAT 主站驱动库(EtherCAT Master Library)中的一个函数,用于同步 EtherCAT 主站的参考时钟。
  • 原型:

    1
    2
    3
    #include <ethercat.h>

    void ecrt_master_sync_reference_clock(ec_master_t *master);
  • 参数:

    • master:指向 EtherCAT 主站的指针,表示要同步参考时钟的主站。
  • 详解:

    • ecrt_master_sync_reference_clock() 函数用于同步 EtherCAT 主站的参考时钟,以确保整个 EtherCAT 网络的同步性。
    • 要使用 ecrt_master_sync_reference_clock() 函数,需要包含头文件 <ethercat.h>。
    • 在 EtherCAT 网络中,参考时钟用于同步主站和从站设备的通信,以保证数据的准确性和一致性。
    • 调用 ecrt_master_sync_reference_clock() 函数时,主站会发送同步命令,从而启动参考时钟的同步过程。
    • 在同步过程中,主站会等待从站设备应答并进行相应的时钟调整,以达到整个网络的同步。
    • 一旦参考时钟同步完成,主站和从站设备之间的通信将在同一时基上进行。
    • ecrt_master_sync_reference_clock() 函数通常在 EtherCAT 网络启动之前被调用,以确保网络中的设备在通信开始之前具有一致的时钟。
    • 请注意,EtherCAT 网络中的参考时钟同步是非常重要的,因为它直接影响到数据的传输和同步性能
  • 注:

    • 需要注意的是,使用 ecrt_master_sync_reference_clock() 函数进行参考时钟同步时,需要确保 EtherCAT 主站驱动库已经成功初始化,并且主站和从站设备已经正确配置和启动。具体的使用方法和注意事项,应根据您所使用的 EtherCAT 主站驱动库的文档和示例进行适当的调整和使用

ecrt_master_sync_slave_clocks

  • 简介:

    • ecrt_master_sync_slave_clocks() 是 EtherCAT 主站驱动库(EtherCAT Master Library)中的一个函数,用于同步 EtherCAT 从站的时钟
  • 原型:

    1
    2
    3
    #include <ethercat.h>

    void ecrt_master_sync_slave_clocks(ec_master_t *master);
  • 参数:

    • master:指向 EtherCAT 主站的指针,表示要同步从站时钟的主站
  • 详解:

    • ecrt_master_sync_slave_clocks() 函数用于同步 EtherCAT 主站下所有从站的时钟,以确保整个 EtherCAT 网络中从站设备之间的时钟同步。
    • 要使用 ecrt_master_sync_slave_clocks() 函数,需要包含头文件 <ethercat.h>。
    • 在 EtherCAT 网络中,从站设备的时钟同步是重要的,以保证数据的传输和同步性能。
    • 调用 ecrt_master_sync_slave_clocks() 函数时,主站会发送同步命令,通知所有从站设备进行时钟调整。
    • 从站设备会根据主站发送的同步命令进行时钟调整,以达到整个网络的同步。
    • 一旦从站时钟同步完成,主站和从站设备之间的通信将在同一时基上进行。
    • ecrt_master_sync_slave_clocks() 函数通常在 EtherCAT 网络启动之前被调用,以确保网络中的所有从站设备在通信开始之前具有一致的时钟。
    • 请注意,EtherCAT 网络中从站的时钟同步对于数据的传输和同步性能非常重要
  • 注:

    • 需要注意的是,使用 ecrt_master_sync_slave_clocks() 函数进行从站时钟同步时,需要确保 EtherCAT 主站驱动库已经成功初始化,并且主站和从站设备已经正确配置和启动。具体的使用方法和注意事项,应根据您所使用的 EtherCAT 主站驱动库的文档和示例进行适当的调整和使用

ecrt_domain_queue

  • 简介:

    • ecrt_domain_queue() 是 EtherCAT 主站驱动库(EtherCAT Master Library)中的一个函数,用于将数据写入 EtherCAT 数据域(Domain)
  • 原型:

    1
    2
    3
    #include <ethercat.h>

    void ecrt_domain_queue(ec_domain_t *domain);
  • 参数:

    • domain:指向 EtherCAT 数据域(Domain)的指针,表示要将数据写入的数据域
  • 详解:

    • ecrt_domain_queue() 函数用于将数据写入 EtherCAT 数据域,以进行数据传输和同步。
    • 要使用 ecrt_domain_queue() 函数,需要包含头文件 <ethercat.h>。
    • EtherCAT 数据域是用于存储和传输与从站设备通信的数据的内存区域。
    • 通过调用 ecrt_domain_queue() 函数,可以将待发送的数据放入数据域中,以待发送到从站设备。
    • 调用 ecrt_domain_queue() 函数后,数据将进入数据域的发送队列,等待适当的时间点发送到从站设备。
    • 一旦数据被发送到从站设备,从站设备将读取并处理这些数据,以进行数据交换和通信。
    • 使用 ecrt_domain_queue() 函数可以实现周期性的数据传输和同步,以满足实时控制系统的要求
  • 注:

    • 需要注意的是,使用 ecrt_domain_queue() 函数进行数据域写入时,需要确保 EtherCAT 主站驱动库已经成功初始化,并且相关的数据域已经正确配置和启动。具体的使用方法和注意事项,应根据您所使用的 EtherCAT 主站驱动库的文档和示例进行适当的调整和使用

ecrt_master_send

  • 简介:

    • ecrt_master_send() 是 EtherCAT 主站驱动库(EtherCAT Master Library)中的一个函数,用于发送数据到 EtherCAT 从站设备。
  • 原型:

    1
    2
    3
    #include <ethercat.h>

    int ecrt_master_send(ec_master_t *master);
  • 参数:

    • master:指向 EtherCAT 主站的指针,表示要发送数据的主站
  • 返回值:

    • ecrt_master_send() 函数返回一个整数值,表示发送操作的结果。通常情况下,0 表示成功,负数表示失败
  • 详解:

    • ecrt_master_send() 函数用于向 EtherCAT 从站设备发送数据,以进行数据传输和通信。
    • 要使用 ecrt_master_send() 函数,需要包含头文件 <ethercat.h>。
    • 在 EtherCAT 网络中,主站负责向从站设备发送数据,并处理从站设备的应答。
    • 通过调用 ecrt_master_send() 函数,可以触发主站向从站设备发送先前通过 ecrt_domain_queue() 函数放置在数据域中的数据。
    • 当调用 ecrt_master_send() 函数时,主站将按照预定的通信周期发送数据到从站设备。
    • ecrt_master_send() 函数会阻塞主线程,直到发送操作完成或发生错误。
    • 发送操作完成后,可以通过调用 ecrt_master_state() 函数来检查发送的结果状态
  • 注:

    • 需要注意的是,使用 ecrt_master_send() 函数发送数据时,需要确保 EtherCAT 主站驱动库已经成功初始化,并且相关的数据域已经正确配置和启动。具体的使用方法和注意事项,应根据您所使用的 EtherCAT 主站驱动库的文档和示例进行适当的调整和使用

简介

  • 数值分析相关笔记

数值分析是什么

数值分析是数学的一个分支,研究使用数值计算方法解决数学问题的理论和算法。它主要涉及到通过计算机进行近似数值解的技术,尤其是在那些无法或难以通过解析方法得到精确解的问题上。数值分析在科学、工程、计算机科学等领域都有广泛的应用。

以下是数值分析的主要内容和概念:

  1. 数值逼近(Numerical Approximation): 研究如何使用有限的计算资源来获得数学问题的近似解。这包括插值、拟合、级数展开等方法。

  2. 数值解法(Numerical Methods): 开发和分析通过计算机进行数值计算的算法,解决代数方程组、微分方程、积分等问题。常见的数值解法包括牛顿法、迭代法、龙格-库塔法等。

  3. 误差分析(Error Analysis): 研究数值计算中产生的误差,包括截断误差和舍入误差。误差分析有助于评估数值算法的准确性和稳定性。

  4. 插值和拟合(Interpolation and Curve Fitting): 插值方法用于估算在已知数据点之间的值,而拟合方法用于找到最佳拟合曲线或曲面。

  5. 数值积分(Numerical Integration): 使用数值方法计算函数在区间上的积分,例如通过数值方法计算定积分的近似值。

  6. 数值微分(Numerical Differentiation): 使用数值方法计算函数在某点的导数,尤其是在没有解析导数表达式的情况下。

  7. 迭代法(Iterative Methods): 通过反复迭代更新来逼近函数的解,是求解非线性方程、线性方程组等问题的常见方法。

  8. 最优化方法(Optimization Methods): 研究在给定约束下找到函数的最大值或最小值的数值方法。

数值分析的应用非常广泛,包括工程设计、科学模拟、金融建模、图像处理、数据分析等领域。在这些领域,数值分析为复杂问题提供了有效的、可计算的解决方案。

简介

  • 数学相关笔记

数学有哪些分支

数学是一门广泛而深刻的学科,涵盖了多个分支和领域。以下是一些主要的数学分支:

  1. 代数学(Algebra): 研究代数结构、方程、多项式、群论、环论等。它包括基本代数、抽象代数等方向。

  2. 分析学(Analysis): 研究极限、微积分、积分学、级数、实变函数、复变函数等。分析学分为实分析和复分析。

  3. 几何学(Geometry): 研究空间和图形的形状、大小、性质以及它们之间的关系。平面几何和空间几何是几何学的两个主要方向。

  4. 概率论与数理统计(Probability and Statistics): 研究随机事件、概率、统计推断、回归分析等,应用于数据分析、科学实验、风险管理等领域。

  5. 数论(Number Theory): 研究整数的性质,涉及素数、同余、数的分布等问题。

  6. 拓扑学(Topology): 研究空间的连通性、紧性、维度等概念,不关注度量和角度,而更注重形状和空间的变换。

  7. 微分方程学(Differential Equations): 研究方程中的导数和微分的关系,以及解这些方程的方法。包括常微分方程和偏微分方程。

  8. 离散数学(Discrete Mathematics): 研究离散结构,如集合、图论、逻辑、代数系统等。在计算机科学中有广泛应用。

  9. 数学逻辑(Mathematical Logic): 研究数学推理和证明的形式系统,包括命题逻辑、谓词逻辑等。

  10. 运筹学(Operations Research): 利用数学方法解决决策问题,包括线性规划、整数规划、动态规划等。

  11. 应用数学(Applied Mathematics): 将数学方法和技术应用于其他学科和实际问题,包括物理学、工程学、经济学等。

这些数学分支之间有许多交叉和相互关联,数学的发展也在不断拓展和丰富这些领域。

几何学是什么

几何学是数学的一个分支,研究空间和图形的性质、形状、大小以及它们之间的相互关系。几何学关注的主要对象包括点、直线、平面、多边形、圆等几何图形,以及这些图形之间的相对位置和性质。

几何学可以分为平面几何和空间几何两个主要方向:

  1. 平面几何: 主要研究在一个平面上的几何关系和性质,包括点、直线、多边形、圆等在平面上的性质和相互关系。欧几里德几何是平面几何的一个经典分支,其中包含了许多基本的几何定理和公理。

  2. 空间几何: 主要研究在三维空间中的几何关系和性质,涉及点、直线、平面、曲线、曲面等在空间中的相互关系。空间几何通常涉及更复杂的数学工具,如向量、矩阵等,用于描述和计算三维空间中的几何对象。

几何学在数学中有着深远的影响,并且在许多其他学科中也有广泛的应用,如物理学、工程学、计算机图形学、地理学、建筑学等。它不仅关注于理论性质和证明,还在实际问题的建模、分析和解决方案中发挥着重要的作用。

简介

  • nvcc是cuda程序的编译器

  • 了解它的一些关键参数有利于我们更加从容,更加准确的构建自己的CUDA项目

  • Nvcc是一种编译器驱动,通过命令行选项可以在不同阶段启动不同的工具完成编译工作,其目的在于隐藏了复杂的CUDA编译细节,

  • 并且它不是一个特殊的CUDA编译驱动而是在模仿一般的通用编译驱动如gcc,它接受一定的传统编译选项如宏定义,库函数路径以及编译过程控制等

cuda编译文件流程

预处理

  • 首先是对输入的cu文件有一个预处理过程,这一过程包括的步骤有将该源文件里的宏以及相关引用文件扩展开,然后将预编译已经产生的与C有关的CUDA系统定义的宏扩展开,并合并分支编译的结果
  • CUDA源文件经过预处理过程后会生成具有.cup后缀名的经过预处理的源文件,经过预处理的源文件是再现程序bug的最好形式。
  • 通常,这个预处理过程是隐式完成的,如果想要显示执行,可以用命令nvcc-E x.cu -o x.cupnvcc -E x.cu > x.cup来实现

cudafe – 前后端设备分离

  • 预处理后,首先将预处理的结果送给CUDA前端,即CUDAfe.通过CUDAfe分离源文件,然后调用不同的编译器分别编译
  • cudafe被称为CUDAfrontend,会被调用两次,完成两个工作:
    • 一是,将主机代码与设备代码分离,生成gpu文件
    • 二是,对gpu文件进行deadcode analysis,传给nvopencc,未来的版本可能没有第二次调用
  • Nvopencc生成ptx文件传给ptxas,最后将cubin或ptx传给fatbin组合成一个设备代码描述符

生成编译代码

  • 在编译阶段CUDA源代码对C语言所扩展的部分将被转成regular ANSIC的源文件,也就可以由一般的C编译器进行更多的编译和连接。也即是设备代码被编译成ptx(parallel threadexecution)代码和/或二进制代码,
  • host代码则以C文件形式输出,在编译时可将设备代码描述符链接到所生成的host代码,将其中的cubin对象作为全局初始化数据数组包含进来,但此时,kernel执行配置也要被转换为CUDA运行启动代码,以加载和启动编译后的kernel
  • 在调用CUDA驱动API时,CUDA运行时系统会查看这个描述符,根据当前的GPU load一块具有合适ISAimage,然后便可单独执行ptx代码或cubin对象,而忽略nvcc编译得到的host代码。
  • Nvcc的各个编译阶段以及行为是可以通过组合输入文件名和选项命令进行选择的。它是不区分输入文件类型的,如object, library or resource files,仅仅把当前要执行编译阶段需要的文件传递给linker

指定编译阶段

  • 主要指定编译的阶段是最基本的编译参数
  • -ccbin : 指定host编译器所在路径

简介

  • 空间几何相关笔记

空间几何是什么

空间几何是几何学的一个分支,主要研究三维空间中的几何关系和性质。在空间几何中,我们考虑点、直线、平面等基本几何元素在三维空间中的相互关系、位置、距离、角度等性质。

主要的几何元素包括:

  1. 点(Point): 在三维空间中的位置,由坐标 ( (x, y, z) ) 表示。

  2. 直线(Line): 由无数个点组成,可以用方程或者参数方程表示。

  3. 平面(Plane): 由无数个点和直线组成,可以用法向量和一个点表示。

  4. 曲线(Curve): 在三维空间中的曲线,可以用参数方程或者其他方式表示。

  5. 曲面(Surface): 在三维空间中的曲面,可以用方程或者参数方程表示。

  6. 体(Solid): 在三维空间中的立体,可以用方程或者参数方程表示。

空间几何研究的问题包括点与直线的位置关系、点与平面的位置关系、直线与平面的位置关系、两条直线的交点、两平面的交线等等。这些关系和性质在计算机图形学、计算机辅助设计(CAD)、工程学、物理学等领域都有广泛的应用。

在空间几何中,通常使用向量、矩阵、坐标系等工具来表示和计算几何对象的性质,以及解决几何问题。

叉积法是什么

叉积法是一种基于向量叉积的几何计算方法。在三维空间中,给定两个向量 (\mathbf{v_1} = (x_1, y_1, z_1)) 和 (\mathbf{v_2} = (x_2, y_2, z_2)),它们的叉积 (\mathbf{v_1} \times \mathbf{v_2}) 是另一个向量,其计算方式为:

[
\mathbf{v_1} \times \mathbf{v_2} = (y_1z_2 - z_1y_2, z_1x_2 - x_1z_2, x_1y_2 - y_1x_2)
]

叉积的结果是一个垂直于原始两个向量的新向量。具体来说,叉积的方向由右手法则确定:将右手的四指从第一个向量的方向转向第二个向量的方向,那么大拇指的方向就是叉积的方向。

在几何学和计算几何中,叉积有很多应用,其中之一就是判断点是否在平面内或者在某个区域内。在本讨论中,叉积被用来判断一个点是否在一个由向量围成的平面或体内。如果两个向量是线段的边,叉积法可以用来判断一个点是否在这两个点围成的区域内。

总体来说,叉积法通过计算向量的方向关系,可以判断点在向量所在的平面的哪一侧,从而用于解决空间几何问题。

射线法是什么

射线法是一种在计算几何中常用的方法,用于判断点是否在多边形内部。该方法基于射线与多边形的交点数量,通过统计交点的奇偶性来确定点是否在多边形内。

具体步骤如下:

  1. 从待判断点发射一条射线(水平或垂直方向均可)。
  2. 记录射线与多边形的交点数量,每次与多边形的一条边相交就增加计数。
  3. 如果交点数量为奇数,那么点在多边形内部;如果为偶数,点在多边形外部。

这个方法的原理是,如果一个点在多边形内部,那么从这个点发射的射线与多边形的边界会有奇数个交点,而如果在外部,则交点数量是偶数。这是因为多边形内的射线与多边形的边界相交的次数总是奇数,而在外部则总是偶数。

射线法的优点是简单易懂,适用于凸多边形和凹多边形。然而,对于自相交的多边形,射线法可能无法正确判断点的位置。

这个方法在计算机图形学、地理信息系统(GIS)等领域经常被使用。在实际编程中,需要考虑浮点数计算误差、边界条件等因素,以提高算法的准确性。

简介

  • 线性代数相关笔记

线性代数是什么

线性代数是数学的一个分支,主要研究向量空间和线性映射的代数结构。它涉及向量、矩阵、线性方程组、线性变换等概念,并在各种学科和应用领域中有广泛的应用。以下是线性代数的一些主要概念:

  1. 向量(Vector): 向量是有大小和方向的量,常用箭头表示。在线性代数中,向量通常表示为一列有序数,例如 ( \mathbf{v} = \begin{bmatrix} v_1 \ v_2 \ \vdots \ v_n \end{bmatrix} )。

  2. 向量空间(Vector Space): 向量空间是一组满足一定条件的向量的集合,其中定义了向量的加法和数乘运算,并满足一些基本性质。

  3. 矩阵(Matrix): 矩阵是一个二维的数组,由数值组成。在线性代数中,矩阵通常用于表示线性变换,解线性方程组等。

  4. 线性变换(Linear Transformation): 线性变换是一个将一个向量空间映射到另一个向量空间的函数,满足线性性质。线性变换可以用矩阵表示。

  5. 行列式(Determinant): 行列式是一个与方阵相关的数值,用于描述线性变换对体积伸缩的影响。它在计算矩阵的逆、解线性方程组等方面很重要。

  6. 特征值与特征向量(Eigenvalues and Eigenvectors): 对于一个线性变换,特征值描述了变换的伸缩因子,而特征向量则是在变换下保持方向不变的向量。

  7. 内积空间和外积空间(Inner Product Space and Outer Product Space): 内积空间定义了向量之间的内积(点乘)运算,而外积空间定义了向量之间的外积运算。

线性代数在科学、工程、计算机科学等多个领域中都具有重要作用。它为许多数学问题的建模和求解提供了强大的工具,同时也是其他高阶数学分支的基础。