2022年9月26日
两轮差速底盘运动解算
- 运动学方程
- 干货
class MotionModel { public: MotionModel(double wheel_radius, double body_radius); virtual ~MotionModel(); // robot speed -> motor speed virtual void MotionSolver(double *robot_speed, double *motor_speed) = 0; // motor speed -> robot speed virtual void GetOdom(odom_t odom, double * motor_speed, uint32_t interval = 20) = 0; protected: double wheel_radius_; // 车轮半径 double body_radius_; // 机器人半径 }; class DiffMotionModel : public MotionModel { public: DiffMotionModel(double wheel_radius, double body_radius); virtual ~DiffMotionModel(); // 通过 MotionModel 继承 virtual void MotionSolver(double* robot_speed, double* motor_speed) override; virtual void GetOdom(odom_t odom, double* motor_speed, uint32_t interval = 20) override; };
// 运动解算 void DiffMotionModel::MotionSolver(double* robot_speed, double* motor_speed) { motor_speed[0] = (robot_speed[0] - robot_speed[2] * body_radius_ ) / wheel_radius_; motor_speed[1] = (robot_speed[0] + robot_speed[2] * body_radius_ ) / wheel_radius_; SYS_DEBUG("robot_speed[%f, %f, %f], motor_speed[%f, %f]", robot_speed[0], robot_speed[1], robot_speed[2], motor_speed[1], motor_speed[0]); } // 速度推算里程计 void odom_interface::calc_vel_odom() { double dt = (curr_time_ - last_time_).toSec(); double delta_x = 0.0; double delta_y = 0.0; double delta_t = 0.0; if (!IS_FLOAT_ZERO(curr_vel_.vx) || !IS_FLOAT_ZERO(curr_vel_.vy) || !IS_FLOAT_ZERO(curr_vel_.vt)) { delta_x = (curr_vel_.vx * cos(curr_vel_.vt) - curr_vel_.vy * sin(curr_vel_.vt)) * dt; delta_y = (curr_vel_.vx * sin(curr_vel_.vt) + curr_vel_.vy * cos(curr_vel_.vt)) * dt; delta_t = curr_vel_.vt * dt; odom_changed_ = true; } if (odom_changed_) { ROS_DEBUG_THROTTLE(LOG_CTRL_SPEED, "calc diff odom. diff_time(%f) diff_odom(%f %f %f=%f).", dt, delta_x, delta_y, delta_t, RADIAN_TO_ANGLE(delta_t)); odom_x_ += delta_x; odom_y_ += delta_y; odom_t_ += delta_t; odom_t_ = fmod(odom_t_, 2 * PI); ROS_DEBUG_THROTTLE(LOG_CTRL_SPEED, "calc total odom. vel(%f %f %f) odom(%f %f %f=%f).", curr_vel_.vx, curr_vel_.vy, curr_vel_.vt, odom_x_, odom_y_, odom_t_, RADIAN_TO_ANGLE(odom_t_)); } }
参考: