机器人学导论P115求雅可比矩阵python实现

代码如下:

import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import plotly.express as px
import plotly.graph_objects as go
from plotly.subplots import make_subplots
from numpy import sin
from numpy import cos
plt.rcParams["font.sans-serif"]=["SimHei"]            #设置字体
plt.rcParams["axes.unicode_minus"]=False              #该语句解决图像中的“-”负号的乱码问题
sns.set_style('whitegrid', {'font.sans-serif': ['simhei', 'Arial']})
sns.set(rc={"axes.facecolor":"#FFF9ED","figure.facecolor":"#FFF9ED", 'font.sans-serif': ['simhei', 'Arial']})   # 对整个文件配置生效,不单单对一个图形!

# 将角度值数据转换为弧度制
def d_to_r(degree):
    """
    将角度值数据转换为弧度制  公式:弧度= (角度×π)/180
    :param degree:
    :return:
    """
    radian = degree * np.pi / 180  # 将角度转换为弧度
    return radian


def abtain_J_orig(L1, L2, L3, theta_1, theta_2, theta_3):
    """
    根据提供的参数求初始时(即第一次循环)的雅可比矩阵
    abtain_theta_der(4, 3, 2, 10, 20, 30)
    :return:J, theta_old
    """
    # 将输入的角度值的theta_1, theta_2, theta_3转化为弧度制
    theta_1 = d_to_r(theta_1)
    theta_2 = d_to_r(theta_2)
    theta_3 = d_to_r(theta_3)

    # 定义雅可比矩阵   shape:3x3
    J = np.array(
        [[-L1*sin(theta_1)-L2*sin(theta_1+theta_2)-L3*sin(theta_1+theta_2+theta_3), -L2*sin(theta_1+theta_2)-L3*sin(theta_1+theta_2+theta_3), -L3*sin(theta_1+theta_2+theta_3)],
         [L1*cos(theta_1)+L2*cos(theta_1+theta_2)+L3*cos(theta_1+theta_2+theta_3), L2*cos(theta_1+theta_2)+L3*cos(theta_1+theta_2+theta_3), L3*cos(theta_1+theta_2+theta_3)],
         [1, 1, 1]])

    # 定义theta_old
    theta_old = np.array([theta_1, theta_2, theta_3]).T

    return J, theta_old


def abtain_J(L1, L2, L3, theta_array):
    """
    根据提供的参数求第2次到第n次循环时的雅可比矩阵
    abtain_theta_der(4, 3, 2, 10, 20, 30)
    :return:J, theta_old
    """
    # 把theta_array拆包为theta_1, theta_2, theta_3
    theta_1 = theta_array[0]
    theta_2 = theta_array[1]
    theta_3 = theta_array[2]

    # 定义雅可比矩阵   shape:3x3
    J = np.array(
        [[-L1*sin(theta_1)-L2*sin(theta_1+theta_2)-L3*sin(theta_1+theta_2+theta_3), -L2*sin(theta_1+theta_2)-L3*sin(theta_1+theta_2+theta_3), -L3*sin(theta_1+theta_2+theta_3)],
         [L1*cos(theta_1)+L2*cos(theta_1+theta_2)+L3*cos(theta_1+theta_2+theta_3), L2*cos(theta_1+theta_2)+L3*cos(theta_1+theta_2+theta_3), L3*cos(theta_1+theta_2+theta_3)],
         [1, 1, 1]])

    # 定义theta_old
    theta_old = np.array([theta_1, theta_2, theta_3]).T

    return J, theta_old


def abtain_theta_der(J):
    """
    根据提供的参数求关节速率theta_der
    abtain_theta_der(4, 3, 2, 10, 20, 30)
    :return:
    """
    # 定义笛卡尔速度Cartesian velocity
    Car_vel = np.array([0.2, -0.3, -0.2]).T

    # 求雅可比矩阵的逆矩阵
    J_inv = np.linalg.inv(J)

    # 求关节速率  theta_derivative  即theta求导
    theta_der = np.dot(J_inv, Car_vel)   # 执行矩阵相乘
    # print("theta_der:", theta_der)

    # 返回关节速率theta_der
    return theta_der


