cmvr_head/applications/erpc/service/src/servo_service_impl.cpp
2026-04-23 09:53:17 +08:00

278 lines
8.0 KiB
C++

//
// Created by Administrator on 2025/12/24.
//
#include "erpc/service/include/servo_service_impl.h"
#include <string>
#include "common/type/common_type.h"
const std::vector<ServoDriver::Config> ServoServiceImpl::kServoCfg = {
{"eye_l_up", "pwm1", 1, 20000000, 500000, 2500000, -0.5f * PI, 0.5f * PI, 0.0f},
// {"eye_r_up", "pwm1", 2, 20000000, 500000, 2500000, 0.0f, kPi, 0.5f * kPi},
// ...
};
ServoServiceImpl::ServoServiceImpl()
: manager_(kServoCfg),
init_err_(RT_EOK),
mode_(MotionMode::Immediate),
mutex_(RT_NULL)
{
mutex_ = rt_mutex_create("sv_svc", RT_IPC_FLAG_PRIO);
if (!mutex_) {
init_err_ = -RT_ENOMEM;
rt_kprintf("[ServoService][E] mutex create FAILED, err=%d\n", (int)init_err_);
return;
}
init_err_ = manager_.init(true, true);
if (init_err_ != RT_EOK) {
rt_kprintf("[ServoService][E] init FAILED, err=%d\n", (int)init_err_);
return;
}
manager_.setUpdatePeriodMs(1);
for (const auto& cfg : kServoCfg) {
ServoControl* servo = manager_.get(cfg.servo_id);
if (!servo) {
init_err_ = -RT_ENOSYS;
rt_kprintf("[ServoService][E] missing servo control, id=%s\n", cfg.servo_id.c_str());
return;
}
servo->setConstraints(
3.14,
31.4,
31.4);
}
init_err_ = manager_.start();
if (init_err_ != RT_EOK) {
rt_kprintf("[ServoService][E] manager start FAILED, err=%d\n", (int)init_err_);
}
}
ServoServiceImpl::~ServoServiceImpl()
{
if (mutex_) {
rt_mutex_delete(mutex_);
mutex_ = RT_NULL;
}
}
bool ServoServiceImpl::setConstraints(const char* id,
float max_velocity_rad,
float max_acceleration_rad,
float max_jerk_rad)
{
if (init_err_ != RT_EOK) {
rt_kprintf("[ServoService][E] setConstraints: service not ready, init_err=%d\n",
(int)init_err_);
return false;
}
if (!id) {
rt_kprintf("[ServoService][E] setConstraints: id is null\n");
return false;
}
if (max_velocity_rad <= 0.0f ||
max_acceleration_rad <= 0.0f ||
max_jerk_rad <= 0.0f) {
rt_kprintf("[ServoService][E] setConstraints: invalid constraints, id=%s v=%.4f a=%.4f j=%.4f\n",
id,
(double)max_velocity_rad,
(double)max_acceleration_rad,
(double)max_jerk_rad);
return false;
}
ServoControl* servo = manager_.get(std::string(id));
if (!servo) {
rt_kprintf("[ServoService][E] setConstraints: servo not found, id=%s\n", id);
return false;
}
servo->setConstraints(max_velocity_rad, max_acceleration_rad, max_jerk_rad);
rt_kprintf("[ServoService] setConstraints: id=%s v=%.4f a=%.4f j=%.4f\n",
id,
(double)max_velocity_rad,
(double)max_acceleration_rad,
(double)max_jerk_rad);
return true;
}
bool ServoServiceImpl::setMode(RpcMotionMode mode)
{
if (init_err_ != RT_EOK) {
rt_kprintf("[ServoService][E] setMode: service not ready, init_err=%d\n",
(int)init_err_);
return false;
}
if (!mutex_) {
rt_kprintf("[ServoService][E] setMode: mutex is null\n");
return false;
}
MotionMode motion_mode;
switch (mode) {
case RpcMotionModeImmediate:
motion_mode = MotionMode::Immediate;
break;
case RpcMotionModeSCurve:
motion_mode = MotionMode::SCurve;
break;
default:
rt_kprintf("[ServoService][E] setMode: invalid mode=%d\n", (int)mode);
return false;
}
rt_mutex_take(mutex_, RT_WAITING_FOREVER);
mode_ = motion_mode;
rt_mutex_release(mutex_);
rt_kprintf("[ServoService] setMode: mode=%d\n", (int)mode);
return true;
}
bool ServoServiceImpl::setUpdatePeriodMs(uint32_t ms)
{
if (init_err_ != RT_EOK) {
rt_kprintf("[ServoService][E] setUpdatePeriodMs: service not ready, init_err=%d\n",
(int)init_err_);
return false;
}
manager_.setUpdatePeriodMs(ms);
manager_.wake();
rt_kprintf("[ServoService] setUpdatePeriodMs: ms=%u\n", (unsigned)ms);
return true;
}
int32_t ServoServiceImpl::move(const list_ServoCmd_1_t* cmds)
{
if (init_err_ != RT_EOK) {
rt_kprintf("[ServoService][E] move: service not ready, init_err=%d\n",
(int)init_err_);
return init_err_;
}
if (!cmds) {
rt_kprintf("[ServoService][E] move: cmds is null\n");
return -RT_EINVAL;
}
if (!cmds->elements || cmds->elementsCount == 0) {
rt_kprintf("[ServoService][E] move: empty list (elements=%p, count=%d)\n",
cmds->elements,
(int)cmds->elementsCount);
return -RT_EINVAL;
}
if (!mutex_) {
rt_kprintf("[ServoService][E] move: mutex is null\n");
return -RT_ENOMEM;
}
rt_mutex_take(mutex_, RT_WAITING_FOREVER);
const MotionMode motion_mode = mode_;
rt_mutex_release(mutex_);
for (uint32_t i = 0; i < cmds->elementsCount; ++i) {
const char* id = cmds->elements[i].id;
if (!id) {
rt_kprintf("[ServoService][E] move: cmds[%d].id is null\n", (int)i);
return -RT_EINVAL;
}
ServoControl* servo = manager_.get(std::string(id));
if (!servo) {
rt_kprintf("[ServoService][E] move: servo not found, id=%s\n", id);
return -RT_ENOSYS;
}
const rt_err_t err = servo->move(cmds->elements[i].angle_rad, motion_mode);
if (err != RT_EOK) {
rt_kprintf("[ServoService][E] move: move failed, id=%s angle=%.4f mode=%d err=%d\n",
id,
(double)cmds->elements[i].angle_rad,
(int)motion_mode,
(int)err);
return err;
}
}
if (motion_mode == MotionMode::SCurve) {
manager_.wake();
}
return RT_EOK;
}
int32_t ServoServiceImpl::moveJ(const list_float_1_t* angles_rad)
{
if (init_err_ != RT_EOK) {
rt_kprintf("[ServoService][E] moveJ: service not ready, init_err=%d\n",
(int)init_err_);
return init_err_;
}
if (!angles_rad) {
rt_kprintf("[ServoService][E] moveJ: angles_rad is null\n");
return -RT_EINVAL;
}
if (!angles_rad->elements || angles_rad->elementsCount == 0) {
rt_kprintf("[ServoService][E] moveJ: empty list (elements=%p, count=%d)\n",
angles_rad->elements,
(int)angles_rad->elementsCount);
return -RT_EINVAL;
}
const size_t need = kServoCfg.size();
const size_t got = (size_t)angles_rad->elementsCount;
if (got != need) {
rt_kprintf("[ServoService][E] moveJ: invalid angles count, need=%d got=%d\n",
(int)need,
(int)got);
return -RT_EINVAL;
}
if (!mutex_) {
rt_kprintf("[ServoService][E] moveJ: mutex is null\n");
return -RT_ENOMEM;
}
rt_mutex_take(mutex_, RT_WAITING_FOREVER);
const MotionMode motion_mode = mode_;
rt_mutex_release(mutex_);
for (size_t i = 0; i < need; ++i) {
ServoControl* servo = manager_.get(kServoCfg[i].servo_id);
if (!servo) {
rt_kprintf("[ServoService][E] moveJ: servo not found, id=%s\n",
kServoCfg[i].servo_id.c_str());
return -RT_ENOSYS;
}
const rt_err_t err = servo->move(angles_rad->elements[i], motion_mode);
if (err != RT_EOK) {
rt_kprintf("[ServoService][E] moveJ: move failed, id=%s angle=%.4f mode=%d err=%d\n",
kServoCfg[i].servo_id.c_str(),
(double)angles_rad->elements[i],
(int)motion_mode,
(int)err);
return err;
}
}
if (motion_mode == MotionMode::SCurve) {
manager_.wake();
}
return RT_EOK;
}