ROS2实用工具

1. 将ROS2的Bag文件转换为CSV、JSON等

具体代码地址:https://github.com/fishros/ros2bag_convert

2.动手学Moveit2|使用配置助手创建自己机械臂的功能包

运行如下配置助手:

ros2 run moveit_setup_assistant moveit_setup_assistant

如果运行报如下错误:

terminate called after throwing an instance of 'ament_index_cpp::PackageNotFoundError'
  what():  package 'elite_description' not found, searching: [/home/zy0035/piper_ros/install/piper_with_gripper_moveit, /home/zy0035/piper_ros/install/piper_no_gripper_moveit, /home/zy0035/piper_ros/install/piper_mujoco, /home/zy0035/piper_ros/install/piper_msgs, /home/zy0035/piper_ros/install/piper_humble, /home/zy0035/piper_ros/install/piper_gazebo, /home/zy0035/piper_ros/install/piper_description, /home/zy0035/piper_ros/install/piper, /home/zy0035/ros2_ws/install/vision, /home/zy0035/ros2_ws/install/ur_bringup, /home/zy0035/ros2_ws/install/ur5e_octomap_moveit, /home/zy0035/ros2_ws/install/ur5e_gripper_control, /home/zy0035/ros2_ws/install/ur5e_gripper_moveit_config, /home/zy0035/ros2_ws/install/ur5e_gripper_description, /home/zy0035/ros2_ws/install/robotiq_moveit_config, /home/zy0035/ros2_ws/install/robotiq_description, /home/zy0035/ros2_ws/install/realsense2_description, /home/zy0035/ros2_ws/install/realsense2_camera_msgs, /home/zy0035/ros2_ws/install/octo_bringup, /home/zy0035/ros2_ws/install/gazebo_grasp_plugin_ros, /home/zy0035/ros2_ws/install/gazebo_version_helpers, /opt/ros/humble]
Stack trace (most recent call last):
#31   Object "/usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5.15.3", at 0x70a086572e46, in QApplicationPrivate::sendMouseEvent(QWidget*, QMouseEvent*, QWidget*, QWidget*, QWidget**, QPointer<QWidget>&, bool, bool)
#30   Object "/usr/lib/x86_64-linux-gnu/libQt5Core.so.5.15.3", at 0x70a0858b9e39, in QCoreApplication::notifyInternal2(QObject*, QEvent*)
#29   Object "/usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5.15.3", at 0x70a086574363, in QApplication::notify(QObject*, QEvent*)
#28   Object "/usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5.15.3", at 0x70a08656c712, in QApplicationPrivate::notify_helper(QObject*, QEvent*)
#27   Object "/usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5.15.3", at 0x70a0865af4ed, in QWidget::event(QEvent*)
#26   Object "/usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5.15.3", at 0x70a0866641e6, in QAbstractButton::mouseReleaseEvent(QMouseEvent*)
#25   Object "/usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5.15.3", at 0x70a086663fc3, in 
#24   Object "/usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5.15.3", at 0x70a08666239d, in 
#23   Object "/usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5.15.3", at 0x70a086662115, in QAbstractButton::clicked(bool)
#22   Object "/usr/lib/x86_64-linux-gnu/libQt5Core.so.5.15.3", at 0x70a0858f17c7, in 
#21   Source "./src/helper_widgets.cpp", line 171, in btnFileDialog [0x70a086faf5ef]
#20   Object "/usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5.15.3", at 0x70a0866c2a91, in QWidgetLineControl::internalSetText(QString const&, int, bool)
#19   Object "/usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5.15.3", at 0x70a0866c27ce, in QWidgetLineControl::finishChange(int, bool, bool)
#18   Object "/usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5.15.3", at 0x70a0866bf0f8, in QWidgetLineControl::textChanged(QString const&)
#17   Object "/usr/lib/x86_64-linux-gnu/libQt5Core.so.5.15.3", at 0x70a0858f17c7, in 
#16   Object "/usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5.15.3", at 0x70a0866b7845, in QLineEdit::textChanged(QString const&)
#15   Object "/usr/lib/x86_64-linux-gnu/libQt5Core.so.5.15.3", at 0x70a0858f17c7, in 
#14   Source "./.obj-x86_64-linux-gnu/include/moveit_setup_framework/qt/moc_helper_widgets.cpp", line 222, in pathChanged [0x70a086fd86c5]
#13   Object "/usr/lib/x86_64-linux-gnu/libQt5Core.so.5.15.3", at 0x70a0858f17c7, in 
#12   Source "./src/start_screen_widget.cpp", line 308, in onUrdfPathChanged [0x70a071141f19]
#11   Source "./src/start_screen.cpp", line 52, in loadURDFFile [0x70a0711400a0]
#10   Source "./src/urdf_config.cpp", line 80, in loadFromPath [0x70a086fba4f4]
#9  | Source "./src/urdf_config.cpp", line 104, in getSharePath
      Source "./include/moveit_setup_framework/utilities.hpp", line 52, in setPackageName [0x70a086fba14f]
#8    Object "/opt/ros/humble/lib/libament_index_cpp.so", at 0x70a086bf0e42, in ament_index_cpp::get_package_share_directory(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)
#7    Object "/opt/ros/humble/lib/libament_index_cpp.so", at 0x70a086beeb19, in 
#6    Object "/usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.30", at 0x70a0870ae4d7, in __cxa_throw
#5    Object "/usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.30", at 0x70a0870ae276, in std::terminate()
#4    Object "/usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.30", at 0x70a0870ae20b, in 
#3    Object "/usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.30", at 0x70a0870a2b9d, in 
#2    Source "./stdlib/abort.c", line 79, in abort [0x70a0852287f2]
#1    Source "../sysdeps/posix/raise.c", line 26, in raise [0x70a085242475]
#0  | Source "./nptl/pthread_kill.c", line 89, in __pthread_kill_internal
    | Source "./nptl/pthread_kill.c", line 78, in __pthread_kill_implementation
      Source "./nptl/pthread_kill.c", line 44, in __pthread_kill [0x70a0852969fc]
