ROS+P3DX代码注解 [ 1 ] -- RosAria_client代码注解
来源:互联网 发布:淘宝店铺和旺铺的区别 编辑:程序博客网 时间:2024/06/06 00:10
首先当拿到源码的时候,应该先从CMakeLists.txt看起来,然后在看对应的源码。
#cmake最小支持的版本cmake_minimum_required(VERSION 2.8.3)#项目的名称project(rosaria_client)#添加一些package的find_package(catkin REQUIRED COMPONENTS roscpp rospy std_msgs geometry_msgs rosaria)catkin_package()#包含的子目录include_directories( ${catkin_INCLUDE_DIRS})## Declare a cpp executable#然后是添加子文件,前面的地方执行文件的名称,后面的是这个cpp的源文件add_executable(go_three_second src/go_three_second.cpp)add_executable(spin_counterclockwise src/spin_counterclockwise.cpp)add_executable(spin_clockwise src/spin_clockwise.cpp)add_executable(teleop src/teleop.cpp)add_executable(print_state src/print_state.cpp)add_executable(interface src/interface.cpp)add_executable(enable_motors src/enable_motors.cpp)#然后就是将每个Cpp文件分别连接库target_link_libraries(go_three_second ${catkin_LIBRARIES})target_link_libraries(spin_counterclockwise ${catkin_LIBRARIES})target_link_libraries(spin_clockwise ${catkin_LIBRARIES})target_link_libraries(teleop ${catkin_LIBRARIES})target_link_libraries(print_state ${catkin_LIBRARIES})target_link_libraries(interface ${catkin_LIBRARIES} )target_link_libraries(enable_motors ${catkin_LIBRARIES} )
总结:
cmakelists.txt的总体的框架
#cmake最小支持的版本cmake_minimum_required(VERSION 2.8.3)#项目的名称project(rosaria_client)#添加一些package的find_package(catkin REQUIRED COMPONENTS roscpp)catkin_package()#包含的子目录include_directories( ${catkin_INCLUDE_DIRS})#然后是添加子文件,前面的地方执行文件的名称,后面的是这个cpp的源文件#add_executable(执行文件的名称 从项目主要目录找到cpp)add_executable(go_three_second src/go_three_second.cpp)#然后就是将每个Cpp文件分别连接库target_link_libraries(go_three_second ${catkin_LIBRARIES})
enable_motors.cpp:
/*作用:启动电机*/#include <ros/ros.h>int main(int argc, char **argv){//初始化 ros::init(argc, argv, "enable_motors");//实例化一个句柄 ros::NodeHandle nh;//std::system("")相当于在终端输入后面的指令std::system("rosservice call /RosAria/enable_motors");//对ros进行输入 ROS_INFO_STREAM("Motors are enabled!"); return 0;}
spin_clockwise.cpp:
/*作用:让车旋转45度后停下来(将角速度和线速度都变成0)*/#include<ros/ros.h>#include<geometry_msgs/Twist.h>int main(int argc, char **argv){//初始化 ros::init(argc, argv, "Spin_Clockwise");//实例化句柄 ros::NodeHandle nh;/*补充:发布消息,在RosAria/cmd_vel这个话题上面发布消息,这里的1000就是一个尺度,意义不大(对与初学者而言)发布的消息的数据类型是是genmetry_msgs/Twist我们可以通过什么指令来查看发布的消息的数据类型输入rostopic type 话题名称(例如:/RosAria/cmd_vel)就会返回geometry_msgs/Twist,当然我们一般对cmd_vel的数据类型,都是吧他定义成geometry_msgs/Twist这个数据类型接着,我们可以输入 rosmsg show geometry_msgs/Twist来显示显示出来是三个浮点形,因此在后面是有三数字的,并且有2组是因为一个是线速度,一个角速度同时,我们也可一在终端发布简单的命令,例如:rostopic pub [话题] [数据类型] [参数例如:--'[2 0 0]' '[0 0 0]']*///在句柄nh上发布话题 ros::Publisher pub = nh.advertise<geometry_msgs::Twist>("RosAria/cmd_vel", 1000);//实例化一个geometry_msgs命名空间下的Twist对象,这个对象的名字就叫做msg geometry_msgs::Twist msg;//设定参数,最开始的速度,运动的时间持续时间,角速度 PI double BASE_SPEED = 0.2, MOVE_TIME = 3.0, CLOCK_SPEED = 0.5, PI = 3.14159;//判断旋转的 int count = 0;//实例化ros命名空间下的Rate对象,对这个对象的进行初始化,将速度赋值进去 ros::Rate rate(CLOCK_SPEED); // Make the robot stop (robot perhaps has a speed already) //为了防止意外,让车的初速度设置为0,这里的原始是根据现实出msg 的数据类型 msg.linear.x = 0; msg.linear.y = 0; msg.linear.z = 0; msg.angular.x = 0; msg.angular.y = 0; msg.angular.z = 0; pub.publish(msg);/*ros::ok()这个函数用于当你按下ctrl+c的时候就会返回false,因此经常用于while,或者其他判断语句当中或者当MOVE_TIME/CLOCK_SPEED +1 这个数值不大于0的时候,首先这里是想要旋转6次,然后count的自己+1就,后面这个部分是一个定值,就是说7.那么就让count循环了6次。*/ while(ros::ok() && count<MOVE_TIME/CLOCK_SPEED + 1) { // Spin PI/4 /*修改msg.angular.z的数值,根据那个结构,然后发布这个消息,这里的move_time/clock_speed 就是让那他每秒转pi/4的6分一。那么旋转6秒这个旋转的框架还是和厉害的。*/ if (count == 0 || count == 1) { msg.angular.z = -1 * PI/ int(MOVE_TIME/CLOCK_SPEED) / 4; pub.publish(msg); } //向屏幕端输出下面的信息 ROS_INFO_STREAM("The robot is now spinning clockwise!"); //然后这里进行自加1 count++; //调用ros命名空间下的spionOnce()函数,如果这个程序当中有订阅者,那么这条语句就必须存在,为什么在这里写,因为咋这里旋转啊 ros::spinOnce(); //休眠一下,默认是每个1HZ,也就是说1秒刷新一次。也就是说,程序到时候刷新几秒 rate.sleep(); } // Stop the spin停止旋转,并且将原来的线速度都变成0,并且将速度为0这个消息在发布到msg当中,这里为什么要用一个for语句循环两侧,我就不知道了 for(int i = 0; i < 2; i++) { msg.angular.x = 0; msg.angular.y = 0; msg.angular.z = 0; pub.publish(msg); } //输出辅助信息 ROS_INFO_STREAM("The robot finished spinning 45 degrees!"); // Guard, make sure the robot stops保证这个时候的线速度也是0,并且进行过发布 rate.sleep(); msg.linear.x = 0; msg.linear.y = 0; msg.linear.z = 0; pub.publish(msg);}
teleop.cpp:
/*功能:实现箭头控制,以及ctrl+c表示暂停*/#include <ros/ros.h>#include <geometry_msgs/Twist.h>#include <signal.h>#include <termios.h>#include <stdio.h>/*箭头和16进制的对应关系*/#define KEYCODE_R 0x43 //右#define KEYCODE_L 0x44 //左#define KEYCODE_U 0x41 //上#define KEYCODE_D 0x42 //下#define KEYCODE_Q 0x71 //停止#define KEYCODE_SPACE 0x20 //空格/*TeleopRosAria的功能*/class TeleopRosAria{ public: TeleopRosAria();//函数功能:函数发布消息,并且给句柄赋值 void keyLoop(); private: ros::NodeHandle nh_;// double linear_, angular_, l_scale_, a_scale_; ros::Publisher twist_pub_;};TeleopRosAria::TeleopRosAria(): linear_(0), angular_(0), l_scale_(2.0), a_scale_(2.0){//这个param给scale_angular附上初始值 nh_.param("scale_angular", a_scale_, a_scale_); nh_.param("scale_linear", l_scale_, l_scale_);//发布一个话题,并且设置队列的长度是1 twist_pub_ = nh_.advertise<geometry_msgs::Twist>("RosAria/cmd_vel", 1);}//这是帧率int kfd = 0;//定义结构体struct termios cooked, raw;/*补充:这个函数包含在 termios.h头文件中tcsetarr(int fd, int optional_action,const struct)函数用于设置终端参数另外const * 在使用的时候,就是& 一一对应就好参数列表: fd 是帧率 optional_action用于控制修改起作用的时间 strcut保存要修改的参数option_action:TCSANOW:不等待数据传输完毕就立即改变属性*//*暂停函数,全局函数*/void quit(int sig){ tcsetattr(kfd, TCSANOW, &cooked); ros::shutdown();//如果按下ctrl+c立即退出 exit(0);}//函数主线程的入口int main(int argc, char** argv){ ros::init(argc, argv, "teleop_RosAria"); TeleopRosAria teleop_RosAria;/*补充:signal()函数在头文件 signal.h中,signal(参数1,参数2)参数1:我们要进行处理的信信号参数2:我们要处理的方式SIGINT是由于interrupt Key产生quit是一个全局函数*///设置某一个信号对应的动作,这里设置的应该是强制结束的动作。 signal(SIGINT,quit);//调用keyloop函数 teleop_RosAria.keyLoop(); return(0);}//功能:键盘控制void TeleopRosAria::keyLoop(){ char c; bool dirty=false; // get the console in raw mode 得到控制的初始模型/*补充:tcgetattr函数在termios.h头文件中,用于获取终端的相关参数 kdf是一个全局变量memcpy函数在string.h文件中,用于从src指定的位置拷贝N个字节到目标dest所指的内存地址的起始的位置memcpy(src,dest,n) raw是一个结构体,表示:结构体的c_flag表示本地模式标志说明:ICANON说明是启动标准模式ECHO应该受到一个ERASE控制符的时候删除前一个显示符号,我觉着这个地方是为了箭头做准备的保护机制。*/ tcgetattr(kfd, &cooked); memcpy(&raw, &cooked, sizeof(struct termios)); raw.c_lflag &=~ (ICANON | ECHO); // Setting a new line, then end of file 在文件后面设置一个新的线程/*c_cc[VEOF]默认的控制符号 D,在标准模式下,使用read()返回0 ,标志一个文件结束c_cc[VEOL]在行尾加上一个换行符号("\n")标志一个行的结束,重新开始一行*/ raw.c_cc[VEOL] = 1; raw.c_cc[VEOF] = 2; tcsetattr(kfd, TCSANOW, &raw);//输出辅助信息 puts("Reading from keyboard"); puts("---------------------------"); puts("Use arrow keys to move the robot."); puts("Press the space bar to stop the robot."); puts("Press q to stop the program");//死循环 for(;;) { // get the next event from the keyboard 从键盘得到下一个事件 if(read(kfd, &c, 1) < 0) { perror("read():");//将上一个函数发生错误的原因输出到设备参数中 exit(-1); }//线速度的角度速度为0 linear_=angular_=0;//信息在程序中运行不直接显示到终端上 ROS_DEBUG("value: 0x%02X\n", c);//箭头控制 switch(c) { case KEYCODE_L: ROS_DEBUG("LEFT"); angular_ = 0.1; linear_ = 0; dirty = true; break; case KEYCODE_R: ROS_DEBUG("RIGHT"); angular_ = -0.1; linear_ = 0; dirty = true; break; case KEYCODE_U: ROS_DEBUG("UP"); linear_ = 0.1; angular_ = 0; dirty = true; break; case KEYCODE_D: ROS_DEBUG("DOWN"); linear_ = -0.1; angular_ = 0; dirty = true; break; case KEYCODE_SPACE: ROS_DEBUG("STOP"); linear_ = 0; angular_ = 0; dirty = true; break; case KEYCODE_Q: ROS_DEBUG("QUIT"); ROS_INFO_STREAM("You quit the teleop successfully"); return; break; } //实例化对象 geometry_msgs::Twist twist; //这个里面angular里面肯定是有继承关系的 twist.angular.z = a_scale_*angular_; twist.linear.x = l_scale_*linear_; // if(dirty ==true) { /* 只是发布一次消息 */ twist_pub_.publish(twist); dirty=false; } } //return 相当与break吧 return;}
print_state.cpp:
/*功能:输出先锋机器人状态的信息*/#include <ros/ros.h>#include <std_msgs/Float32.h>#include <std_msgs/Float64.h>#include <std_msgs/Int8.h>#include <std_msgs/Bool.h>#include <nav_msgs/Odometry.h>#include <rosaria/BumperState.h>#include <iomanip> // for std :: setprecision and std :: fixedint battery_msg_count = 0, bumper_msg_count = 0;//初始化保险杠的距离和电池的状态/*补充:setprecision 控制输出流显示的浮点数的有效数字的个数(会有四舍五入) 需要加入头文件iomanip.hstd::fix表示用一般的方式输出浮点数*//* checks pose messages and outputs them to user 输出当前位置的和角度,用浮点数输出*/void poseMessageReceived(const nav_msgs::Odometry& msg) { std::cout << std::setprecision(2) << std::fixed << /* output the pose information using standard output */ "Current position=(" << msg.pose.pose.position.x << ", " << msg.pose.pose.position.y << ") " << "Current direction=" << std::setprecision(2) << std::fixed << msg.pose.pose.orientation.w<<"\r"; std::flush(std::cout);}/* output the state of the bumpers using rosaria 使出保险杠的状态*/void bumperStateMessageReceived(const rosaria::BumperState &msg)//这个地方是一个形参{ int front_size, rear_size; //定义前面的距离和后面的剧烈 if (bumper_msg_count == 0) {// ROS_INFO_STREAM("The front bumpers are "<<msg.front_bumpers<<std::endl<<"The rear bumpers are "<<msg.rear_bumpers); front_size = sizeof(msg.front_bumpers) / sizeof(bool); rear_size = sizeof(msg.rear_bumpers) / sizeof(bool); ROS_INFO_STREAM("The front bumpers state are('1' means good): ");//输出辅助信息 std::cout << " "; for (int i=0;i<front_size;i++) if (msg.front_bumpers[i]) std::cout<<'1'; else std::cout<<'0';//换行 std::cout<<std::endl; ROS_INFO_STREAM("The rear bumpers state are('1' means good): "); std::cout << " "; for (int i=0;i<rear_size;i++) if (msg.rear_bumpers[i]) std::cout<<'1'; else std::cout<<'0'; std::cout<<std::endl; bumper_msg_count++; }}/* check the status of the battery charge 检查电池的状态 分别对应msg的类型,然后输出就可以啦*/void batteryStateOfChargeMessageReceived(const std_msgs::Float32 msg){ // Right now this feature is not included in the pioneer-3 robot ROS_INFO_STREAM("The battery state of charge is "<<msg);}/* check + output the voltage of the battery using standard output 检查电压的状态 */void batteryVoltageMessageReceived(const std_msgs::Float64 msg){ if (battery_msg_count == 0) { battery_msg_count++; ROS_INFO_STREAM("The battery voltage is "<< msg); }}void batteryChargeStateMessageReceived(const std_msgs::Int8 msg){ // Right now this feature is not included in the pioneer-3 robot ROS_INFO_STREAM("The battery charge state message received is "<< msg);}/* check the state of the motor and output using standard output 检查发动机的状态*/void motorsStateMessageReceived(const std_msgs::Bool msg){ if (msg.data) ROS_INFO_STREAM("The motor is good"); else ROS_INFO_STREAM("The motor is bad");}/* call all of the functions implemented above and provide user with robot state info */int main(int argc, char **argv){ // Initialize the ROS system and become a node.初始化 ros::init(argc, argv, "print_aria_state"); ros::NodeHandle nh; // Create a subscriber object . //就爱嗯这个订阅各自的话题 ros::Subscriber pose, bumper_state, battery_state_of_charge, battery_voltage, battery_charge_state, motors_state; pose = nh.subscribe("RosAria/pose", 1000, &poseMessageReceived) ; //supply pose bumper_state = nh.subscribe("RosAria/bumper_state", 1000, &bumperStateMessageReceived) ; //inform bumper state battery_state_of_charge = nh.subscribe("RosAria/bumper_state_of_charge", 1000, &batteryStateOfChargeMessageReceived) ; //inform state of charge battery_voltage = nh.subscribe("RosAria/battery_voltage", 1000, &batteryVoltageMessageReceived) ; //inform battery voltage level battery_charge_state = nh.subscribe("RosAria/battery_charge_state", 1000, &batteryChargeStateMessageReceived) ; //inform charge state motors_state = nh.subscribe("RosAria/motors_state", 1000, &motorsStateMessageReceived) ; //inform motor state // Let ROS take over.悬停 ros::spin(); }
RosAria_client.launch文件
<launch> <node pkg = "rosaria" type = "RosAria" name = "RosAria"> <param name="port" value="/dev/ttyUSB0" type="string"/> </node> <node pkg="rosaria_client" type="interface" name="RosAria_interface" output="screen"/></launch>
在launch文件中添加节点和节点名称,以及对一些参数的修改
1 0
- ROS+P3DX代码注解 [ 1 ] -- RosAria_client代码注解
- 注解代码
- 2440启动代码注解
- 注解学习笔记代码
- TFTP文件传输代码注解
- s3c2440启动代码注解
- kmem_cache_free代码注解
- Word2Vec代码注解-distance
- swift:代码 注释,注解
- PHY驱动:代码注解
- 五子棋代码详细注解
- 汇编代码注解
- Netty 示例代码注解
- caffe代码详细注解
- halcon标定代码注解
- 使用注解处理器生成代码-1 注解类型
- 先锋机器人实践(二):RosAria_client代码注释
- 求助:jsp代码注解!!!谢谢!!!
- for循环中取索引,取到之后return直接跳出循环
- 欢迎使用CSDN-markdown编辑器
- 虚拟地址与物理地址之间的关系
- 动态加载表格
- Linux环境下tomcat的catalina.out日志按日分割生成实现
- ROS+P3DX代码注解 [ 1 ] -- RosAria_client代码注解
- 【Java基础】Java变量
- opencv之形态学重建
- jvisualvm远程监控Tomcat
- sass & compass总结(一)
- HashMap源码实现
- node编写一个简单的服务器
- 常用数据库连接池 (DBCP、c3p0、Druid) 配置说明
- php(二)