Auto commit at 2025-05-29 14:24:58

This commit is contained in:
cxh 2025-05-29 14:24:58 +08:00
parent 80eb36066d
commit 579182ba07

View File

@ -10,8 +10,16 @@
CANDriver canctl; CANDriver canctl;
// 急停状态量 struct CanHandlerContext
std::atomic<bool> estop_active = false; {
rclcpp::Node::SharedPtr node;
std::shared_ptr<rclcpp::Publisher<mc::msg::CanFrame>> publisher;
};
std::atomic<bool> estop_active = false; // 急停状态量
std::atomic<bool> estop_msg_received = false; // 是否收到过急停帧
std::atomic<bool> vcu_awake = false; // 是否唤醒成功
rclcpp::Time last_estop_msg_time; // 上次收到急停帧的时间
struct ControlCache struct ControlCache
{ {
@ -79,19 +87,15 @@ mc::msg::McCtrl get_safe_control()
void receiveHandler(const CANFrame &frame, void *userData) void receiveHandler(const CANFrame &frame, void *userData)
{ {
// 获取 ROS 2 Publisher // 获取 ROS 2 Publisher
auto publisher = *static_cast<std::shared_ptr<rclcpp::Publisher<mc::msg::CanFrame>> *>(userData); auto context = static_cast<CanHandlerContext *>(userData);
auto publisher = context->publisher;
auto now = context->node->now();
// 创建一个新的消息 // 创建一个新的消息
auto msg = mc::msg::CanFrame(); auto msg = mc::msg::CanFrame();
msg.id = frame.id; msg.id = frame.id;
msg.dlc = frame.dlc; msg.dlc = frame.dlc;
msg.data.resize(frame.dlc); msg.data.assign(frame.data, frame.data + frame.dlc);
// 复制数据
for (int i = 0; i < frame.dlc; ++i)
{
msg.data[i] = frame.data[i];
}
// 发布消息 // 发布消息
publisher->publish(msg); publisher->publish(msg);
@ -116,6 +120,10 @@ void receiveHandler(const CANFrame &frame, void *userData)
// 检查是否为急停报文 // 检查是否为急停报文
if (frame.id == 0x18FA0121 && frame.dlc >= 3) if (frame.id == 0x18FA0121 && frame.dlc >= 3)
{ {
last_estop_msg_time = now; // 更新时间
estop_msg_received.store(true);
vcu_awake.store(true); // 唤醒成功
uint8_t estop_status = (frame.data[2] & 0x0c) >> 2; // 急停状态位 uint8_t estop_status = (frame.data[2] & 0x0c) >> 2; // 急停状态位
// 急停被按下 // 急停被按下
@ -167,8 +175,60 @@ void mcCtrlCallback(const mc::msg::McCtrl::SharedPtr msg)
control_cache.update(*msg); control_cache.update(*msg);
} }
void VCUWakeUp()
{
CANFrame frame;
// 公共设置
frame.id = 0x18FF8017;
frame.dlc = 8;
frame.ext = true; // 使用扩展帧
frame.rtr = false; // 不是远程帧
// 第1帧握手帧
frame.data[0] = 0x55;
frame.data[1] = 0x21;
for (int i = 2; i < 8; ++i)
frame.data[i] = 0xFF;
canctl.sendFrame(frame);
// 延时,例如 50ms
std::this_thread::sleep_for(std::chrono::milliseconds(50));
// 第2帧启动帧
frame.data[0] = 0xAA;
frame.data[1] = 0x21;
for (int i = 2; i < 8; ++i)
frame.data[i] = 0xFF;
canctl.sendFrame(frame);
}
void setupTimers(rclcpp::Node::SharedPtr node) void setupTimers(rclcpp::Node::SharedPtr node)
{ {
// VCU 唤醒帧发送定时器1Hz
static rclcpp::TimerBase::SharedPtr timer_wakeup = node->create_wall_timer(
std::chrono::seconds(1), []()
{
if (!vcu_awake.load())
{
std::cout << "[VCU] 未唤醒,发送唤醒帧..." << std::endl;
VCUWakeUp(); // 发唤醒帧函数
} });
// 急停报文 watchdog 检查200ms
static rclcpp::TimerBase::SharedPtr timer_estop_watchdog = node->create_wall_timer(
std::chrono::milliseconds(200), [node]()
{
auto now = node->now();
auto elapsed = now - last_estop_msg_time;
if (estop_msg_received.load() && elapsed > rclcpp::Duration::from_seconds(0.5))
{
std::cout << "[VCU] 急停报文超时,重置唤醒状态。" << std::endl;
estop_msg_received.store(false);
vcu_awake.store(false);
} });
// MCU、VCU1 控制50Hz // MCU、VCU1 控制50Hz
static rclcpp::TimerBase::SharedPtr timer_mcu = node->create_wall_timer( static rclcpp::TimerBase::SharedPtr timer_mcu = node->create_wall_timer(
std::chrono::milliseconds(20), []() std::chrono::milliseconds(20), []()
@ -236,34 +296,6 @@ void setupTimers(rclcpp::Node::SharedPtr node)
canctl.sendFrame(edge_brush_cmd.toFrame()); }); canctl.sendFrame(edge_brush_cmd.toFrame()); });
} }
void VCUWakeUp()
{
CANFrame frame;
// 公共设置
frame.id = 0x18FF8017;
frame.dlc = 8;
frame.ext = true; // 使用扩展帧
frame.rtr = false; // 不是远程帧
// 第1帧握手帧
frame.data[0] = 0x55;
frame.data[1] = 0x21;
for (int i = 2; i < 8; ++i)
frame.data[i] = 0xFF;
canctl.sendFrame(frame);
// 延时,例如 50ms
std::this_thread::sleep_for(std::chrono::milliseconds(50));
// 第2帧启动帧
frame.data[0] = 0xAA;
frame.data[1] = 0x21;
for (int i = 2; i < 8; ++i)
frame.data[i] = 0xFF;
canctl.sendFrame(frame);
}
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
rclcpp::init(argc, argv); // 初始化 ROS 2 rclcpp::init(argc, argv); // 初始化 ROS 2
@ -274,7 +306,7 @@ int main(int argc, char **argv)
auto node = rclcpp::Node::make_shared("can_driver_node"); auto node = rclcpp::Node::make_shared("can_driver_node");
// 创建一个 Publisher // 创建一个 Publisher
auto publisher = node->create_publisher<mc::msg::CanFrame>("can_data", 10); auto can_publisher = node->create_publisher<mc::msg::CanFrame>("can_data", 10);
// 创建 Subscriber收控制指令 // 创建 Subscriber收控制指令
auto subscriber = node->create_subscription<mc::msg::McCtrl>( auto subscriber = node->create_subscription<mc::msg::McCtrl>(
@ -293,10 +325,13 @@ int main(int argc, char **argv)
return -1; return -1;
} }
VCUWakeUp(); // 创建上下文
auto context = std::make_shared<CanHandlerContext>();
context->node = node;
context->publisher = can_publisher;
// 设置接收回调并传递 ROS 2 Publisher 作为 userData // 设置接收回调并传递上下文
canctl.setReceiveCallback(receiveHandler, (void *)&publisher); canctl.setReceiveCallback(receiveHandler, (void *)context.get());
// 添加定时器设置 // 添加定时器设置
setupTimers(node); setupTimers(node);