Aborted (Signal sent by tkill() 2007497 1000)
[ros2run]: Aborted

解决方案:

有stl文件在urdf里边,或者你应该在你的含有urdf文件的功能包的src目录下打开moveit setup assistant,然后再去找你的urdf文件

Moveit2生成的参数有BUG修复

具体配置参考:https://zhuanlan.zhihu.com/p/567246503

这里,给出我使用松灵的piper臂生成的文件下载地址:

https://download.csdn.net/download/caokaifa/91669593

不知道为啥生成的joint_limits.yaml调用ros2 launch piper_control_arm demo.launch.py会报错,只要把文件中的5改为5.0就OK了,正确的如下图参数。

# joint_limits.yaml allows the dynamics properties specified in the URDF to be overwritten or augmented as needed

# For beginners, we downscale velocity and acceleration limits.
# You can always specify higher scaling factors (<= 1.0) in your motion requests.  # Increase the values below to 1.0 to always move at maximum speed.
default_velocity_scaling_factor: 0.1
default_acceleration_scaling_factor: 0.1

# Specific joint properties can be changed with the keys [max_position, min_position, max_velocity, max_acceleration]
# Joint limits can be turned off with [has_velocity_limits, has_acceleration_limits]
joint_limits:
  joint1:
    has_velocity_limits: true
    max_velocity: 5.0
    has_acceleration_limits: false
    max_acceleration: 0
  joint2:
    has_velocity_limits: true
    max_velocity: 5.0
    has_acceleration_limits: false
    max_acceleration: 0
  joint3:
    has_velocity_limits: true
    max_velocity: 5.0
    has_acceleration_limits: false
    max_acceleration: 0
  joint4:
    has_velocity_limits: true
    max_velocity: 5.0
    has_acceleration_limits: false
    max_acceleration: 0
  joint5:
    has_velocity_limits: true
    max_velocity: 5.0
    has_acceleration_limits: false
    max_acceleration: 0
  joint6:
    has_velocity_limits: true
    max_velocity: 5.0
    has_acceleration_limits: false
    max_acceleration: 0

生成的文件调用没有错误,但是控制不了臂,原谅是moveit_controllers.yaml中有问题:

把这个文件修改一下:原代码如下:

# MoveIt uses this configuration for controller management

moveit_controller_manager: moveit_simple_controller_manager/MoveItSimpleControllerManager

moveit_simple_controller_manager:
  controller_names:
    - piper_arm_controller

  piper_arm_controller:
    type: FollowJointTrajectory
    joints:
      - joint1
      - joint2
      - joint3
      - joint4
      - joint5
      - joint6

修改后如下:

# MoveIt uses this configuration for controller management

moveit_controller_manager: moveit_simple_controller_manager/MoveItSimpleControllerManager

moveit_simple_controller_manager:
  controller_names:
    - piper_arm_controller

  piper_arm_controller:
    type: FollowJointTrajectory
    action_ns: follow_joint_trajectory
    default: true
    joints:
      - joint1
      - joint2
      - joint3
      - joint4
      - joint5
      - joint6

这样就可以控制臂规划了!!!!

相关moveit应用例子代码参考:

https://github.com/LitchiCheng/ros2_package

Hybrid Planning — MoveIt Documentation: Rolling documentation

https://github.com/agilexrobotics/piper_ros/tree/humble

3.ROS2 查看话题是谁订阅以及发布指令

 ros2 topic info /joint_states --verbose

就是通过info查看话题有几个发布,几个订阅,通过--verbose显示话题的详细信息

4.ROS2 查看msg类型

ros2 interface show sensor_msgs/msg/JointState

5.yolo的使用与数据模型

参考论文

yolo11超详细教程_ultralytics yolo11-CSDN博客

Ultralytics YOLO11 - Documentos Ultralytics YOLO

6.调用moveit2中的C++接口控制

piper_control.cpp内容如下:

#include <rclcpp/rclcpp.hpp>
#include <moveit/move_group_interface/move_group_interface.h>
#include <memory>
 
void move_robot(rclcpp::Node::SharedPtr node)
{
    //创建一个MoveGroupInterface对象,用于控制机械臂的运动
    auto arm_move_group = moveit::planning_interface::MoveGroupInterface(node, "arm");
 
    // 设置机械臂各个关节的角度
    std::vector<double> arm_joint_goal = {0.5, 0.5, 0, 0, 0, 0};
    bool arm_within_bounds = arm_move_group.setJointValueTarget(arm_joint_goal);  
 
    if (!arm_within_bounds)
    {
        RCLCPP_WARN(rclcpp::get_logger("moveit_api_test"), "失败");
        return;
    }
 
    // 创建一个Plan对象,用于存储规划结果
    moveit::planning_interface::MoveGroupInterface::Plan arm_plan;
 
    // 调用plan()函数进行规划,返回规划是否成功
    bool arm_plan_success = (arm_move_group.plan(arm_plan) == moveit::core::MoveItErrorCode::SUCCESS);
    if (!arm_plan_success)
    {
        RCLCPP_WARN(rclcpp::get_logger("moveit_api_test"), "失败");
        return;
    }
    else
    {
        RCLCPP_INFO(rclcpp::get_logger("moveit_api_test"), "成功");
        arm_move_group.move();
    }
}
 
int main(int argc, char **argv)
{
    // 初始化ROS2通信上下文
    rclcpp::init(argc, argv);
    
    // 创建ROS2节点实例,节点名称为"simple_moveit_interface"
    rclcpp::Node::SharedPtr node = rclcpp::Node::make_shared("simple_moveit_interface");
    
    move_robot(node);
 
 
    // 进入事件循环,等待处理回调(此处尚未添加具体回调逻辑)
    rclcpp::spin(node);
    
    // 关闭ROS2通信上下文
    rclcpp::shutdown();
 
    return 0;  // 程序正常退出
}

