V-REP和Python的联合仿真

news2024/11/26 7:34:25

机器人仿真软件 各类免费的的机器人仿真软件优缺点汇总_robot 仿真 软件收费么_dyannacon的博客-CSDN博客

课程地址 https://class.guyuehome.com/p/t_pc/course_pc_detail/column/p_605af87be4b007b4183a42e7

课程资料 guyueclass: 古月学院课程代码

旋转变换 旋转的左乘与右乘 - 知乎

四足机器人站立控制原理 【基础知识】四足机器人的站立姿态控制原理 - 知乎

单腿逆解参考 https://github.com/richardbloemenkamp/Robotdog

Vrep文档

Vrep放大object

Vrep 导入模型步骤:

1. plugins-->urdf import导入机器人URDF文件

2. 删除机器人对象中的world_joint和world_link_visual

3. 双击设置机器人参数

碰撞参数设置:body参数设置,自身碰撞勾选前四个勾,leg参数设置,自身碰撞勾选后四个勾,即不计算与自身的碰撞关系

设置关节参数

调节颜色

python联合仿真

remote API路径:C:\Program Files\CoppeliaRobotics\CoppeliaSimEdu\programming\remoteApiBindings

1. 选择仿真器

2. 创建Vrep脚本用于远程连接

3. 绑定脚本到机器人

4. 编辑脚本,添加远程连接代码

4. 编写python脚本并测试(将腿部足端位置转换为关节的角度)

连接V-REP需要从remote API路径拷贝相关文件

"""
连接VREP Server并测试控制四足机器人
"""
try:
    import sim
except ImportError:
    print('--------------------------------------------------------------')
    print('"sim.py" could not be imported. This means very probably that')
    print('either "sim.py" or the remoteApi library could not be found.')
    print('Make sure both are in the same folder as this file,')
    print('or appropriately adjust the file "sim.py"')
    print('--------------------------------------------------------------')
    print('')

    sim = None

import time
import numpy as np


def start_simulation():
    sim.simxFinish(-1)
    # 开启套接字与server进行通信
    clientID = sim.simxStart('127.0.0.1', 19999, True, True, 5000, 5)
    if clientID != -1:
        print('Connected to remote API server with ClientID ', clientID)
        # 开始模拟
        sim.simxStartSimulation(clientID, sim.simx_opmode_oneshot)

        return clientID
    else:
        return -1


