Show HN: Cubic Doggo 06R:配备 IMU 的 12 自由度四足机器人
Show HN: Cubic Doggo 06R: 12-DOF 4-Legged Robot with IMU

原始链接: https://github.com/SphericalCowww/CubicDoggo_06R

**Cubic Doggo 06R 高机动版**是基础版 Cubic Doggo 的升级型号,通过机械结构的改进并整合了全新的惯性测量单元(IMU),显著提升了平衡性。该项目旨在增强运动过程中的稳定性,利用 Adafruit BNO055 IMU 和 PID 控制步态调整,实现机器人在站立与行走时的平衡。 **主要特性与更新:** * **机械升级:** 改进了关节耐用性,采用弹簧脚以吸收冲击,并优化了重心布局,以支持平稳的小跑。 * **软件/控制:** 基于 ROS2 运行,支持多种运行模式(站立、行走及 IMU 辅助模式)。利用 `ros2_control` 实现,并具备高抬腿步态能力。 * **硬件配置:** 文档包含树莓派的 I2C 引脚映射、舵机校准说明,以及用于 RViz 可视化的自定义 URDF 模型集成。 * **性能:** 虽然目前使用 BNO055,但该架构允许未来迁移至更高频率的 IMU(如 BMI088 或 ICM-42688-P),以减少当前延迟导致的 PID 振荡。 详细的 CAD 文件、组装指南和启动脚本可在项目的 GitHub 仓库中获取。用户可通过 PlotJuggler 监控性能,或通过特定的 ROS2 主题发布器(Topic Publishers)来指挥机器人的步态。

抱歉。
相关文章

原文

Cubic Doggo 06R High Mobility is an upgrade from the base Cubic Doggo. It receives several mechanical improvements and applies an IMU for balance. The upgraded CADv2 files can be found in GitHub directory/Printables.

Demos: wobbly IMU (Reddit/Reddit), standing IMU tunning (Reddit/Reddit), leg lifting (Reddit), walking with IMU (Reddit)

  • Left: the following shows the high-lift mode available after all the mechanical improvements. The black notepad in the center is 1cm in height, and the robot is able to land on it with all 4 of its feet. However, you can see that landing off the notepad gives a rather high impact load to the landing leg.
  • Right: walking with IMU balance correction based on BNO055, controlled using PID (technically on kP to avoid diverging oscillation). It's walking down from the notepad because the current IMU system cannot support the high-lift mode. Although the effect is not obvious, the robot is constantly trying to balance itself after standing up and during walking.
  • Note also that a servo (or servos) from the robot's back-right leg is likely damaged/performance-reduced from dimension collisions during the test using the spring/compliant feet (see Reddit)
  1. Support on the 1st servos on both sides
  2. Support on the 3rd servos. These joints always broke first
  3. Spring-like feet (Reddit)
  4. Smaller feet tip. Swinging less mass should cause less wobbling
  5. Start using PLA+

Also updated the initial leg position such that the center of mass is optimized at trotting in place.

device models count specification
IMU Adafruit BNO055 [ADA2472] 1 in-system Kalman Filter, but rate capped at 100 Hz
IMU BMI088 1 rate available at 200 Hz after ROS2 imu_filter_madgwick
IMU ICM-42688-P 1 rate available at 200-400 Hz after ROS2 imu_filter_madgwick

So far, only BNO055 is tested. Future incorporation with BMI088 or ICM-42688-P will likely improve the IMU performance: the current PID oscillation is potentially caused by delayed IMU correction at the BNO055 readout rate set of 50 Hz.

Following link. It's a bit outdated, so do change up a bit and actually connect via I2C instead for RaspPi > 3:

  • Vin to 1
  • GND to 9
  • SDA to 3
  • SCL to 5
  • RST to 11

Then do:

sudo apt update && sudo apt install -y i2c-tools gpiod libgpiod-dev
sudo gpiodetect
sudo gpioset gpiochip4 17=1                                         # enable reset pin
sudo i2cdetect -y 1                                                 # if 28 lights up, it's alive

sudo usermod -aG i2c $USER
sudo usermod -aG dialout $USER
sudo reboot
i2cdetect -y 1

To test BNO055 without ROS:

sudo apt install -y python3-venv python3-pip python3-lgpio
cd CubicDoggo_06R/python_test_scripts
python3 -m venv env
source env/bin/activate
pip install adafruit-circuitpython-bno055 rpi-lgpio
python bno_test.py

To test BNO055 with ROS:

