diff --git a/config/cabin_robot.xml b/config/cabin_robot.xml index 08542302..9626b78a 100644 --- a/config/cabin_robot.xml +++ b/config/cabin_robot.xml @@ -105,7 +105,7 @@ - + diff --git a/src/devices/biohead/biohead_esp32/include/biohead_esp32.h b/src/devices/biohead/biohead_esp32/include/biohead_esp32.h index 0e6937ae..52b34d5d 100644 --- a/src/devices/biohead/biohead_esp32/include/biohead_esp32.h +++ b/src/devices/biohead/biohead_esp32/include/biohead_esp32.h @@ -44,6 +44,10 @@ namespace cmvr::device { uint16_t angleToRaw(double angle); double normalizeToAngle(double normalized, size_t index); + void sendExpression(const std::vector& device_64_angles, const std::vector& device_65_angles, int step_ms); + + + std::shared_ptr serial_; std::string port_name_; diff --git a/src/devices/biohead/biohead_esp32/src/biohead_esp32.cpp b/src/devices/biohead/biohead_esp32/src/biohead_esp32.cpp index 91d6ecf8..9064ed4b 100644 --- a/src/devices/biohead/biohead_esp32/src/biohead_esp32.cpp +++ b/src/devices/biohead/biohead_esp32/src/biohead_esp32.cpp @@ -290,95 +290,6 @@ void BioHeadRobot::speakstop() { LOG(INFO) << "[BioHeadRobot] speak thread stopped."; } -// void BioHeadRobot::speakthread() { -// LOG(INFO) << "[BioHeadRobot] speakthread running."; -// -// // 固定参数 -// const double freq = 3.0; // Hz -// const int step_ms = 40; // 下发周期(ms) -// const double closed_angle = 90.0; -// const double open8 = 83.0; // ch8 张嘴角 -// const double open9 = 97.0; // ch9 张嘴角 -// -// // 找到 channels_ 中对应索引(addr=65 ch=8/9) -// int idx8 = -1, idx9 = -1; -// for (size_t i = 0; i < channels_.size(); ++i) { -// if (channels_[i].addr == 65 && channels_[i].channel == 8) idx8 = static_cast(i); -// if (channels_[i].addr == 65 && channels_[i].channel == 9) idx9 = static_cast(i); -// } -// if (idx8 < 0 || idx9 < 0) { -// LOG(ERROR) << "[BioHeadRobot] speakthread: required channels (65:8/9) not found. Exiting thread."; -// speak_running_.store(false); -// return; -// } -// -// // 以当前角度为基准 -// std::vector base = current_joints_; -// if (base.size() != channels_.size()) base.resize(channels_.size(), 90.0); -// -// auto start = std::chrono::steady_clock::now(); -// -// while (speak_running_.load()) { -// auto now = std::chrono::steady_clock::now(); -// double t = std::chrono::duration_cast>(now - start).count(); -// -// // 正弦产生 0..1 区间因子 -// double phase = 2.0 * M_PI * freq * t; -// double s = 0.5 * (1.0 + std::sin(phase)); // 0..1 -// -// // 计算角度(直接使用度数,不用normalizeToAngle) -// double target8 = closed_angle + (open8 - closed_angle) * s; -// double target9 = closed_angle + (open9 - closed_angle) * s; -// -// // clamp 到限位 -// target8 = std::clamp(target8, min_angles_[idx8], max_angles_[idx8]); -// target9 = std::clamp(target9, min_angles_[idx9], max_angles_[idx9]); -// -// // 构建目标角数组(只修改 idx8/idx9) -// std::vector tgt = base; -// tgt[idx8] = target8; -// tgt[idx9] = target9; -// -// // ---- 构造 ESP32 协议帧 ---- -// std::vector raw_data; -// for (int idx : {idx8, idx9}) { -// uint16_t angle_raw = static_cast(std::round(tgt[idx])); // 直接角度 -// raw_data.push_back(channels_[idx].addr); // 地址 -// raw_data.push_back(channels_[idx].channel); // 通道 -// raw_data.push_back(angle_raw); // 角度(1字节即可) -// raw_data.push_back(step_ms & 0xFF); // 持续时间低字节 -// raw_data.push_back((step_ms >> 8) & 0xFF); // 持续时间高字节 -// } -// -// // 打印发送数据 -// std::string json_output = "{ \"raw_data\": ["; -// for (size_t i = 0; i < raw_data.size(); ++i) { -// json_output += std::to_string(raw_data[i]); -// if (i < raw_data.size() - 1) json_output += ", "; -// } -// json_output += "] }"; -// std::cout << "Sending data at step: " << json_output << std::endl; -// -// // 下发 -// serial_->sendRawServoData(raw_data); -// -// // 控制循环频率 -// std::this_thread::sleep_for(std::chrono::milliseconds(step_ms)); -// } -// -// // 退出前恢复基准角 -// std::vector restore_data; -// for (int idx : {idx8, idx9}) { -// uint16_t angle_raw = static_cast(std::round(base[idx])); -// restore_data.push_back(channels_[idx].addr); -// restore_data.push_back(channels_[idx].channel); -// restore_data.push_back(angle_raw); -// restore_data.push_back(200 & 0xFF); -// restore_data.push_back((200 >> 8) & 0xFF); -// } -// serial_->sendRawServoData(restore_data); -// LOG(INFO) << "[BioHeadRobot] speakthread exiting and restored base pose."; -// } void BioHeadRobot::speakthread() { LOG(INFO) << "[BioHeadRobot] speakthread running."; @@ -576,20 +487,10 @@ void BioHeadRobot::speakthread() { LOG(INFO) << "[BioHeadRobot] speakthread exiting and restored base pose."; } - - - -void BioHeadRobot::expressionHappy() { - const int step_ms = 200; - - // 设备64角度(10通道) - const std::vector device_64_angles = {90, 90, 90, 90, 40, 120, 125, 50, 90, 90}; - // 设备65角度(10通道) - const std::vector device_65_angles = {90, 85, 95, 100, 90, 105, 80, 110, 85, 95}; - +void BioHeadRobot::sendExpression(const std::vector& device_64_angles, const std::vector& device_65_angles, int step_ms) { std::vector raw_data; - // 下发设备64的10个通道(0~9) + // 处理设备64角度 for (int ch = 0; ch < 10; ++ch) { uint8_t angle = static_cast(std::round(device_64_angles[ch])); raw_data.push_back(64); // 地址 @@ -599,7 +500,7 @@ void BioHeadRobot::expressionHappy() { raw_data.push_back((step_ms >> 8) & 0xFF); // 高字节 } - // 下发设备65的10个通道(0~9) + // 处理设备65角度 for (int ch = 0; ch < 10; ++ch) { uint8_t angle = static_cast(std::round(device_65_angles[ch])); raw_data.push_back(65); // 地址 @@ -612,6 +513,7 @@ void BioHeadRobot::expressionHappy() { serial_->sendRawServoData(raw_data); std::this_thread::sleep_for(std::chrono::seconds(3)); + // 恢复到原始角度 // 设备64角度(10通道) const std::vector device_64_neutral = {90, 90, 90, 90, 90, 90, 90, 90, 90, 90}; // 设备65角度(10通道) @@ -642,289 +544,41 @@ void BioHeadRobot::expressionHappy() { serial_->sendRawServoData(raw_data_neutral); } +void BioHeadRobot::expressionHappy() { + const std::vector device_64_angles = {60, 90, 120, 90, 35, 145, 160, 25, 90, 90}; + const std::vector device_65_angles = {90, 85, 95, 100, 90, 105, 80, 110, 85, 95}; + sendExpression(device_64_angles, device_65_angles, 0); +} void BioHeadRobot::expressionSurprised() { - const int step_ms = 200; - - const std::vector device_64_angles = {60, 170, 120, 20, 35, 145, 160, 25, 90, 90}; - const std::vector device_65_angles = {90, 90, 90, 90, 90, 90, 90, 90, 83, 97}; - - std::vector raw_data; - - for (size_t i = 0; i < 10; ++i) { - int idx = -1; - for (size_t j = 0; j < channels_.size(); ++j) { - if (channels_[j].addr == 64 && channels_[j].channel == 4 + i) { - idx = j; - break; - } - } - if (idx >= 0) { - uint8_t angle = static_cast(std::round(device_64_angles[i])); - raw_data.push_back(64); - raw_data.push_back(4 + i); - raw_data.push_back(angle); - raw_data.push_back(step_ms & 0xFF); - raw_data.push_back((step_ms >> 8) & 0xFF); - } - } - - for (size_t i = 0; i < 10; ++i) { - int idx = -1; - for (size_t j = 0; j < channels_.size(); ++j) { - if (channels_[j].addr == 65 && channels_[j].channel == 8 + i) { - idx = j; - break; - } - } - if (idx >= 0) { - uint8_t angle = static_cast(std::round(device_65_angles[i])); - raw_data.push_back(65); - raw_data.push_back(8 + i); - raw_data.push_back(angle); - raw_data.push_back(step_ms & 0xFF); - raw_data.push_back((step_ms >> 8) & 0xFF); - } - } - - serial_->sendRawServoData(raw_data); + const std::vector device_64_angles = {60, 90, 90, 90, 90, 90, 90, 90, 90, 90}; + const std::vector device_65_angles = {90, 90, 90, 90, 90, 90, 90, 90, 85, 95}; + sendExpression(device_64_angles, device_65_angles, 200); } void BioHeadRobot::expressionTired() { - const int step_ms = 200; - const std::vector device_64_angles = {90, 90, 90, 90, 75, 105, 105, 75, 90, 90}; const std::vector device_65_angles = {90, 90, 90, 90, 90, 90, 90, 90, 83, 97}; - - std::vector raw_data; - - for (size_t i = 0; i < 10; ++i) { - int idx = -1; - for (size_t j = 0; j < channels_.size(); ++j) { - if (channels_[j].addr == 64 && channels_[j].channel == 4 + i) { - idx = j; - break; - } - } - if (idx >= 0) { - uint8_t angle = static_cast(std::round(device_64_angles[i])); - raw_data.push_back(64); - raw_data.push_back(4 + i); - raw_data.push_back(angle); - raw_data.push_back(step_ms & 0xFF); - raw_data.push_back((step_ms >> 8) & 0xFF); - } - } - - for (size_t i = 0; i < 10; ++i) { - int idx = -1; - for (size_t j = 0; j < channels_.size(); ++j) { - if (channels_[j].addr == 65 && channels_[j].channel == 8 + i) { - idx = j; - break; - } - } - if (idx >= 0) { - uint8_t angle = static_cast(std::round(device_65_angles[i])); - raw_data.push_back(65); - raw_data.push_back(8 + i); - raw_data.push_back(angle); - raw_data.push_back(step_ms & 0xFF); - raw_data.push_back((step_ms >> 8) & 0xFF); - } - } - - serial_->sendRawServoData(raw_data); + sendExpression(device_64_angles, device_65_angles, 200); } void BioHeadRobot::expressionAngry() { - const int step_ms = 200; - - // 设备64角度(10通道) const std::vector device_64_angles = {90, 90, 90, 90, 40, 120, 125, 50, 90, 90}; - // 设备65角度(10通道) const std::vector device_65_angles = {90, 85, 95, 100, 90, 105, 80, 110, 85, 95}; - - std::vector raw_data; - - // 下发设备64的10个通道(0~9) - for (int ch = 0; ch < 10; ++ch) { - uint8_t angle = static_cast(std::round(device_64_angles[ch])); - raw_data.push_back(64); // 地址 - raw_data.push_back(ch); // 通道号 - raw_data.push_back(angle); // 角度 - raw_data.push_back(step_ms & 0xFF); // 低字节 - raw_data.push_back((step_ms >> 8) & 0xFF); // 高字节 - } - - // 下发设备65的10个通道(0~9) - for (int ch = 0; ch < 10; ++ch) { - uint8_t angle = static_cast(std::round(device_65_angles[ch])); - raw_data.push_back(65); // 地址 - raw_data.push_back(ch); // 通道号 - raw_data.push_back(angle); // 角度 - raw_data.push_back(step_ms & 0xFF); // 低字节 - raw_data.push_back((step_ms >> 8) & 0xFF); // 高字节 - } - - serial_->sendRawServoData(raw_data); - std::this_thread::sleep_for(std::chrono::seconds(3)); - - // 设备64角度(10通道) - const std::vector device_64_neutral = {90, 90, 90, 90, 90, 90, 90, 90, 90, 90}; - // 设备65角度(10通道) - const std::vector device_65_neutral = {90, 90, 90, 90, 90, 90, 90, 90, 90, 90}; - - std::vector raw_data_neutral; - - // 下发设备64的10个通道(0~9) - for (int ch = 0; ch < 10; ++ch) { - uint8_t angle = static_cast(std::round(device_64_neutral[ch])); - raw_data_neutral.push_back(64); // 地址 - raw_data_neutral.push_back(ch); // 通道号 - raw_data_neutral.push_back(angle); // 角度 - raw_data_neutral.push_back(step_ms & 0xFF); // 低字节 - raw_data_neutral.push_back((step_ms >> 8) & 0xFF); // 高字节 - } - - // 下发设备65的10个通道(0~9) - for (int ch = 0; ch < 10; ++ch) { - uint8_t angle = static_cast(std::round(device_65_neutral[ch])); - raw_data_neutral.push_back(65); // 地址 - raw_data_neutral.push_back(ch); // 通道号 - raw_data_neutral.push_back(angle); // 角度 - raw_data_neutral.push_back(step_ms & 0xFF); // 低字节 - raw_data_neutral.push_back((step_ms >> 8) & 0xFF); // 高字节 - } - - serial_->sendRawServoData(raw_data_neutral); + sendExpression(device_64_angles, device_65_angles, 200); } void BioHeadRobot::expressionSadness() { - const int step_ms = 200; - - // 设备64角度(10通道) const std::vector device_64_angles = {90, 90, 90, 90, 40, 120, 125, 50, 90, 90}; - // 设备65角度(10通道) const std::vector device_65_angles = {90, 85, 95, 100, 90, 105, 80, 110, 85, 95}; - - std::vector raw_data; - - // 下发设备64的10个通道(0~9) - for (int ch = 0; ch < 10; ++ch) { - uint8_t angle = static_cast(std::round(device_64_angles[ch])); - raw_data.push_back(64); // 地址 - raw_data.push_back(ch); // 通道号 - raw_data.push_back(angle); // 角度 - raw_data.push_back(step_ms & 0xFF); // 低字节 - raw_data.push_back((step_ms >> 8) & 0xFF); // 高字节 - } - - // 下发设备65的10个通道(0~9) - for (int ch = 0; ch < 10; ++ch) { - uint8_t angle = static_cast(std::round(device_65_angles[ch])); - raw_data.push_back(65); // 地址 - raw_data.push_back(ch); // 通道号 - raw_data.push_back(angle); // 角度 - raw_data.push_back(step_ms & 0xFF); // 低字节 - raw_data.push_back((step_ms >> 8) & 0xFF); // 高字节 - } - - serial_->sendRawServoData(raw_data); - std::this_thread::sleep_for(std::chrono::seconds(3)); - - // 设备64角度(10通道) - const std::vector device_64_neutral = {90, 90, 90, 90, 90, 90, 90, 90, 90, 90}; - // 设备65角度(10通道) - const std::vector device_65_neutral = {90, 90, 90, 90, 90, 90, 90, 90, 90, 90}; - - std::vector raw_data_neutral; - - // 下发设备64的10个通道(0~9) - for (int ch = 0; ch < 10; ++ch) { - uint8_t angle = static_cast(std::round(device_64_neutral[ch])); - raw_data_neutral.push_back(64); // 地址 - raw_data_neutral.push_back(ch); // 通道号 - raw_data_neutral.push_back(angle); // 角度 - raw_data_neutral.push_back(step_ms & 0xFF); // 低字节 - raw_data_neutral.push_back((step_ms >> 8) & 0xFF); // 高字节 - } - - // 下发设备65的10个通道(0~9) - for (int ch = 0; ch < 10; ++ch) { - uint8_t angle = static_cast(std::round(device_65_neutral[ch])); - raw_data_neutral.push_back(65); // 地址 - raw_data_neutral.push_back(ch); // 通道号 - raw_data_neutral.push_back(angle); // 角度 - raw_data_neutral.push_back(step_ms & 0xFF); // 低字节 - raw_data_neutral.push_back((step_ms >> 8) & 0xFF); // 高字节 - } - - serial_->sendRawServoData(raw_data_neutral); + sendExpression(device_64_angles, device_65_angles, 200); } void BioHeadRobot::expressionYawn() { - const int step_ms = 200; - - // 设备64角度(10通道) const std::vector device_64_angles = {90, 90, 90, 90, 40, 120, 125, 50, 90, 90}; - // 设备65角度(10通道) const std::vector device_65_angles = {90, 85, 95, 100, 90, 105, 80, 110, 85, 95}; - - std::vector raw_data; - - // 下发设备64的10个通道(0~9) - for (int ch = 0; ch < 10; ++ch) { - uint8_t angle = static_cast(std::round(device_64_angles[ch])); - raw_data.push_back(64); // 地址 - raw_data.push_back(ch); // 通道号 - raw_data.push_back(angle); // 角度 - raw_data.push_back(step_ms & 0xFF); // 低字节 - raw_data.push_back((step_ms >> 8) & 0xFF); // 高字节 - } - - // 下发设备65的10个通道(0~9) - for (int ch = 0; ch < 10; ++ch) { - uint8_t angle = static_cast(std::round(device_65_angles[ch])); - raw_data.push_back(65); // 地址 - raw_data.push_back(ch); // 通道号 - raw_data.push_back(angle); // 角度 - raw_data.push_back(step_ms & 0xFF); // 低字节 - raw_data.push_back((step_ms >> 8) & 0xFF); // 高字节 - } - - serial_->sendRawServoData(raw_data); - std::this_thread::sleep_for(std::chrono::seconds(3)); - - // 设备64角度(10通道) - const std::vector device_64_neutral = {90, 90, 90, 90, 90, 90, 90, 90, 90, 90}; - // 设备65角度(10通道) - const std::vector device_65_neutral = {90, 90, 90, 90, 90, 90, 90, 90, 90, 90}; - - std::vector raw_data_neutral; - - // 下发设备64的10个通道(0~9) - for (int ch = 0; ch < 10; ++ch) { - uint8_t angle = static_cast(std::round(device_64_neutral[ch])); - raw_data_neutral.push_back(64); // 地址 - raw_data_neutral.push_back(ch); // 通道号 - raw_data_neutral.push_back(angle); // 角度 - raw_data_neutral.push_back(step_ms & 0xFF); // 低字节 - raw_data_neutral.push_back((step_ms >> 8) & 0xFF); // 高字节 - } - - // 下发设备65的10个通道(0~9) - for (int ch = 0; ch < 10; ++ch) { - uint8_t angle = static_cast(std::round(device_65_neutral[ch])); - raw_data_neutral.push_back(65); // 地址 - raw_data_neutral.push_back(ch); // 通道号 - raw_data_neutral.push_back(angle); // 角度 - raw_data_neutral.push_back(step_ms & 0xFF); // 低字节 - raw_data_neutral.push_back((step_ms >> 8) & 0xFF); // 高字节 - } - - serial_->sendRawServoData(raw_data_neutral); + sendExpression(device_64_angles, device_65_angles, 200); }