def get_joints(client_id):
    # 机器人电机力矩参数
    rotation_forces = [
        # RB
        [500, 500, 500],
        # RF
        [500, 500, 500],
        # LB
        [500, 500, 500],
        # LF
        [500, 500, 500]
    ]

    # 获取机器人关节对象句柄
    rec, rb_rot_1 = sim.simxGetObjectHandle(client_id, 'rb_rot_1', sim.simx_opmode_blocking)
    rec, rb_rot_2 = sim.simxGetObjectHandle(client_id, 'rb_rot_2', sim.simx_opmode_blocking)
    rec, rb_rot_3 = sim.simxGetObjectHandle(client_id, 'rb_rot_3', sim.simx_opmode_blocking)

    rec, rf_rot_1 = sim.simxGetObjectHandle(client_id, 'rf_rot_1', sim.simx_opmode_blocking)
    rec, rf_rot_2 = sim.simxGetObjectHandle(client_id, 'rf_rot_2', sim.simx_opmode_blocking)
    rec, rf_rot_3 = sim.simxGetObjectHandle(client_id, 'rf_rot_3', sim.simx_opmode_blocking)

    rec, lb_rot_1 = sim.simxGetObjectHandle(client_id, 'lb_rot_1', sim.simx_opmode_blocking)
    rec, lb_rot_2 = sim.simxGetObjectHandle(client_id, 'lb_rot_2', sim.simx_opmode_blocking)
    rec, lb_rot_3 = sim.simxGetObjectHandle(client_id, 'lb_rot_3', sim.simx_opmode_blocking)

    rec, lf_rot_1 = sim.simxGetObjectHandle(client_id, 'lf_rot_1', sim.simx_opmode_blocking)
    rec, lf_rot_2 = sim.simxGetObjectHandle(client_id, 'lf_rot_2', sim.simx_opmode_blocking)
    rec, lf_rot_3 = sim.simxGetObjectHandle(client_id, 'lf_rot_3', sim.simx_opmode_blocking)

    # 设置电机力矩
    rec = sim.simxSetJointForce(client_id, rb_rot_1, rotation_forces[0][0], sim.simx_opmode_blocking)
    rec = sim.simxSetJointForce(client_id, rb_rot_2, rotation_forces[0][1], sim.simx_opmode_blocking)
    rec = sim.simxSetJointForce(client_id, rb_rot_3, rotation_forces[0][2], sim.simx_opmode_blocking)

    rec = sim.simxSetJointForce(client_id, rf_rot_1, rotation_forces[1][0], sim.simx_opmode_blocking)
    rec = sim.simxSetJointForce(client_id, rf_rot_2, rotation_forces[1][1], sim.simx_opmode_blocking)
    rec = sim.simxSetJointForce(client_id, rf_rot_3, rotation_forces[1][2], sim.simx_opmode_blocking)

    rec = sim.simxSetJointForce(client_id, lb_rot_1, rotation_forces[2][0], sim.simx_opmode_blocking)
    rec = sim.simxSetJointForce(client_id, lb_rot_2, rotation_forces[2][1], sim.simx_opmode_blocking)
    rec = sim.simxSetJointForce(client_id, lb_rot_3, rotation_forces[2][2], sim.simx_opmode_blocking)

    rec = sim.simxSetJointForce(client_id, lf_rot_1, rotation_forces[3][0], sim.simx_opmode_blocking)
    rec = sim.simxSetJointForce(client_id, lf_rot_2, rotation_forces[3][1], sim.simx_opmode_blocking)
    rec = sim.simxSetJointForce(client_id, lf_rot_3, rotation_forces[3][2], sim.simx_opmode_blocking)

    return [rb_rot_1, rb_rot_2, rb_rot_3], \
           [rf_rot_1, rf_rot_2, rf_rot_3], \
           [lb_rot_1, lb_rot_2, lb_rot_3], \
           [lf_rot_1, lf_rot_2, lf_rot_3]


def leg_inverse_kine(x, y, z):
    # h,hu和hl分别是单条腿杆件的长度
    h = 0.15
    hu = 0.35
    hl = 0.382
    dyz = np.sqrt(y**2 + z**2)
    lyz = np.sqrt(dyz**2 - h**2)
    gamma_yz = -np.arctan(y/z)
    gamma_h_offset = -np.arctan(h/lyz)
    gamma = gamma_yz - gamma_h_offset

    lxzp = np.sqrt(lyz**2 + x**2)
    n = (lxzp**2 - hl**2 - hu**2) / (2 * hu)
    beta = -np.arccos(n / hl)

    alfa_xzp = -np.arctan(x/lyz)
    alfa_off = np.arccos((hu + n) / lxzp)
    alfa = alfa_xzp + alfa_off

    return gamma, alfa, beta


