• ROS源代码阅读(1)


    ros工作空间创建教程 

    http://wiki.ros.org/kinetic/Installation/Source

    1、首先ros源码获取可以通过github获取:

    https://github.com/ros/ros_comm

    1. git clone https://github.com/ros/ros_comm.git

    3、main入口函数

    我们知道一个程序入口 都是从main开始的,那么我们就拿维基中ros的一个例程来讲

     源码地址:

    http://wiki.ros.org/ROS/Tutorials/WritingServiceClient%28c%2B%2B%29

    1. 1 #include "ros/ros.h"
    2. 2 #include "beginner_tutorials/AddTwoInts.h"
    3. 3
    4. 4 bool add(beginner_tutorials::AddTwoInts::Request &req,
    5. 5 beginner_tutorials::AddTwoInts::Response &res)
    6. 6 {
    7. 7 res.sum = req.a + req.b;
    8. 8 ROS_INFO("request: x=%ld, y=%ld", (long int)req.a, (long int)req.b);
    9. 9 ROS_INFO("sending back response: [%ld]", (long int)res.sum);
    10. 10 return true;
    11. 11 }
    12. 12
    13. 13 int main(int argc, char **argv)
    14. 14 {
    15. 15 ros::init(argc, argv, "add_two_ints_server");
    16. 16 ros::NodeHandle n;
    17. 17
    18. 18 ros::ServiceServer service = n.advertiseService("add_two_ints", add);
    19. 19 ROS_INFO("Ready to add two ints.");
    20. 20 ros::spin();
    21. 21
    22. 22 return 0;
    23. 23 }

    main进来就调用了ros::init(argc, argv, "add_two_ints_server");,这个就是可以去ros源码

    ros_comm/clients /roscpp/src/init.cpp 中找到入口函数 

    void init(int& argc, char** argv, const std::string& name, uint32_t options)

    如果你看别人写程序也基本都有ros::init(argc, argv, "add_two_ints_server");基本上可以确认这个就是入函数

    4、命令行传参

    我们在去维基查看ros的命令行使用:


    http://wiki.ros.org/ROS/Tutorials/UnderstandingNodes

    rosrun turtlesim turtlesim_node __name:=my_turtle

    这个使用方法有:=,这个就对应到函数init(int& argc, char** argv, const std::string& name, uint32_t options)中里面的下面的源代码,查找到:=并把:=两边的字符串存在remappings中

    1. for (int i = 0; i < argc; )
    2. {
    3. std::string arg = argv[i];
    4. size_t pos = arg.find(":=");
    5. if (pos != std::string::npos)
    6. {
    7. std::string local_name = arg.substr(0, pos);
    8. std::string external_name = arg.substr(pos + 2);
    9. ROSCPP_LOG_DEBUG("remap: %s => %s", local_name.c_str(), external_name.c_str());
    10. remappings[local_name] = external_name;
    11. // shuffle everybody down and stuff this guy at the end of argv
    12. char *tmp = argv[i];
    13. for (int j = i; j < full_argc - 1; j++)
    14. argv[j] = argv[j+1];
    15. argv[argc-1] = tmp;
    16. argc--;
    17. }
    18. else
    19. {
    20. i++; // move on, since we didn't shuffle anybody here to replace it
    21. }
    22. }

    ros源码注释

    1. //入口函数
    2. void init(int& argc, char** argv, const std::string& name, uint32_t options)
    3. {
    4. //追踪M_string可以看到定义typedef std::map M_string;
    5. M_string remappings;
    6. int full_argc = argc;
    7. // now, move the remapping argv's to the end, and decrement argc as needed
    8. //将程序运行传入参数转换为remapping
    9. for (int i = 0; i < argc; )
    10. {
    11. std::string arg = argv[i];
    12. size_t pos = arg.find(":=");
    13. if (pos != std::string::npos)
    14. {
    15. std::string local_name = arg.substr(0, pos);
    16. std::string external_name = arg.substr(pos + 2);
    17. ROSCPP_LOG_DEBUG("remap: %s => %s", local_name.c_str(), external_name.c_str());
    18. remappings[local_name] = external_name;
    19. // shuffle everybody down and stuff this guy at the end of argv
    20. char *tmp = argv[i];
    21. for (int j = i; j < full_argc - 1; j++)
    22. argv[j] = argv[j+1];
    23. argv[argc-1] = tmp;
    24. argc--;
    25. }
    26. else
    27. {
    28. i++; // move on, since we didn't shuffle anybody here to replace it
    29. }
    30. }
    31. //将程序运行传入参数转换为remapping后调用另一个init函数
    32. init(remappings, name, options);
    33. }
    34. //转换传入参数为remapping后调用调用此函数
    35. void init(const M_string& remappings, const std::string& name, uint32_t options)
    36. {
    37. if (!g_atexit_registered)
    38. {
    39. g_atexit_registered = true;
    40. //atexit函数是一个特殊的函数,它是在正常程序退出时调用的函数,我们把他叫为登记函数,
    41. // 一个进程可以登记32个函数,这些函数由exit自动调用,这些函数被称为终止处理函数,
    42. //atexit函数可以登记这些函数。exit调用终止处理函数的顺序和atexit登记的顺序相反,
    43. //如果一个函数被多次登记,也会被多次调用,也就是说退出时将调用atexitCallback这个函数。
    44. atexit(atexitCallback);
    45. }
    46. if (!g_global_queue)
    47. {
    48. g_global_queue.reset(new CallbackQueue);
    49. }
    50. if (!g_initialized)
    51. {
    52. g_init_options = options;
    53. g_ok = true;
    54. ROSCONSOLE_AUTOINIT;
    55. // Disable SIGPIPE
    56. #ifndef WIN32
    57. signal(SIGPIPE, SIG_IGN);
    58. #endif
    59. check_ipv6_environment();
    60. //network相关的初始化
    61. network::init(remappings);
    62. //master相关的初始化
    63. master::init(remappings);
    64. // names:: namespace is initialized by this_node
    65. this_node::init(name, remappings, options);
    66. file_log::init(remappings);
    67. param::init(remappings);
    68. g_initialized = true;
    69. }
    70. }

    参考自:

    ROS源代码阅读(1):找切入点_正心公子的博客-CSDN博客https://blog.csdn.net/wanghuiquan0712/article/details/78010697

  • 相关阅读:
    Chromium Mojo通信
    开放式运动耳机好不好用,五款最好用的骨传导耳机推荐
    【C/PTA】数组进阶练习(一)
    shell_51.Linux获取用户输入_无显示读取,从文件中读取
    基于前后端分离的增删改查
    Java泛型
    Learn Prompt-提供示例
    Mysql数据库安装配置详细教程
    linux基本命令(跑路人笔记)
    中文写代码?开始不信后来用中文写了剧情小游戏!嗯,真香~
  • 原文地址:https://blog.csdn.net/lxj362343/article/details/126088735