cd CubicDoggo_06R
colcon build
source install/setup.bash
ros2 run my_robot_peripheral imu_bno055_node
# on another terminal
ros2 topic echo /imu/euler              # show IMU content
ros2 topic hz /imu/euler                # show IMU read speed

Testing the joystick controller:

ls /dev/input/js*
# output: /dev/input/js0
# otherwise do: sudo jstest /dev/input/js0
ros2 run joy joy_enumerate_devices
# if no device found
sudo usermod -aG input $USER
sudo reboot

cd CubicDoggo_06R
colcon build
source install/setup.bash
ros2 run joy joy_node
# on another terminal
ros2 run my_robot_controller cubic_doggo_joy_control
# on yet another terminal
ros2 node info /cubic_doggo_joy_control    
ros2 topic info /joy --verbose
ros2 topic echo /joy
for d in /sys/class/hwmon/hwmon*; do echo -n "$d: "; cat "$d/name"; done   # find the correct path for power alarm
# update /home/cubicdoggo/Documents/CubicDoggo_06R/src/my_robot_bringup/launch/cubic_doggo.with_lifecycle.launch.py
echo timer | sudo tee /sys/class/leds/ACT/trigger                          # trigger LED first
sudo chmod -R 777 /sys/class/leds/ACT/                                     # enable LED to indicate battery condition
sudo chmod -R 777 /sys/class/hwmon/hwmon*/                                 # enable reading of power alarm/voltage
# test the node 
echo 0 > /tmp/fake_alarm                                                   # create a fake alarm by
ros2 run my_robot_peripheral rasp_pi_peripheral_node --ros-args -p alarm_path:=/tmp/fake_alarm
echo 1 > /tmp/fake_alarm                                                   # create a fake alarm by

Follow this GitHub section to set up the servos.

Assembly and Launching URDF

Run the following to view the moving parts:

cd CubicDoggo_06R
colcon build
source install/setup.bash
ros2 launch my_robot_description cubic_doggo.rviz.launch.xacro.py

Notice that the placement of the first servo is different between the front and back legs.

Under: CubicDoggo_06R/src/my_robot_description/urdf/cubic_doggo.ros2_control.xacro

  • use <plugin>mock_components/GenericSystem</plugin> if just want rViz
  • use <<plugin>cubic_doggo_namespace/HardwareInterfaceU2D2_cubic_doggo</plugin> if want to control hardware

Under: CubicDoggo_06R/src/my_robot_bringup/launch/cubic_doggo.with_lifecycle.launch.py

  • choose from:

    • executable="cubic_doggo_lifecycle" for no IMU
    • executable="cubic_doggo_lifecycle_imuNode" for standing with an IMU node
    • executable="cubic_doggo_lifecycle_imuController" for standing with an IMU controller using ros2_control
    • executable="cubic_doggo_lifecycle_imuController_walking" for standing/walking with an IMU controller using ros2_control
    • executable="cubic_doggo_lifecycle_imuController_walkingToggle" to start with no IMU, but can toggle on for standing/walking with an IMU controller using ros2_control
  • comment out imu_node unless using executable="cubic_doggo_lifecycle_imuNode"

  • comment out rviz_node if don't want rViz to show

  • comment out joy_driver_node and joy_controller_node if don't want the joystick controller

  • comment out peripheral_node if don't want warning from low power

Start the robot (skip launching rviz_node, joy_driver_node, or joy_controller_node if needed):

cd CubicDoggo_06R
colcon build
source install/setup.bash
# comment in rvis node in CubicDoggo_06R/src/my_robot_bringup/launch/cubic_doggo.with_lifecycle.launch.py
ros2 launch my_robot_bringup cubic_doggo.with_lifecycle.launch.py
# on another terminal
ros2 topic pub -1 /leg_set_named example_interfaces/msg/String "{data: "rest"}"
ros2 topic pub -1 /leg_set_named example_interfaces/msg/String "{data: "stand"}"
ros2 topic pub -1 /leg_set_named example_interfaces/msg/String "{data: "sit"}"
ros2 topic pub -1 /leg_set_named example_interfaces/msg/String "{data: "bow"}"
ros2 topic pub -1 /leg_set_joint example_interfaces/msg/Float64MultiArray "{data: [0, 3.14, 3.14, 3.54]}"
ros2 topic pub -1 /leg_set_pose my_robot_interface/msg/CubicDoggoLegPoseTarget "{leg_index: 0, x: -0.092, y: 0.053, z: 0.135}" 
ros2 service call /leg_walk_toggle std_srvs/srv/SetBool "{data: true}"
ros2 service call /leg_walk_toggle std_srvs/srv/SetBool "{data: false}"