if __name__ == '__main__':
    # 机器人电机角度参数
    rb_poses = [40*np.pi/180, 0, 0]
    rf_poses = [0, 0, 0]
    lb_poses = [0, 0, 0]
    lf_poses = [0, 0, 0]

    client_id = start_simulation()
    if client_id != -1:
        joints = get_joints(client_id)
        rb_joints = joints[0]
        rf_joints = joints[1]
        lb_joints = joints[2]
        lf_joints = joints[3]

        time.sleep(1)
        timeout = 60
        start_time = time.time()
        curr_time = time.time()

        # 初始关节角度
        rb_poses = leg_inverse_kine(0, -0.3, -0.632)
        rf_poses = leg_inverse_kine(0, -0.3, -0.632)
        lb_poses = leg_inverse_kine(0, -0.3, -0.632)
        lf_poses = leg_inverse_kine(0, -0.3, -0.632)

        while curr_time - start_time < timeout:
            # 设置关节角度
            rec = sim.simxSetJointTargetPosition(client_id, rb_joints[0], -rb_poses[0], sim.simx_opmode_oneshot)
            rec = sim.simxSetJointTargetPosition(client_id, rb_joints[1], rb_poses[1], sim.simx_opmode_oneshot)
            rec = sim.simxSetJointTargetPosition(client_id, rb_joints[2], rb_poses[2], sim.simx_opmode_oneshot)

            rec = sim.simxSetJointTargetPosition(client_id, rf_joints[0], rf_poses[0], sim.simx_opmode_oneshot)
            rec = sim.simxSetJointTargetPosition(client_id, rf_joints[1], rf_poses[1], sim.simx_opmode_oneshot)
            rec = sim.simxSetJointTargetPosition(client_id, rf_joints[2], rf_poses[2], sim.simx_opmode_oneshot)

            rec = sim.simxSetJointTargetPosition(client_id, lb_joints[0], -lb_poses[0], sim.simx_opmode_oneshot)
            rec = sim.simxSetJointTargetPosition(client_id, lb_joints[1], lb_poses[1], sim.simx_opmode_oneshot)
            rec = sim.simxSetJointTargetPosition(client_id, lb_joints[2], lb_poses[2], sim.simx_opmode_oneshot)

            rec = sim.simxSetJointTargetPosition(client_id, lf_joints[0], lf_poses[0], sim.simx_opmode_oneshot)
            rec = sim.simxSetJointTargetPosition(client_id, lf_joints[1], lf_poses[1], sim.simx_opmode_oneshot)
            rec = sim.simxSetJointTargetPosition(client_id, lf_joints[2], lf_poses[2], sim.simx_opmode_oneshot)

            curr_time = time.time()
            # print("curr time :", curr_time - start_time)

        # 完成模拟
        sim.simxStopSimulation(client_id, sim.simx_opmode_blocking)
        sim.simxFinish(client_id)
    else:
        print('Failed connecting to remote API server')

显示足端轨迹

1. 打开shape编辑模式,并在vertex编辑模式下选择节点,在添加dummy

将dummy移动到腿部object下

2. 添加图用于创建curve

3. 设置3D Curve

4. 修改位置控制速度上限(将速度上限修改为500)

步态控制

utils.py

import sim
import numpy as np


def start_simulation():
    sim.simxFinish(-1)
    # 开启套接字与server进行通信
    clientID = sim.simxStart('127.0.0.1', 19999, True, True, 5000, 5)
    if clientID != -1:
        print('Connected to remote API server with ClientID ', clientID)
        # 开始模拟
        sim.simxStartSimulation(clientID, sim.simx_opmode_oneshot)

        return clientID
    else:
        return -1


