![](/media/cache/img/default_profile.jpg.50x50_q85.jpg)
WRS2020用にメカナム台車をROS化
Dependencies: mbed PID2 JY901 QuaternionMath ros_lib_melodic i2cmaster WRS2020_mecanum_node
Dependents: WRS2020_mecanum_node
robot_operator.h
- Committer:
- sgrsn
- Date:
- 2021-02-23
- Revision:
- 5:17ede03f1fa5
- Parent:
- 4:40167450cdf0
File content as of revision 5:17ede03f1fa5:
#include "motor_controller.h" #include "MyOdometer.h" #include "define.h" #include "PID.h" // 目標位置制御用の制御周期 const float pose_tick = 0.010; // sec const float L = 0.233; //233 [mm] class MakePath { public: int target_x; int target_y; int target_z; MakePath() { } int makePath(int targetX, int targetY, int targetZ, int x, int y, int z) { target_x = targetX; target_y = targetY; target_z = targetZ; int num = float( sqrt( double( abs(targetX-x)*abs(targetX-x) + abs(targetY-y)*abs(targetY-y) ) )+ abs(targetZ-z) ) / 5.0; //5mm間隔 //printf("num = %d\r\n", num); for(int i = 1; i <= num; i++) { float a = float(i) / num; PATH[i-1][0] = x + (float(targetX - x) * a);// * cos( last_angleZ*DEG_TO_RAD); PATH[i-1][1] = y + (float(targetY - y)* a);// * sin(-last_angleZ*DEG_TO_RAD); PATH[i-1][2] = z + float(targetZ - z) * a; } if(num > 0) { PATH[num-1][0] = targetX; PATH[num-1][1] = targetY; PATH[num-1][2] = targetZ; } else { PATH[0][0] = targetX; PATH[0][1] = targetY; PATH[0][2] = targetZ; num = 1; } return num; } int getPathX(int i) { return PATH[i][0]; } int getPathY(int i) { return PATH[i][1]; } int getPathZ(int i) { return PATH[i][2]; } private: int PATH[500][3]; }; Ticker ticker_pose_controll; MakePath myPath; int path = 0; int pathSize; bool bool_tmp = true; bool *is_stop_ptr_ = &bool_tmp; Timer timer2; PID pid_x(&timer2); PID pid_y(&timer2); PID pid_theta(&timer2); void robot_vel_controll(float vel_x, float vel_y, float vel_theta); void moveStart(float pose_x, float pose_y, float pose_theta); void moveStop(); void pose_controll(); void robot_vel_controll(float vel_x, float vel_y, float vel_theta) { float v[MOTOR_NUM] = {}; // 各車輪の速度 v[0] = -vel_x + vel_y - L * vel_theta; // m/sec v[1] = -vel_x - vel_y - L * vel_theta; v[2] = vel_x - vel_y - L * vel_theta; v[3] = vel_x + vel_y - L * vel_theta; // 本当はこうするべき // f = v * ppr / ( 2*PI * r); // controlMotor(i, (int)f[i]); for(int i = 0; i < MOTOR_NUM; i++) { float f = v[i] / wheel_r * RAD_TO_DEG / deg_per_pulse; controlMotor(i, (int)f); } } void moveStart(float pose_x, float pose_y, float pose_theta, bool* is_stop_pointer) { is_stop_ptr_ = is_stop_pointer; *is_stop_ptr_ = false; pid_x.setParameter(0.40, 0.0, 0.0); pid_y.setParameter(0.40, 0.0, 0.0); pid_theta.setParameter(0.10, 0.0, 0.0); pathSize = myPath.makePath(pose_x*1000, pose_y*1000, pose_theta*RAD_TO_DEG, my_odometry.x*1000, my_odometry.y*1000, my_odometry.theta*RAD_TO_DEG); ticker_pose_controll.attach(&pose_controll, 0.010); path = 0; } void moveStop() { ticker_pose_controll.detach(); *is_stop_ptr_ = true; } void pose_controll() { float x_robot = my_odometry.x*1000; float y_robot = my_odometry.y*1000; float theta_robot = my_odometry.theta; // 目標位置判定 float err_x = myPath.target_x - x_robot; float err_y = myPath.target_y - y_robot; float err_theta = myPath.target_z - theta_robot; // 目標速度計算 // 慣性座標での速度 float xI_dot = pid_x.controlPID(myPath.getPathX(path), x_robot); float yI_dot = pid_y.controlPID(myPath.getPathY(path), y_robot); float theta_dot = pid_theta.controlPID( float( myPath.getPathZ(path))*DEG_TO_RAD, theta_robot); if(path < pathSize-1) path++; else path = pathSize-1; // ロボット座標での速度 float x_dot = cos(theta_robot) * xI_dot + sin(theta_robot) * yI_dot; float y_dot = -sin(theta_robot) * xI_dot + cos(theta_robot) * yI_dot; robot_vel_controll(x_dot/1000, y_dot/1000, theta_dot); // 目標位置到達した場合 if ( abs(err_x) < threshold_x && abs(err_y) < threshold_y && abs(err_theta) < threshold_theta) { // 車輪を停止 coastAllMotor(); //pid_x.reset(); //pid_y.reset(); //pid_theta.reset(); wait_ms(500); jy901.reset(); // 制御を停止 moveStop(); } }