Check out all the gait/IMU options under CubicDoggo_06R/src/my_robot_commander/src/cubic_doggo_lifecycle_imuController_walking.cpp:

# rclcpp::get_logger("").set_level(rclcpp::Logger::Level::Warn);        // for silencing output
...
# aw_strat.i_max =  0.05;
# aw_strat.i_min = -0.05;
# double kP = 0.0016, kI = 0.0001, kD = 0.0;     // NOTE: PID
# double corr_v_thres = 3.0, corr_d_thres = 1.0;              // threshold on pitch/roll and their vel 
# double corr_z_limit_kD = 0.01, corr_z_limit = 0.025;       // limit on +/- z
# double pitch_shift = 0.643, roll_shift = -2.917;              // basic on-support reference

# auto loop_rate = rclcpp::WallRate(update_rate_);        // Hz, for consistent loop rate
# double maxVelScale = 1.0, maxAccScale = 1.0;
# int    waypoint_N_walk   = 40;                         // number of waypoints for each cycle
# double waypoint_dt_walk  = 0.5/double(update_rate_);    // second for each waypoint, to match loop rate
# int    waypoint_N_stand  = 1;                           // standing require immidiate reaction
# double waypoint_dt_stand = 1.0/double(update_rate_);    // standing require faster trajectory
# double IK_bufferTime     = 0.10;                        // time at end of cycle buffer for IK calc
# double swing_fraction    = 0.32;                        // creep < 0.25 < stable trot < 0.5 < trot
# double lift = 0.02, x_stride_max = 0.02, y_stride_max = 0.03, x_shift = 0.0, y_shift = -0.007;

Launching at the start of RaspPi

chmod +x /home/cubicdoggo/Documents/CubicDoggo_06R/start_robot.sh
sudo cp /home/cubicdoggo/Documents/CubicDoggo_06R/robot_startup.service /etc/systemd/system/robot_startup.service
sudo chmod 644 /etc/systemd/system/robot_startup.service
sudo systemctl enable robot_startup.service                                # now will start at reboot
sudo systemctl daemon-reload                                               # reload whenever there is a change
# sudo systemctl restart robot_startup.service                             # restart, even if is rrunning
# sudo systemctl stop    robot_startup.service                             # stop right now, kill all relevant nodes
# sudo systemctl disable robot_startup.service                             # disable at reboot
# journalctl -u robot_startup.service -n 100 > start_robot_output.txt      # to check the output
# journalctl -u robot_startup.service -f

Run the robot first:

cd CubicDoggo_06R
colcon build
source install/setup.bash
ros2 launch my_robot_bringup cubic_doggo.with_lifecycle.launch.py

Reading out variables from ROS

# on another terminal for joint states
ros2 topic echo /joint_states
# on another terminal for IMU
ros2 topic echo /imu/euler

Tracking/plotting variables using PlotJuggler

To track the values (remember to connect the RaspPi to a monitor):

# on another terminal for plotjuggler
sudo apt install ros-jazzy-plotjuggler-ros
ros2 run plotjuggler plotjuggler
# load CubicDoggo_06R/monitor_plot.xml 
# or starting over again:
## start => locate the following
### /imu/data
### /imu/euler
### /joint_states
## OK
## on the left panel, expand /imu and /joint_states and drag the variable to the center for live plotting

Note that to enable plotting, the robot needs an HDMI cable to connect to the monitor, a mouse, a keyboard, and a direct power source (it's rather energy-consuming). The controller is still remote. This means extra weights are placed on the robot, and so what's being plotted is not exactly equivalent to battery mode. The photo shows the connections:

Configuration (update the code if direction differs):

roll, negative when tilting forward
pitch, negative when tilting leftward

Checking loop speed for latency, including IK calculation and IMU readout:

ros2 topic hz /joint_states

Standing up and then changing to a slope, with Kp parameter only. Never correct to the exact values:

Standing up and then changing to a slope, with full PID parameters. Large oscillations:

Walking gait, trotting in place:

Walking gait with IMU, trotting in place:

High-lift walking gait, trotting in place:

  • Dr Jon EA: Pico & Pico 2, The BNO055: At Last, an IMU I Can Tame Quickly - C/C++ (YouTube)
  • ROS1 Packages for CHAMP Quadruped Controller (GitHub) => node based IMU control with classical walk gait
  • Spot Micro (GitHub, link) => node based IMU control with classical walk gait
  • Pupper V3 (link) => ros2_control based IMU control with RL walk gait
联系我们 contact @ memedata.com