def get_joints(client_id):
    # 机器人电机力矩参数
    rotation_forces = [
        # RB
        [500, 500, 500],
        # RF
        [500, 500, 500],
        # LB
        [500, 500, 500],
        # LF
        [500, 500, 500]
    ]

    # 获取机器人关节对象句柄
    rec, rb_rot_1 = sim.simxGetObjectHandle(client_id, 'rb_rot_1', sim.simx_opmode_blocking)
    rec, rb_rot_2 = sim.simxGetObjectHandle(client_id, 'rb_rot_2', sim.simx_opmode_blocking)
    rec, rb_rot_3 = sim.simxGetObjectHandle(client_id, 'rb_rot_3', sim.simx_opmode_blocking)

    rec, rf_rot_1 = sim.simxGetObjectHandle(client_id, 'rf_rot_1', sim.simx_opmode_blocking)
    rec, rf_rot_2 = sim.simxGetObjectHandle(client_id, 'rf_rot_2', sim.simx_opmode_blocking)
    rec, rf_rot_3 = sim.simxGetObjectHandle(client_id, 'rf_rot_3', sim.simx_opmode_blocking)

    rec, lb_rot_1 = sim.simxGetObjectHandle(client_id, 'lb_rot_1', sim.simx_opmode_blocking)
    rec, lb_rot_2 = sim.simxGetObjectHandle(client_id, 'lb_rot_2', sim.simx_opmode_blocking)
    rec, lb_rot_3 = sim.simxGetObjectHandle(client_id, 'lb_rot_3', sim.simx_opmode_blocking)

    rec, lf_rot_1 = sim.simxGetObjectHandle(client_id, 'lf_rot_1', sim.simx_opmode_blocking)
    rec, lf_rot_2 = sim.simxGetObjectHandle(client_id, 'lf_rot_2', sim.simx_opmode_blocking)
    rec, lf_rot_3 = sim.simxGetObjectHandle(client_id, 'lf_rot_3', sim.simx_opmode_blocking)

    # 设置电机力矩
    rec = sim.simxSetJointForce(client_id, rb_rot_1, rotation_forces[0][0], sim.simx_opmode_blocking)
    rec = sim.simxSetJointForce(client_id, rb_rot_2, rotation_forces[0][1], sim.simx_opmode_blocking)
    rec = sim.simxSetJointForce(client_id, rb_rot_3, rotation_forces[0][2], sim.simx_opmode_blocking)

    rec = sim.simxSetJointForce(client_id, rf_rot_1, rotation_forces[1][0], sim.simx_opmode_blocking)
    rec = sim.simxSetJointForce(client_id, rf_rot_2, rotation_forces[1][1], sim.simx_opmode_blocking)
    rec = sim.simxSetJointForce(client_id, rf_rot_3, rotation_forces[1][2], sim.simx_opmode_blocking)

    rec = sim.simxSetJointForce(client_id, lb_rot_1, rotation_forces[2][0], sim.simx_opmode_blocking)
    rec = sim.simxSetJointForce(client_id, lb_rot_2, rotation_forces[2][1], sim.simx_opmode_blocking)
    rec = sim.simxSetJointForce(client_id, lb_rot_3, rotation_forces[2][2], sim.simx_opmode_blocking)

    rec = sim.simxSetJointForce(client_id, lf_rot_1, rotation_forces[3][0], sim.simx_opmode_blocking)
    rec = sim.simxSetJointForce(client_id, lf_rot_2, rotation_forces[3][1], sim.simx_opmode_blocking)
    rec = sim.simxSetJointForce(client_id, lf_rot_3, rotation_forces[3][2], sim.simx_opmode_blocking)

    return [rb_rot_1, rb_rot_2, rb_rot_3], \
           [rf_rot_1, rf_rot_2, rf_rot_3], \
           [lb_rot_1, lb_rot_2, lb_rot_3], \
           [lf_rot_1, lf_rot_2, lf_rot_3]


def leg_inverse_kine(x, y, z):
    """
    求四足机器人单条腿的逆运动学,输入足端位置,返回单腿关节的旋转的角度
    """
    # h,hu和hl分别是单条腿杆件的长度
    h = 0.15
    hu = 0.35
    hl = 0.382
    dyz = np.sqrt(y ** 2 + z ** 2)
    lyz = np.sqrt(dyz ** 2 - h ** 2)
    gamma_yz = -np.arctan(y / z)
    gamma_h_offset = -np.arctan(h / lyz)
    gamma = gamma_yz - gamma_h_offset

    lxzp = np.sqrt(lyz ** 2 + x ** 2)
    n = (lxzp ** 2 - hl ** 2 - hu ** 2) / (2 * hu)
    beta = -np.arccos(n / hl)

    alfa_xzp = -np.arctan(x / lyz)
    alfa_off = np.arccos((hu + n) / lxzp)
    alfa = alfa_xzp + alfa_off

    return gamma, alfa, beta