CMakeLists.txt中

cmake_minimum_required(VERSION 3.8)
project(piper_control)

if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
  add_compile_options(-Wall -Wextra -Wpedantic)
endif()

# find dependencies
find_package(ament_cmake REQUIRED)
# uncomment the following section in order to fill in
# further dependencies manually.
# find_package(<dependency> REQUIRED)
find_package(rclcpp REQUIRED)

find_package(moveit_core REQUIRED)

find_package(moveit_ros_planning_interface REQUIRED)

find_package(moveit_ros_planning REQUIRED)

add_executable(moveit_node src/piper_control.cpp)

ament_target_dependencies(moveit_node

        rclcpp

        moveit_core

        moveit_ros_planning_interface

        moveit_ros_planning

)
install(TARGETS

        moveit_node

        DESTINATION lib/${PROJECT_NAME}

)
if(BUILD_TESTING)
  find_package(ament_lint_auto REQUIRED)
  # the following line skips the linter which checks for copyrights
  # comment the line when a copyright and license is added to all source files
  set(ament_cmake_copyright_FOUND TRUE)
  # the following line skips cpplint (only works in a git repo)
  # comment the line when this package is in a git repo and when
  # a copyright and license is added to all source files
  set(ament_cmake_cpplint_FOUND TRUE)
  ament_lint_auto_find_test_dependencies()
endif()

ament_package()

package.xml中

<?xml version="1.0"?>
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3">
  <name>piper_control</name>
  <version>0.0.0</version>
  <description>TODO: Package description</description>
  <maintainer email="caokaifa2015@sina.com">robert</maintainer>
  <license>TODO: License declaration</license>

  <buildtool_depend>ament_cmake</buildtool_depend>
  <depend>rclcpp</depend>
  <depend>moveit_core</depend>
  <depend>moveit_ros_move_group</depend>
  <depend>moveit_kinematics</depend>
  <depend>moveit_ros_planning_interface</depend>  
  <depend>tf2_ros</depend>
  <depend>controller_manager</depend>
  <depend>moveit_ros_planning</depend>
  <depend>moveit_ros_occupancy_map_monitor</depend>
  <depend>pluginlib</depend>
  <depend>class_loader</depend>
  
 
 
  <depend>geometry_msgs</depend>
  <depend>moveit_visual_tools</depend>


  <test_depend>ament_lint_auto</test_depend>
  <test_depend>ament_lint_common</test_depend>

  <export>
    <build_type>ament_cmake</build_type>
  </export>
</package>

具体可以参考:ROS2调用Moveit2的C++接口-CSDN博客

roslaunch piper_with_gripper_moveit demo.launch use_rviz:=false

7.获取手机陀螺仪数据进行滤波

import asyncio
import websockets
import socket
import json
import math
import time
import numpy as np
from piper_sdk import *


def get_ip():
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    try:
        s.connect(('10.255.255.255', 1))
        IP = s.getsockname()[0]
    except Exception:
        IP = '127.0.0.1'
    finally:
        s.close()
    return IP

def quat_from_euler(pitch, roll, yaw):
    cy = np.cos(yaw * 0.5)
    sy = np.sin(yaw * 0.5)
    cp = np.cos(pitch * 0.5)
    sp = np.sin(pitch * 0.5)
    cr = np.cos(roll * 0.5)
    sr = np.sin(roll * 0.5)
    q0 = cy * cp * cr + sy * sp * sr
    q1 = cy * sp * cr + sy * cp * sr
    q2 = sy * cp * cr - cy * sp * sr
    q3 = cy * cp * sr - sy * sp * cr
    return np.array([q0, q1, q2, q3])

def euler_from_quat(q):
    q0, q1, q2, q3 = q
    roll = np.arctan2(2*(q0*q1 + q2*q3), 1 - 2*(q1*q1 + q2*q2))
    pitch = np.arcsin(2*(q0*q2 - q3*q1))
    yaw = np.arctan2(2*(q0*q3 + q1*q2), 1 - 2*(q2*q2 + q3*q3))
    return pitch, roll, yaw

def normalize_quat(q):
    return q / np.linalg.norm(q)


class EKFAHRS:
    def __init__(self):
        # State vector: [q0, q1, q2, q3, bgx, bgy, bgz]
        self.x = np.zeros(7)
        self.x[0] = 1.0  # Initial quaternion
        self.P = np.eye(7)
        # Noise parameters
        self.Q = np.diag([1e-6]*4 + [1e-8]*3)
        self.R = np.diag([1e-1]*3)
        self.g = 9.81

    def set_init(self, acc, mag):
        # acc: 3, mag: 3, units g and μT
        acc = acc / np.linalg.norm(acc)
        pitch = np.arcsin(-acc[0])
        roll = np.arctan2(acc[1], acc[2])
        # Initialize yaw using magnetometer
        mx, my, mz = mag
        mag_x = mx * np.cos(pitch) + my * np.sin(roll) * np.sin(pitch) + mz * np.cos(roll) * np.sin(pitch)
        mag_y = my * np.cos(roll) - mz * np.sin(roll)
        yaw = np.arctan2(-mag_y, mag_x)
        q = quat_from_euler(pitch, roll, yaw)
        self.x[:4] = normalize_quat(q)

    def predict(self, gyro, dt):
        # gyro: rad/s, dt: s
        q = self.x[:4]
        bg = self.x[4:]
        omega = gyro - bg
        wx, wy, wz = omega
        Omega = np.array([
            [0, -wx, -wy, -wz],
            [wx, 0, wz, -wy],
            [wy, -wz, 0, wx],
            [wz, wy, -wx, 0]
        ])
        dq = 0.5 * Omega @ q
        q_new = q + dq * dt
        q_new = normalize_quat(q_new)
        self.x[:4] = q_new
        # Approximate state transition matrix
        F = np.eye(7)
        F[:4, :4] += 0.5 * Omega * dt
        self.P = F @ self.P @ F.T + self.Q

    def update(self, acc):
        # acc: 3, unit g
        q = self.x[:4]
        # Observation model: acc = R(q)^T * [0,0,1]
        hx = np.array([
            2*(q[1]*q[3] - q[0]*q[2]),
            2*(q[0]*q[1] + q[2]*q[3]),
            q[0]**2 + q[3]**2 - q[1]**2 - q[2]**2
        ])
        acc = acc / np.linalg.norm(acc)
        y = acc - hx
        # Jacobian matrix
        H = np.zeros((3,7))
        q0, q1, q2, q3 = q
        H[0,0] = -2*q2
        H[0,1] = 2*q3
        H[0,2] = -2*q0
        H[0,3] = 2*q1
        H[1,0] = 2*q1
        H[1,1] = 2*q0
        H[1,2] = 2*q3
        H[1,3] = 2*q2
        H[2,0] = 2*q0
        H[2,1] = -2*q1
        H[2,2] = -2*q2
        H[2,3] = 2*q3
        S = H @ self.P @ H.T + self.R
        K = self.P @ H.T @ np.linalg.inv(S)
        dx = K @ y
        self.x += dx
        self.x[:4] = normalize_quat(self.x[:4])
        self.P = (np.eye(7) - K @ H) @ self.P

    def get_euler(self):
        return euler_from_quat(self.x[:4])


