Files
balance/dm_imu/imu_driver.cpp
ydy0615 74a2d8c355 new file: .vscode/settings.json
new file:   Legs_controller.py
	modified:   README.md
	new file:   __pycache__/Legs_controller.cpython-310.pyc
	new file:   __pycache__/Legs_controller.cpython-313.pyc
	new file:   __pycache__/balance.cpython-310.pyc
	new file:   __pycache__/gradio.cpython-310.pyc
	new file:   __pycache__/gradio.cpython-313.pyc
	new file:   app_ui.py
	new file:   balance.py
	new file:   build/.cmake/api/v1/query/client-vscode/query.json
	new file:   build/.cmake/api/v1/reply/cache-v2-ae4a9db768b4bbb36baa.json
	new file:   build/.cmake/api/v1/reply/cmakeFiles-v1-389eb8769a8295e7571d.json
	new file:   build/.cmake/api/v1/reply/codemodel-v2-5ea8cfc0b9263cbe5ae5.json
	new file:   build/.cmake/api/v1/reply/directory-.-Debug-f5ebdc15457944623624.json
	new file:   build/.cmake/api/v1/reply/index-2025-09-11T04-53-20-0515.json
	new file:   build/.cmake/api/v1/reply/target-imu_py-Debug-3913d741f2156d7faae9.json
	new file:   build/.cmake/api/v1/reply/toolchains-v1-3105704d088db7adbfb5.json
	new file:   build/CMakeCache.txt
	new file:   build/CMakeFiles/3.22.1/CMakeCXXCompiler.cmake
	new file:   build/CMakeFiles/3.22.1/CMakeDetermineCompilerABI_CXX.bin
	new file:   build/CMakeFiles/3.22.1/CMakeSystem.cmake
	new file:   build/CMakeFiles/3.22.1/CompilerIdCXX/CMakeCXXCompilerId.cpp
	new file:   build/CMakeFiles/3.22.1/CompilerIdCXX/a.out
	new file:   build/CMakeFiles/CMakeDirectoryInformation.cmake
	new file:   build/CMakeFiles/CMakeOutput.log
	new file:   build/CMakeFiles/Makefile.cmake
	new file:   build/CMakeFiles/Makefile2
	new file:   build/CMakeFiles/TargetDirectories.txt
	new file:   build/CMakeFiles/cmake.check_cache
	new file:   build/CMakeFiles/imu_py.dir/DependInfo.cmake
	new file:   build/CMakeFiles/imu_py.dir/build.make
	new file:   build/CMakeFiles/imu_py.dir/cmake_clean.cmake
	new file:   build/CMakeFiles/imu_py.dir/compiler_depend.make
	new file:   build/CMakeFiles/imu_py.dir/compiler_depend.ts
	new file:   build/CMakeFiles/imu_py.dir/depend.make
	new file:   build/CMakeFiles/imu_py.dir/flags.make
	new file:   build/CMakeFiles/imu_py.dir/link.txt
	new file:   build/CMakeFiles/imu_py.dir/progress.make
	new file:   build/CMakeFiles/progress.marks
	new file:   build/Makefile
	new file:   build/cmake_install.cmake
	new file:   build/compile_commands.json
	new file:   dm_imu/bsp_crc.cpp
	new file:   dm_imu/bsp_crc.h
	new file:   dm_imu/imu_data.csv
	new file:   dm_imu/imu_driver.cpp
	new file:   dm_imu/imu_driver.h
	new file:   dm_imu/imu_plot.png
	new file:   dm_imu/plot_imu.py
	new file:   dm_imu/test_imu.cpp
	new file:   imu_data.csv
	new file:   pybind_imu/CMakeLists.txt
	new file:   pybind_imu/README.md
	new file:   pybind_imu/build/CMakeCache.txt
	new file:   pybind_imu/build/CMakeFiles/3.22.1/CMakeCXXCompiler.cmake
	new file:   pybind_imu/build/CMakeFiles/3.22.1/CMakeDetermineCompilerABI_CXX.bin
	new file:   pybind_imu/build/CMakeFiles/3.22.1/CMakeSystem.cmake
	new file:   pybind_imu/build/CMakeFiles/3.22.1/CompilerIdCXX/CMakeCXXCompilerId.cpp
	new file:   pybind_imu/build/CMakeFiles/3.22.1/CompilerIdCXX/a.out
	new file:   pybind_imu/build/CMakeFiles/CMakeDirectoryInformation.cmake
	new file:   pybind_imu/build/CMakeFiles/CMakeOutput.log
	new file:   pybind_imu/build/CMakeFiles/Makefile.cmake
	new file:   pybind_imu/build/CMakeFiles/Makefile2
	new file:   pybind_imu/build/CMakeFiles/TargetDirectories.txt
	new file:   pybind_imu/build/CMakeFiles/cmake.check_cache
	new file:   pybind_imu/build/CMakeFiles/imu_py.dir/DependInfo.cmake
	new file:   pybind_imu/build/CMakeFiles/imu_py.dir/build.make
	new file:   pybind_imu/build/CMakeFiles/imu_py.dir/cmake_clean.cmake
	new file:   pybind_imu/build/CMakeFiles/imu_py.dir/compiler_depend.make
	new file:   pybind_imu/build/CMakeFiles/imu_py.dir/compiler_depend.ts
	new file:   pybind_imu/build/CMakeFiles/imu_py.dir/depend.make
	new file:   pybind_imu/build/CMakeFiles/imu_py.dir/flags.make
	new file:   pybind_imu/build/CMakeFiles/imu_py.dir/home/allenyuan/balance/dm_imu/bsp_crc.cpp.o
	new file:   pybind_imu/build/CMakeFiles/imu_py.dir/home/allenyuan/balance/dm_imu/bsp_crc.cpp.o.d
	new file:   pybind_imu/build/CMakeFiles/imu_py.dir/home/allenyuan/balance/dm_imu/imu_driver.cpp.o
	new file:   pybind_imu/build/CMakeFiles/imu_py.dir/home/allenyuan/balance/dm_imu/imu_driver.cpp.o.d
	new file:   pybind_imu/build/CMakeFiles/imu_py.dir/link.txt
	new file:   pybind_imu/build/CMakeFiles/imu_py.dir/progress.make
	new file:   pybind_imu/build/CMakeFiles/imu_py.dir/pybind_imu.cpp.o
	new file:   pybind_imu/build/CMakeFiles/imu_py.dir/pybind_imu.cpp.o.d
	new file:   pybind_imu/build/CMakeFiles/progress.marks
	new file:   pybind_imu/build/Makefile
	new file:   pybind_imu/build/cmake_install.cmake
	new file:   pybind_imu/build/imu_py.cpython-310-aarch64-linux-gnu.so
	new file:   pybind_imu/example.py
	new file:   pybind_imu/pybind_imu.cpp
	new file:   src/example.py
	new file:   test_imu
	new file:   u2can/DM_CAN.py
	new file:   u2can/DM_Motor_Test.py
	new file:   u2can/LICENSE
	new file:   u2can/README.md
	new file:   u2can/__pycache__/DM_CAN.cpython-310.pyc
	new file:   u2can/__pycache__/DM_CAN.cpython-312.pyc
	new file:   u2can/__pycache__/DM_CAN.cpython-313.pyc
	new file:   u2can/__pycache__/gradio.cpython-313.pyc
	new file:   u2can/__pycache__/motor_interface.cpython-313.pyc
	new file:   u2can/motor_interface.py
	new file:   u2can/requirements.txt
	new file:   ui.log