def pose_control(roll, pitch, yaw, pos_x, pos_y, pos_z):
    """
    输入
    """
    b = 0.4
    l = 0.8
    w = 0.7
    # 基座的高度
    h = 0.732

    # 转换角度
    R = roll * np.pi / 180
    P = pitch * np.pi / 180
    Y = yaw * np.pi / 180

    pos = np.mat([pos_x, pos_y, pos_z]).T

    # 定义旋转矩阵
    rotx = np.mat([[1, 0, 0],
                   [0, np.cos(R), -np.sin(R)],
                   [0, np.sin(R), np.cos(R)]])

    roty = np.mat([[np.cos(P), 0, -np.sin(P)],
                   [0, 1, 0],
                   [np.sin(P), 0, np.cos(P)]])

    rotz = np.mat([[np.cos(Y), -np.sin(Y), 0],
                   [np.sin(Y), np.cos(Y), 0],
                   [0, 0, 1]])

    rot_mat = rotx * roty * rotz

    # 基座位置
    body_struct = np.mat([[l / 2, b / 2, h],
                          [l / 2, -b / 2, h],
                          [-l / 2, b / 2, h],
                          [-l / 2, -b / 2, h]]).T

    # 足端位置
    footpoint_struct = np.mat([[l / 2, w / 2, 0],
                               [l / 2, -w / 2, 0],
                               [-l / 2, w / 2, 0],
                               [-l / 2, -w / 2, 0]]).T

    leg_pose = np.mat(np.zeros((3, 4)))

    for i in range(4):
        leg_pose[:, i] = -pos - rot_mat * body_struct[:, i] + footpoint_struct[:, i]

    return np.squeeze(np.array(leg_pose[:, 3])), np.squeeze(np.array(leg_pose[:, 0])), \
           np.squeeze(np.array(leg_pose[:, 1])), np.squeeze(np.array(leg_pose[:, 2]))


def cycloid(dt: float, period: float = 1.0, xs: float = -0.1, xf: float = 0.1, zs: float = -0.582, h: float = 0.1):
    """
    计算摆线上在给定时间t处的坐标。

    参数:
    t (float): 当前时间点
    Ts (float): 摆线运动总时间,默认为1.0
    xs (float): 起始x坐标,默认为-0.1
    xf (float): 终点x坐标,默认为0.1
    zs (float): 起始z坐标,默认为-0.582
    h (float): 摆线垂直位移,默认为0.1

    返回:
    tuple[float, float]: xep和zep的坐标值
    """
    sigma = 2 * np.pi * dt / period
    x_p = (xf - xs) * ((sigma - np.sin(sigma)) / (2 * np.pi)) + xs
    y_p = h * (1 - np.cos(sigma)) / 2 + zs
    return x_p, y_p


if __name__ == '__main__':
    for pos in pose_control(30, 0, 0, 0, 0, 0.732):
        print(pos)

main.py

import time
from utils import *

walk_period = 1.0
trot_period = 0.4

gait = 1


def cal_phase(dt, T, factor, zs = -0.482, h = 0.15):
    if dt < T * factor:
        return cycloid(dt, period=T * factor, zs=zs, h=h)
    else:
        return 0.1 - 0.2 / (T * (1 - factor)) * (dt - T * factor), zs


def walk_gait(dt):
    zs = -0.482
    h = 0.15

    lb_dt = dt % walk_period
    rf_dt = (dt + 0.25) % walk_period
    rb_dt = (dt + 0.5) % walk_period
    lf_dt = (dt + 0.75) % walk_period

    lb_pos = cal_phase(lb_dt, T=walk_period, factor=0.25, zs=zs, h=h)
    rf_pos = cal_phase(rf_dt, T=walk_period, factor=0.25, zs=zs, h=h)
    rb_pos = cal_phase(rb_dt, T=walk_period, factor=0.25, zs=zs, h=h)
    lf_pos = cal_phase(lf_dt, T=walk_period, factor=0.25, zs=zs, h=h)

    return lb_pos, rf_pos, rb_pos, lf_pos


def trot_gait(dt):
    zs = -0.482
    h = 0.1

    dt_1 = dt % trot_period
    dt_2 = (dt + 0.2) % trot_period

    pos_1 = cal_phase(dt_1, T=trot_period, factor=0.5, zs=zs, h=h)
    pos_2 = cal_phase(dt_2, T=trot_period, factor=0.5, zs=zs, h=h)
    return pos_1, pos_2