async def echo(websocket, path):
    global last_time, ekf_initialized
    async for message in websocket:
        try:
            data = json.loads(message)
            sensor_name = data.get("SensorName", "").lower()
            timestamp = data.get("Timestamp", 0)

            if sensor_name in sensor_data:
                sensor_data[sensor_name]['x'] = float(data.get('x', 0))
                sensor_data[sensor_name]['y'] = float(data.get('y', 0))
                sensor_data[sensor_name]['z'] = float(data.get('z', 0))
                sensor_data[sensor_name]['timestamp'] = timestamp

                # Check if all three types of data are fresh
                accel_ts = sensor_data['accelerometer']['timestamp']
                gyro_ts = sensor_data['gyroscope']['timestamp']
                mag_ts = sensor_data['magnetometer']['timestamp']
                if abs(accel_ts - gyro_ts) < 100 and abs(accel_ts - mag_ts) < 100:
                    current_time = time.time()
                    dt = current_time - last_time
                    last_time = current_time

                    # Unit Explanation:
                    # Accelerometer ax, ay, az units are g (gravity)
                    # Gyroscope gx, gy, gz units are rad/s
                    # Magnetometer mx, my, mz units are μT
                    gx = sensor_data['gyroscope']['x']
                    gy = sensor_data['gyroscope']['y']
                    gz = sensor_data['gyroscope']['z']
                    ax = sensor_data['accelerometer']['x']
                    ay = sensor_data['accelerometer']['y']
                    az = sensor_data['accelerometer']['z']
                    mx = sensor_data['magnetometer']['x']
                    my = sensor_data['magnetometer']['y']
                    mz = sensor_data['magnetometer']['z']

                    # EKF Initialization
                    if not ekf_initialized:
                        ekf.set_init(np.array([ax, ay, az]), np.array([mx, my, mz]))
                        ekf_initialized = True

                    # EKF Calculation
                    ekf.predict(np.array([gx, gy, gz]), dt)
                    ekf.update(np.array([ax, ay, az]))
                    epitch, eroll, eyaw = ekf.get_euler()
                    print(f"EKF - Roll: {math.degrees(eroll):.2f}, Pitch: {math.degrees(epitch):.2f}, Yaw: {math.degrees(eyaw):.2f}")

                    # Send results to the robotic arm
                    ctl = [round(initial_position[0] * 1000),
                           round(initial_position[1] * 1000),
                           round(initial_position[2] * 1000),
                           round(math.degrees(eroll) * 1000),
                           round(math.degrees(epitch) * 1000),
                           round(math.degrees(eyaw) * 1000)]
                    robot.EndPoseCtrl(*ctl)

        except Exception as e:
            print(f"Error: {e}")

async def main():
    port = 5000
    async with websockets.serve(echo, '0.0.0.0', port, max_size=1_000_000_000):
        await asyncio.Future()


if __name__ == "__main__":
    robot = C_PiperInterface_V2()
    robot.ConnectPort()

    # Enable Piper
    while not robot.EnablePiper():
        time.sleep(0.01)
        
    # Set control mode
    mode = 0xAD
    spd = 100
    robot.MotionCtrl_2(0x01, 0x00, spd, mode)
    time.sleep(0.1)
    robot.MotionCtrl_2(0x01, 0x00, spd, mode)

    # Set initial position
    initial_position = [0, 0, 500]  # X, Y, Z (0.001mm)
    # Send initial position to the robotic arm
    robot.EndPoseCtrl(
                    initial_position[0] * 1000,     # X
                    initial_position[1] * 1000,     # Y
                    initial_position[2] * 1000,     # Z
                    0 * 1000,                       # RX
                    0 * 1000,                       # RY
                    0 * 1000                        # RZ
                )
    
    # Sensor data cache
    sensor_data = {
        'accelerometer': {'x': 0.0, 'y': 0.0, 'z': 0.0, 'timestamp': 0},
        'gyroscope': {'x': 0.0, 'y': 0.0, 'z': 0.0, 'timestamp': 0},
        'magnetometer': {'x': 0.0, 'y': 0.0, 'z': 0.0, 'timestamp': 0},
    }

    last_time = time.time()
    ekf = EKFAHRS()
    ekf_initialized = False
    
    hostname = socket.gethostname()
    IPAddr = get_ip()
    port = 5000
    print("Your Computer Name is: " + hostname)
    print("Your Computer IP Address is: " + IPAddr)
    print("* Enter {0}:{1} in the app.\n* Press the 'Set IP Address' button.\n* Select the sensors to stream.\n* Update the 'update interval' by entering a value in ms.".format(IPAddr, port))

    # Start WebSocket server
    asyncio.run(main())

