@1257261547 89793abb-de57-486a-836b-49d3d0d37589-图片.png
code_text
main.cpp
#include <Arduino.h>
#include <Esp32PcntEncoder.h>
#include <Esp32McpwmMotor.h>
#include <PidController.h>
#include <Kinematics.h>
#include <Warning.h>
#include <ImuDriver.h>
#include <WiFi.h>
#include <micro_ros_platformio.h>
#include <rcl/rcl.h>
#include <rclc/rclc.h>
#include <rclc/executor.h>
#include <geometry_msgs/msg/twist.h>
#include <nav_msgs/msg/odometry.h>
#include <micro_ros_utilities/string_utilities.h>
#include <sensor_msgs/msg/imu.h>
rcl_allocator_t allocator;
rclc_support_t support;
rclc_executor_t executor;
rcl_node_t node;
rcl_subscription_t sub_cmd_vel;
geometry_msgs__msg__Twist msg_cmd_vel;
rcl_publisher_t pub_odom;
nav_msgs__msg__Odometry msg_odom;
rcl_timer_t timer;
rcl_publisher_t pub_imu;
sensor_msgs__msg__Imu msg_imu;
Esp32PcntEncoder encoders[2]; // 创建一个数组用于存储两个编码器
Esp32McpwmMotor motor; // 创建一个名为motor的对象,用于控制电机
PidController pid_controller[2];
Kinematics kinematics;
MPU6050 mpu(Wire); // 初始化MPU6050对象
ImuDriver imu(mpu); // 初始化Imu对象
imu_t imu_data; // IMU 数据对象
float target_linear_speed = 20.0; // 单位 毫米每秒
float target_angular_speed = 0.1; // 单位 弧度每秒
float out_left_speed = 0.0; // 输出的左右轮速度,不是反馈的左右轮速度
float out_right_speed = 0.0;
void start()
{
pinMode(TRIG, OUTPUT);
pinMode(ECHO, INPUT);
pinMode(WARN, OUTPUT);
}
void timer_callback(rcl_timer_t* timer,int64_t last_call_time)
{
odom_t odom = kinematics.get_odom();
int64_t stamp = rmw_uros_epoch_millis();
msg_odom.header.stamp.sec = static_cast<int32_t>(stamp/1000);
msg_odom.header.stamp.nanosec = static_cast<int32_t>((stamp%1000)*1e6);
msg_odom.pose.pose.position.x = odom.x;
msg_odom.pose.pose.position.y = odom.y;
msg_odom.pose.pose.orientation.w = cos(odom.angle*0.5);
msg_odom.pose.pose.orientation.x = 0;
msg_odom.pose.pose.orientation.y = 0;
msg_odom.pose.pose.orientation.z = sin(odom.angle*0.5);
msg_odom.twist.twist.linear.x = odom.linear_speed;
msg_odom.twist.twist.angular.z = odom.angular_speed;
imu.getImuDriverData(imu_data);
msg_imu.header.stamp.sec = static_cast<int32_t>(stamp / 1000); // 秒部分
msg_imu.header.stamp.nanosec = static_cast<uint32_t>((stamp % 1000) * 1e6); // 纳秒部分
msg_imu.angular_velocity.x = imu_data.angular_velocity.x;
msg_imu.angular_velocity.y = imu_data.angular_velocity.y;
msg_imu.angular_velocity.z = imu_data.angular_velocity.z;
msg_imu.linear_acceleration.x = imu_data.linear_acceleration.x;
msg_imu.linear_acceleration.y = imu_data.linear_acceleration.y;
msg_imu.linear_acceleration.z = imu_data.linear_acceleration.z;
msg_imu.orientation.x = imu_data.orientation.x;
msg_imu.orientation.y = imu_data.orientation.y;
msg_imu.orientation.z = imu_data.orientation.z;
msg_imu.orientation.w = imu_data.orientation.w;
if(rcl_publish(&pub_odom,&msg_odom,NULL)!=RCL_RET_OK)
{
Serial.printf("error: odom pub failed!");
}
if(rcl_publish(&pub_imu, &msg_imu, NULL)!=RCL_RET_OK)
{
Serial.printf("error: imu pub failed!");
}
}
void twist_callback(const void * msg_in)
{
const geometry_msgs__msg__Twist* msg = (const geometry_msgs__msg__Twist*)msg_in;
target_linear_speed = msg->linear.x*1000;
target_angular_speed = msg->angular.z;
kinematics.kinematics_inverse(target_linear_speed, target_angular_speed, &out_left_speed, &out_right_speed);
Serial.printf("OUT:left_speed=%f,right_speed=%f\n", out_left_speed, out_right_speed);
pid_controller[0].update_target(out_left_speed);
pid_controller[1].update_target(out_right_speed);
}
void microros_task(void* args)
{
IPAddress agent_ip;
agent_ip.fromString("192.168.188.93");
set_microros_wifi_transports("xbw_mi","Xbw159357",agent_ip,8888);
delay(2000);
allocator = rcl_get_default_allocator();
rclc_support_init(&support,0,NULL,&allocator);
rclc_node_init_default(&node,"example_xbwbot_motion_control","",&support);
unsigned int num_handles = 3;
rclc_executor_init(&executor,&support.context,num_handles,&allocator);
rclc_subscription_init_best_effort(&sub_cmd_vel,&node,ROSIDL_GET_MSG_TYPE_SUPPORT(geometry_msgs,msg,Twist),"/cmd_vel");
rclc_executor_add_subscription(&executor,&sub_cmd_vel,&msg_cmd_vel,&twist_callback,ON_NEW_DATA);
msg_odom.header.frame_id = micro_ros_string_utilities_set(msg_odom.header.frame_id,"odom");
msg_odom.child_frame_id = micro_ros_string_utilities_set(msg_odom.child_frame_id,"base_footprint");
msg_imu.header.frame_id = micro_ros_string_utilities_set(msg_imu.header.frame_id,"imu");
rclc_publisher_init_best_effort(&pub_odom,&node,ROSIDL_GET_MSG_TYPE_SUPPORT(nav_msgs,msg,Odometry),"/odom");
rclc_publisher_init_best_effort(&pub_imu,&node,ROSIDL_GET_MSG_TYPE_SUPPORT(sensor_msgs, msg, Imu),"/imu");
rclc_timer_init_default(&timer,&support,RCL_MS_TO_NS(50),timer_callback);
rclc_executor_add_timer(&executor,&timer);
while(!rmw_uros_epoch_synchronized())
{
rmw_uros_sync_session(1000);
delay(10);
}
rclc_executor_spin(&executor);
}
// v=wr r = v/w
void setup()
{
// 初始化串口
Serial.begin(115200); // 初始化串口通信,设置通信速率为115200
// 初始化电机驱动器2
encoders[0].init(0, 32, 33); // 初始化第一个编码器,使用GPIO 32和33连接
encoders[1].init(1, 26, 25); // 初始化第二个编码器,使用GPIO 26和25连接
// 初始化PID控制器的参数
pid_controller[0].update_pid(0.625, 0.125, 0.0);
pid_controller[1].update_pid(0.625, 0.125, 0.0);
pid_controller[0].out_limit(-100, 100);
pid_controller[1].out_limit(-100, 100);
// 初始化运动学参数
kinematics.set_wheel_distance(175); // mm
kinematics.set_motor_param(0, 0.103657);
kinematics.set_motor_param(1, 0.103657);
// 测试下运动学逆解
xTaskCreate(microros_task,"microros_task",10240,NULL,1,NULL);
start();
imu.begin(18, 19);
}
void loop()
{
digitalWrite(TRIG, HIGH);
delayMicroseconds(10);
digitalWrite(TRIG, LOW);
double delta_time = pulseIn(ECHO, HIGH);
float detect_distance = delta_time * 0.0343 / 2;
if(detect_distance<50)
{
digitalWrite(WARN,HIGH);
}
else
{
digitalWrite(WARN,LOW);
}
delayMicroseconds(9990);
kinematics.update_motor_speed(millis(), encoders[0].getTicks(), encoders[1].getTicks());
motor.updateMotorSpeed(0, pid_controller[0].update(kinematics.get_motor_speed(0)));
motor.updateMotorSpeed(1, pid_controller[1].update(kinematics.get_motor_speed(1)));
// Serial.printf("speed1=%d,speed2=%d\n",kinematics.get_motor_speed(0),kinematics.get_motor_speed(1));
// Serial.printf("x,y,yaw=%f,%f,%f\n",kinematics.get_odom().x,kinematics.get_odom().y,kinematics.get_odom().angle);
imu.update();
}
我使用的main.cpp,PidController.h和PidController.h与第九章的代码相同,ImuDriver.h和.cpp是从https://github.dev/fishros/fishbot_motion_control_microros复制过来的。