if __name__ == '__main__':
    # 连接到V-REP服务器
    clientID = start_simulation()

    # 检查连接是否成功
    if clientID != -1:
        joints = get_joints(clientID)
        rb_joints = joints[0]
        rf_joints = joints[1]
        lb_joints = joints[2]
        lf_joints = joints[3]

        timeout = 60
        start_time = time.time()
        curr_time = start_time

        sim_start_time, sim_curr_time = None, None
        lb_pos, rf_pos, rb_pos, lf_pos = None, None, None, None

        # 获取仿真时间
        while curr_time - start_time < timeout:
            res, sim_curr_time = sim.simxGetFloatSignal(clientID, 'time', sim.simx_opmode_oneshot)
            if res == sim.simx_return_ok:
                if sim_start_time is None:
                    sim_start_time = sim_curr_time

                print("time ", sim_curr_time - sim_start_time)

            if sim_start_time:
                dt = sim_curr_time - sim_start_time
                if gait == 0:
                    # dt = (sim_curr_time - sim_start_time) % walk_period
                    lb_pos, rf_pos, rb_pos, lf_pos = walk_gait(dt)
                elif gait == 1:
                    # dt = (sim_curr_time - sim_start_time) % trot_period
                    pos_1, pos_2 = trot_gait(dt)
                    lb_pos = pos_1
                    rf_pos = pos_1
                    rb_pos = pos_2
                    lf_pos = pos_2

                # 从足端位置求解关节角度
                rb_pose = leg_inverse_kine(rb_pos[0], -0.15, rb_pos[1])
                rf_pose = leg_inverse_kine(rf_pos[0], -0.15, rf_pos[1])
                lb_pose = leg_inverse_kine(lb_pos[0], -0.15, lb_pos[1])
                lf_pose = leg_inverse_kine(lf_pos[0], -0.15, lf_pos[1])

                rec = sim.simxSetJointTargetPosition(clientID, rb_joints[0], -rb_pose[0], sim.simx_opmode_oneshot)
                rec = sim.simxSetJointTargetPosition(clientID, rb_joints[1], rb_pose[1], sim.simx_opmode_oneshot)
                rec = sim.simxSetJointTargetPosition(clientID, rb_joints[2], rb_pose[2], sim.simx_opmode_oneshot)

                rec = sim.simxSetJointTargetPosition(clientID, rf_joints[0], rf_pose[0], sim.simx_opmode_oneshot)
                rec = sim.simxSetJointTargetPosition(clientID, rf_joints[1], rf_pose[1], sim.simx_opmode_oneshot)
                rec = sim.simxSetJointTargetPosition(clientID, rf_joints[2], rf_pose[2], sim.simx_opmode_oneshot)

                rec = sim.simxSetJointTargetPosition(clientID, lb_joints[0], -lb_pose[0], sim.simx_opmode_oneshot)
                rec = sim.simxSetJointTargetPosition(clientID, lb_joints[1], lb_pose[1], sim.simx_opmode_oneshot)
                rec = sim.simxSetJointTargetPosition(clientID, lb_joints[2], lb_pose[2], sim.simx_opmode_oneshot)

                rec = sim.simxSetJointTargetPosition(clientID, lf_joints[0], lf_pose[0], sim.simx_opmode_oneshot)
                rec = sim.simxSetJointTargetPosition(clientID, lf_joints[1], lf_pose[1], sim.simx_opmode_oneshot)
                rec = sim.simxSetJointTargetPosition(clientID, lf_joints[2], lf_pose[2], sim.simx_opmode_oneshot)

        # 停止仿真并断开与V-REP的连接
        sim.simxStopSimulation(clientID, sim.simx_opmode_oneshot)
        sim.simxFinish(clientID)

    else:
        print("无法连接到V-REP")

walk步态

trot步态

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

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

相关文章

灵魂拷问:读取 excel 测试数据真的慢吗?

&#x1f4e2;专注于分享软件测试干货内容&#xff0c;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01;&#x1f4e2;交流讨论&#xff1a;欢迎加入我们一起学习&#xff01;&#x1f4e2;资源分享&#xff1a;耗时200小时精选的「软件测试」资…