参考:https://github.com/agilexrobotics/Agilex-College/blob/master/piper/mobilePhoneCtl/main.py

8.下载文件是否完整

使用如下语句检测:

sha256sum model.safetensors

9.使用nvtop查看GPU使用情况

sudo apt install nvtop

使用nvtop查看

10.docker常用指令

docker run创建容器
docker images 查看镜像
docker run -it --name pi0_train 899566afc09e /bin/bash 通过镜像建立容器
docker ps -a 查看容器ID号
docker start ID 启动建的容器
docker exec -it ID  /bin/bash  交互启动
docker cp lerobot-mujoco-tutorial 32af88f50f8c:/workspace 复制

docker commit ba4c1bbcd75c pi0_test:v1 打包镜像
docker run -it --gpus all  -v /data02:/data02  --shm-size=128g --name name   pi0_test:v1  /bin/bash

docker安装参考文章地址:

https://blog.csdn.net/qq_33665793/article/details/150762218

  1. 安装所需的软件包,以支持通过 HTTPS 使用 Docker 仓库:
sudo apt install apt-transport-https ca-certificates curl software-properties-common
  1. 添加 Docker 的官方 GPG 密钥:
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
  1. 添加 Docker 的 APT 仓库:
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
  1. 更新软件包索引:
sudo apt update
  1. 安装 Docker:
sudo apt install docker-ce
  1. 验证 Docker 是否安装成功:
sudo docker --version

使用docker出现zy0035 is not in the sudoers file.  This incident will be reported:

这里 -aG 选项表示将用户添加到指定的组中,并且如果该组不存在则创建它

sudo usermod -aG sudo zy0035

拉镜像:

国外nvidia:

https://hub.docker.com/r/nvidia/cuda/tags?name=12.4

国内的:

sudo docker pull nvcr.io/nvidia/cuda:12.4.1-cudnn-devel-ubuntu22.04

拉取之后使用run创建:

sudo docker run --gpus all -it --name pi0 nvcr.io/nvidia/cuda:12.4.1-cudnn-devel-ubuntu22.04

使用docker ps -a查看

挂载:

docker run -it --gpus all -p 30010:22 -v /data:/data -v /media:/media --shm-size=128g --name   my_container *****  /bin/bash

打包容器:

docker commit fddcb1d2b419  nvcr.io/nvidia/cuda:12.4.1-cudnn-devel-ubuntu22.04-1113

could not select device driver "" with capabilities: [[gpu]]

1. 安装和确认 NVIDIA 驱动

确保你的宿主机安装了支持你的NVIDIA GPU的驱动。可以通过运行 nvidia-smi 来检查驱动是否已安装和GPU是否被识别。
2. 安装NVIDIA Container Toolkit

NVIDIA Container Toolkit(包括nvidia-docker)是必需的,以便Docker可以管理和使用GPU。可以按照NVIDIA官方文档的指示进行安装。(https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html)

以下是一个基本的安装步骤概览(以Ubuntu为例):

# 设置稳定版仓库和GPG密钥
distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add -
curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list

# 安装nvidia-docker2和重启Docker服务
sudo apt-get update
sudo apt-get install -y nvidia-docker2
sudo systemctl restart docker
具体可以参考:https://blog.csdn.net/weixin_44212848/article/details/137013980?spm=1001.2101.3001.6650.3&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ECtr-3-137013980-blog-145335593.235%5Ev43%5Epc_blog_bottom_relevance_base1&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ECtr-3-137013980-blog-145335593.235%5Ev43%5Epc_blog_bottom_relevance_base1

下载git 代码出现:

the authenticity of host 'github.com (20.205.243.166)' can't be established.
ED25519 key fingerprint is SHA256:+DiY3wvvV6TuJJhbpZisF/zLDA0zPMSvHdkr4UvCOqU.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'github.com' (ED25519) to the list of known hosts.
git@github.com: Permission denied (publickey).
fatal: Could not read from remote repository.

ssh-keygen -t ed25519 -C "***@qq.com"

然后进入cat /root/.ssh/id_ed25519.pub里面内容拷贝到github中

写一个脚本直接登入docker并切换文件夹:

docker exec -it fddcb1d2b419 /bin/bash -c "cd /root && exec bash"

11.解决运行smoVLA中huggingface下载不下的问题