def abtain_theta_new(theta_old, theta_der):
    """
    计算求出theta_new
    :param theta_old:
    :param theta_der:
    :return:
    """
    # 定义delta_t的值   "delta"(希腊字母 Δ)
    delta_t = 0.1
    # 计算新的theta
    theta_new = theta_old + theta_der*delta_t
    # print("theta_new:",theta_new)
    return theta_new


def run():
    """
    执行
    :return:
    """
    # 定义循环次数
    loop_num = 50
    # 定义第一次循环时的参数
    L1 = 4
    L2 = 3
    L3 = 2
    theta1_orig = 10
    theta2_orig = 20
    theta3_orig = 30
    # 求第一次循环时的雅可比矩阵J,并返回theta_old
    J, theta_old = abtain_J_orig(L1, L2, L3, theta1_orig, theta2_orig, theta3_orig)
    print("初始时的J(雅可比矩阵):\n", J)
    # 定义所有关节角数组
    theta_all = theta_old.reshape((1,3))
    # 求第一次循环时的关节速率theta_der
    theta_der = abtain_theta_der(J)
    # 定义所有关节速率数组
    theta_der_all = theta_der.reshape((1,3))
    # 求第一次循环时的theta_new
    theta_new = abtain_theta_new(theta_old, theta_der)
    # 循环第2次到第n次
    for i in range(loop_num-1):  # 循环次数需减去初始时的一次计算
        J, theta_old = abtain_J(L1, L2, L3, theta_new)
        print(f"执行了{i+1}次循环后的J(雅可比矩阵):\n", J)
        theta_der = abtain_theta_der(J)
        # 把关节角数组拼接到所有关节角数组
        theta_all = np.concatenate((theta_all, theta_new.reshape((1, 3))))
        theta_new = abtain_theta_new(theta_old, theta_der)
        # 将关节速率数组拼接到所有关节速率数组
        theta_der_all = np.concatenate((theta_der_all, theta_der.reshape((1,3))))
    print(theta_der_all)
    return theta_der_all,theta_all