64位Office API声明语句第112讲

跟我学VBA&#xff0c;我这里专注VBA, 授人以渔。我98年开始&#xff0c;从源码接触VBA已经20余年了&#xff0c;随着年龄的增长&#xff0c;越来越觉得有必要把这项技能传递给需要这项技术的职场人员。希望职场和数据打交道的朋友&#xff0c;都来学习VBA,利用VBA,起码可以提高…

Linux开发工具的使用(vim、gcc/g++ 、make/makefile)

文章目录 一 &#xff1a;vim1:vim基本概念2:vim的常用三种模式3:vim三种模式的相互转换4:vim命令模式下的命令集- 移动光标-删除文字-剪切/删除-复制-替换-撤销和恢复-跳转至指定行 5:vim底行模式下的命令集 二:gcc/g1:gcc/g的作用2:gcc/g的语法3:预处理4:编译5:汇编6:链接7:函…

【ARFoundation学习笔记】ARFoundation基础(下)

写在前面的话 本系列笔记旨在记录作者在学习Unity中的AR开发过程中需要记录的问题和知识点。难免出现纰漏&#xff0c;更多详细内容请阅读原文。 文章目录 TrackablesTrackableManager可跟踪对象事件管理可跟踪对象 Session管理 Trackables 在AR Foundation中&#xff0c;平面…

大厂面试题-b树和b+树的理解

为了更清晰的解答这个问题&#xff0c;从三个方面来回答&#xff1a; a.了解二叉树、AVL树、B树的概念 b.B树和B树的应用场景 1.B树是一种多路平衡查找树&#xff0c;为了更形象的理解&#xff0c;我们来看这张图。 二叉树&#xff0c;每个节点支持两个分支的树结构&#xff…

第十五届全国交通运输领域青年学术会议,和鲸 Heywhale 携手龙船科技联合发布科研服务解决方案

2023年10月29日&#xff0c;由中国交通运输协会青年科技工作者工作委员会主办&#xff0c;集美大学承办的“第十五届全国交通运输领域青年学术会议”在一片热烈的氛围中圆满落幕。 本届会议以“低碳•智能•安全•可持续综合交通发展创新”为主题&#xff0c;围绕综合立体交通…

JavaScript_document对象_方法_获取元素

1、document.getElementsByTagName 2、 document.getElementsByClassName() document.getElementsByClassName方法返回一个类似数组的对象&#xff08;HTMLCollection实例&#xff09;&#xff0c;包括了所有class名字符合指定条件的元素&#xff0c;元素的变化实时反映在返回…

FL Studio21.2中文高级版数字音乐工作站(DAW)

FL Studio是一款功能强大的数字音乐工作站&#xff08;DAW&#xff09;&#xff0c;软件提供了丰富的功能和工具&#xff0c;使音乐制作变得更加轻松和富有创意性。而在其中&#xff0c;一个关键的功能就是Fruity Wrapper&#xff0c;它在FL Studio中扮演着重要的角色。接下来给…

idea必装插件EditStarters(快速引入依赖)

前言 一般来说我们要向一个 servlet 或者 Spring 项目中引入依赖都需要先到中心仓库找到对应的依赖&#xff0c;选择依赖的版本&#xff0c;把依赖添加到配置文件 pom.xml 中&#xff0c;这其实还是有点麻烦的&#xff0c;而通过 EditStarters 插件我们可以迅速的添加依赖到项目…

计算机网络第4章-IPv6和寻址

IP地址的分配 为了获取一块IP地址用于一个组织的子网内&#xff0c;于是我们向ISP联系&#xff0c;ISP则会从已分给我们的更大 地址块中提供一些地址。 例如&#xff0c;ISP也许已经分配了地址块200.23.16.0/20。 该ISP可以依次将该地址块分成8个长度相等的连续地址块&…

Jakarta-JVM篇