2025-12-06 22:47:57 +08:00

312 lines
8.6 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "imu_driver.h"
#include <chrono>
#include <iostream>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
namespace dmbot_serial
{
DmImu::DmImu(const std::string& port, int baud)
: imu_serial_port(port), imu_seial_baud(baud), stop_thread_(false)
{
// 初始化串口并完成 IMU 配置
init_imu_serial();
// 进入配置模式并初始化 IMU
enter_setting_mode();
std::this_thread::sleep_for(std::chrono::milliseconds(10));
turn_on_accel();
std::this_thread::sleep_for(std::chrono::milliseconds(10));
turn_on_gyro();
std::this_thread::sleep_for(std::chrono::milliseconds(10));
turn_on_euler();
std::this_thread::sleep_for(std::chrono::milliseconds(10));
turn_off_quat();
std::this_thread::sleep_for(std::chrono::milliseconds(10));
set_output_1000HZ();
std::this_thread::sleep_for(std::chrono::milliseconds(10));
save_imu_para();
std::this_thread::sleep_for(std::chrono::milliseconds(10));
exit_setting_mode();
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
DmImu::~DmImu()
{
stop();
if (serial_fd >= 0)
{
close(serial_fd);
serial_fd = -1;
}
}
// -------------------------------
// Public API
// -------------------------------
bool DmImu::start()
{
if (rec_thread.joinable())
{
// 已经在运行
return true;
}
// 确保串口已打开
if (serial_fd < 0)
{
init_imu_serial();
}
stop_thread_ = false;
rec_thread = std::thread(&DmImu::get_imu_data_thread, this);
return true;
}
void DmImu::stop()
{
stop_thread_ = true;
if (rec_thread.joinable())
{
rec_thread.join();
}
if (serial_fd >= 0)
{
close(serial_fd);
serial_fd = -1;
}
}
IMU_Data DmImu::getData() const
{
std::lock_guard<std::mutex> lock(data_mutex);
return data;
}
// -------------------------------
// Private implementation
// -------------------------------
void DmImu::init_imu_serial()
{
// 打开串口
serial_fd = open(imu_serial_port.c_str(), O_RDWR | O_NOCTTY | O_SYNC);
if (serial_fd < 0)
{
std::cerr << "Failed to open IMU serial port: " << imu_serial_port << std::endl;
std::exit(EXIT_FAILURE);
}
// 配置波特率和串口属性
struct termios tty;
if (tcgetattr(serial_fd, &tty) != 0)
{
std::cerr << "Error from tcgetattr" << std::endl;
std::exit(EXIT_FAILURE);
}
// 设置波特率
speed_t speed;
switch (imu_seial_baud)
{
case 115200: speed = B115200; break;
case 230400: speed = B230400; break;
case 460800: speed = B460800; break;
case 921600: speed = B921600; break;
default:
std::cerr << "Unsupported baud rate: " << imu_seial_baud << std::endl;
std::exit(EXIT_FAILURE);
}
cfsetospeed(&tty, speed);
cfsetispeed(&tty, speed);
// 8N1, 无硬件流控制
tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8; // 8 位字符
tty.c_iflag &= ~IGNBRK; // 禁用 BREAK 处理
tty.c_lflag = 0; // 无信号字符、回显、规范模式
tty.c_oflag = 0; // 原始输出
tty.c_cc[VMIN] = 0; // 读取不阻塞
tty.c_cc[VTIME] = 5; // 0.5 秒读取超时
tty.c_cflag |= (CLOCAL | CREAD); // 忽略调制解调器控制线,启用接收
tty.c_cflag &= ~(PARENB | PARODD); // 无奇偶校验
tty.c_cflag &= ~CSTOPB; // 1 位停止位
tty.c_cflag &= ~CRTSCTS; // 无硬件流控制
if (tcsetattr(serial_fd, TCSANOW, &tty) != 0)
{
std::cerr << "Error from tcsetattr" << std::endl;
std::exit(EXIT_FAILURE);
}
std::cout << "IMU serial port opened successfully." << std::endl;
}
// -------------------------------
// 配置指令(与原始 ROS 代码保持一致,仅去掉 ros::Duration
// -------------------------------
void DmImu::enter_setting_mode()
{
uint8_t txbuf[4] = {0xAA, 0x06, 0x01, 0x0D};
for (int i = 0; i < 5; ++i)
{
write(serial_fd, txbuf, sizeof(txbuf));
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
void DmImu::turn_on_accel()
{
uint8_t txbuf[4] = {0xAA, 0x01, 0x14, 0x0D};
for (int i = 0; i < 5; ++i)
{
write(serial_fd, txbuf, sizeof(txbuf));
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
void DmImu::turn_on_gyro()
{
uint8_t txbuf[4] = {0xAA, 0x01, 0x15, 0x0D};
for (int i = 0; i < 5; ++i)
{
write(serial_fd, txbuf, sizeof(txbuf));
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
void DmImu::turn_on_euler()
{
uint8_t txbuf[4] = {0xAA, 0x01, 0x16, 0x0D};
for (int i = 0; i < 5; ++i)
{
write(serial_fd, txbuf, sizeof(txbuf));
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
void DmImu::turn_off_quat()
{
uint8_t txbuf[4] = {0xAA, 0x01, 0x07, 0x0D};
for (int i = 0; i < 5; ++i)
{
write(serial_fd, txbuf, sizeof(txbuf));
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
void DmImu::set_output_1000HZ()
{
uint8_t txbuf[5] = {0xAA, 0x02, 0x01, 0x00, 0x0D};
for (int i = 0; i < 5; ++i)
{
write(serial_fd, txbuf, sizeof(txbuf));
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
void DmImu::save_imu_para()
{
uint8_t txbuf[4] = {0xAA, 0x03, 0x01, 0x0D};
for (int i = 0; i < 5; ++i)
{
write(serial_fd, txbuf, sizeof(txbuf));
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
void DmImu::exit_setting_mode()
{
uint8_t txbuf[4] = {0xAA, 0x06, 0x00, 0x0D};
for (int i = 0; i < 5; ++i)
{
write(serial_fd, txbuf, sizeof(txbuf));
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
void DmImu::restart_imu()
{
uint8_t txbuf[4] = {0xAA, 0x00, 0x00, 0x0D};
for (int i = 0; i < 5; ++i)
{
write(serial_fd, txbuf, sizeof(txbuf));
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
// -------------------------------
// 数据采集线程
// -------------------------------
void DmImu::get_imu_data_thread()
{
int error_num = 0;
while (!stop_thread_)
{
if (serial_fd < 0)
{
std::cerr << "IMU serial port not open in data thread." << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(10));
continue;
}
// 读取完整帧(共 57 字节)
ssize_t len = read(serial_fd, &receive_data, sizeof(receive_data));
if (len != static_cast<ssize_t>(sizeof(receive_data)))
{
++error_num;
continue;
}
// 验证帧头
if (receive_data.FrameHeader1 == 0x55 && receive_data.flag1 == 0xAA &&
receive_data.slave_id1 == 0x01 && receive_data.reg_acc == 0x01)
{
// CRC 校验并提取数据
if (Get_CRC16(reinterpret_cast<uint8_t*>(&receive_data.FrameHeader1), 16) == receive_data.crc1)
{
data.accx = *reinterpret_cast<float*>(&receive_data.accx_u32);
data.accy = *reinterpret_cast<float*>(&receive_data.accy_u32);
data.accz = *reinterpret_cast<float*>(&receive_data.accz_u32);
}
if (Get_CRC16(reinterpret_cast<uint8_t*>(&receive_data.FrameHeader2), 16) == receive_data.crc2)
{
data.gyrox = *reinterpret_cast<float*>(&receive_data.gyrox_u32);
data.gyroy = *reinterpret_cast<float*>(&receive_data.gyroy_u32);
data.gyroz = *reinterpret_cast<float*>(&receive_data.gyroz_u32);
}
if (Get_CRC16(reinterpret_cast<uint8_t*>(&receive_data.FrameHeader3), 16) == receive_data.crc3)
{
data.roll = *reinterpret_cast<float*>(&receive_data.roll_u32);
data.pitch = *reinterpret_cast<float*>(&receive_data.pitch_u32);
data.yaw = *reinterpret_cast<float*>(&receive_data.yaw_u32);
}
// 线程安全更新共享数据
{
std::lock_guard<std::mutex> lock(data_mutex);
// data 已在上面更新,无需额外操作
}
}
else
{
++error_num;
if (error_num > 1200)
{
std::cerr << "Failed to find correct IMU frame header (0x55)." << std::endl;
error_num = 0;
}
}
}
}
}