def plot():
    """
    画图
    画图可用三个库实现:matplotlib、seaborn、plotly。
    用哪个就需要安装对应的库。
    :return:
    """
    # 拆包run函数返回的两个数组
    theta_der_all, theta_all = run()

    # print("打印输入50个周期内的关节速率:\n", theta_der_all)
    # print(theta_der_all.shape)
    # 从theta_der_all数组中取出单独的每一列,即每个主动关节速率数据
    theta_der_1 = theta_der_all[:,0]
    theta_der_2 = theta_der_all[:,1]
    theta_der_3 = theta_der_all[:,2]
    # 从theta_all数组中取出单独的每一列,即每个主动关节角数据
    theta_1 = theta_all[:,0]
    theta_2 = theta_all[:,1]
    theta_3 = theta_all[:,2]

    # 时间数组
    time_array = np.arange(0,5,0.1)

    # 创建画布(容器层)
    figure, axes = plt.subplots(nrows=1, ncols=2,figsize=(8,4))

    # 创建折线图:theta_der
    axes[0].plot(time_array, theta_der_1, label='theta_der_1', color='blue')
    axes[0].plot(time_array, theta_der_2, label='theta_der_2', color='green')
    axes[0].plot(time_array, theta_der_3, label='theta_der_3', color='red')

    # 设置图形标题和轴标签
    axes[0].set_title('3个主动关节速率与时间的关系')
    axes[0].set_xlabel("时间")
    axes[0].set_ylabel("关节速率")

    # 修改x刻度   刻度有三个要素:一是起始值,二是末尾值,三是步长
    x_ticks = np.arange(0,5.5,0.5)
    axes[0].set_xticks(x_ticks, fontsize=2)  # 面向对象设置刻度说明需要另外set_xticklabels()函数

    # 显示图例
    axes[0].legend()

    # 创建折线图:theta
    axes[1].plot(time_array, theta_1, label='theta_1', color='blue')
    axes[1].plot(time_array, theta_2, label='theta_2', color='green')
    axes[1].plot(time_array, theta_3, label='theta_3', color='red')

    # 设置图形标题和轴标签
    axes[1].set_title('3个主动关节角与时间的关系')
    axes[1].set_xlabel("时间")
    axes[1].set_ylabel("关节角")

    # 修改x刻度   刻度有三个要素:一是起始值,二是末尾值,三是步长
    x_ticks = np.arange(0,5.5,0.5)
    axes[1].set_xticks(x_ticks)  # 面向对象设置刻度说明需要另外set_xticklabels()函数

    # 显示图例
    axes[0].legend()
    axes[1].legend()

    # 保存图形
    plt.savefig('result.png')

    # 显示图形
    plt.show()

    # # 用seaborn绘图
    # # 创建画布(容器层)
    # figure, axes = plt.subplots(nrows=1, ncols=2, figsize=(8, 4))
    #
    # # 创建折线图: theta_der
    # sns.lineplot(x=time_array, y=theta_der_1, label='theta_der_1', ax=axes[0], color='blue')
    # sns.lineplot(x=time_array, y=theta_der_2, label='theta_der_2', ax=axes[0], color='green')
    # sns.lineplot(x=time_array, y=theta_der_3, label='theta_der_3', ax=axes[0], color='red')
    #
    # # 设置图形标题和轴标签
    # axes[0].set_title('3个主动关节速率与时间的关系')
    # axes[0].set_xlabel("时间")
    # axes[0].set_ylabel("关节速率")
    #
    # # 修改x刻度
    # x_ticks = np.arange(0, 5.5, 0.5)
    # axes[0].set_xticks(x_ticks)
    #
    # # 显示图例
    # axes[0].legend()
    #
    # # 创建折线图: theta
    # sns.lineplot(x=time_array, y=theta_1, label='theta_1', ax=axes[1], color='blue')
    # sns.lineplot(x=time_array, y=theta_2, label='theta_2', ax=axes[1], color='green')
    # sns.lineplot(x=time_array, y=theta_3, label='theta_3', ax=axes[1], color='red')
    #
    # # 设置图形标题和轴标签
    # axes[1].set_title('3个主动关节角与时间的关系')
    # axes[1].set_xlabel("时间")
    # axes[1].set_ylabel("关节角")
    #
    # # 修改x刻度
    # axes[1].set_xticks(x_ticks)
    #
    # # 显示图例
    # axes[1].legend()
    #
    # # 保存图形
    # plt.savefig('result.png')
    #
    # # 显示图形
    # plt.show()

    # # 用px绘制图形
    # # 创建子图
    # fig = make_subplots(rows=1, cols=2, subplot_titles=("3个主动关节速率与时间的关系", "3个主动关节角与时间的关系"))  # subplot_titles这是单个子图的标题
    #
    # # 添加第一个子图
    # trace1_1 = go.Scatter(x=time_array, y=theta_der_1, mode='lines', name="theta_der_1")
    # trace1_2 = go.Scatter(x=time_array, y=theta_der_2, mode='lines', name="theta_der_2")
    # trace1_3 = go.Scatter(x=time_array, y=theta_der_3, mode='lines', name="theta_der_3")
    # fig.add_trace(trace1_1, row=1, col=1)
    # fig.add_trace(trace1_2, row=1, col=1)
    # fig.add_trace(trace1_3, row=1, col=1)
    #
    # # 添加第二个子图
    # trace2_1 = go.Scatter(x=time_array, y=theta_1, mode='lines', name="theta_1")
    # trace2_2 = go.Scatter(x=time_array, y=theta_2, mode='lines', name="theta_2")
    # trace2_3 = go.Scatter(x=time_array, y=theta_3, mode='lines', name="theta_3")
    # fig.add_trace(trace2_1, row=1, col=2)
    # fig.add_trace(trace2_2, row=1, col=2)
    # fig.add_trace(trace2_3, row=1, col=2)
    #
    # # 更新图表布局
    # fig.update_layout(
    #     title="可视化",   # 这是整个图幅的标题
    #     title_x=0.5,  # 设置标题的水平位置为中央
    #     width=1000,  # 设置图幅宽度
    #     height=600,  # 设置图幅高度
    #     xaxis=dict(title="时间"),
    #     yaxis=dict(title="关节速率"),
    #     xaxis2=dict(title="时间"),
    #     yaxis2=dict(title="关节角"),
    # )
    #
    # # 设置横坐标刻度值
    # fig.update_xaxes(tickvals=np.arange(0,5.5,0.5), row=1, col=1)
    # fig.update_xaxes(tickvals=np.arange(0,5.5,0.5), row=1, col=2)
    #
    # # 展示图像
    # fig.show()


if __name__ == '__main__':
    plot()

绘制图像如下:

在这里插入图片描述

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值