文章目录 一.前言1. 1 JVM-堆常用调参1.2 JVM-方法区常用参数1.3 JVM-codeCache 二.JVM内存结构三. 对象创建四. JVM垃圾回收算法4.1 可达性分析算法4.1.1 对象引用4.1.2 回收方法区. 4.2 分代回收4.3 标记清除4.4 标记复制4.5 标记整理 五.垃圾回收器5.1 根节点枚举5.2 安全点…

2023-11-06今日最大收获:坑爹的 JpaRepository!

1.坑爹的 JpaRepository&#xff01; org.springframework.dao.InvalidDataAccessResourceUsageException: could not extract ResultSet; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet 2023-11-06 18:38:53.12…

光链路测试6271B光纤温度分布测试仪

6271B 光纤温度分布测试 6271B 光纤温度分布测试仪主要基于光纤拉曼散射效应和光时域反射技术研制&#xff0c;利用温度传感光缆&#xff08;纤&#xff09;&#xff0c;实现空间温度的在线、实时、连续分布式测试。光纤温度分布测试仪由主机&#xff08;信号处理单元&#xff…

c++学习之AVL树

目录 一&#xff0c;什么是AVL树 二&#xff0c;AVL树的实现 结构体 insert 左单旋 右单旋 双旋 双旋右边高 双旋左边高 最终实现的插入函数 遍历 判断平衡 一&#xff0c;什么是AVL树 在之前&#xff0c;我们已经了解到了二叉搜索树&#xff0c;提到过它的搜索效率…

【OS】操作系统课程笔记 第六章 并发性——死锁

6.1 死锁的概念 所谓死锁&#xff0c;是指多个进程因竞争资源而造成的一种僵局&#xff0c;若无外力作用&#xff0c;这些进程都将永远不能再向前推进。 下面举个例子&#xff0c;进程P1已经占用了资源R1&#xff0c;进程P2已经占用了资源R2&#xff0c;而P1和P2都要同时使用…

全自动批量AI改写文章发布软件【软件脚本+技术教程】

项目原理&#xff1a; 利用AI工具将爆款文章改写发布到平台上流量变现,通过播放量赚取收益 软件功能&#xff1a; 1.可以根据你选的文章领域&#xff0c;识别你在网站上抓取的文章链接进来自动洗稿生成过原创的文章&#xff0c;自动配图 2.同时还可以将管理的账号导入进脚本软…

Java基础(第五期): 一维数组 二维数组 数组 引用数据类型在内存中的存储图解

Java基础专栏 文章目录 一、数组介绍和静态初始化1.1 数组初始化1.2 数组的定义格式1.3 数组的静态初始化格式 二、 数组元素访问三、数组遍历操作四、数组遍历求和等练习2.数组求最大值 五、数组动态初始化六、两种初始化的区别七、数组内存图和方法参数传递八、二维数组静态…

深入详解高性能消息队列中间件 RabbitMQ

目录 1、引言 2、什么是 RabbitMQ &#xff1f; 3、RabbitMQ 优势 4、RabbitMQ 整体架构剖析 4.1、发送消息流程 4.2、消费消息流程 5、RabbitMQ 应用 5.1、广播 5.2、RPC VC常用功能开发汇总&#xff08;专栏文章列表&#xff0c;欢迎订阅&#xff0c;持续更新...&am…

【工具使用-信号叠加演示】一种演示不同频率信号叠加的工具

一&#xff0c;简介 本文主要介绍一种网页演示不同频率的正弦信号叠加的工具&#xff0c;供参考。 二&#xff0c;说明 网址&#xff1a;https://teropa.info/harmonics-explorer/ 打开后可以设置不同的信号&#xff0c;然后最上面是不同信号的频率叠加之后的效果&#xff…

Blender vs 3ds Max:谁才是3D软件的未来

在不断发展的3D建模和动画领域&#xff0c;两大软件巨头Blender和3ds Max一直在争夺顶级地位。 随着技术的进步和用户需求的演变&#xff0c;一个重要问题逐渐浮出水面&#xff1a;Blender是否最终会取代3ds Max&#xff1f;本文将深入探讨二者各自的优势和劣势、当前状况&…