Traceback (most recent call last): File "/home/zy0035/anaconda3/envs/lerobot_mujoco/lib/python3.10/site-packages/urllib3/connectionpool.py", line 464, in _make_request self._validate_conn(conn) File "/home/zy0035/anaconda3/envs/lerobot_mujoco/lib/python3.10/site-packages/urllib3/connectionpool.py", line 1093, in _validate_conn conn.connect() File "/home/zy0035/anaconda3/envs/lerobot_mujoco/lib/python3.10/site-packages/urllib3/connection.py", line 790, in connect sock_and_verified = _ssl_wrap_socket_and_match_hostname( File "/home/zy0035/anaconda3/envs/lerobot_mujoco/lib/python3.10/site-packages/urllib3/connection.py", line 969, in _ssl_wrap_socket_and_match_hostname ssl_sock = ssl_wrap_socket( File "/home/zy0035/anaconda3/envs/lerobot_mujoco/lib/python3.10/site-packages/urllib3/util/ssl_.py", line 480, in ssl_wrap_socket ssl_sock = _ssl_wrap_socket_impl(sock, context, tls_in_tls, server_hostname) File "/home/zy0035/anaconda3/envs/lerobot_mujoco/lib/python3.10/site-packages/urllib3/util/ssl_.py", line 524, in _ssl_wrap_socket_impl return ssl_context.wrap_socket(sock, server_hostname=server_hostname) File "/home/zy0035/anaconda3/envs/lerobot_mujoco/lib/python3.10/ssl.py", line 512, in wrap_socket return self.sslsocket_class._create( File "/home/zy0035/anaconda3/envs/lerobot_mujoco/lib/python3.10/ssl.py", line 1070, in _create self.do_handshake() File "/home/zy0035/anaconda3/envs/lerobot_mujoco/lib/python3.10/ssl.py", line 1341, in do_handshake self._sslobj.do_handshake() TimeoutError: _ssl.c:980: The handshake operation timed out The above exception was the direct cause of the following exception: Traceback (most recent call last): File "/home/zy0035/anaconda3/envs/lerobot_mujoco/lib/python3.10/site-packages/requests/adapters.py", line 644, in send resp = conn.urlopen( File "/home/zy0035/anaconda3/envs/lerobot_mujoco/lib/python3.10/site-packages/urllib3/connectionpool.py", line 841, in urlopen retries = retries.increment( File "/home/zy0035/anaconda3/envs/lerobot_mujoco/lib/python3.10/site-packages/urllib3/util/retry.py", line 474, in increment raise reraise(type(error), error, _stacktrace) File "/home/zy0035/anaconda3/envs/lerobot_mujoco/lib/python3.10/site-packages/urllib3/util/util.py", line 39, in reraise raise value File "/home/zy0035/anaconda3/envs/lerobot_mujoco/lib/python3.10/site-packages/urllib3/connectionpool.py", line 787, in urlopen response = self._make_request( File "/home/zy0035/anaconda3/envs/lerobot_mujoco/lib/python3.10/site-packages/urllib3/connectionpool.py", line 488, in _make_request raise new_e File "/home/zy0035/anaconda3/envs/lerobot_mujoco/lib/python3.10/site-packages/urllib3/connectionpool.py", line 466, in _make_request self._raise_timeout(err=e, url=url, timeout_value=conn.timeout) File "/home/zy0035/anaconda3/envs/lerobot_mujoco/lib/python3.10/site-packages/urllib3/connectionpool.py", line 367, in _raise_timeout raise ReadTimeoutError( urllib3.exceptions.ReadTimeoutError: HTTPSConnectionPool(host='huggingface.co', port=443): Read timed out. (read timeout=10) During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/home/zy0035/anaconda3/envs/lerobot_mujoco/lib/python3.10/site-packages/huggingface_hub/file_download.py", line 1546, in _get_metadata_or_catch_error metadata = get_hf_file_metadata( File "/home/zy0035/anaconda3/envs/lerobot_mujoco/lib/python3.10/site-packages/huggingface_hub/utils/_validators.py", line 114, in _inner_fn return fn(*args, **kwargs) File "/home/zy0035/anaconda3/envs/lerobot_mujoco/lib/python3.10/site-packages/huggingface_hub/file_download.py", line 1463, in get_hf_file_metadata r = _request_wrapper( File "/home/zy0035/anaconda3/envs/lerobot_mujoco/lib/python3.10/site-packages/huggingface_hub/file_download.py", line 286, in _request_wrapper response = _request_wrapper( File "/home/zy0035/anaconda3/envs/lerobot_mujoco/lib/python3.10/site-packages/huggingface_hub/file_download.py", line 309, in _request_wrapper response = http_backoff(method=method, url=url, **params, retry_on_exceptions=(), retry_on_status_codes=(429,)) File "/home/zy0035/anaconda3/envs/lerobot_mujoco/lib/python3.10/site-packages/huggingface_hub/utils/_http.py", line 310, in http_backoff response = session.request(method=method, url=url, **kwargs) File "/home/zy0035/anaconda3/envs/lerobot_mujoco/lib/python3.10/site-packages/requests/sessions.py", line 589, in request resp = self.send(prep, **send_kwargs) File "/home/zy0035/anaconda3/envs/lerobot_mujoco/lib/python3.10/site-packages/requests/sessions.py", line 703, in send r = adapter.send(request, **kwargs) File "/home/zy0035/anaconda3/envs/lerobot_mujoco/lib/python3.10/site-packages/huggingface_hub/utils/_http.py", line 96, in send return super().send(request, *args, **kwargs) File "/home/zy0035/anaconda3/envs/lerobot_mujoco/lib/python3.10/site-packages/requests/adapters.py", line 690, in send raise ReadTimeout(e, request=request) requests.exceptions.ReadTimeout: (ReadTimeoutError("HTTPSConnectionPool(host='huggingface.co', port=443): Read timed out. (read timeout=10)"), '(Request ID: 6191a71e-1234-41c4-8c83-ca43043ac261)') The above exception was the direct cause of the following exception: Traceback (most recent call last): File "/home/zy0035/anaconda3/envs/lerobot_mujoco/lib/python3.10/site-packages/transformers/utils/hub.py", line 424, in cached_files hf_hub_download( File "/home/zy0035/anaconda3/envs/lerobot_mujoco/lib/python3.10/site-packages/huggingface_hub/utils/_validators.py", line 114, in _inner_fn return fn(*args, **kwargs) File "/home/zy0035/anaconda3/envs/lerobot_mujoco/lib/python3.10/site-packages/huggingface_hub/file_download.py", line 1010, in hf_hub_download return _hf_hub_download_to_cache_dir( File "/home/zy0035/anaconda3/envs/lerobot_mujoco/lib/python3.10/site-packages/huggingface_hub/file_download.py", line 1117, in _hf_hub_download_to_cache_dir _raise_on_head_call_error(head_call_error, force_download, local_files_only) File "/home/zy0035/anaconda3/envs/lerobot_mujoco/lib/python3.10/site-packages/huggingface_hub/file_download.py", line 1661, in _raise_on_head_call_error raise LocalEntryNotFoundError( huggingface_hub.errors.LocalEntryNotFoundError: An error happened while trying to locate the file on the Hub and we cannot find the requested files in the local cache. Please check your connection and try again or make sure your Internet connection is on. The above exception was the direct cause of the following exception: Traceback (most recent call last): File "/home/zy0035/lerobot-mujoco-tutorial/smolvla_deploy.py", line 32, in <module> policy = SmolVLAPolicy.from_pretrained('./omy_pnp_smolvla', config=cfg, dataset_stats=dataset_metadata.stats) File "/home/zy0035/lerobot-mujoco-tutorial/./lerobot/lerobot/common/policies/pretrained.py", line 109, in from_pretrained instance = cls(config, **kwargs) File "/home/zy0035/lerobot-mujoco-tutorial/./lerobot/lerobot/common/policies/smolvla/modeling_smolvla.py", line 257, in __init__ self.language_tokenizer = AutoProcessor.from_pretrained(self.config.vlm_model_name).tokenizer File "/home/zy0035/anaconda3/envs/lerobot_mujoco/lib/python3.10/site-packages/transformers/models/auto/processing_auto.py", line 316, in from_pretrained config = AutoConfig.from_pretrained( File "/home/zy0035/anaconda3/envs/lerobot_mujoco/lib/python3.10/site-packages/transformers/models/auto/configuration_auto.py", line 1096, in from_pretrained config_dict, unused_kwargs = PretrainedConfig.get_config_dict(pretrained_model_name_or_path, **kwargs) File "/home/zy0035/anaconda3/envs/lerobot_mujoco/lib/python3.10/site-packages/transformers/configuration_utils.py", line 594, in get_config_dict config_dict, kwargs = cls._get_config_dict(pretrained_model_name_or_path, **kwargs) File "/home/zy0035/anaconda3/envs/lerobot_mujoco/lib/python3.10/site-packages/transformers/configuration_utils.py", line 653, in _get_config_dict resolved_config_file = cached_file( File "/home/zy0035/anaconda3/envs/lerobot_mujoco/lib/python3.10/site-packages/transformers/utils/hub.py", line 266, in cached_file file = cached_files(path_or_repo_id=path_or_repo_id, filenames=[filename], **kwargs) File "/home/zy0035/anaconda3/envs/lerobot_mujoco/lib/python3.10/site-packages/transformers/utils/hub.py", line 491, in cached_files raise EnvironmentError( OSError: We couldn't connect to 'https://huggingface.co' to load the files, and couldn't find them in the cached files. Checkout your internet connection or see how to run the library in offline mode at 'https://huggingface.co/docs/transformers/installation#offline-mode' 怎么解决这个问题

修改conda环境路径下的constants.py,如我的:

/home/zy0035/anaconda3/envs/lerobot_mujoco/lib/python3.10/site-packages/huggingface_hub/constants.py

修改HUGGINGFACE_CO_URL_HOME和_HF_DEFAULT_ENDPOINT

将HUGGINGFACE_CO_URL_HOME修改为HUGGINGFACE_CO_URL_HOME = "https://hf-mirror.com/"

将_HF_DEFAULT_ENDPOINT修改为_HF_DEFAULT_ENDPOINT = "https://hf-mirror.com"
修改完运行即可

12. 建立conda环境如果没法建立,后面指定conda-forge

conda create --name pi0.5  python=3.11 -c conda-forge

13. ssh登入需要安装

sudo apt install openssh-server

14.python 库tyro处理复杂的配置结构,同时保持代码的简洁和类型安全

@dataclass
class Args:
    exp_name: str = os.path.basename(__file__)[: -len(".py")]
    """the name of this experiment"""
    seed: int = 1
    """seed of the experiment"""
    track: bool = False
    """if toggled, this experiment will be tracked with Weights and Biases"""
    wandb_project_name: str = "cleanRL"
    """the wandb's project name"""
    capture_video: bool = False
    """whether to capture videos of the agent performances (check out `videos` folder)"""
    env_id: str = 'dm_control/walker-run-v0'
    """the id of the environment"""
    action_repeat: int = 4
    """number of times the same action is repeated"""
    
    # Model learning
    total_timesteps: int = 1_000_000
    """total timesteps of the experiments"""
    learning_rate: float = 3e-4
    """the learning rate of the optimizer"""
    gamma: float = 0.95
    """the discount factor gamma"""
    tau: float = 0.01
    """target smoothing coefficient"""
    batch_size: int = 512
    """the batch size of sample from the reply memory"""
    exploration_noise: float = 0.05
    """the scale of exploration noise"""
    learning_starts: int = 25e3
    """timestep to start learning"""
    grad_clip_norm = 20.0
    """the norm for gradient clipping"""
    latent_dim: int = 512
    """coefficient of transition loss term"""
    consis_coef: float = 2.0
    """coefficient of transition loss term"""
    reward_coef: float = 0.5
    """coefficient of reward loss term"""
    value_coef: float = 0.1
    """coefficient of value loss term"""
    rho: float = 0.5
    """coefficient of loss decay over time"""
    target_network_frequency: int = 2
    "the frequency of updates for the target nerworks"

    # Planning (MPPI)
    horizon: int = 3
    """planning horizon length in time steps"""
    iterations: int = 6
    """number of updates during planning"""
    num_samples: int = 512
    """number of samples drawn from the distribution"""
    num_actor_traj: int = 16
    """number of trajectory samples generated by the actor"""
    num_elites: int = 64
    """number of elite samples for optimization"""
    temperature: float = 0.5
    """temperature parameter controlling the scale of updates"""

调用:

  args = tyro.cli(Args)
    run_name = f"{args.env_id}__{args.exp_name}__{args.seed}__{int(time.time())}"
    group_name = f"{args.env_id}__{args.exp_name}"

15.NVIDIA驱动失效简单解决方案:NVIDIA-SMI has failed because it couldn‘t communicate with the NVIDIA driver.

第一步,打开终端,输入:vidia-smi

NVIDIA-SMI has failed because it couldn't communicate with the NVIDIA driver. 
Make sure that the latest NVIDIA driver is installed and running.

第二步,使用nvcc -V检查驱动和cuda。

nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2018 NVIDIA Corporation
Built on Sat_Aug_25_21:08:01_CDT_2018

Cuda compilation tools, release 10.0, V10.0.130

发现驱动是存在的,于是进行下一步。

第三步,查看已安装驱动的版本信息

ls /usr/src | grep nvidia

比如我的驱动版本是:nvidia-535.161.08

第四步,依次输入以下命令

sudo apt-get install dkms

sudo dkms install -m nvidia -v 535.161.08

发现:

Error! Could not locate dkms.conf file.
File: /usr/src/nvidia-535.161.08/dkms.conf does not exist.

直接卸载:

sudo apt-get remove --purge '^nvidia-.*'

打开软件与更新,重新装对应驱动即可

https://www.cnblogs.com/nannandbk/p/18144618

设置使用几张GPU卡训练模型

import os

os.environ["CUDA_VISIBLE_DEVICES"] = "0,1,2,3"

这里设置使用0,1,2,3

刷新nvidia指令

watch -n 1 -c nvidia-smi

python代码可以使用pdb进行微调

import pdb; pdb.set_trace()  # 程序会在这里暂停
例子:
def calculate_sum(a, b):
    import pdb; pdb.set_trace()  # 程序会在这里暂停
    result = a + b
    return result

x = 5
y = 3
print(calculate_sum(x, y))

基本导航

  • n (next) - 执行下一行

  • s (step) - 进入函数调用

  • c (continue) - 继续执行直到下一个断点

  • q (quit) - 退出调试器

huggingface 下载设置地址:

https://hf-mirror.com/

uv与python环境不同,可以设置把uv环境设置为python运行环境为

uv venv --python $(conda activate pi0.5 && which python)

du查找哪个文件占用

sudo du -h --max-depth=1 /home | sort -hr | head -n 20

python配置参数hydra

这个运行最后结果为python main.py:

App Name: my_application
Server: localhost:8080

完整配置:
app:
  name: my_application
  debug: false
server:
  host: localhost
  port: 8080

免费Google AI Studio平台使用地址:

https://aistudio.google.com/prompts/new_chat?model=gemini-3-pro-preview

使用sshpass登入,仿真终端掉落

这两个参数组合起来构成了保活机制(Keep-Alive),主要用于防止因防火墙或路由器认为连接空闲而将其断开。

  • -o ServerAliveInterval=60

    • 含义:客户端每隔 60秒 向服务器发送一个空的“心跳包”(KeepAlive 数据包)。

    • 作用:告诉服务器“我还在线,不要断开我”,同时也通过产生流量防止中间的防火墙或 NAT 设备因连接空闲超时而切断连接。

  • -o ServerAliveCountMax=3

    • 含义:设置允许发送心跳包但没有收到服务器响应的最大次数。

    • 作用:判定掉线。如果客户端发送了心跳包,服务器没有回应,计数器加 1。当连续 3次(即 3 × 60秒 = 180秒)都没有收到回应时,客户端会判定连接已断开并自动终止 SSH 进程。

sshpass -p 密码 ssh -o ServerAliveInterval=60 -o ServerAliveCountMax=3 用户名@IP

查找那张nvidia卡被占用

详细的:sudo lsof /dev/nvidia5

nvtop

把程序挂起来:

XLA_PYTHON_CLIENT_MEM_FRACTION=0.9 nohup uv run scripts/train.py pi05_flatten_fold_awbc --exp_name=run1 --overwrite > train.log 2>&1 &

命令原理解析:

  • nohup:告诉系统,即使你关闭了终端/断开了SSH,也不要杀掉这个程序。

  • > train.log:把程序原本打印在屏幕上的输出(如进度条、loss)保存到 train.log 文件中。

  • 2>&1:把“错误信息”也一并合并保存到 train.log 里。

  • &:关键所在,让程序在后台运行,把控制台马上还给你

如何查看进度?
因为在后台运行,你看不到输出,可以使用这行命令实时查看日志:

code Bash

tail -f train.log

补充:如何关掉后台的程序?

如果你想强行终止后台的训练进程:

  • 如果是用 nohup 跑的,输入 ps -ef | grep scripts/train.py 找到进程号(PID),然后 kill -9 <PID>。

linux安装codex

curl -fsSL https://deb.nodesource.com/setup_22.x | sudo bash -
sudo apt-get install -y nodejs
node -v
npm -v
安装 Codex CLI

Bash

npm install -g @openai/codex

开发板自启动调用:

在目录下/etc/systemd/system建立一个文件

从容器配置可以看到:
 主机系统启动 → /etc/systemd/system/chassis.service → /home/startup.sh → 启动Docker容器 nav2 → Docker Entrypoint执行/scripts/project_startup/startup.sh → 启动完整的ROS导航定位系统。
  Config.Cmd: ["/bin/bash"]
  Config.Entrypoint: ["/bin/bash", "/scripts/project_startup/startup.sh"]

  1. 镜像中的Entrypoint: ["/bin/bash", "/scripts/project_startup/startup.sh"]
  2. 创建容器时指定的Cmd: ["/bin/bash"]
 
  查看创建容器的命令(来自/home/startup.sh):
 
  docker run -it \
      -e "ROS_DOMAIN_ID=69" \
      -e "ROS_LOG_DIR=/root/.ros/log/" \
      --privileged=true \
      --shm-size 2147483648 \
      --net host \
      --volume /home/robot:/home/robot \
      --volume /root/.ros/log:/root/.ros/log \
      --name nav2 \
      -d \
      nav2/arm64:latest \
      /bin/bash  # <-- 这个就是Cmd参数

强制指定底层为 CycloneDDS 并绑定物理网卡:
(注意:请把下面这段命令里的 eth0 替换成你第一步查到的真实网卡名!双端都要替换为各自对应的网卡)

code Bash

export RMW_IMPLEMENTATION=rmw_cyclonedds_cpp
export CYCLONEDDS_URI='<CycloneDDS><Domain><General><NetworkInterfaceAddress>eth0</NetworkInterfaceAddress></General></Domain></CycloneDDS>'

export ROS_DOMAIN_ID=2 export ROS_DISCOVERY_SERVER="12.16.2.6:11811" export ROS_SUPER_CLIENT=TRUE # 关键:不加则 ros2 topic list 看不全

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值