[{"data":1,"prerenderedAt":7303},["ShallowReactive",2],{"wiki-page-\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F0800-zuo-biao-bian-huan-tf":3,"wiki-doc-items-2023-12-30-ros2-tutorial":6884,"wiki:author-members":7291},{"id":4,"title":5,"authors":6,"body":8,"chapterDepth":6871,"chapterOrder":6872,"date":6873,"description":25,"docKey":6874,"docRoot":6875,"docTitle":6876,"extension":6877,"isWikiDoc":140,"isWikiIndex":6878,"meta":6879,"navigation":140,"path":6880,"seo":6881,"stem":6882,"wikiDepth":137,"__hash__":6883},"wiki\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F0800-坐标变换TF.md","坐标变换TF",[7],"董佳辉",{"type":9,"value":10,"toc":6863},"minimark",[11,15,19,27,36,43,50,57,60,65,70,73,76,81,84,87,92,98,106,111,116,119,122,125,201,206,217,275,280,283,302,305,308,326,333,338,341,344,355,358,362,365,383,386,557,560,563,566,569,572,575,578,581,592,595,601,606,611,616,619,624,627,632,635,637,653,655,732,735,738,741,752,755,758,761,766,769,773,779,784,790,795,799,802,812,816,819,836,839,842,846,849,891,894,897,900,903,906,910,921,926,929,989,994,997,1002,1005,1008,1015,1018,1023,1026,1085,1096,1100,1103,1128,1133,1138,1141,1144,1147,1151,1158,1169,1172,1177,1180,1183,1234,1237,1286,1291,1295,1298,1427,1430,2319,2324,2329,2332,2337,2340,2345,2348,2353,2356,2361,2364,2369,2372,2375,2380,2383,2402,2405,2448,2455,2460,2465,2468,2473,2476,2481,2486,2489,2494,2497,2502,2505,2509,2512,2515,2560,2563,2586,2589,3321,3326,3329,3332,3335,3338,3343,3348,3353,3356,3361,3365,3368,3373,3379,3384,3389,3395,3400,3403,3417,3419,3421,3466,3468,3495,3498,4033,4038,4041,4046,4051,4053,4091,4094,4118,4123,4129,4134,4139,4142,4145,4150,4153,4156,4159,4162,4165,4174,4179,4186,4191,4195,4198,4202,4205,4217,4219,4224,4227,4263,4271,4274,4279,4282,4287,4290,4293,4296,4299,4304,4307,4310,4313,4316,4990,4995,4998,5003,5008,5011,5014,5017,5020,5025,5028,5033,5036,5041,5044,5049,5052,5057,5062,5065,5068,5101,5103,5134,5137,5160,5163,5168,5173,5176,5181,5186,5189,5195,5198,5203,5206,5211,5216,5219,5222,5228,5234,5322,5325,5484,5487,6271,6276,6279,6284,6289,6294,6297,6302,6305,6308,6313,6316,6354,6356,6378,6381,6405,6408,6411,6416,6421,6424,6432,6437,6449,6454,6459,6471,6476,6486,6489,6535,6538,6584,6587,6603,6606,6620,6623,6647,6652,6655,6659,6664,6667,6683,6686,6691,6694,6697,6700,6704,6706,6726,6728,6733,6736,6740,6743,6745,6767,6769,6774,6777,6785,6790,6793,6797,6800,6802,6819,6826,6831,6834,6839,6844,6847,6850,6853,6856,6859],[12,13,14],"h3",{"id":14},"坐标变换",[16,17,18],"h4",{"id":18},"引言与应用场景",[20,21,22],"p",{},[23,24],"img",{"alt":25,"src":26},"","https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1264.webp",[20,28,29],{},[30,31,32],"strong",{},[33,34,35],"code",{},"里程计ODOM",[20,37,38],{},[30,39,40],{},[33,41,42],{},"惯性计IMU",[20,44,45],{},[30,46,47],{},[33,48,49],{},"激光雷达Laser",[20,51,52],{},[30,53,54],{},[33,55,56],{},"摄像头Camera",[20,58,59],{},"场景1：现有一移动式机器人底盘，在底盘上安装了一雷达，雷达相对于底盘的偏移量已知，现雷达检测到一障碍物信息，获取到坐标分别为(x,y,z)，该坐标是以雷达为参考系的，如何将这个坐标转换成以小车为参考系的坐标呢？",[20,61,62],{},[23,63],{"alt":25,"src":64},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1265.webp",[20,66,67],{},[23,68],{"alt":25,"src":69},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1266.webp",[20,71,72],{},"激光雷达与小车的中心或边缘相差的横纵距离，以及激光雷达与墙的距离及小车与墙的距离。",[20,74,75],{},"场景2:现有一带机械臂的机器人(比如:PR2)需要夹取目标物，当前机器人头部摄像头可以探测到目标物的坐标(x,y,z)，不过该坐标是以摄像头为参考系的，而实际操作目标物的是机械臂的夹具，当前我们需要将该坐标转换成相对于机械臂夹具的坐标，这个过程如何实现？",[20,77,78],{},[23,79],{"alt":25,"src":80},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1267.webp",[20,82,83],{},"以上通过TF即可算",[16,85,86],{"id":86},"概念与作用",[20,88,89],{},[23,90],{"alt":25,"src":91},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1268.webp",[20,93,94,95],{},"TF实行",[30,96,97],{},"右手坐标系",[20,99,100,103],{},[23,101],{"alt":25,"src":102},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1269.webp",[23,104],{"alt":25,"src":105},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1270.webp",[20,107,108],{},[23,109],{"alt":25,"src":110},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1271.webp",[20,112,113],{},[23,114],{"alt":25,"src":115},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1272.webp",[20,117,118],{},"重要的就是相对位置和时间，在某个时间某个物体位于某个位置。（时间差太大，数据会被废弃）",[16,120,121],{"id":121},"案例安装以及运行",[20,123,124],{},"安装乌龟案列：",[126,127,131],"pre",{"className":128,"code":129,"language":130,"meta":25,"style":25},"language-bash shiki shiki-themes github-light github-dark","\n# Humble版本安装\nsudo apt-get install ros-humble-turtle-tf2-py ros-humble-tf2-tools ros-humble-tf-transformations\n\n# Jazzy版本安装\nsudo apt-get install ros-jazzy-turtle-tf2-py ros-jazzy-tf2-tools ros-jazzy-tf-transformations\n","bash",[33,132,133,142,149,172,177,183],{"__ignoreMap":25},[134,135,138],"span",{"class":136,"line":137},"line",1,[134,139,141],{"emptyLinePlaceholder":140},true,"\n",[134,143,145],{"class":136,"line":144},2,[134,146,148],{"class":147},"sJ8bj","# Humble版本安装\n",[134,150,152,156,160,163,166,169],{"class":136,"line":151},3,[134,153,155],{"class":154},"sScJk","sudo",[134,157,159],{"class":158},"sZZnC"," apt-get",[134,161,162],{"class":158}," install",[134,164,165],{"class":158}," ros-humble-turtle-tf2-py",[134,167,168],{"class":158}," ros-humble-tf2-tools",[134,170,171],{"class":158}," ros-humble-tf-transformations\n",[134,173,175],{"class":136,"line":174},4,[134,176,141],{"emptyLinePlaceholder":140},[134,178,180],{"class":136,"line":179},5,[134,181,182],{"class":147},"# Jazzy版本安装\n",[134,184,186,188,190,192,195,198],{"class":136,"line":185},6,[134,187,155],{"class":154},[134,189,159],{"class":158},[134,191,162],{"class":158},[134,193,194],{"class":158}," ros-jazzy-turtle-tf2-py",[134,196,197],{"class":158}," ros-jazzy-tf2-tools",[134,199,200],{"class":158}," ros-jazzy-tf-transformations\n",[20,202,203],{},[23,204],{"alt":25,"src":205},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1273.webp",[20,207,208,209,212,213,216],{},"此外，还需要安装一个名为 ",[33,210,211],{},"transforms3d"," 的 Python 包，它为 ",[33,214,215],{},"tf_transformations","包提供四元数和欧拉角变换功能，安装命令如下：",[126,218,220],{"className":128,"code":219,"language":130,"meta":25,"style":25},"\n# 方式一（不推荐）\nsudo apt intall python3-pip\npip3 install transforms3d\n\n#方式二（推荐）\nsudo apt install python3-transforms3d\n",[33,221,222,226,231,244,254,258,263],{"__ignoreMap":25},[134,223,224],{"class":136,"line":137},[134,225,141],{"emptyLinePlaceholder":140},[134,227,228],{"class":136,"line":144},[134,229,230],{"class":147},"# 方式一（不推荐）\n",[134,232,233,235,238,241],{"class":136,"line":151},[134,234,155],{"class":154},[134,236,237],{"class":158}," apt",[134,239,240],{"class":158}," intall",[134,242,243],{"class":158}," python3-pip\n",[134,245,246,249,251],{"class":136,"line":174},[134,247,248],{"class":154},"pip3",[134,250,162],{"class":158},[134,252,253],{"class":158}," transforms3d\n",[134,255,256],{"class":136,"line":179},[134,257,141],{"emptyLinePlaceholder":140},[134,259,260],{"class":136,"line":185},[134,261,262],{"class":147},"#方式二（推荐）\n",[134,264,266,268,270,272],{"class":136,"line":265},7,[134,267,155],{"class":154},[134,269,237],{"class":158},[134,271,162],{"class":158},[134,273,274],{"class":158}," python3-transforms3d\n",[20,276,277],{},[23,278],{"alt":25,"src":279},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1274.webp",[20,281,282],{},"启动两个终端，终端1输入如下命令：",[126,284,286],{"className":128,"code":285,"language":130,"meta":25,"style":25},"ros2 launch turtle_tf2_py turtle_tf2_demo.launch.py\n",[33,287,288],{"__ignoreMap":25},[134,289,290,293,296,299],{"class":136,"line":137},[134,291,292],{"class":154},"ros2",[134,294,295],{"class":158}," launch",[134,297,298],{"class":158}," turtle_tf2_py",[134,300,301],{"class":158}," turtle_tf2_demo.launch.py\n",[20,303,304],{},"该命令会启动 turtlesim_node 节点，turtlesim_node 节点中自带一只小乌龟 turtle1，除此之外还会新生成一只乌龟 turtle2，turtle2 会运行至 turtle1 的位置。",[20,306,307],{},"终端2输入如下命令：",[126,309,311],{"className":128,"code":310,"language":130,"meta":25,"style":25},"ros2 run turtlesim turtle_teleop_key\n",[33,312,313],{"__ignoreMap":25},[134,314,315,317,320,323],{"class":136,"line":137},[134,316,292],{"class":154},[134,318,319],{"class":158}," run",[134,321,322],{"class":158}," turtlesim",[134,324,325],{"class":158}," turtle_teleop_key\n",[20,327,328,329,332],{},"该终端下可以通过键盘控制 turtle1 运动，并且 turtle2 会跟随 turtle1 运动（参考引言部分的 ",[30,330,331],{},"案例1"," ）。",[20,334,335],{},[23,336],{"alt":25,"src":337},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1275.webp",[20,339,340],{},"龟男🐢🚹会跟随前面的乌龟🐢运动",[16,342,343],{"id":343},"坐标变换相关消息",[20,345,346,347,350,351,354],{},"坐标变换的实现其本质是基于话题通信的发布订阅模型的，发布方可以发布坐标系之间的相对关系，订阅方则可以监听这些消息，并实现不同坐标系之间的变换。显然的根据之前介绍，在话题通信中，接口消息作为数据载体在整个通信模型中是比较重要的一部分，本节将会介绍坐标变换中常用的两种接口消息：",[33,348,349],{},"geometry_msgs\u002Fmsg\u002FTransformStamped","和",[33,352,353],{},"geometry_msgs\u002Fmsg\u002FPointStamped","。",[20,356,357],{},"前者用于描述某一时刻两个坐标系之间相对关系的接口，后者用于描述某一时刻坐标系内某个坐标点的位置的接口。在坐标变换中，会经常性的使用到坐标系相对关系以及坐标点信息。",[359,360,349],"h5",{"id":361},"geometry_msgsmsgtransformstamped",[20,363,364],{},"通过如下命令查看接口定义：",[126,366,368],{"className":128,"code":367,"language":130,"meta":25,"style":25},"ros2 interface show geometry_msgs\u002Fmsg\u002FTransformStamped\n",[33,369,370],{"__ignoreMap":25},[134,371,372,374,377,380],{"class":136,"line":137},[134,373,292],{"class":154},[134,375,376],{"class":158}," interface",[134,378,379],{"class":158}," show",[134,381,382],{"class":158}," geometry_msgs\u002Fmsg\u002FTransformStamped\n",[20,384,385],{},"接口定义解释：",[126,387,389],{"className":128,"code":388,"language":130,"meta":25,"style":25},"std_msgs\u002FHeader header\n    builtin_interfaces\u002FTime stamp     # 时间戳\n        int32 sec         #秒\n        uint32 nanosec    #纳秒\n    string frame_id                   # 父级坐标系\nstring child_frame_id                 # 子级坐标系\nTransform transform                   # 子级坐标系相对于父级坐标系的位姿\n    Vector3 translation               # 三维偏移量\n        float64 x\n        float64 y\n        float64 z\n    Quaternion rotation               # 四元数\n        float64 x 0\n        float64 y 0\n        float64 z 0\n        float64 w 1\n",[33,390,391,399,410,421,432,443,454,465,477,486,494,502,514,526,536,546],{"__ignoreMap":25},[134,392,393,396],{"class":136,"line":137},[134,394,395],{"class":154},"std_msgs\u002FHeader",[134,397,398],{"class":158}," header\n",[134,400,401,404,407],{"class":136,"line":144},[134,402,403],{"class":154},"    builtin_interfaces\u002FTime",[134,405,406],{"class":158}," stamp",[134,408,409],{"class":147},"     # 时间戳\n",[134,411,412,415,418],{"class":136,"line":151},[134,413,414],{"class":154},"        int32",[134,416,417],{"class":158}," sec",[134,419,420],{"class":147},"         #秒\n",[134,422,423,426,429],{"class":136,"line":174},[134,424,425],{"class":154},"        uint32",[134,427,428],{"class":158}," nanosec",[134,430,431],{"class":147},"    #纳秒\n",[134,433,434,437,440],{"class":136,"line":179},[134,435,436],{"class":154},"    string",[134,438,439],{"class":158}," frame_id",[134,441,442],{"class":147},"                   # 父级坐标系\n",[134,444,445,448,451],{"class":136,"line":185},[134,446,447],{"class":154},"string",[134,449,450],{"class":158}," child_frame_id",[134,452,453],{"class":147},"                 # 子级坐标系\n",[134,455,456,459,462],{"class":136,"line":265},[134,457,458],{"class":154},"Transform",[134,460,461],{"class":158}," transform",[134,463,464],{"class":147},"                   # 子级坐标系相对于父级坐标系的位姿\n",[134,466,468,471,474],{"class":136,"line":467},8,[134,469,470],{"class":154},"    Vector3",[134,472,473],{"class":158}," translation",[134,475,476],{"class":147},"               # 三维偏移量\n",[134,478,480,483],{"class":136,"line":479},9,[134,481,482],{"class":154},"        float64",[134,484,485],{"class":158}," x\n",[134,487,489,491],{"class":136,"line":488},10,[134,490,482],{"class":154},[134,492,493],{"class":158}," y\n",[134,495,497,499],{"class":136,"line":496},11,[134,498,482],{"class":154},[134,500,501],{"class":158}," z\n",[134,503,505,508,511],{"class":136,"line":504},12,[134,506,507],{"class":154},"    Quaternion",[134,509,510],{"class":158}," rotation",[134,512,513],{"class":147},"               # 四元数\n",[134,515,517,519,522],{"class":136,"line":516},13,[134,518,482],{"class":154},[134,520,521],{"class":158}," x",[134,523,525],{"class":524},"sj4cs"," 0\n",[134,527,529,531,534],{"class":136,"line":528},14,[134,530,482],{"class":154},[134,532,533],{"class":158}," y",[134,535,525],{"class":524},[134,537,539,541,544],{"class":136,"line":538},15,[134,540,482],{"class":154},[134,542,543],{"class":158}," z",[134,545,525],{"class":524},[134,547,549,551,554],{"class":136,"line":548},16,[134,550,482],{"class":154},[134,552,553],{"class":158}," w",[134,555,556],{"class":524}," 1\n",[20,558,559],{},"描述一个物体运动一般有6个自由度：X，Y，Z，Yaw，Pitch，Roll。",[20,561,562],{},"三个平动，三个旋转：",[20,564,565],{},"Vector3 translation代表3个平移",[20,567,568],{},"Quaternion rotation四元数可以转化为三个欧拉角(yaw，pitch，roll)",[20,570,571],{},"（Q：为何不用欧拉角而用四元数？A：因为用欧拉角计算会出现死锁现象，所以选择用四元数，而不用欧拉角，以便避免欧拉角的缺陷。）",[20,573,574],{},"3个平移以米meter为单位",[20,576,577],{},"3个旋转以弧度rad为单位",[20,579,580],{},"四元数类似于欧拉角用于表示坐标系的相对姿态，",[20,582,583,584,591],{},"具体转化详见",[585,586,590],"a",{"href":587,"rel":588},"https:\u002F\u002Fsdutvincirobot.feishu.cn\u002Fwiki\u002FPVS8wQzRgiTRqpko9l4cEK33nhw",[589],"nofollow","大疆开发板C型嵌入式软件教程文档.pdf","的18.3节",[20,593,594],{},"具体转化算法（Mahony算法）（ROS2的TF2库中也有具体的转化算法）：",[20,596,597],{},[585,598,599],{"href":599,"rel":600},"https:\u002F\u002Fx-io.co.uk\u002Fopen-source-imu-and-ahrs-algorithms\u002F",[589],[20,602,603],{},[23,604],{"alt":25,"src":605},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1276.webp",[20,607,608],{},[23,609],{"alt":25,"src":610},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1277.webp",[20,612,613],{},[23,614],{"alt":25,"src":615},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1278.webp",[20,617,618],{},"按右手坐标系来看，N2相对于N1沿X轴平移了1m(一格代表1米）。",[20,620,621],{},[23,622],{"alt":25,"src":623},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1279.webp",[20,625,626],{},"旋转",[20,628,629],{},[23,630],{"alt":25,"src":631},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1280.webp",[359,633,353],{"id":634},"geometry_msgsmsgpointstamped",[20,636,364],{},[126,638,640],{"className":128,"code":639,"language":130,"meta":25,"style":25},"ros2 interface show geometry_msgs\u002Fmsg\u002FPointStamped\n",[33,641,642],{"__ignoreMap":25},[134,643,644,646,648,650],{"class":136,"line":137},[134,645,292],{"class":154},[134,647,376],{"class":158},[134,649,379],{"class":158},[134,651,652],{"class":158}," geometry_msgs\u002Fmsg\u002FPointStamped\n",[20,654,385],{},[126,656,658],{"className":128,"code":657,"language":130,"meta":25,"style":25},"std_msgs\u002FHeader header\n    builtin_interfaces\u002FTime stamp    # 时间戳\n        int32 sec   #秒\n        uint32 nanosec   #纳秒\n    string frame_id                  # 参考系\nPoint point                          # 三维坐标\n    float64 x\n    float64 y\n    float64 z\n",[33,659,660,666,675,684,693,702,713,720,726],{"__ignoreMap":25},[134,661,662,664],{"class":136,"line":137},[134,663,395],{"class":154},[134,665,398],{"class":158},[134,667,668,670,672],{"class":136,"line":144},[134,669,403],{"class":154},[134,671,406],{"class":158},[134,673,674],{"class":147},"    # 时间戳\n",[134,676,677,679,681],{"class":136,"line":151},[134,678,414],{"class":154},[134,680,417],{"class":158},[134,682,683],{"class":147},"   #秒\n",[134,685,686,688,690],{"class":136,"line":174},[134,687,425],{"class":154},[134,689,428],{"class":158},[134,691,692],{"class":147},"   #纳秒\n",[134,694,695,697,699],{"class":136,"line":179},[134,696,436],{"class":154},[134,698,439],{"class":158},[134,700,701],{"class":147},"                  # 参考系\n",[134,703,704,707,710],{"class":136,"line":185},[134,705,706],{"class":154},"Point",[134,708,709],{"class":158}," point",[134,711,712],{"class":147},"                          # 三维坐标\n",[134,714,715,718],{"class":136,"line":265},[134,716,717],{"class":154},"    float64",[134,719,485],{"class":158},[134,721,722,724],{"class":136,"line":467},[134,723,717],{"class":154},[134,725,493],{"class":158},[134,727,728,730],{"class":136,"line":479},[134,729,717],{"class":154},[134,731,501],{"class":158},[20,733,734],{},"在三维中的坐标点",[12,736,737],{"id":737},"坐标变换广播",[16,739,740],{"id":740},"引言与案例及分析",[20,742,743,744,747,748,751],{},"坐标系相对关系主要有两种： ",[30,745,746],{},"静态坐标系相对关系"," 与 ",[30,749,750],{},"动态坐标系相对关系"," 。",[20,753,754],{},"所谓静态坐标系相对关系是指两个坐标系之间的相对位置是固定不变的，比如：车辆上的雷达、摄像头等组件一般是固定式的，那么雷达坐标系相对于车辆底盘坐标系或摄像头坐标系相对于车辆底盘坐标系就是一种静态关系。",[20,756,757],{},"所谓动态坐标系相对关系是指两个坐标系之间的相对位置关系是动态改变的，比如：车辆上机械臂的关节或夹爪、多车编队中不同车辆等都是可以运动的，那么机械臂的关节或夹爪坐标系相对车辆底盘坐标系或不同车辆坐标系的相对关系就是一种动态关系。",[20,759,760],{},"本节会主要介绍如何实现静态坐标变换广播与动态坐标变换广播。另外，本节还会演示如何发布坐标点消息。",[20,762,763],{},[23,764],{"alt":25,"src":765},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1281.webp",[20,767,768],{},"激光雷达Laser和色相头与底盘位置是静态的，而机械臂的末端执行器与机器人的位置是动态的。",[359,770,772],{"id":771},"_1案例需求","1.案例需求",[20,774,775,778],{},[30,776,777],{},"案例1："," 现有一无人车，在无人车底盘上装有固定式的雷达与摄像头，已知车辆底盘、雷达与摄像头各对应一坐标系，各坐标系的原点取其几何中心。现又已知雷达坐标系相对于底盘坐标系的三维平移量分别为：x方向0.4米，y方向0米，z方向0.2米，无旋转。摄像头坐标系相对于底盘坐标系的三维平移量分别为：x方向-0.5米，y方向0米，z方向0.4米，无旋转。请广播雷达与底盘的坐标系相对关系，摄像头与底盘的坐标系相对关系，并在 rviz2 中查看广播的结果。",[20,780,781],{},[23,782],{"alt":25,"src":783},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1282.webp",[20,785,786,789],{},[30,787,788],{},"案例2："," 启动 turtlesim_node，设该节点中窗体有一个世界坐标系(左下角为坐标系原点)，乌龟是另一个坐标系，乌龟可以通过键盘控制运动，请动态发布乌龟坐标系与世界坐标系的相对关系。",[20,791,792],{},[23,793],{"alt":25,"src":794},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1283.webp",[359,796,798],{"id":797},"_2案例分析","2.案例分析",[20,800,801],{},"在上述案例中，案例1需要使用到静态坐标变换，案例2则需要使用动态坐标变换，不论无论何种实现关注的要素都有两个：",[803,804,805,809],"ol",{},[806,807,808],"li",{},"如何广播坐标系相对关系；",[806,810,811],{},"如何使用 rviz2 显示坐标系相对关系。",[359,813,815],{"id":814},"_3流程简介","3.流程简介",[20,817,818],{},"以编码的实现实现静态或动态坐标变换的流程类似，主要步骤如下：",[803,820,821,824,827,830,833],{},[806,822,823],{},"编写广播实现；",[806,825,826],{},"编辑配置文件；",[806,828,829],{},"编译；",[806,831,832],{},"执行；",[806,834,835],{},"在 rviz2 中查看坐标系关系。",[20,837,838],{},"案例我们会采用 C++ 和 Python 分别实现，二者都遵循上述实现流程。",[20,840,841],{},"另外：需要说明的是，静态广播器除了可以以编码的方式实现外，在 tf2 中还内置了相关工具，可以无需编码，直接执行节点并传入表示坐标系相对关系的参数，即可实现静态坐标系关系的发布（即命令行，有命令行可以优先用命令行）。而动态广播器没有提供类似的工具。（即必须敲代码）",[359,843,845],{"id":844},"_4准备工作","4.准备工作",[20,847,848],{},"终端下进入工作空间的src目录，调用如下两条命令分别创建C++功能包。",[126,850,852],{"className":128,"code":851,"language":130,"meta":25,"style":25},"ros2 pkg create cpp03_tf_broadcaster --build-type ament_cmake --dependencies rclcpp tf2 tf2_ros geometry_msgs turtlesim\n",[33,853,854],{"__ignoreMap":25},[134,855,856,858,861,864,867,870,873,876,879,882,885,888],{"class":136,"line":137},[134,857,292],{"class":154},[134,859,860],{"class":158}," pkg",[134,862,863],{"class":158}," create",[134,865,866],{"class":158}," cpp03_tf_broadcaster",[134,868,869],{"class":524}," --build-type",[134,871,872],{"class":158}," ament_cmake",[134,874,875],{"class":524}," --dependencies",[134,877,878],{"class":158}," rclcpp",[134,880,881],{"class":158}," tf2",[134,883,884],{"class":158}," tf2_ros",[134,886,887],{"class":158}," geometry_msgs",[134,889,890],{"class":158}," turtlesim\n",[20,892,893],{},"tf2功能包内包含了四元数与欧拉角的转换算法。",[20,895,896],{},"tf2_ros功能包内包含了广播对象。",[20,898,899],{},"geometry_msgs功能包消息载体",[20,901,902],{},"turtlesim功能包是获取乌龟🐢位姿",[16,904,905],{"id":905},"静态广播器_命令行实现",[359,907,909],{"id":908},"_1静态广播器工具","1.静态广播器工具",[20,911,912,913,916,917,920],{},"在 ",[33,914,915],{},"tf2_ros","功能包中提供了一个名为",[33,918,919],{},"static_transform_publisher","的可执行文件，通过该文件可以直接广播静态坐标系关系，其使用语法如下。",[20,922,923],{},[30,924,925],{},"格式1：",[20,927,928],{},"使用以米为单位的 x\u002Fy\u002Fz 偏移量和以弧度为单位的roll\u002Fpitch\u002Fyaw（可直译为滚动\u002F俯仰\u002F偏航，分别指的是围绕 x\u002Fy\u002Fz 轴的旋转）向 tf2 发布静态坐标变换。",[126,930,932],{"className":128,"code":931,"language":130,"meta":25,"style":25},"ros2 run tf2_ros static_transform_publisher --x x --y y --z z --yaw yaw --pitch pitch --roll roll --frame-id frame_id --child-frame-id child_frame_id\n",[33,933,934],{"__ignoreMap":25},[134,935,936,938,940,942,945,948,950,953,955,958,960,963,966,969,972,975,978,981,983,986],{"class":136,"line":137},[134,937,292],{"class":154},[134,939,319],{"class":158},[134,941,884],{"class":158},[134,943,944],{"class":158}," static_transform_publisher",[134,946,947],{"class":524}," --x",[134,949,521],{"class":158},[134,951,952],{"class":524}," --y",[134,954,533],{"class":158},[134,956,957],{"class":524}," --z",[134,959,543],{"class":158},[134,961,962],{"class":524}," --yaw",[134,964,965],{"class":158}," yaw",[134,967,968],{"class":524}," --pitch",[134,970,971],{"class":158}," pitch",[134,973,974],{"class":524}," --roll",[134,976,977],{"class":158}," roll",[134,979,980],{"class":524}," --frame-id",[134,982,439],{"class":158},[134,984,985],{"class":524}," --child-frame-id",[134,987,988],{"class":158}," child_frame_id\n",[20,990,991],{},[23,992],{"alt":25,"src":993},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1284.webp",[20,995,996],{},"父级坐标系和子级坐标系是必须要写的。",[20,998,999],{},[23,1000],{"alt":25,"src":1001},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1285.webp",[20,1003,1004],{},"如果这些可选参数不选的话，默认父级坐标系和子级坐标系重合，也就是偏移量和旋转度都是0。",[20,1006,1007],{},"偏移量：X,Y,Z",[20,1009,1010,1011,1014],{},"旋转度：QX,QY,QZ,QW ",[30,1012,1013],{},"或者"," ROLL,PITCH,YAW（单位是弧度）",[20,1016,1017],{},"时间戳：不用设置，会以发布的时间为起点",[20,1019,1020],{},[30,1021,1022],{},"格式2：",[20,1024,1025],{},"使用以米为单位的 x\u002Fy\u002Fz 偏移量和 qx\u002Fqy\u002Fqz\u002Fqw 四元数向 tf2 发布静态坐标变换。",[126,1027,1029],{"className":128,"code":1028,"language":130,"meta":25,"style":25},"ros2 run tf2_ros static_transform_publisher --x x --y y --z z --qx qx --qy qy --qz qz --qw qw --frame-id frame_id --child-frame-id child_frame_id\n",[33,1030,1031],{"__ignoreMap":25},[134,1032,1033,1035,1037,1039,1041,1043,1045,1047,1049,1051,1053,1056,1059,1062,1065,1068,1071,1074,1077,1079,1081,1083],{"class":136,"line":137},[134,1034,292],{"class":154},[134,1036,319],{"class":158},[134,1038,884],{"class":158},[134,1040,944],{"class":158},[134,1042,947],{"class":524},[134,1044,521],{"class":158},[134,1046,952],{"class":524},[134,1048,533],{"class":158},[134,1050,957],{"class":524},[134,1052,543],{"class":158},[134,1054,1055],{"class":524}," --qx",[134,1057,1058],{"class":158}," qx",[134,1060,1061],{"class":524}," --qy",[134,1063,1064],{"class":158}," qy",[134,1066,1067],{"class":524}," --qz",[134,1069,1070],{"class":158}," qz",[134,1072,1073],{"class":524}," --qw",[134,1075,1076],{"class":158}," qw",[134,1078,980],{"class":524},[134,1080,439],{"class":158},[134,1082,985],{"class":524},[134,1084,988],{"class":158},[20,1086,1087,1088,1091,1092,1095],{},"注意：在上述两种格式中除了用于表示父级坐标系的",[33,1089,1090],{},"--frame-id","和用于表示子级坐标系的",[33,1093,1094],{},"--child-frame-id","之外，其他参数都是可选的，如果未指定特定选项，那么将直接使用默认值。",[359,1097,1099],{"id":1098},"_2静态广播器工具使用","2.静态广播器工具使用",[20,1101,1102],{},"打开两个终端，终端1输入如下命令发布雷达（laser）相对于底盘（base_link）的静态坐标变换（重合）：",[126,1104,1106],{"className":128,"code":1105,"language":130,"meta":25,"style":25},"ros2 run tf2_ros static_transform_publisher --frame-id base_link --child-frame-id laser\n",[33,1107,1108],{"__ignoreMap":25},[134,1109,1110,1112,1114,1116,1118,1120,1123,1125],{"class":136,"line":137},[134,1111,292],{"class":154},[134,1113,319],{"class":158},[134,1115,884],{"class":158},[134,1117,944],{"class":158},[134,1119,980],{"class":524},[134,1121,1122],{"class":158}," base_link",[134,1124,985],{"class":524},[134,1126,1127],{"class":158}," laser\n",[20,1129,1130],{},[23,1131],{"alt":25,"src":1132},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1286.webp",[20,1134,1135],{},[23,1136],{"alt":25,"src":1137},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1287.webp",[20,1139,1140],{},"base_link是父级参考系",[20,1142,1143],{},"laser是子级参考系",[20,1145,1146],{},"一般选父系参考系",[359,1148,1150],{"id":1149},"_3rviz2-查看坐标系关系","3.rviz2 查看坐标系关系",[20,1152,1153,1154,1157],{},"新建终端，通过命令",[33,1155,1156],{},"rviz2","打开 rviz2 并配置相关插件查看坐标变换消息：",[803,1159,1160,1163,1166],{},[806,1161,1162],{},"将 Global Options 中的 Fixed Frame 设置为 base_link；",[806,1164,1165],{},"点击 add 按钮添加 TF 插件；",[806,1167,1168],{},"勾选 TF 插件中的 show names。",[20,1170,1171],{},"右侧 Grid 中将以图形化的方式显示坐标变换关系。",[20,1173,1174],{},[23,1175],{"alt":25,"src":1176},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1288.webp",[20,1178,1179],{},"如图，两个参考系重合。",[20,1181,1182],{},"打开两个终端，终端1输入如下命令发布雷达（laser）相对于底盘（base_link）的静态坐标变换：",[126,1184,1186],{"className":128,"code":1185,"language":130,"meta":25,"style":25},"ros2 run tf2_ros static_transform_publisher --x 0.4 --y 0 --z 0.2 --yaw 0.5 --roll 0 --pitch 0 --frame-id base_link --child-frame-id laser\n",[33,1187,1188],{"__ignoreMap":25},[134,1189,1190,1192,1194,1196,1198,1200,1203,1205,1208,1210,1213,1215,1218,1220,1222,1224,1226,1228,1230,1232],{"class":136,"line":137},[134,1191,292],{"class":154},[134,1193,319],{"class":158},[134,1195,884],{"class":158},[134,1197,944],{"class":158},[134,1199,947],{"class":524},[134,1201,1202],{"class":524}," 0.4",[134,1204,952],{"class":524},[134,1206,1207],{"class":524}," 0",[134,1209,957],{"class":524},[134,1211,1212],{"class":524}," 0.2",[134,1214,962],{"class":524},[134,1216,1217],{"class":524}," 0.5",[134,1219,974],{"class":524},[134,1221,1207],{"class":524},[134,1223,968],{"class":524},[134,1225,1207],{"class":524},[134,1227,980],{"class":524},[134,1229,1122],{"class":158},[134,1231,985],{"class":524},[134,1233,1127],{"class":158},[20,1235,1236],{},"终端2输入如下命令发布摄像头（camera）相对于底盘（base_link）的静态坐标变换：",[126,1238,1240],{"className":128,"code":1239,"language":130,"meta":25,"style":25},"ros2 run tf2_ros static_transform_publisher --x -0.5 --y 0 --z 0.4 --yaw 0 --roll 0 --pitch 0 --frame-id base_link --child-frame-id camera\n",[33,1241,1242],{"__ignoreMap":25},[134,1243,1244,1246,1248,1250,1252,1254,1257,1259,1261,1263,1265,1267,1269,1271,1273,1275,1277,1279,1281,1283],{"class":136,"line":137},[134,1245,292],{"class":154},[134,1247,319],{"class":158},[134,1249,884],{"class":158},[134,1251,944],{"class":158},[134,1253,947],{"class":524},[134,1255,1256],{"class":524}," -0.5",[134,1258,952],{"class":524},[134,1260,1207],{"class":524},[134,1262,957],{"class":524},[134,1264,1202],{"class":524},[134,1266,962],{"class":524},[134,1268,1207],{"class":524},[134,1270,974],{"class":524},[134,1272,1207],{"class":524},[134,1274,968],{"class":524},[134,1276,1207],{"class":524},[134,1278,980],{"class":524},[134,1280,1122],{"class":158},[134,1282,985],{"class":524},[134,1284,1285],{"class":158}," camera\n",[20,1287,1288],{},[23,1289],{"alt":25,"src":1290},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1289.webp",[16,1292,1294],{"id":1293},"静态广播器_c实现","静态广播器_C++实现",[359,1296,1297],{"id":1297},"框架搭建",[126,1299,1303],{"className":1300,"code":1301,"language":1302,"meta":25,"style":25},"language-cmake shiki shiki-themes github-light github-dark","find_package(ament_cmake REQUIRED)\nfind_package(rclcpp REQUIRED)\nfind_package(tf2 REQUIRED)\nfind_package(tf2_ros REQUIRED)\nfind_package(geometry_msgs REQUIRED)\nfind_package(turtlesim REQUIRED)\n\nadd_executable(demo01_static_tf_broadcaster src\u002Fdemo01_static_tf_broadcaster.cpp)\nament_target_dependencies(\n  demo01_static_tf_broadcaster\n  \"rclcpp\"\n  \"tf2\"\n  \"tf2_ros\"\n  \"geometry_msgs\"\n  \"turtlesim\"\n)\n\ninstall(TARGETS demo01_static_tf_broadcaster\n  DESTINATION lib\u002F${PROJECT_NAME})\n","cmake",[33,1304,1305,1315,1322,1329,1336,1343,1350,1354,1362,1367,1372,1377,1382,1387,1392,1397,1402,1407,1416],{"__ignoreMap":25},[134,1306,1307,1311],{"class":136,"line":137},[134,1308,1310],{"class":1309},"szBVR","find_package",[134,1312,1314],{"class":1313},"sVt8B","(ament_cmake REQUIRED)\n",[134,1316,1317,1319],{"class":136,"line":144},[134,1318,1310],{"class":1309},[134,1320,1321],{"class":1313},"(rclcpp REQUIRED)\n",[134,1323,1324,1326],{"class":136,"line":151},[134,1325,1310],{"class":1309},[134,1327,1328],{"class":1313},"(tf2 REQUIRED)\n",[134,1330,1331,1333],{"class":136,"line":174},[134,1332,1310],{"class":1309},[134,1334,1335],{"class":1313},"(tf2_ros REQUIRED)\n",[134,1337,1338,1340],{"class":136,"line":179},[134,1339,1310],{"class":1309},[134,1341,1342],{"class":1313},"(geometry_msgs REQUIRED)\n",[134,1344,1345,1347],{"class":136,"line":185},[134,1346,1310],{"class":1309},[134,1348,1349],{"class":1313},"(turtlesim REQUIRED)\n",[134,1351,1352],{"class":136,"line":265},[134,1353,141],{"emptyLinePlaceholder":140},[134,1355,1356,1359],{"class":136,"line":467},[134,1357,1358],{"class":1309},"add_executable",[134,1360,1361],{"class":1313},"(demo01_static_tf_broadcaster src\u002Fdemo01_static_tf_broadcaster.cpp)\n",[134,1363,1364],{"class":136,"line":479},[134,1365,1366],{"class":1313},"ament_target_dependencies(\n",[134,1368,1369],{"class":136,"line":488},[134,1370,1371],{"class":1313},"  demo01_static_tf_broadcaster\n",[134,1373,1374],{"class":136,"line":496},[134,1375,1376],{"class":158},"  \"rclcpp\"\n",[134,1378,1379],{"class":136,"line":504},[134,1380,1381],{"class":158},"  \"tf2\"\n",[134,1383,1384],{"class":136,"line":516},[134,1385,1386],{"class":158},"  \"tf2_ros\"\n",[134,1388,1389],{"class":136,"line":528},[134,1390,1391],{"class":158},"  \"geometry_msgs\"\n",[134,1393,1394],{"class":136,"line":538},[134,1395,1396],{"class":158},"  \"turtlesim\"\n",[134,1398,1399],{"class":136,"line":548},[134,1400,1401],{"class":1313},")\n",[134,1403,1405],{"class":136,"line":1404},17,[134,1406,141],{"emptyLinePlaceholder":140},[134,1408,1410,1413],{"class":136,"line":1409},18,[134,1411,1412],{"class":1309},"install",[134,1414,1415],{"class":1313},"(TARGETS demo01_static_tf_broadcaster\n",[134,1417,1419,1422,1425],{"class":136,"line":1418},19,[134,1420,1421],{"class":1313},"  DESTINATION lib\u002F",[134,1423,1424],{"class":1309},"${PROJECT_NAME}",[134,1426,1401],{"class":1313},[359,1428,1429],{"id":1429},"广播实现",[126,1431,1435],{"className":1432,"code":1433,"language":1434,"meta":25,"style":25},"language-cpp shiki shiki-themes github-light github-dark","\u002F*  \n  需求：编写静态坐标变换程序，执行时传入两个坐标系的相对位姿关系以及父子级坐标系id，\n       程序运行发布静态坐标变换。\n  步骤：\n    1.包含头文件；\n    2.判断终端传入的参数是否合法；\n    3.初始化 ROS 客户端；\n    4.定义节点类；\n      4-1.创建静态坐标变换发布方；\n      4-2.组织并发布消息。\n    5.调用 spin 函数，并传入对象指针；\n    6.释放资源。\n\n*\u002F\n\n\u002F\u002F 1.包含头文件；\n#include \u003Cgeometry_msgs\u002Fmsg\u002Ftransform_stamped.hpp>\n\n#include \u003Crclcpp\u002Frclcpp.hpp>\n#include \u003Ctf2\u002FLinearMath\u002FQuaternion.h>\n#include \u003Ctf2_ros\u002Fstatic_transform_broadcaster.h>\n\nusing std::placeholders::_1;\n\n\u002F\u002F 4.定义节点类；\nclass MinimalStaticFrameBroadcaster : public rclcpp::Node\n{\npublic:\n  explicit MinimalStaticFrameBroadcaster(char * transformation[]): Node(\"minimal_static_frame_broadcaster\")\n  {\n    \u002F\u002F 4-1.创建静态坐标变换发布方；\n    tf_publisher_ = std::make_shared\u003Ctf2_ros::StaticTransformBroadcaster>(this);\n\n    this->make_transforms(transformation);\n  }\n\nprivate:\n  \u002F\u002F 4-2.组织并发布消息。\n  void make_transforms(char * transformation[])\n  {\n    \u002F\u002F 组织消息\n    geometry_msgs::msg::TransformStamped t;\n\n    rclcpp::Time now = this->get_clock()->now();\n    t.header.stamp = now;\n    t.header.frame_id = transformation[7];\n    t.child_frame_id = transformation[8];\n\n    t.transform.translation.x = atof(transformation[1]);\n    t.transform.translation.y = atof(transformation[2]);\n    t.transform.translation.z = atof(transformation[3]);\n    tf2::Quaternion q;\n    q.setRPY(\n      atof(transformation[4]),\n      atof(transformation[5]),\n      atof(transformation[6]));\n    t.transform.rotation.x = q.x();\n    t.transform.rotation.y = q.y();\n    t.transform.rotation.z = q.z();\n    t.transform.rotation.w = q.w();\n\n    \u002F\u002F 发布消息\n    tf_publisher_->sendTransform(t);\n  }\n  std::shared_ptr\u003Ctf2_ros::StaticTransformBroadcaster> tf_publisher_;\n};\n\nint main(int argc, char * argv[])\n{\n  \u002F\u002F 2.判断终端传入的参数是否合法；\n  auto logger = rclcpp::get_logger(\"logger\");\n\n  if (argc != 9) {\n    RCLCPP_INFO(\n      logger, \"运行程序时请按照：x y z roll pitch yaw frame_id child_frame_id 的格式传入参数\");\n    return 1;\n  }\n\n  \u002F\u002F 3.初始化 ROS 客户端；\n  rclcpp::init(argc, argv);\n  \u002F\u002F 5.调用 spin 函数，并传入对象指针；\n  rclcpp::spin(std::make_shared\u003CMinimalStaticFrameBroadcaster>(argv));\n  \u002F\u002F 6.释放资源。\n  rclcpp::shutdown();\n  return 0;\n}\n","cpp",[33,1436,1437,1442,1447,1452,1457,1462,1467,1472,1477,1482,1487,1492,1497,1501,1506,1510,1515,1523,1527,1534,1542,1550,1555,1573,1578,1584,1606,1612,1618,1652,1658,1664,1699,1704,1719,1725,1730,1736,1742,1762,1767,1773,1787,1792,1820,1831,1848,1863,1868,1888,1905,1922,1931,1943,1957,1969,1982,1998,2013,2028,2043,2048,2054,2066,2071,2093,2099,2104,2132,2137,2143,2168,2173,2191,2199,2210,2222,2227,2232,2238,2252,2258,2285,2291,2303,2313],{"__ignoreMap":25},[134,1438,1439],{"class":136,"line":137},[134,1440,1441],{"class":147},"\u002F*  \n",[134,1443,1444],{"class":136,"line":144},[134,1445,1446],{"class":147},"  需求：编写静态坐标变换程序，执行时传入两个坐标系的相对位姿关系以及父子级坐标系id，\n",[134,1448,1449],{"class":136,"line":151},[134,1450,1451],{"class":147},"       程序运行发布静态坐标变换。\n",[134,1453,1454],{"class":136,"line":174},[134,1455,1456],{"class":147},"  步骤：\n",[134,1458,1459],{"class":136,"line":179},[134,1460,1461],{"class":147},"    1.包含头文件；\n",[134,1463,1464],{"class":136,"line":185},[134,1465,1466],{"class":147},"    2.判断终端传入的参数是否合法；\n",[134,1468,1469],{"class":136,"line":265},[134,1470,1471],{"class":147},"    3.初始化 ROS 客户端；\n",[134,1473,1474],{"class":136,"line":467},[134,1475,1476],{"class":147},"    4.定义节点类；\n",[134,1478,1479],{"class":136,"line":479},[134,1480,1481],{"class":147},"      4-1.创建静态坐标变换发布方；\n",[134,1483,1484],{"class":136,"line":488},[134,1485,1486],{"class":147},"      4-2.组织并发布消息。\n",[134,1488,1489],{"class":136,"line":496},[134,1490,1491],{"class":147},"    5.调用 spin 函数，并传入对象指针；\n",[134,1493,1494],{"class":136,"line":504},[134,1495,1496],{"class":147},"    6.释放资源。\n",[134,1498,1499],{"class":136,"line":516},[134,1500,141],{"emptyLinePlaceholder":140},[134,1502,1503],{"class":136,"line":528},[134,1504,1505],{"class":147},"*\u002F\n",[134,1507,1508],{"class":136,"line":538},[134,1509,141],{"emptyLinePlaceholder":140},[134,1511,1512],{"class":136,"line":548},[134,1513,1514],{"class":147},"\u002F\u002F 1.包含头文件；\n",[134,1516,1517,1520],{"class":136,"line":1404},[134,1518,1519],{"class":1309},"#include",[134,1521,1522],{"class":158}," \u003Cgeometry_msgs\u002Fmsg\u002Ftransform_stamped.hpp>\n",[134,1524,1525],{"class":136,"line":1409},[134,1526,141],{"emptyLinePlaceholder":140},[134,1528,1529,1531],{"class":136,"line":1418},[134,1530,1519],{"class":1309},[134,1532,1533],{"class":158}," \u003Crclcpp\u002Frclcpp.hpp>\n",[134,1535,1537,1539],{"class":136,"line":1536},20,[134,1538,1519],{"class":1309},[134,1540,1541],{"class":158}," \u003Ctf2\u002FLinearMath\u002FQuaternion.h>\n",[134,1543,1545,1547],{"class":136,"line":1544},21,[134,1546,1519],{"class":1309},[134,1548,1549],{"class":158}," \u003Ctf2_ros\u002Fstatic_transform_broadcaster.h>\n",[134,1551,1553],{"class":136,"line":1552},22,[134,1554,141],{"emptyLinePlaceholder":140},[134,1556,1558,1561,1564,1567,1570],{"class":136,"line":1557},23,[134,1559,1560],{"class":1309},"using",[134,1562,1563],{"class":154}," std",[134,1565,1566],{"class":1313},"::",[134,1568,1569],{"class":154},"placeholders",[134,1571,1572],{"class":1313},"::_1;\n",[134,1574,1576],{"class":136,"line":1575},24,[134,1577,141],{"emptyLinePlaceholder":140},[134,1579,1581],{"class":136,"line":1580},25,[134,1582,1583],{"class":147},"\u002F\u002F 4.定义节点类；\n",[134,1585,1587,1590,1593,1596,1599,1601,1603],{"class":136,"line":1586},26,[134,1588,1589],{"class":1309},"class",[134,1591,1592],{"class":154}," MinimalStaticFrameBroadcaster",[134,1594,1595],{"class":1313}," : ",[134,1597,1598],{"class":1309},"public",[134,1600,878],{"class":154},[134,1602,1566],{"class":1313},[134,1604,1605],{"class":154},"Node\n",[134,1607,1609],{"class":136,"line":1608},27,[134,1610,1611],{"class":1313},"{\n",[134,1613,1615],{"class":136,"line":1614},28,[134,1616,1617],{"class":1309},"public:\n",[134,1619,1621,1624,1626,1629,1632,1635,1639,1642,1645,1647,1650],{"class":136,"line":1620},29,[134,1622,1623],{"class":1309},"  explicit",[134,1625,1592],{"class":154},[134,1627,1628],{"class":1313},"(",[134,1630,1631],{"class":1309},"char",[134,1633,1634],{"class":1309}," *",[134,1636,1638],{"class":1637},"s4XuR"," transformation",[134,1640,1641],{"class":1313},"[]): ",[134,1643,1644],{"class":154},"Node",[134,1646,1628],{"class":1313},[134,1648,1649],{"class":158},"\"minimal_static_frame_broadcaster\"",[134,1651,1401],{"class":1313},[134,1653,1655],{"class":136,"line":1654},30,[134,1656,1657],{"class":1313},"  {\n",[134,1659,1661],{"class":136,"line":1660},31,[134,1662,1663],{"class":147},"    \u002F\u002F 4-1.创建静态坐标变换发布方；\n",[134,1665,1667,1670,1673,1675,1677,1680,1683,1685,1687,1690,1693,1696],{"class":136,"line":1666},32,[134,1668,1669],{"class":1313},"    tf_publisher_ ",[134,1671,1672],{"class":1309},"=",[134,1674,1563],{"class":154},[134,1676,1566],{"class":1313},[134,1678,1679],{"class":154},"make_shared",[134,1681,1682],{"class":1313},"\u003C",[134,1684,915],{"class":154},[134,1686,1566],{"class":1313},[134,1688,1689],{"class":154},"StaticTransformBroadcaster",[134,1691,1692],{"class":1313},">(",[134,1694,1695],{"class":524},"this",[134,1697,1698],{"class":1313},");\n",[134,1700,1702],{"class":136,"line":1701},33,[134,1703,141],{"emptyLinePlaceholder":140},[134,1705,1707,1710,1713,1716],{"class":136,"line":1706},34,[134,1708,1709],{"class":524},"    this",[134,1711,1712],{"class":1313},"->",[134,1714,1715],{"class":154},"make_transforms",[134,1717,1718],{"class":1313},"(transformation);\n",[134,1720,1722],{"class":136,"line":1721},35,[134,1723,1724],{"class":1313},"  }\n",[134,1726,1728],{"class":136,"line":1727},36,[134,1729,141],{"emptyLinePlaceholder":140},[134,1731,1733],{"class":136,"line":1732},37,[134,1734,1735],{"class":1309},"private:\n",[134,1737,1739],{"class":136,"line":1738},38,[134,1740,1741],{"class":147},"  \u002F\u002F 4-2.组织并发布消息。\n",[134,1743,1745,1748,1751,1753,1755,1757,1759],{"class":136,"line":1744},39,[134,1746,1747],{"class":1309},"  void",[134,1749,1750],{"class":154}," make_transforms",[134,1752,1628],{"class":1313},[134,1754,1631],{"class":1309},[134,1756,1634],{"class":1309},[134,1758,1638],{"class":1637},[134,1760,1761],{"class":1313},"[])\n",[134,1763,1765],{"class":136,"line":1764},40,[134,1766,1657],{"class":1313},[134,1768,1770],{"class":136,"line":1769},41,[134,1771,1772],{"class":147},"    \u002F\u002F 组织消息\n",[134,1774,1776,1779,1781,1784],{"class":136,"line":1775},42,[134,1777,1778],{"class":154},"    geometry_msgs",[134,1780,1566],{"class":1313},[134,1782,1783],{"class":154},"msg",[134,1785,1786],{"class":1313},"::TransformStamped t;\n",[134,1788,1790],{"class":136,"line":1789},43,[134,1791,141],{"emptyLinePlaceholder":140},[134,1793,1795,1798,1801,1803,1806,1808,1811,1814,1817],{"class":136,"line":1794},44,[134,1796,1797],{"class":154},"    rclcpp",[134,1799,1800],{"class":1313},"::Time now ",[134,1802,1672],{"class":1309},[134,1804,1805],{"class":524}," this",[134,1807,1712],{"class":1313},[134,1809,1810],{"class":154},"get_clock",[134,1812,1813],{"class":1313},"()->",[134,1815,1816],{"class":154},"now",[134,1818,1819],{"class":1313},"();\n",[134,1821,1823,1826,1828],{"class":136,"line":1822},45,[134,1824,1825],{"class":1313},"    t.header.stamp ",[134,1827,1672],{"class":1309},[134,1829,1830],{"class":1313}," now;\n",[134,1832,1834,1837,1839,1842,1845],{"class":136,"line":1833},46,[134,1835,1836],{"class":1313},"    t.header.frame_id ",[134,1838,1672],{"class":1309},[134,1840,1841],{"class":1313}," transformation[",[134,1843,1844],{"class":524},"7",[134,1846,1847],{"class":1313},"];\n",[134,1849,1851,1854,1856,1858,1861],{"class":136,"line":1850},47,[134,1852,1853],{"class":1313},"    t.child_frame_id ",[134,1855,1672],{"class":1309},[134,1857,1841],{"class":1313},[134,1859,1860],{"class":524},"8",[134,1862,1847],{"class":1313},[134,1864,1866],{"class":136,"line":1865},48,[134,1867,141],{"emptyLinePlaceholder":140},[134,1869,1871,1874,1876,1879,1882,1885],{"class":136,"line":1870},49,[134,1872,1873],{"class":1313},"    t.transform.translation.x ",[134,1875,1672],{"class":1309},[134,1877,1878],{"class":154}," atof",[134,1880,1881],{"class":1313},"(transformation[",[134,1883,1884],{"class":524},"1",[134,1886,1887],{"class":1313},"]);\n",[134,1889,1891,1894,1896,1898,1900,1903],{"class":136,"line":1890},50,[134,1892,1893],{"class":1313},"    t.transform.translation.y ",[134,1895,1672],{"class":1309},[134,1897,1878],{"class":154},[134,1899,1881],{"class":1313},[134,1901,1902],{"class":524},"2",[134,1904,1887],{"class":1313},[134,1906,1908,1911,1913,1915,1917,1920],{"class":136,"line":1907},51,[134,1909,1910],{"class":1313},"    t.transform.translation.z ",[134,1912,1672],{"class":1309},[134,1914,1878],{"class":154},[134,1916,1881],{"class":1313},[134,1918,1919],{"class":524},"3",[134,1921,1887],{"class":1313},[134,1923,1925,1928],{"class":136,"line":1924},52,[134,1926,1927],{"class":154},"    tf2",[134,1929,1930],{"class":1313},"::Quaternion q;\n",[134,1932,1934,1937,1940],{"class":136,"line":1933},53,[134,1935,1936],{"class":1313},"    q.",[134,1938,1939],{"class":154},"setRPY",[134,1941,1942],{"class":1313},"(\n",[134,1944,1946,1949,1951,1954],{"class":136,"line":1945},54,[134,1947,1948],{"class":154},"      atof",[134,1950,1881],{"class":1313},[134,1952,1953],{"class":524},"4",[134,1955,1956],{"class":1313},"]),\n",[134,1958,1960,1962,1964,1967],{"class":136,"line":1959},55,[134,1961,1948],{"class":154},[134,1963,1881],{"class":1313},[134,1965,1966],{"class":524},"5",[134,1968,1956],{"class":1313},[134,1970,1972,1974,1976,1979],{"class":136,"line":1971},56,[134,1973,1948],{"class":154},[134,1975,1881],{"class":1313},[134,1977,1978],{"class":524},"6",[134,1980,1981],{"class":1313},"]));\n",[134,1983,1985,1988,1990,1993,1996],{"class":136,"line":1984},57,[134,1986,1987],{"class":1313},"    t.transform.rotation.x ",[134,1989,1672],{"class":1309},[134,1991,1992],{"class":1313}," q.",[134,1994,1995],{"class":154},"x",[134,1997,1819],{"class":1313},[134,1999,2001,2004,2006,2008,2011],{"class":136,"line":2000},58,[134,2002,2003],{"class":1313},"    t.transform.rotation.y ",[134,2005,1672],{"class":1309},[134,2007,1992],{"class":1313},[134,2009,2010],{"class":154},"y",[134,2012,1819],{"class":1313},[134,2014,2016,2019,2021,2023,2026],{"class":136,"line":2015},59,[134,2017,2018],{"class":1313},"    t.transform.rotation.z ",[134,2020,1672],{"class":1309},[134,2022,1992],{"class":1313},[134,2024,2025],{"class":154},"z",[134,2027,1819],{"class":1313},[134,2029,2031,2034,2036,2038,2041],{"class":136,"line":2030},60,[134,2032,2033],{"class":1313},"    t.transform.rotation.w ",[134,2035,1672],{"class":1309},[134,2037,1992],{"class":1313},[134,2039,2040],{"class":154},"w",[134,2042,1819],{"class":1313},[134,2044,2046],{"class":136,"line":2045},61,[134,2047,141],{"emptyLinePlaceholder":140},[134,2049,2051],{"class":136,"line":2050},62,[134,2052,2053],{"class":147},"    \u002F\u002F 发布消息\n",[134,2055,2057,2060,2063],{"class":136,"line":2056},63,[134,2058,2059],{"class":1313},"    tf_publisher_->",[134,2061,2062],{"class":154},"sendTransform",[134,2064,2065],{"class":1313},"(t);\n",[134,2067,2069],{"class":136,"line":2068},64,[134,2070,1724],{"class":1313},[134,2072,2074,2077,2080,2082,2084,2087,2090],{"class":136,"line":2073},65,[134,2075,2076],{"class":154},"  std",[134,2078,2079],{"class":1313},"::shared_ptr",[134,2081,1682],{"class":1309},[134,2083,915],{"class":154},[134,2085,2086],{"class":1313},"::StaticTransformBroadcaster",[134,2088,2089],{"class":1309},">",[134,2091,2092],{"class":1313}," tf_publisher_;\n",[134,2094,2096],{"class":136,"line":2095},66,[134,2097,2098],{"class":1313},"};\n",[134,2100,2102],{"class":136,"line":2101},67,[134,2103,141],{"emptyLinePlaceholder":140},[134,2105,2107,2110,2113,2115,2117,2120,2123,2125,2127,2130],{"class":136,"line":2106},68,[134,2108,2109],{"class":1309},"int",[134,2111,2112],{"class":154}," main",[134,2114,1628],{"class":1313},[134,2116,2109],{"class":1309},[134,2118,2119],{"class":1637}," argc",[134,2121,2122],{"class":1313},", ",[134,2124,1631],{"class":1309},[134,2126,1634],{"class":1309},[134,2128,2129],{"class":1637}," argv",[134,2131,1761],{"class":1313},[134,2133,2135],{"class":136,"line":2134},69,[134,2136,1611],{"class":1313},[134,2138,2140],{"class":136,"line":2139},70,[134,2141,2142],{"class":147},"  \u002F\u002F 2.判断终端传入的参数是否合法；\n",[134,2144,2146,2149,2152,2154,2156,2158,2161,2163,2166],{"class":136,"line":2145},71,[134,2147,2148],{"class":1309},"  auto",[134,2150,2151],{"class":1313}," logger ",[134,2153,1672],{"class":1309},[134,2155,878],{"class":154},[134,2157,1566],{"class":1313},[134,2159,2160],{"class":154},"get_logger",[134,2162,1628],{"class":1313},[134,2164,2165],{"class":158},"\"logger\"",[134,2167,1698],{"class":1313},[134,2169,2171],{"class":136,"line":2170},72,[134,2172,141],{"emptyLinePlaceholder":140},[134,2174,2176,2179,2182,2185,2188],{"class":136,"line":2175},73,[134,2177,2178],{"class":1309},"  if",[134,2180,2181],{"class":1313}," (argc ",[134,2183,2184],{"class":1309},"!=",[134,2186,2187],{"class":524}," 9",[134,2189,2190],{"class":1313},") {\n",[134,2192,2194,2197],{"class":136,"line":2193},74,[134,2195,2196],{"class":154},"    RCLCPP_INFO",[134,2198,1942],{"class":1313},[134,2200,2202,2205,2208],{"class":136,"line":2201},75,[134,2203,2204],{"class":1313},"      logger, ",[134,2206,2207],{"class":158},"\"运行程序时请按照：x y z roll pitch yaw frame_id child_frame_id 的格式传入参数\"",[134,2209,1698],{"class":1313},[134,2211,2213,2216,2219],{"class":136,"line":2212},76,[134,2214,2215],{"class":1309},"    return",[134,2217,2218],{"class":524}," 1",[134,2220,2221],{"class":1313},";\n",[134,2223,2225],{"class":136,"line":2224},77,[134,2226,1724],{"class":1313},[134,2228,2230],{"class":136,"line":2229},78,[134,2231,141],{"emptyLinePlaceholder":140},[134,2233,2235],{"class":136,"line":2234},79,[134,2236,2237],{"class":147},"  \u002F\u002F 3.初始化 ROS 客户端；\n",[134,2239,2241,2244,2246,2249],{"class":136,"line":2240},80,[134,2242,2243],{"class":154},"  rclcpp",[134,2245,1566],{"class":1313},[134,2247,2248],{"class":154},"init",[134,2250,2251],{"class":1313},"(argc, argv);\n",[134,2253,2255],{"class":136,"line":2254},81,[134,2256,2257],{"class":147},"  \u002F\u002F 5.调用 spin 函数，并传入对象指针；\n",[134,2259,2261,2263,2265,2268,2270,2273,2275,2277,2279,2282],{"class":136,"line":2260},82,[134,2262,2243],{"class":154},[134,2264,1566],{"class":1313},[134,2266,2267],{"class":154},"spin",[134,2269,1628],{"class":1313},[134,2271,2272],{"class":154},"std",[134,2274,1566],{"class":1313},[134,2276,1679],{"class":154},[134,2278,1682],{"class":1313},[134,2280,2281],{"class":154},"MinimalStaticFrameBroadcaster",[134,2283,2284],{"class":1313},">(argv));\n",[134,2286,2288],{"class":136,"line":2287},83,[134,2289,2290],{"class":147},"  \u002F\u002F 6.释放资源。\n",[134,2292,2294,2296,2298,2301],{"class":136,"line":2293},84,[134,2295,2243],{"class":154},[134,2297,1566],{"class":1313},[134,2299,2300],{"class":154},"shutdown",[134,2302,1819],{"class":1313},[134,2304,2306,2309,2311],{"class":136,"line":2305},85,[134,2307,2308],{"class":1309},"  return",[134,2310,1207],{"class":524},[134,2312,2221],{"class":1313},[134,2314,2316],{"class":136,"line":2315},86,[134,2317,2318],{"class":1313},"}\n",[20,2320,2321],{},[23,2322],{"alt":25,"src":2323},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1290.webp",[20,2325,2326],{},[23,2327],{"alt":25,"src":2328},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1291.webp",[20,2330,2331],{},"必须传参正确，否则抛错。",[20,2333,2334],{},[23,2335],{"alt":25,"src":2336},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1292.webp",[20,2338,2339],{},"创建组织并发布数据的函数",[20,2341,2342],{},[23,2343],{"alt":25,"src":2344},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1293.webp",[20,2346,2347],{},"用最简单的重载。",[20,2349,2350],{},[23,2351],{"alt":25,"src":2352},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1294.webp",[20,2354,2355],{},"这样就可以发送了，接下来编辑发送的内容。",[20,2357,2358],{},[23,2359],{"alt":25,"src":2360},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1295.webp",[20,2362,2363],{},"stamp时间戳设置为当前时间，now()函数是设置为当前时间。",[20,2365,2366],{},[23,2367],{"alt":25,"src":2368},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1296.webp",[20,2370,2371],{},"atof()是转化为float浮点类型",[20,2373,2374],{},"x()和getx()都是获取四元数x。（y，z，w以此类推）",[20,2376,2377],{},[23,2378],{"alt":25,"src":2379},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1297.webp",[20,2381,2382],{},"终端中进入当前工作空间，编译功能包：",[126,2384,2386],{"className":128,"code":2385,"language":130,"meta":25,"style":25},"colcon build --packages-select cpp03_tf_broadcaster\n",[33,2387,2388],{"__ignoreMap":25},[134,2389,2390,2393,2396,2399],{"class":136,"line":137},[134,2391,2392],{"class":154},"colcon",[134,2394,2395],{"class":158}," build",[134,2397,2398],{"class":524}," --packages-select",[134,2400,2401],{"class":158}," cpp03_tf_broadcaster\n",[20,2403,2404],{},"当前工作空间下，启动两个终端，终端1输入如下命令发布雷达（laser）相对于底盘（base_link）的静态坐标变换：",[126,2406,2408],{"className":128,"code":2407,"language":130,"meta":25,"style":25},". install\u002Fsetup.bash \nros2 run cpp03_tf_broadcaster demo01_static_tf_broadcaster 0.4 0 0.2 0 0 0 base_link laser\n",[33,2409,2410,2421],{"__ignoreMap":25},[134,2411,2412,2415,2418],{"class":136,"line":137},[134,2413,2414],{"class":524},".",[134,2416,2417],{"class":158}," install\u002Fsetup.bash",[134,2419,2420],{"class":1313}," \n",[134,2422,2423,2425,2427,2429,2432,2434,2436,2438,2440,2442,2444,2446],{"class":136,"line":144},[134,2424,292],{"class":154},[134,2426,319],{"class":158},[134,2428,866],{"class":158},[134,2430,2431],{"class":158}," demo01_static_tf_broadcaster",[134,2433,1202],{"class":524},[134,2435,1207],{"class":524},[134,2437,1212],{"class":524},[134,2439,1207],{"class":524},[134,2441,1207],{"class":524},[134,2443,1207],{"class":524},[134,2445,1122],{"class":158},[134,2447,1127],{"class":158},[20,2449,2450,2451,2454],{},"参考 ",[30,2452,2453],{},"静态广播器（命令）"," 内容启动并配置 rviz2，最终执行结果与案例1类似。",[20,2456,2457],{},[23,2458],{"alt":25,"src":2459},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1298.webp",[20,2461,2462],{},[23,2463],{"alt":25,"src":2464},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1299.webp",[20,2466,2467],{},"本质就是话题通信，但这个话题通信的topic是啥呢？",[20,2469,2470],{},[23,2471],{"alt":25,"src":2472},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1300.webp",[20,2474,2475],{},"通过查看该类源码，就得知，话题为\u002Ftf_static",[20,2477,2478],{},[23,2479],{"alt":25,"src":2480},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1301.webp",[20,2482,2483],{},[23,2484],{"alt":25,"src":2485},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1302.webp",[20,2487,2488],{},"发布方有俩，订阅方有一个。",[20,2490,2491],{},[23,2492],{"alt":25,"src":2493},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1303.webp",[20,2495,2496],{},"这俩是发布方",[20,2498,2499],{},[23,2500],{"alt":25,"src":2501},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1304.webp",[20,2503,2504],{},"这个是订阅方",[16,2506,2508],{"id":2507},"动态广播器_c实现","动态广播器_C++实现",[359,2510,1297],{"id":2511},"框架搭建-1",[20,2513,2514],{},"CMakeLists.txt 文件需要添加如下内容：",[126,2516,2518],{"className":1300,"code":2517,"language":1302,"meta":25,"style":25},"add_executable(demo02_dynamic_tf_broadcaster src\u002Fdemo02_dynamic_tf_broadcaster.cpp)\nament_target_dependencies(\n  demo02_dynamic_tf_broadcaster\n  \"rclcpp\"\n  \"tf2\"\n  \"tf2_ros\"\n  \"geometry_msgs\"\n  \"turtlesim\"\n)\n",[33,2519,2520,2527,2531,2536,2540,2544,2548,2552,2556],{"__ignoreMap":25},[134,2521,2522,2524],{"class":136,"line":137},[134,2523,1358],{"class":1309},[134,2525,2526],{"class":1313},"(demo02_dynamic_tf_broadcaster src\u002Fdemo02_dynamic_tf_broadcaster.cpp)\n",[134,2528,2529],{"class":136,"line":144},[134,2530,1366],{"class":1313},[134,2532,2533],{"class":136,"line":151},[134,2534,2535],{"class":1313},"  demo02_dynamic_tf_broadcaster\n",[134,2537,2538],{"class":136,"line":174},[134,2539,1376],{"class":158},[134,2541,2542],{"class":136,"line":179},[134,2543,1381],{"class":158},[134,2545,2546],{"class":136,"line":185},[134,2547,1386],{"class":158},[134,2549,2550],{"class":136,"line":265},[134,2551,1391],{"class":158},[134,2553,2554],{"class":136,"line":467},[134,2555,1396],{"class":158},[134,2557,2558],{"class":136,"line":479},[134,2559,1401],{"class":1313},[20,2561,2562],{},"文件中 install 修改为如下内容：",[126,2564,2566],{"className":1300,"code":2565,"language":1302,"meta":25,"style":25},"install(TARGETS demo01_static_tf_broadcaster\n  demo02_dynamic_tf_broadcaster\n  DESTINATION lib\u002F${PROJECT_NAME})\n",[33,2567,2568,2574,2578],{"__ignoreMap":25},[134,2569,2570,2572],{"class":136,"line":137},[134,2571,1412],{"class":1309},[134,2573,1415],{"class":1313},[134,2575,2576],{"class":136,"line":144},[134,2577,2535],{"class":1313},[134,2579,2580,2582,2584],{"class":136,"line":151},[134,2581,1421],{"class":1313},[134,2583,1424],{"class":1309},[134,2585,1401],{"class":1313},[359,2587,1429],{"id":2588},"广播实现-1",[126,2590,2592],{"className":1432,"code":2591,"language":1434,"meta":25,"style":25},"\u002F*   \n  需求：编写动态坐标变换程序，启动 turtlesim_node 以及 turtle_teleop_key 后，该程序可以发布\n       乌龟坐标系到窗口坐标系的坐标变换，并且键盘控制乌龟运动时，乌龟坐标系与窗口坐标系的相对关系\n       也会实时更新。\n\n  步骤：\n    1.包含头文件；\n    2.初始化 ROS 客户端；\n    3.定义节点类；\n      3-1.创建动态坐标变换发布方；\n      3-2.创建乌龟位姿订阅方；\n      3-3.根据订阅到的乌龟位姿生成坐标帧并广播。\n    4.调用 spin 函数，并传入对象指针；\n    5.释放资源。\n\n*\u002F\n\u002F\u002F 1.包含头文件；\n#include \u003Cgeometry_msgs\u002Fmsg\u002Ftransform_stamped.hpp>\n\n#include \u003Crclcpp\u002Frclcpp.hpp>\n#include \u003Ctf2\u002FLinearMath\u002FQuaternion.h>\n#include \u003Ctf2_ros\u002Ftransform_broadcaster.h>\n#include \u003Cturtlesim\u002Fmsg\u002Fpose.hpp>\n\nusing std::placeholders::_1;\n\n\u002F\u002F 3.定义节点类；\nclass MinimalDynamicFrameBroadcaster : public rclcpp::Node\n{\npublic:\n  MinimalDynamicFrameBroadcaster(): Node(\"minimal_dynamic_frame_broadcaster\")\n  {\n    \u002F\u002F 3-1.创建动态坐标变换发布方；\n    tf_broadcaster_ = std::make_unique\u003Ctf2_ros::TransformBroadcaster>(*this);\n\n    std::string topic_name = \"\u002Fturtle1\u002Fpose\";\n\n    \u002F\u002F 3-2.创建乌龟位姿订阅方；\n    subscription_ = this->create_subscription\u003Cturtlesim::msg::Pose>(\n      topic_name, 10,\n      std::bind(&MinimalDynamicFrameBroadcaster::handle_turtle_pose, this, _1));\n  }\n\nprivate:\n  \u002F\u002F 3-3.根据订阅到的乌龟位姿生成坐标帧并广播。   \n  void handle_turtle_pose(const turtlesim::msg::Pose & msg)\n  {\n    \u002F\u002F 组织消息\n    geometry_msgs::msg::TransformStamped t;\n    rclcpp::Time now = this->get_clock()->now();\n\n    t.header.stamp = now;\n    t.header.frame_id = \"world\";   \u002F\u002F窗体坐标系\n    t.child_frame_id = \"turtle1\";  \u002F\u002F乌龟坐标系\n\n    t.transform.translation.x = msg.x;\n    t.transform.translation.y = msg.y;\n    t.transform.translation.z = 0.0;      \u002F\u002F乌龟在平面内运动\n\n    \u002F\u002F从欧拉角转换为四元数\n    tf2::Quaternion q;\n    q.setRPY(0, 0, msg.theta);        \u002F\u002F乌龟只有Yaw\n    t.transform.rotation.x = q.x();\n    t.transform.rotation.y = q.y();\n    t.transform.rotation.z = q.z();\n    t.transform.rotation.w = q.w();\n    \u002F\u002F 发布消息\n    tf_broadcaster_->sendTransform(t);\n  }\n  rclcpp::Subscription\u003Cturtlesim::msg::Pose>::SharedPtr subscription_;\n  std::unique_ptr\u003Ctf2_ros::TransformBroadcaster> tf_broadcaster_;\n};\n\nint main(int argc, char * argv[])\n{\n  \u002F\u002F 2.初始化 ROS 客户端；\n  rclcpp::init(argc, argv);\n  \u002F\u002F 4.调用 spin 函数，并传入对象指针；\n  rclcpp::spin(std::make_shared\u003CMinimalDynamicFrameBroadcaster>());\n  \u002F\u002F 5.释放资源。\n  rclcpp::shutdown();\n  return 0;\n}\n",[33,2593,2594,2599,2604,2609,2614,2618,2622,2626,2631,2636,2641,2646,2651,2656,2661,2665,2669,2673,2679,2683,2689,2695,2702,2709,2713,2725,2729,2734,2751,2755,2759,2776,2780,2785,2817,2821,2836,2840,2845,2873,2884,2910,2914,2918,2922,2927,2958,2962,2966,2976,2996,3000,3008,3023,3037,3041,3050,3059,3073,3077,3082,3088,3109,3121,3133,3145,3157,3161,3170,3174,3198,3217,3221,3225,3247,3251,3256,3266,3271,3294,3299,3309,3317],{"__ignoreMap":25},[134,2595,2596],{"class":136,"line":137},[134,2597,2598],{"class":147},"\u002F*   \n",[134,2600,2601],{"class":136,"line":144},[134,2602,2603],{"class":147},"  需求：编写动态坐标变换程序，启动 turtlesim_node 以及 turtle_teleop_key 后，该程序可以发布\n",[134,2605,2606],{"class":136,"line":151},[134,2607,2608],{"class":147},"       乌龟坐标系到窗口坐标系的坐标变换，并且键盘控制乌龟运动时，乌龟坐标系与窗口坐标系的相对关系\n",[134,2610,2611],{"class":136,"line":174},[134,2612,2613],{"class":147},"       也会实时更新。\n",[134,2615,2616],{"class":136,"line":179},[134,2617,141],{"emptyLinePlaceholder":140},[134,2619,2620],{"class":136,"line":185},[134,2621,1456],{"class":147},[134,2623,2624],{"class":136,"line":265},[134,2625,1461],{"class":147},[134,2627,2628],{"class":136,"line":467},[134,2629,2630],{"class":147},"    2.初始化 ROS 客户端；\n",[134,2632,2633],{"class":136,"line":479},[134,2634,2635],{"class":147},"    3.定义节点类；\n",[134,2637,2638],{"class":136,"line":488},[134,2639,2640],{"class":147},"      3-1.创建动态坐标变换发布方；\n",[134,2642,2643],{"class":136,"line":496},[134,2644,2645],{"class":147},"      3-2.创建乌龟位姿订阅方；\n",[134,2647,2648],{"class":136,"line":504},[134,2649,2650],{"class":147},"      3-3.根据订阅到的乌龟位姿生成坐标帧并广播。\n",[134,2652,2653],{"class":136,"line":516},[134,2654,2655],{"class":147},"    4.调用 spin 函数，并传入对象指针；\n",[134,2657,2658],{"class":136,"line":528},[134,2659,2660],{"class":147},"    5.释放资源。\n",[134,2662,2663],{"class":136,"line":538},[134,2664,141],{"emptyLinePlaceholder":140},[134,2666,2667],{"class":136,"line":548},[134,2668,1505],{"class":147},[134,2670,2671],{"class":136,"line":1404},[134,2672,1514],{"class":147},[134,2674,2675,2677],{"class":136,"line":1409},[134,2676,1519],{"class":1309},[134,2678,1522],{"class":158},[134,2680,2681],{"class":136,"line":1418},[134,2682,141],{"emptyLinePlaceholder":140},[134,2684,2685,2687],{"class":136,"line":1536},[134,2686,1519],{"class":1309},[134,2688,1533],{"class":158},[134,2690,2691,2693],{"class":136,"line":1544},[134,2692,1519],{"class":1309},[134,2694,1541],{"class":158},[134,2696,2697,2699],{"class":136,"line":1552},[134,2698,1519],{"class":1309},[134,2700,2701],{"class":158}," \u003Ctf2_ros\u002Ftransform_broadcaster.h>\n",[134,2703,2704,2706],{"class":136,"line":1557},[134,2705,1519],{"class":1309},[134,2707,2708],{"class":158}," \u003Cturtlesim\u002Fmsg\u002Fpose.hpp>\n",[134,2710,2711],{"class":136,"line":1575},[134,2712,141],{"emptyLinePlaceholder":140},[134,2714,2715,2717,2719,2721,2723],{"class":136,"line":1580},[134,2716,1560],{"class":1309},[134,2718,1563],{"class":154},[134,2720,1566],{"class":1313},[134,2722,1569],{"class":154},[134,2724,1572],{"class":1313},[134,2726,2727],{"class":136,"line":1586},[134,2728,141],{"emptyLinePlaceholder":140},[134,2730,2731],{"class":136,"line":1608},[134,2732,2733],{"class":147},"\u002F\u002F 3.定义节点类；\n",[134,2735,2736,2738,2741,2743,2745,2747,2749],{"class":136,"line":1614},[134,2737,1589],{"class":1309},[134,2739,2740],{"class":154}," MinimalDynamicFrameBroadcaster",[134,2742,1595],{"class":1313},[134,2744,1598],{"class":1309},[134,2746,878],{"class":154},[134,2748,1566],{"class":1313},[134,2750,1605],{"class":154},[134,2752,2753],{"class":136,"line":1620},[134,2754,1611],{"class":1313},[134,2756,2757],{"class":136,"line":1654},[134,2758,1617],{"class":1309},[134,2760,2761,2764,2767,2769,2771,2774],{"class":136,"line":1660},[134,2762,2763],{"class":154},"  MinimalDynamicFrameBroadcaster",[134,2765,2766],{"class":1313},"(): ",[134,2768,1644],{"class":154},[134,2770,1628],{"class":1313},[134,2772,2773],{"class":158},"\"minimal_dynamic_frame_broadcaster\"",[134,2775,1401],{"class":1313},[134,2777,2778],{"class":136,"line":1666},[134,2779,1657],{"class":1313},[134,2781,2782],{"class":136,"line":1701},[134,2783,2784],{"class":147},"    \u002F\u002F 3-1.创建动态坐标变换发布方；\n",[134,2786,2787,2790,2792,2794,2796,2799,2801,2803,2805,2808,2810,2813,2815],{"class":136,"line":1706},[134,2788,2789],{"class":1313},"    tf_broadcaster_ ",[134,2791,1672],{"class":1309},[134,2793,1563],{"class":154},[134,2795,1566],{"class":1313},[134,2797,2798],{"class":154},"make_unique",[134,2800,1682],{"class":1313},[134,2802,915],{"class":154},[134,2804,1566],{"class":1313},[134,2806,2807],{"class":154},"TransformBroadcaster",[134,2809,1692],{"class":1313},[134,2811,2812],{"class":1309},"*",[134,2814,1695],{"class":524},[134,2816,1698],{"class":1313},[134,2818,2819],{"class":136,"line":1721},[134,2820,141],{"emptyLinePlaceholder":140},[134,2822,2823,2826,2829,2831,2834],{"class":136,"line":1727},[134,2824,2825],{"class":154},"    std",[134,2827,2828],{"class":1313},"::string topic_name ",[134,2830,1672],{"class":1309},[134,2832,2833],{"class":158}," \"\u002Fturtle1\u002Fpose\"",[134,2835,2221],{"class":1313},[134,2837,2838],{"class":136,"line":1732},[134,2839,141],{"emptyLinePlaceholder":140},[134,2841,2842],{"class":136,"line":1738},[134,2843,2844],{"class":147},"    \u002F\u002F 3-2.创建乌龟位姿订阅方；\n",[134,2846,2847,2850,2852,2854,2857,2859,2862,2864,2866,2869,2871],{"class":136,"line":1744},[134,2848,2849],{"class":1313},"    subscription_ ",[134,2851,1672],{"class":1309},[134,2853,1805],{"class":524},[134,2855,2856],{"class":1313},"->create_subscription",[134,2858,1682],{"class":1309},[134,2860,2861],{"class":154},"turtlesim",[134,2863,1566],{"class":1313},[134,2865,1783],{"class":154},[134,2867,2868],{"class":1313},"::Pose",[134,2870,2089],{"class":1309},[134,2872,1942],{"class":1313},[134,2874,2875,2878,2881],{"class":136,"line":1764},[134,2876,2877],{"class":1313},"      topic_name, ",[134,2879,2880],{"class":524},"10",[134,2882,2883],{"class":1313},",\n",[134,2885,2886,2889,2891,2894,2896,2899,2902,2905,2907],{"class":136,"line":1769},[134,2887,2888],{"class":154},"      std",[134,2890,1566],{"class":1313},[134,2892,2893],{"class":154},"bind",[134,2895,1628],{"class":1313},[134,2897,2898],{"class":1309},"&",[134,2900,2901],{"class":154},"MinimalDynamicFrameBroadcaster",[134,2903,2904],{"class":1313},"::handle_turtle_pose, ",[134,2906,1695],{"class":524},[134,2908,2909],{"class":1313},", _1));\n",[134,2911,2912],{"class":136,"line":1775},[134,2913,1724],{"class":1313},[134,2915,2916],{"class":136,"line":1789},[134,2917,141],{"emptyLinePlaceholder":140},[134,2919,2920],{"class":136,"line":1794},[134,2921,1735],{"class":1309},[134,2923,2924],{"class":136,"line":1822},[134,2925,2926],{"class":147},"  \u002F\u002F 3-3.根据订阅到的乌龟位姿生成坐标帧并广播。   \n",[134,2928,2929,2931,2934,2936,2939,2941,2943,2945,2947,2950,2953,2956],{"class":136,"line":1833},[134,2930,1747],{"class":1309},[134,2932,2933],{"class":154}," handle_turtle_pose",[134,2935,1628],{"class":1313},[134,2937,2938],{"class":1309},"const",[134,2940,322],{"class":154},[134,2942,1566],{"class":1313},[134,2944,1783],{"class":154},[134,2946,1566],{"class":1313},[134,2948,2949],{"class":154},"Pose",[134,2951,2952],{"class":1309}," &",[134,2954,2955],{"class":1637}," msg",[134,2957,1401],{"class":1313},[134,2959,2960],{"class":136,"line":1850},[134,2961,1657],{"class":1313},[134,2963,2964],{"class":136,"line":1865},[134,2965,1772],{"class":147},[134,2967,2968,2970,2972,2974],{"class":136,"line":1870},[134,2969,1778],{"class":154},[134,2971,1566],{"class":1313},[134,2973,1783],{"class":154},[134,2975,1786],{"class":1313},[134,2977,2978,2980,2982,2984,2986,2988,2990,2992,2994],{"class":136,"line":1890},[134,2979,1797],{"class":154},[134,2981,1800],{"class":1313},[134,2983,1672],{"class":1309},[134,2985,1805],{"class":524},[134,2987,1712],{"class":1313},[134,2989,1810],{"class":154},[134,2991,1813],{"class":1313},[134,2993,1816],{"class":154},[134,2995,1819],{"class":1313},[134,2997,2998],{"class":136,"line":1907},[134,2999,141],{"emptyLinePlaceholder":140},[134,3001,3002,3004,3006],{"class":136,"line":1924},[134,3003,1825],{"class":1313},[134,3005,1672],{"class":1309},[134,3007,1830],{"class":1313},[134,3009,3010,3012,3014,3017,3020],{"class":136,"line":1933},[134,3011,1836],{"class":1313},[134,3013,1672],{"class":1309},[134,3015,3016],{"class":158}," \"world\"",[134,3018,3019],{"class":1313},";",[134,3021,3022],{"class":147},"   \u002F\u002F窗体坐标系\n",[134,3024,3025,3027,3029,3032,3034],{"class":136,"line":1945},[134,3026,1853],{"class":1313},[134,3028,1672],{"class":1309},[134,3030,3031],{"class":158}," \"turtle1\"",[134,3033,3019],{"class":1313},[134,3035,3036],{"class":147},"  \u002F\u002F乌龟坐标系\n",[134,3038,3039],{"class":136,"line":1959},[134,3040,141],{"emptyLinePlaceholder":140},[134,3042,3043,3045,3047],{"class":136,"line":1971},[134,3044,1873],{"class":1313},[134,3046,1672],{"class":1309},[134,3048,3049],{"class":1313}," msg.x;\n",[134,3051,3052,3054,3056],{"class":136,"line":1984},[134,3053,1893],{"class":1313},[134,3055,1672],{"class":1309},[134,3057,3058],{"class":1313}," msg.y;\n",[134,3060,3061,3063,3065,3068,3070],{"class":136,"line":2000},[134,3062,1910],{"class":1313},[134,3064,1672],{"class":1309},[134,3066,3067],{"class":524}," 0.0",[134,3069,3019],{"class":1313},[134,3071,3072],{"class":147},"      \u002F\u002F乌龟在平面内运动\n",[134,3074,3075],{"class":136,"line":2015},[134,3076,141],{"emptyLinePlaceholder":140},[134,3078,3079],{"class":136,"line":2030},[134,3080,3081],{"class":147},"    \u002F\u002F从欧拉角转换为四元数\n",[134,3083,3084,3086],{"class":136,"line":2045},[134,3085,1927],{"class":154},[134,3087,1930],{"class":1313},[134,3089,3090,3092,3094,3096,3099,3101,3103,3106],{"class":136,"line":2050},[134,3091,1936],{"class":1313},[134,3093,1939],{"class":154},[134,3095,1628],{"class":1313},[134,3097,3098],{"class":524},"0",[134,3100,2122],{"class":1313},[134,3102,3098],{"class":524},[134,3104,3105],{"class":1313},", msg.theta);",[134,3107,3108],{"class":147},"        \u002F\u002F乌龟只有Yaw\n",[134,3110,3111,3113,3115,3117,3119],{"class":136,"line":2056},[134,3112,1987],{"class":1313},[134,3114,1672],{"class":1309},[134,3116,1992],{"class":1313},[134,3118,1995],{"class":154},[134,3120,1819],{"class":1313},[134,3122,3123,3125,3127,3129,3131],{"class":136,"line":2068},[134,3124,2003],{"class":1313},[134,3126,1672],{"class":1309},[134,3128,1992],{"class":1313},[134,3130,2010],{"class":154},[134,3132,1819],{"class":1313},[134,3134,3135,3137,3139,3141,3143],{"class":136,"line":2073},[134,3136,2018],{"class":1313},[134,3138,1672],{"class":1309},[134,3140,1992],{"class":1313},[134,3142,2025],{"class":154},[134,3144,1819],{"class":1313},[134,3146,3147,3149,3151,3153,3155],{"class":136,"line":2095},[134,3148,2033],{"class":1313},[134,3150,1672],{"class":1309},[134,3152,1992],{"class":1313},[134,3154,2040],{"class":154},[134,3156,1819],{"class":1313},[134,3158,3159],{"class":136,"line":2101},[134,3160,2053],{"class":147},[134,3162,3163,3166,3168],{"class":136,"line":2106},[134,3164,3165],{"class":1313},"    tf_broadcaster_->",[134,3167,2062],{"class":154},[134,3169,2065],{"class":1313},[134,3171,3172],{"class":136,"line":2134},[134,3173,1724],{"class":1313},[134,3175,3176,3178,3180,3183,3185,3187,3189,3191,3193,3195],{"class":136,"line":2139},[134,3177,2243],{"class":154},[134,3179,1566],{"class":1313},[134,3181,3182],{"class":154},"Subscription",[134,3184,1682],{"class":1313},[134,3186,2861],{"class":154},[134,3188,1566],{"class":1313},[134,3190,1783],{"class":154},[134,3192,1566],{"class":1313},[134,3194,2949],{"class":154},[134,3196,3197],{"class":1313},">::SharedPtr subscription_;\n",[134,3199,3200,3202,3205,3207,3209,3212,3214],{"class":136,"line":2145},[134,3201,2076],{"class":154},[134,3203,3204],{"class":1313},"::unique_ptr",[134,3206,1682],{"class":1309},[134,3208,915],{"class":154},[134,3210,3211],{"class":1313},"::TransformBroadcaster",[134,3213,2089],{"class":1309},[134,3215,3216],{"class":1313}," tf_broadcaster_;\n",[134,3218,3219],{"class":136,"line":2170},[134,3220,2098],{"class":1313},[134,3222,3223],{"class":136,"line":2175},[134,3224,141],{"emptyLinePlaceholder":140},[134,3226,3227,3229,3231,3233,3235,3237,3239,3241,3243,3245],{"class":136,"line":2193},[134,3228,2109],{"class":1309},[134,3230,2112],{"class":154},[134,3232,1628],{"class":1313},[134,3234,2109],{"class":1309},[134,3236,2119],{"class":1637},[134,3238,2122],{"class":1313},[134,3240,1631],{"class":1309},[134,3242,1634],{"class":1309},[134,3244,2129],{"class":1637},[134,3246,1761],{"class":1313},[134,3248,3249],{"class":136,"line":2201},[134,3250,1611],{"class":1313},[134,3252,3253],{"class":136,"line":2212},[134,3254,3255],{"class":147},"  \u002F\u002F 2.初始化 ROS 客户端；\n",[134,3257,3258,3260,3262,3264],{"class":136,"line":2224},[134,3259,2243],{"class":154},[134,3261,1566],{"class":1313},[134,3263,2248],{"class":154},[134,3265,2251],{"class":1313},[134,3267,3268],{"class":136,"line":2229},[134,3269,3270],{"class":147},"  \u002F\u002F 4.调用 spin 函数，并传入对象指针；\n",[134,3272,3273,3275,3277,3279,3281,3283,3285,3287,3289,3291],{"class":136,"line":2234},[134,3274,2243],{"class":154},[134,3276,1566],{"class":1313},[134,3278,2267],{"class":154},[134,3280,1628],{"class":1313},[134,3282,2272],{"class":154},[134,3284,1566],{"class":1313},[134,3286,1679],{"class":154},[134,3288,1682],{"class":1313},[134,3290,2901],{"class":154},[134,3292,3293],{"class":1313},">());\n",[134,3295,3296],{"class":136,"line":2240},[134,3297,3298],{"class":147},"  \u002F\u002F 5.释放资源。\n",[134,3300,3301,3303,3305,3307],{"class":136,"line":2254},[134,3302,2243],{"class":154},[134,3304,1566],{"class":1313},[134,3306,2300],{"class":154},[134,3308,1819],{"class":1313},[134,3310,3311,3313,3315],{"class":136,"line":2260},[134,3312,2308],{"class":1309},[134,3314,1207],{"class":524},[134,3316,2221],{"class":1313},[134,3318,3319],{"class":136,"line":2287},[134,3320,2318],{"class":1313},[20,3322,3323],{},[23,3324],{"alt":25,"src":3325},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1305.webp",[20,3327,3328],{},"入口参数：",[20,3330,3331],{},"参数1话题名称",[20,3333,3334],{},"参数2QoS",[20,3336,3337],{},"参数3回调函数",[20,3339,3340],{},[23,3341],{"alt":25,"src":3342},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1306.webp",[20,3344,3345],{},[23,3346],{"alt":25,"src":3347},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1307.webp",[20,3349,3350],{},[23,3351],{"alt":25,"src":3352},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1308.webp",[20,3354,3355],{},"操控乌龟运动，会使乌龟在Rviz2里也运动",[20,3357,3358],{},[23,3359],{"alt":25,"src":3360},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1309.webp",[16,3362,3364],{"id":3363},"坐标点发布_c实现","坐标点发布_C++实现",[359,3366,3367],{"id":3367},"案例与分析",[20,3369,3370],{},[30,3371,3372],{},"案例需求",[20,3374,3375,3378],{},[30,3376,3377],{},"案例："," 无人车上安装有激光雷达，现激光雷达扫描到一点状障碍物并且可以定位障碍物的坐标，请在雷达坐标系下发布障碍物坐标点数据，并在 rviz2 中查看发布结果。",[20,3380,3381],{},[23,3382],{"alt":25,"src":3383},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1310.webp",[20,3385,3386],{},[30,3387,3388],{},"案例分析",[20,3390,3391,3392,3394],{},"上述案例，是一个简单的话题发布程序，在了解坐标点",[33,3393,353],{},"接口消息之后，直接通过话题发布方按照一定逻辑发布消息即可。",[20,3396,3397],{},[30,3398,3399],{},"流程简介",[20,3401,3402],{},"程序实现主要步骤如下：",[803,3404,3405,3408,3410,3412,3414],{},[806,3406,3407],{},"编写话题发布实现；",[806,3409,826],{},[806,3411,829],{},[806,3413,832],{},[806,3415,3416],{},"在 rviz2 中查看运行结果。",[20,3418,838],{},[20,3420,2514],{},[126,3422,3424],{"className":1300,"code":3423,"language":1302,"meta":25,"style":25},"add_executable(demo03_point_publisher src\u002Fdemo03_point_publisher.cpp)\nament_target_dependencies(\n  demo03_point_publisher\n  \"rclcpp\"\n  \"tf2\"\n  \"tf2_ros\"\n  \"geometry_msgs\"\n  \"turtlesim\"\n)\n",[33,3425,3426,3433,3437,3442,3446,3450,3454,3458,3462],{"__ignoreMap":25},[134,3427,3428,3430],{"class":136,"line":137},[134,3429,1358],{"class":1309},[134,3431,3432],{"class":1313},"(demo03_point_publisher src\u002Fdemo03_point_publisher.cpp)\n",[134,3434,3435],{"class":136,"line":144},[134,3436,1366],{"class":1313},[134,3438,3439],{"class":136,"line":151},[134,3440,3441],{"class":1313},"  demo03_point_publisher\n",[134,3443,3444],{"class":136,"line":174},[134,3445,1376],{"class":158},[134,3447,3448],{"class":136,"line":179},[134,3449,1381],{"class":158},[134,3451,3452],{"class":136,"line":185},[134,3453,1386],{"class":158},[134,3455,3456],{"class":136,"line":265},[134,3457,1391],{"class":158},[134,3459,3460],{"class":136,"line":467},[134,3461,1396],{"class":158},[134,3463,3464],{"class":136,"line":479},[134,3465,1401],{"class":1313},[20,3467,2562],{},[126,3469,3471],{"className":1300,"code":3470,"language":1302,"meta":25,"style":25},"install(TARGETS demo01_static_tf_broadcaster\n  demo02_dynamic_tf_broadcaster\n  demo03_point_publisher\n  DESTINATION lib\u002F${PROJECT_NAME})\n",[33,3472,3473,3479,3483,3487],{"__ignoreMap":25},[134,3474,3475,3477],{"class":136,"line":137},[134,3476,1412],{"class":1309},[134,3478,1415],{"class":1313},[134,3480,3481],{"class":136,"line":144},[134,3482,2535],{"class":1313},[134,3484,3485],{"class":136,"line":151},[134,3486,3441],{"class":1313},[134,3488,3489,3491,3493],{"class":136,"line":174},[134,3490,1421],{"class":1313},[134,3492,1424],{"class":1309},[134,3494,1401],{"class":1313},[359,3496,3497],{"id":3497},"实现",[126,3499,3501],{"className":1432,"code":3500,"language":1434,"meta":25,"style":25},"\u002F*  \n    需求：发布雷达坐标系中某个坐标点相对于雷达（laser）坐标系的位姿。\n    步骤：\n        1.包含头文件；\n        2.初始化 ROS 客户端；\n        3.定义节点类；\n            3-1.创建坐标点发布方；\n            3-2.创建定时器；\n            3-3.组织并发布坐标点消息。\n        4.调用 spin 函数，并传入对象指针；\n        5.释放资源。\n\n*\u002F\n\u002F\u002F 1.包含头文件；\n#include \"rclcpp\u002Frclcpp.hpp\"\n#include \"geometry_msgs\u002Fmsg\u002Fpoint_stamped.hpp\"\n\nusing namespace std::chrono_literals;\n\n\u002F\u002F 3.定义节点类；\nclass MinimalPointPublisher: public rclcpp::Node {\npublic:\n    MinimalPointPublisher(): Node(\"minimal_point_publisher\"),x(0.1){\n        \u002F\u002F 3-1.创建坐标点发布方；\n        point_pub_ = this->create_publisher\u003Cgeometry_msgs::msg::PointStamped>(\"point\",10);\n        \u002F\u002F 3-2.创建定时器；\n        timer_ = this->create_wall_timer(0.1s,std::bind(&MinimalPointPublisher::on_timer, this));\n    }\nprivate:\n    void on_timer(){\n        \u002F\u002F 3-3.组织并发布坐标点消息。\n        geometry_msgs::msg::PointStamped point;\n        point.header.frame_id = \"laser\";\n        point.header.stamp = this->now();\n        x += 0.004;\n        point.point.x = x;\n        point.point.y = 0.0;\n        point.point.z = 0.1;        \n        point_pub_->publish(point);\n    }\n    rclcpp::Publisher\u003Cgeometry_msgs::msg::PointStamped>::SharedPtr point_pub_;\n    rclcpp::TimerBase::SharedPtr timer_;\n    double_t x;\n};\n\nint main(int argc, char const *argv[])\n{\n    \u002F\u002F 2.初始化 ROS 客户端；\n    rclcpp::init(argc,argv);\n    \u002F\u002F 4.调用 spin 函数，并传入对象指针；\n    rclcpp::spin(std::make_shared\u003CMinimalPointPublisher>());\n    \u002F\u002F 5.释放资源。\n    rclcpp::shutdown();\n    return 0;\n}\n",[33,3502,3503,3507,3512,3517,3522,3527,3532,3537,3542,3547,3552,3557,3561,3565,3569,3576,3583,3587,3603,3607,3611,3632,3636,3663,3668,3706,3711,3755,3760,3764,3775,3780,3792,3804,3819,3832,3842,3853,3866,3877,3881,3906,3918,3925,3929,3933,3959,3963,3968,3979,3984,4006,4011,4021,4029],{"__ignoreMap":25},[134,3504,3505],{"class":136,"line":137},[134,3506,1441],{"class":147},[134,3508,3509],{"class":136,"line":144},[134,3510,3511],{"class":147},"    需求：发布雷达坐标系中某个坐标点相对于雷达（laser）坐标系的位姿。\n",[134,3513,3514],{"class":136,"line":151},[134,3515,3516],{"class":147},"    步骤：\n",[134,3518,3519],{"class":136,"line":174},[134,3520,3521],{"class":147},"        1.包含头文件；\n",[134,3523,3524],{"class":136,"line":179},[134,3525,3526],{"class":147},"        2.初始化 ROS 客户端；\n",[134,3528,3529],{"class":136,"line":185},[134,3530,3531],{"class":147},"        3.定义节点类；\n",[134,3533,3534],{"class":136,"line":265},[134,3535,3536],{"class":147},"            3-1.创建坐标点发布方；\n",[134,3538,3539],{"class":136,"line":467},[134,3540,3541],{"class":147},"            3-2.创建定时器；\n",[134,3543,3544],{"class":136,"line":479},[134,3545,3546],{"class":147},"            3-3.组织并发布坐标点消息。\n",[134,3548,3549],{"class":136,"line":488},[134,3550,3551],{"class":147},"        4.调用 spin 函数，并传入对象指针；\n",[134,3553,3554],{"class":136,"line":496},[134,3555,3556],{"class":147},"        5.释放资源。\n",[134,3558,3559],{"class":136,"line":504},[134,3560,141],{"emptyLinePlaceholder":140},[134,3562,3563],{"class":136,"line":516},[134,3564,1505],{"class":147},[134,3566,3567],{"class":136,"line":528},[134,3568,1514],{"class":147},[134,3570,3571,3573],{"class":136,"line":538},[134,3572,1519],{"class":1309},[134,3574,3575],{"class":158}," \"rclcpp\u002Frclcpp.hpp\"\n",[134,3577,3578,3580],{"class":136,"line":548},[134,3579,1519],{"class":1309},[134,3581,3582],{"class":158}," \"geometry_msgs\u002Fmsg\u002Fpoint_stamped.hpp\"\n",[134,3584,3585],{"class":136,"line":1404},[134,3586,141],{"emptyLinePlaceholder":140},[134,3588,3589,3591,3594,3596,3598,3601],{"class":136,"line":1409},[134,3590,1560],{"class":1309},[134,3592,3593],{"class":1309}," namespace",[134,3595,1563],{"class":154},[134,3597,1566],{"class":1313},[134,3599,3600],{"class":154},"chrono_literals",[134,3602,2221],{"class":1313},[134,3604,3605],{"class":136,"line":1418},[134,3606,141],{"emptyLinePlaceholder":140},[134,3608,3609],{"class":136,"line":1536},[134,3610,2733],{"class":147},[134,3612,3613,3615,3618,3621,3623,3625,3627,3629],{"class":136,"line":1544},[134,3614,1589],{"class":1309},[134,3616,3617],{"class":154}," MinimalPointPublisher",[134,3619,3620],{"class":1313},": ",[134,3622,1598],{"class":1309},[134,3624,878],{"class":154},[134,3626,1566],{"class":1313},[134,3628,1644],{"class":154},[134,3630,3631],{"class":1313}," {\n",[134,3633,3634],{"class":136,"line":1552},[134,3635,1617],{"class":1309},[134,3637,3638,3641,3643,3645,3647,3650,3653,3655,3657,3660],{"class":136,"line":1557},[134,3639,3640],{"class":154},"    MinimalPointPublisher",[134,3642,2766],{"class":1313},[134,3644,1644],{"class":154},[134,3646,1628],{"class":1313},[134,3648,3649],{"class":158},"\"minimal_point_publisher\"",[134,3651,3652],{"class":1313},"),",[134,3654,1995],{"class":154},[134,3656,1628],{"class":1313},[134,3658,3659],{"class":524},"0.1",[134,3661,3662],{"class":1313},"){\n",[134,3664,3665],{"class":136,"line":1575},[134,3666,3667],{"class":147},"        \u002F\u002F 3-1.创建坐标点发布方；\n",[134,3669,3670,3673,3675,3677,3680,3682,3685,3687,3689,3692,3694,3696,3699,3702,3704],{"class":136,"line":1580},[134,3671,3672],{"class":1313},"        point_pub_ ",[134,3674,1672],{"class":1309},[134,3676,1805],{"class":524},[134,3678,3679],{"class":1313},"->create_publisher",[134,3681,1682],{"class":1309},[134,3683,3684],{"class":154},"geometry_msgs",[134,3686,1566],{"class":1313},[134,3688,1783],{"class":154},[134,3690,3691],{"class":1313},"::PointStamped",[134,3693,2089],{"class":1309},[134,3695,1628],{"class":1313},[134,3697,3698],{"class":158},"\"point\"",[134,3700,3701],{"class":1313},",",[134,3703,2880],{"class":524},[134,3705,1698],{"class":1313},[134,3707,3708],{"class":136,"line":1586},[134,3709,3710],{"class":147},"        \u002F\u002F 3-2.创建定时器；\n",[134,3712,3713,3716,3718,3720,3722,3725,3727,3729,3732,3734,3736,3738,3740,3742,3744,3747,3750,3752],{"class":136,"line":1608},[134,3714,3715],{"class":1313},"        timer_ ",[134,3717,1672],{"class":1309},[134,3719,1805],{"class":524},[134,3721,1712],{"class":1313},[134,3723,3724],{"class":154},"create_wall_timer",[134,3726,1628],{"class":1313},[134,3728,3659],{"class":524},[134,3730,3731],{"class":1309},"s",[134,3733,3701],{"class":1313},[134,3735,2272],{"class":154},[134,3737,1566],{"class":1313},[134,3739,2893],{"class":154},[134,3741,1628],{"class":1313},[134,3743,2898],{"class":1309},[134,3745,3746],{"class":154},"MinimalPointPublisher",[134,3748,3749],{"class":1313},"::on_timer, ",[134,3751,1695],{"class":524},[134,3753,3754],{"class":1313},"));\n",[134,3756,3757],{"class":136,"line":1614},[134,3758,3759],{"class":1313},"    }\n",[134,3761,3762],{"class":136,"line":1620},[134,3763,1735],{"class":1309},[134,3765,3766,3769,3772],{"class":136,"line":1654},[134,3767,3768],{"class":1309},"    void",[134,3770,3771],{"class":154}," on_timer",[134,3773,3774],{"class":1313},"(){\n",[134,3776,3777],{"class":136,"line":1660},[134,3778,3779],{"class":147},"        \u002F\u002F 3-3.组织并发布坐标点消息。\n",[134,3781,3782,3785,3787,3789],{"class":136,"line":1666},[134,3783,3784],{"class":154},"        geometry_msgs",[134,3786,1566],{"class":1313},[134,3788,1783],{"class":154},[134,3790,3791],{"class":1313},"::PointStamped point;\n",[134,3793,3794,3797,3799,3802],{"class":136,"line":1701},[134,3795,3796],{"class":1313},"        point.header.frame_id ",[134,3798,1672],{"class":1309},[134,3800,3801],{"class":158}," \"laser\"",[134,3803,2221],{"class":1313},[134,3805,3806,3809,3811,3813,3815,3817],{"class":136,"line":1706},[134,3807,3808],{"class":1313},"        point.header.stamp ",[134,3810,1672],{"class":1309},[134,3812,1805],{"class":524},[134,3814,1712],{"class":1313},[134,3816,1816],{"class":154},[134,3818,1819],{"class":1313},[134,3820,3821,3824,3827,3830],{"class":136,"line":1721},[134,3822,3823],{"class":1313},"        x ",[134,3825,3826],{"class":1309},"+=",[134,3828,3829],{"class":524}," 0.004",[134,3831,2221],{"class":1313},[134,3833,3834,3837,3839],{"class":136,"line":1727},[134,3835,3836],{"class":1313},"        point.point.x ",[134,3838,1672],{"class":1309},[134,3840,3841],{"class":1313}," x;\n",[134,3843,3844,3847,3849,3851],{"class":136,"line":1732},[134,3845,3846],{"class":1313},"        point.point.y ",[134,3848,1672],{"class":1309},[134,3850,3067],{"class":524},[134,3852,2221],{"class":1313},[134,3854,3855,3858,3860,3863],{"class":136,"line":1738},[134,3856,3857],{"class":1313},"        point.point.z ",[134,3859,1672],{"class":1309},[134,3861,3862],{"class":524}," 0.1",[134,3864,3865],{"class":1313},";        \n",[134,3867,3868,3871,3874],{"class":136,"line":1744},[134,3869,3870],{"class":1313},"        point_pub_->",[134,3872,3873],{"class":154},"publish",[134,3875,3876],{"class":1313},"(point);\n",[134,3878,3879],{"class":136,"line":1764},[134,3880,3759],{"class":1313},[134,3882,3883,3885,3887,3890,3892,3894,3896,3898,3900,3903],{"class":136,"line":1769},[134,3884,1797],{"class":154},[134,3886,1566],{"class":1313},[134,3888,3889],{"class":154},"Publisher",[134,3891,1682],{"class":1313},[134,3893,3684],{"class":154},[134,3895,1566],{"class":1313},[134,3897,1783],{"class":154},[134,3899,1566],{"class":1313},[134,3901,3902],{"class":154},"PointStamped",[134,3904,3905],{"class":1313},">::SharedPtr point_pub_;\n",[134,3907,3908,3910,3912,3915],{"class":136,"line":1775},[134,3909,1797],{"class":154},[134,3911,1566],{"class":1313},[134,3913,3914],{"class":154},"TimerBase",[134,3916,3917],{"class":1313},"::SharedPtr timer_;\n",[134,3919,3920,3923],{"class":136,"line":1789},[134,3921,3922],{"class":524},"    double_t",[134,3924,3841],{"class":1313},[134,3926,3927],{"class":136,"line":1794},[134,3928,2098],{"class":1313},[134,3930,3931],{"class":136,"line":1822},[134,3932,141],{"emptyLinePlaceholder":140},[134,3934,3935,3937,3939,3941,3943,3945,3947,3949,3952,3954,3957],{"class":136,"line":1833},[134,3936,2109],{"class":1309},[134,3938,2112],{"class":154},[134,3940,1628],{"class":1313},[134,3942,2109],{"class":1309},[134,3944,2119],{"class":1637},[134,3946,2122],{"class":1313},[134,3948,1631],{"class":1309},[134,3950,3951],{"class":1309}," const",[134,3953,1634],{"class":1309},[134,3955,3956],{"class":1637},"argv",[134,3958,1761],{"class":1313},[134,3960,3961],{"class":136,"line":1850},[134,3962,1611],{"class":1313},[134,3964,3965],{"class":136,"line":1865},[134,3966,3967],{"class":147},"    \u002F\u002F 2.初始化 ROS 客户端；\n",[134,3969,3970,3972,3974,3976],{"class":136,"line":1870},[134,3971,1797],{"class":154},[134,3973,1566],{"class":1313},[134,3975,2248],{"class":154},[134,3977,3978],{"class":1313},"(argc,argv);\n",[134,3980,3981],{"class":136,"line":1890},[134,3982,3983],{"class":147},"    \u002F\u002F 4.调用 spin 函数，并传入对象指针；\n",[134,3985,3986,3988,3990,3992,3994,3996,3998,4000,4002,4004],{"class":136,"line":1907},[134,3987,1797],{"class":154},[134,3989,1566],{"class":1313},[134,3991,2267],{"class":154},[134,3993,1628],{"class":1313},[134,3995,2272],{"class":154},[134,3997,1566],{"class":1313},[134,3999,1679],{"class":154},[134,4001,1682],{"class":1313},[134,4003,3746],{"class":154},[134,4005,3293],{"class":1313},[134,4007,4008],{"class":136,"line":1924},[134,4009,4010],{"class":147},"    \u002F\u002F 5.释放资源。\n",[134,4012,4013,4015,4017,4019],{"class":136,"line":1933},[134,4014,1797],{"class":154},[134,4016,1566],{"class":1313},[134,4018,2300],{"class":154},[134,4020,1819],{"class":1313},[134,4022,4023,4025,4027],{"class":136,"line":1945},[134,4024,2215],{"class":1309},[134,4026,1207],{"class":524},[134,4028,2221],{"class":1313},[134,4030,4031],{"class":136,"line":1959},[134,4032,2318],{"class":1313},[20,4034,4035],{},[23,4036],{"alt":25,"src":4037},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1311.webp",[20,4039,4040],{},"创建定时器用create_wall_time()函数，要填时间间隔和对应的回调函数。",[20,4042,4043],{},[23,4044],{"alt":25,"src":4045},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1312.webp",[20,4047,4048],{},[30,4049,4050],{},"执行",[20,4052,2404],{},[126,4054,4055],{"className":128,"code":2407,"language":130,"meta":25,"style":25},[33,4056,4057,4065],{"__ignoreMap":25},[134,4058,4059,4061,4063],{"class":136,"line":137},[134,4060,2414],{"class":524},[134,4062,2417],{"class":158},[134,4064,2420],{"class":1313},[134,4066,4067,4069,4071,4073,4075,4077,4079,4081,4083,4085,4087,4089],{"class":136,"line":144},[134,4068,292],{"class":154},[134,4070,319],{"class":158},[134,4072,866],{"class":158},[134,4074,2431],{"class":158},[134,4076,1202],{"class":524},[134,4078,1207],{"class":524},[134,4080,1212],{"class":524},[134,4082,1207],{"class":524},[134,4084,1207],{"class":524},[134,4086,1207],{"class":524},[134,4088,1122],{"class":158},[134,4090,1127],{"class":158},[20,4092,4093],{},"终端2输入如下命令发布障碍物相对于雷达（laser）的坐标点：",[126,4095,4097],{"className":128,"code":4096,"language":130,"meta":25,"style":25},". install\u002Fsetup.bash \nros2 run cpp03_tf_broadcaster demo03_point_publisher\n",[33,4098,4099,4107],{"__ignoreMap":25},[134,4100,4101,4103,4105],{"class":136,"line":137},[134,4102,2414],{"class":524},[134,4104,2417],{"class":158},[134,4106,2420],{"class":1313},[134,4108,4109,4111,4113,4115],{"class":136,"line":144},[134,4110,292],{"class":154},[134,4112,319],{"class":158},[134,4114,866],{"class":158},[134,4116,4117],{"class":158}," demo03_point_publisher\n",[20,4119,4120],{},[30,4121,4122],{},"rviz2 查看坐标系关系",[20,4124,2450,4125,4128],{},[30,4126,4127],{},"5.3.2 静态广播器（命令）"," 内容启动并配置 rviz2，显示坐标变换后，再添加 PointStamped 插件并将其话题设置为 \u002Fpoint，最终显示结果与案例演示类似。",[20,4130,4131],{},[23,4132],{"alt":25,"src":4133},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1313.webp",[20,4135,4136],{},[23,4137],{"alt":25,"src":4138},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1314.webp",[20,4140,4141],{},"通过这里可以改球的透明度和大小",[16,4143,4144],{"id":4144},"小结",[20,4146,4147],{},[23,4148],{"alt":25,"src":4149},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1315.webp",[20,4151,4152],{},"静态广播只发布一次。",[20,4154,4155],{},"而动态广播和坐标点广播都是发布多次。",[20,4157,4158],{},"但实质上就是话题通信。",[12,4160,4161],{"id":4161},"坐标变换监听",[16,4163,3367],{"id":4164},"案例与分析-1",[20,4166,4167,4169,4170,4173],{},[30,4168,777],{}," 在 ",[30,4171,4172],{},"5.3 坐标变换广播"," 中发布了laser相对于base_link和camra相对于base_link的坐标系关系，请求解laser相对于camera的坐标系关系。",[20,4175,4176],{},[23,4177],{"alt":25,"src":4178},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1316.webp",[20,4180,4181,4169,4183,4185],{},[30,4182,788],{},[30,4184,4172],{}," 中发布了laser相对于base_link的坐标系关系且发布了laser坐标系下的障碍物的坐标点数据，请求解base_link坐标系下该障碍物的坐标。",[20,4187,4188],{},[23,4189],{"alt":25,"src":4190},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1317.webp",[20,4192,4193],{},[30,4194,3388],{},[20,4196,4197],{},"在上述案例中，案例1是多坐标系的场景下实现不同坐标系之间的变换，案例2则是要实现同一坐标点在不同坐标系下的变换，虽然需求不同，但是相关算法都被封装好了，我们只需要调用相关 API 即可。",[20,4199,4200],{},[30,4201,3399],{},[20,4203,4204],{},"两个案例的实现流程类似，主要步骤如下：",[803,4206,4207,4210,4212,4214],{},[806,4208,4209],{},"编写坐标变换程序实现；",[806,4211,826],{},[806,4213,829],{},[806,4215,4216],{},"执行。",[20,4218,838],{},[20,4220,4221],{},[30,4222,4223],{},"准备工作",[20,4225,4226],{},"终端下进入工作空间的src目录，调用如下两条命令分别创建C++功能包和Python功能包。",[126,4228,4230],{"className":128,"code":4229,"language":130,"meta":25,"style":25},"ros2 pkg create cpp04_tf_listener --build-type ament_cmake --dependencies rclcpp tf2 tf2_ros geometry_msgs --node-name demo01_tf_listener\n",[33,4231,4232],{"__ignoreMap":25},[134,4233,4234,4236,4238,4240,4243,4245,4247,4249,4251,4253,4255,4257,4260],{"class":136,"line":137},[134,4235,292],{"class":154},[134,4237,860],{"class":158},[134,4239,863],{"class":158},[134,4241,4242],{"class":158}," cpp04_tf_listener",[134,4244,869],{"class":524},[134,4246,872],{"class":158},[134,4248,875],{"class":524},[134,4250,878],{"class":158},[134,4252,881],{"class":158},[134,4254,884],{"class":158},[134,4256,887],{"class":158},[134,4258,4259],{"class":524}," --node-name",[134,4261,4262],{"class":158}," demo01_tf_listener\n",[16,4264,4266,4267,4270],{"id":4265},"坐标-系-变换监听_c","坐标 ",[30,4268,4269],{},"系"," 变换监听_C++",[359,4272,4273],{"id":4273},"实例分析",[20,4275,4276],{},[23,4277],{"alt":25,"src":4278},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1318.webp",[20,4280,4281],{},"与之前实现不太一样，要保存到buffer中。",[20,4283,4284],{},[23,4285],{"alt":25,"src":4286},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1319.webp",[20,4288,4289],{},"因为之前的广播是发一条订阅一条。",[20,4291,4292],{},"但是在坐标变换中，是多对一实现的。",[20,4294,4295],{},"多个广播发布的消息组成一个坐标树，要从坐标树中获取不同坐标帧的变换。",[20,4297,4298],{},"把多条广播方的消息组成坐标树，就要使用buffer，把消息全部存到缓存buffer中。",[20,4300,4301],{},[23,4302],{"alt":25,"src":4303},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1320.webp",[20,4305,4306],{},"这里为何要做异常处理呢？",[20,4308,4309],{},"因为进程间的通信开销比较大，是有延迟的，可能程序要开始做变换了，可惜消息还没订阅到。",[20,4311,4312],{},"消息都没有，就会抛异常。直到buffer里有数据，坐标也转化成功，才不会抛异常。",[359,4314,3497],{"id":4315},"实现-1",[126,4317,4319],{"className":1432,"code":4318,"language":1434,"meta":25,"style":25},"\u002F*  \n  需求：订阅 laser 到 base_link 以及 camera 到 base_link 的坐标系关系，\n       并生成 laser 到 camera 的坐标变换。\n  步骤：\n    1.包含头文件；\n    2.初始化 ROS 客户端；\n    3.定义节点类；\n      3-1.创建tf缓存对象指针；融合多个坐标系相对关系为一棵坐标树。\n      3-2.创建tf监听器；指定缓存对象，会将所有广播器广播的数据写入缓存。\n      3-3.编写定时器，循环实现转换；按照条件查找符合条件的坐标系并生成变换后的坐标帧。\n    4.调用 spin 函数，并传入对象指针；\n    5.释放资源。\n\n*\u002F\n#include \"rclcpp\u002Frclcpp.hpp\"\n#include \"tf2_ros\u002Ftransform_listener.h\"\n#include \"tf2_ros\u002Fbuffer.h\"\n#include \"tf2\u002FLinearMath\u002FQuaternion.h\"\n\nusing namespace std::chrono_literals;\n\n\u002F\u002F 3.定义节点类；\nclass MinimalFrameListener : public rclcpp::Node {\npublic:\n  MinimalFrameListener():Node(\"minimal_frame_listener\"){\n    tf_buffer_ = std::make_unique\u003Ctf2_ros::Buffer>(this->get_clock());\n    transform_listener_ = std::make_shared\u003Ctf2_ros::TransformListener>(*tf_buffer_);\n    timer_ = this->create_wall_timer(1s, std::bind(&MinimalFrameListener::on_timer,this));\n  }\n\nprivate:\n  void on_timer(){\n    try\n    {\n      auto transformStamped = tf_buffer_->lookupTransform(\"camera\",\"laser\",tf2::TimePointZero);\n      RCLCPP_INFO(this->get_logger(),\"----------------------转换结果----------------------\");\n      RCLCPP_INFO(this->get_logger(),\"frame_id:%s\",transformStamped.header.frame_id.c_str());\n      RCLCPP_INFO(this->get_logger(),\"child_frame_id:%s\",transformStamped.child_frame_id.c_str());\n      RCLCPP_INFO(this->get_logger(),\"坐标:(%.2f,%.2f,%.2f)\",\n                transformStamped.transform.translation.x,\n                transformStamped.transform.translation.y,\n                transformStamped.transform.translation.z);\n\n    }\n    catch(const tf2::LookupException& e)\n    {\n      RCLCPP_INFO(this->get_logger(),\"坐标变换异常：%s\",e.what());\n    }\n\n  }\n  rclcpp::TimerBase::SharedPtr timer_;\n  std::shared_ptr\u003Ctf2_ros::TransformListener> transform_listener_;\n  std::unique_ptr\u003Ctf2_ros::Buffer> tf_buffer_;\n};\n\nint main(int argc, char const *argv[])\n{\n  \u002F\u002F 2.初始化 ROS 客户端；\n  rclcpp::init(argc,argv);\n  \u002F\u002F 4.调用 spin 函数，并传入对象指针；\n  rclcpp::spin(std::make_shared\u003CMinimalFrameListener>());\n  \u002F\u002F 5.释放资源。\n  rclcpp::shutdown();\n  return 0;\n}\n",[33,4320,4321,4325,4330,4335,4339,4343,4347,4351,4356,4361,4366,4370,4374,4378,4382,4388,4395,4402,4409,4413,4427,4431,4435,4454,4458,4475,4508,4537,4578,4582,4586,4590,4598,4603,4608,4642,4663,4694,4722,4755,4760,4765,4770,4774,4778,4797,4801,4830,4834,4838,4842,4852,4870,4888,4892,4896,4920,4924,4928,4938,4942,4964,4968,4978,4986],{"__ignoreMap":25},[134,4322,4323],{"class":136,"line":137},[134,4324,1441],{"class":147},[134,4326,4327],{"class":136,"line":144},[134,4328,4329],{"class":147},"  需求：订阅 laser 到 base_link 以及 camera 到 base_link 的坐标系关系，\n",[134,4331,4332],{"class":136,"line":151},[134,4333,4334],{"class":147},"       并生成 laser 到 camera 的坐标变换。\n",[134,4336,4337],{"class":136,"line":174},[134,4338,1456],{"class":147},[134,4340,4341],{"class":136,"line":179},[134,4342,1461],{"class":147},[134,4344,4345],{"class":136,"line":185},[134,4346,2630],{"class":147},[134,4348,4349],{"class":136,"line":265},[134,4350,2635],{"class":147},[134,4352,4353],{"class":136,"line":467},[134,4354,4355],{"class":147},"      3-1.创建tf缓存对象指针；融合多个坐标系相对关系为一棵坐标树。\n",[134,4357,4358],{"class":136,"line":479},[134,4359,4360],{"class":147},"      3-2.创建tf监听器；指定缓存对象，会将所有广播器广播的数据写入缓存。\n",[134,4362,4363],{"class":136,"line":488},[134,4364,4365],{"class":147},"      3-3.编写定时器，循环实现转换；按照条件查找符合条件的坐标系并生成变换后的坐标帧。\n",[134,4367,4368],{"class":136,"line":496},[134,4369,2655],{"class":147},[134,4371,4372],{"class":136,"line":504},[134,4373,2660],{"class":147},[134,4375,4376],{"class":136,"line":516},[134,4377,141],{"emptyLinePlaceholder":140},[134,4379,4380],{"class":136,"line":528},[134,4381,1505],{"class":147},[134,4383,4384,4386],{"class":136,"line":538},[134,4385,1519],{"class":1309},[134,4387,3575],{"class":158},[134,4389,4390,4392],{"class":136,"line":548},[134,4391,1519],{"class":1309},[134,4393,4394],{"class":158}," \"tf2_ros\u002Ftransform_listener.h\"\n",[134,4396,4397,4399],{"class":136,"line":1404},[134,4398,1519],{"class":1309},[134,4400,4401],{"class":158}," \"tf2_ros\u002Fbuffer.h\"\n",[134,4403,4404,4406],{"class":136,"line":1409},[134,4405,1519],{"class":1309},[134,4407,4408],{"class":158}," \"tf2\u002FLinearMath\u002FQuaternion.h\"\n",[134,4410,4411],{"class":136,"line":1418},[134,4412,141],{"emptyLinePlaceholder":140},[134,4414,4415,4417,4419,4421,4423,4425],{"class":136,"line":1536},[134,4416,1560],{"class":1309},[134,4418,3593],{"class":1309},[134,4420,1563],{"class":154},[134,4422,1566],{"class":1313},[134,4424,3600],{"class":154},[134,4426,2221],{"class":1313},[134,4428,4429],{"class":136,"line":1544},[134,4430,141],{"emptyLinePlaceholder":140},[134,4432,4433],{"class":136,"line":1552},[134,4434,2733],{"class":147},[134,4436,4437,4439,4442,4444,4446,4448,4450,4452],{"class":136,"line":1557},[134,4438,1589],{"class":1309},[134,4440,4441],{"class":154}," MinimalFrameListener",[134,4443,1595],{"class":1313},[134,4445,1598],{"class":1309},[134,4447,878],{"class":154},[134,4449,1566],{"class":1313},[134,4451,1644],{"class":154},[134,4453,3631],{"class":1313},[134,4455,4456],{"class":136,"line":1575},[134,4457,1617],{"class":1309},[134,4459,4460,4463,4466,4468,4470,4473],{"class":136,"line":1580},[134,4461,4462],{"class":154},"  MinimalFrameListener",[134,4464,4465],{"class":1313},"():",[134,4467,1644],{"class":154},[134,4469,1628],{"class":1313},[134,4471,4472],{"class":158},"\"minimal_frame_listener\"",[134,4474,3662],{"class":1313},[134,4476,4477,4480,4482,4484,4486,4488,4490,4492,4494,4497,4499,4501,4503,4505],{"class":136,"line":1586},[134,4478,4479],{"class":1313},"    tf_buffer_ ",[134,4481,1672],{"class":1309},[134,4483,1563],{"class":154},[134,4485,1566],{"class":1313},[134,4487,2798],{"class":154},[134,4489,1682],{"class":1313},[134,4491,915],{"class":154},[134,4493,1566],{"class":1313},[134,4495,4496],{"class":154},"Buffer",[134,4498,1692],{"class":1313},[134,4500,1695],{"class":524},[134,4502,1712],{"class":1313},[134,4504,1810],{"class":154},[134,4506,4507],{"class":1313},"());\n",[134,4509,4510,4513,4515,4517,4519,4521,4523,4525,4527,4530,4532,4534],{"class":136,"line":1608},[134,4511,4512],{"class":1313},"    transform_listener_ ",[134,4514,1672],{"class":1309},[134,4516,1563],{"class":154},[134,4518,1566],{"class":1313},[134,4520,1679],{"class":154},[134,4522,1682],{"class":1313},[134,4524,915],{"class":154},[134,4526,1566],{"class":1313},[134,4528,4529],{"class":154},"TransformListener",[134,4531,1692],{"class":1313},[134,4533,2812],{"class":1309},[134,4535,4536],{"class":1313},"tf_buffer_);\n",[134,4538,4539,4542,4544,4546,4548,4550,4552,4554,4556,4558,4560,4562,4564,4566,4568,4571,4574,4576],{"class":136,"line":1614},[134,4540,4541],{"class":1313},"    timer_ ",[134,4543,1672],{"class":1309},[134,4545,1805],{"class":524},[134,4547,1712],{"class":1313},[134,4549,3724],{"class":154},[134,4551,1628],{"class":1313},[134,4553,1884],{"class":524},[134,4555,3731],{"class":1309},[134,4557,2122],{"class":1313},[134,4559,2272],{"class":154},[134,4561,1566],{"class":1313},[134,4563,2893],{"class":154},[134,4565,1628],{"class":1313},[134,4567,2898],{"class":1309},[134,4569,4570],{"class":154},"MinimalFrameListener",[134,4572,4573],{"class":1313},"::on_timer,",[134,4575,1695],{"class":524},[134,4577,3754],{"class":1313},[134,4579,4580],{"class":136,"line":1620},[134,4581,1724],{"class":1313},[134,4583,4584],{"class":136,"line":1654},[134,4585,141],{"emptyLinePlaceholder":140},[134,4587,4588],{"class":136,"line":1660},[134,4589,1735],{"class":1309},[134,4591,4592,4594,4596],{"class":136,"line":1666},[134,4593,1747],{"class":1309},[134,4595,3771],{"class":154},[134,4597,3774],{"class":1313},[134,4599,4600],{"class":136,"line":1701},[134,4601,4602],{"class":1309},"    try\n",[134,4604,4605],{"class":136,"line":1706},[134,4606,4607],{"class":1313},"    {\n",[134,4609,4610,4613,4616,4618,4621,4624,4626,4629,4631,4634,4636,4639],{"class":136,"line":1721},[134,4611,4612],{"class":1309},"      auto",[134,4614,4615],{"class":1313}," transformStamped ",[134,4617,1672],{"class":1309},[134,4619,4620],{"class":1313}," tf_buffer_->",[134,4622,4623],{"class":154},"lookupTransform",[134,4625,1628],{"class":1313},[134,4627,4628],{"class":158},"\"camera\"",[134,4630,3701],{"class":1313},[134,4632,4633],{"class":158},"\"laser\"",[134,4635,3701],{"class":1313},[134,4637,4638],{"class":154},"tf2",[134,4640,4641],{"class":1313},"::TimePointZero);\n",[134,4643,4644,4647,4649,4651,4653,4655,4658,4661],{"class":136,"line":1727},[134,4645,4646],{"class":154},"      RCLCPP_INFO",[134,4648,1628],{"class":1313},[134,4650,1695],{"class":524},[134,4652,1712],{"class":1313},[134,4654,2160],{"class":154},[134,4656,4657],{"class":1313},"(),",[134,4659,4660],{"class":158},"\"----------------------转换结果----------------------\"",[134,4662,1698],{"class":1313},[134,4664,4665,4667,4669,4671,4673,4675,4677,4680,4683,4686,4689,4692],{"class":136,"line":1732},[134,4666,4646],{"class":154},[134,4668,1628],{"class":1313},[134,4670,1695],{"class":524},[134,4672,1712],{"class":1313},[134,4674,2160],{"class":154},[134,4676,4657],{"class":1313},[134,4678,4679],{"class":158},"\"frame_id:",[134,4681,4682],{"class":524},"%s",[134,4684,4685],{"class":158},"\"",[134,4687,4688],{"class":1313},",transformStamped.header.frame_id.",[134,4690,4691],{"class":154},"c_str",[134,4693,4507],{"class":1313},[134,4695,4696,4698,4700,4702,4704,4706,4708,4711,4713,4715,4718,4720],{"class":136,"line":1738},[134,4697,4646],{"class":154},[134,4699,1628],{"class":1313},[134,4701,1695],{"class":524},[134,4703,1712],{"class":1313},[134,4705,2160],{"class":154},[134,4707,4657],{"class":1313},[134,4709,4710],{"class":158},"\"child_frame_id:",[134,4712,4682],{"class":524},[134,4714,4685],{"class":158},[134,4716,4717],{"class":1313},",transformStamped.child_frame_id.",[134,4719,4691],{"class":154},[134,4721,4507],{"class":1313},[134,4723,4724,4726,4728,4730,4732,4734,4736,4739,4742,4744,4746,4748,4750,4753],{"class":136,"line":1744},[134,4725,4646],{"class":154},[134,4727,1628],{"class":1313},[134,4729,1695],{"class":524},[134,4731,1712],{"class":1313},[134,4733,2160],{"class":154},[134,4735,4657],{"class":1313},[134,4737,4738],{"class":158},"\"坐标:(",[134,4740,4741],{"class":524},"%.2f",[134,4743,3701],{"class":158},[134,4745,4741],{"class":524},[134,4747,3701],{"class":158},[134,4749,4741],{"class":524},[134,4751,4752],{"class":158},")\"",[134,4754,2883],{"class":1313},[134,4756,4757],{"class":136,"line":1764},[134,4758,4759],{"class":1313},"                transformStamped.transform.translation.x,\n",[134,4761,4762],{"class":136,"line":1769},[134,4763,4764],{"class":1313},"                transformStamped.transform.translation.y,\n",[134,4766,4767],{"class":136,"line":1775},[134,4768,4769],{"class":1313},"                transformStamped.transform.translation.z);\n",[134,4771,4772],{"class":136,"line":1789},[134,4773,141],{"emptyLinePlaceholder":140},[134,4775,4776],{"class":136,"line":1794},[134,4777,3759],{"class":1313},[134,4779,4780,4783,4785,4787,4789,4792,4794],{"class":136,"line":1822},[134,4781,4782],{"class":1309},"    catch",[134,4784,1628],{"class":1313},[134,4786,2938],{"class":1309},[134,4788,881],{"class":154},[134,4790,4791],{"class":1313},"::LookupException",[134,4793,2898],{"class":1309},[134,4795,4796],{"class":1313}," e)\n",[134,4798,4799],{"class":136,"line":1833},[134,4800,4607],{"class":1313},[134,4802,4803,4805,4807,4809,4811,4813,4815,4818,4820,4822,4825,4828],{"class":136,"line":1850},[134,4804,4646],{"class":154},[134,4806,1628],{"class":1313},[134,4808,1695],{"class":524},[134,4810,1712],{"class":1313},[134,4812,2160],{"class":154},[134,4814,4657],{"class":1313},[134,4816,4817],{"class":158},"\"坐标变换异常：",[134,4819,4682],{"class":524},[134,4821,4685],{"class":158},[134,4823,4824],{"class":1313},",e.",[134,4826,4827],{"class":154},"what",[134,4829,4507],{"class":1313},[134,4831,4832],{"class":136,"line":1865},[134,4833,3759],{"class":1313},[134,4835,4836],{"class":136,"line":1870},[134,4837,141],{"emptyLinePlaceholder":140},[134,4839,4840],{"class":136,"line":1890},[134,4841,1724],{"class":1313},[134,4843,4844,4846,4848,4850],{"class":136,"line":1907},[134,4845,2243],{"class":154},[134,4847,1566],{"class":1313},[134,4849,3914],{"class":154},[134,4851,3917],{"class":1313},[134,4853,4854,4856,4858,4860,4862,4865,4867],{"class":136,"line":1924},[134,4855,2076],{"class":154},[134,4857,2079],{"class":1313},[134,4859,1682],{"class":1309},[134,4861,915],{"class":154},[134,4863,4864],{"class":1313},"::TransformListener",[134,4866,2089],{"class":1309},[134,4868,4869],{"class":1313}," transform_listener_;\n",[134,4871,4872,4874,4876,4878,4880,4883,4885],{"class":136,"line":1933},[134,4873,2076],{"class":154},[134,4875,3204],{"class":1313},[134,4877,1682],{"class":1309},[134,4879,915],{"class":154},[134,4881,4882],{"class":1313},"::Buffer",[134,4884,2089],{"class":1309},[134,4886,4887],{"class":1313}," tf_buffer_;\n",[134,4889,4890],{"class":136,"line":1945},[134,4891,2098],{"class":1313},[134,4893,4894],{"class":136,"line":1959},[134,4895,141],{"emptyLinePlaceholder":140},[134,4897,4898,4900,4902,4904,4906,4908,4910,4912,4914,4916,4918],{"class":136,"line":1971},[134,4899,2109],{"class":1309},[134,4901,2112],{"class":154},[134,4903,1628],{"class":1313},[134,4905,2109],{"class":1309},[134,4907,2119],{"class":1637},[134,4909,2122],{"class":1313},[134,4911,1631],{"class":1309},[134,4913,3951],{"class":1309},[134,4915,1634],{"class":1309},[134,4917,3956],{"class":1637},[134,4919,1761],{"class":1313},[134,4921,4922],{"class":136,"line":1984},[134,4923,1611],{"class":1313},[134,4925,4926],{"class":136,"line":2000},[134,4927,3255],{"class":147},[134,4929,4930,4932,4934,4936],{"class":136,"line":2015},[134,4931,2243],{"class":154},[134,4933,1566],{"class":1313},[134,4935,2248],{"class":154},[134,4937,3978],{"class":1313},[134,4939,4940],{"class":136,"line":2030},[134,4941,3270],{"class":147},[134,4943,4944,4946,4948,4950,4952,4954,4956,4958,4960,4962],{"class":136,"line":2045},[134,4945,2243],{"class":154},[134,4947,1566],{"class":1313},[134,4949,2267],{"class":154},[134,4951,1628],{"class":1313},[134,4953,2272],{"class":154},[134,4955,1566],{"class":1313},[134,4957,1679],{"class":154},[134,4959,1682],{"class":1313},[134,4961,4570],{"class":154},[134,4963,3293],{"class":1313},[134,4965,4966],{"class":136,"line":2050},[134,4967,3298],{"class":147},[134,4969,4970,4972,4974,4976],{"class":136,"line":2056},[134,4971,2243],{"class":154},[134,4973,1566],{"class":1313},[134,4975,2300],{"class":154},[134,4977,1819],{"class":1313},[134,4979,4980,4982,4984],{"class":136,"line":2068},[134,4981,2308],{"class":1309},[134,4983,1207],{"class":524},[134,4985,2221],{"class":1313},[134,4987,4988],{"class":136,"line":2073},[134,4989,2318],{"class":1313},[20,4991,4992],{},[23,4993],{"alt":25,"src":4994},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1321.webp",[20,4996,4997],{},"要填回调函数",[20,4999,5000],{},[23,5001],{"alt":25,"src":5002},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1322.webp",[20,5004,5005],{},[23,5006],{"alt":25,"src":5007},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1323.webp",[20,5009,5010],{},"实现坐标系转换的核心函数就是lookuptransform()",[20,5012,5013],{},"target_frame就是父级",[20,5015,5016],{},"source_frame就是子级",[20,5018,5019],{},"time是时间，一般都写最新时刻的",[20,5021,5022],{},[23,5023],{"alt":25,"src":5024},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1324.webp",[20,5026,5027],{},"如果buffer没捕获到，抛异常的函数实现",[20,5029,5030],{},[23,5031],{"alt":25,"src":5032},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1325.webp",[20,5034,5035],{},"这样就成功转换坐标了，可以打印转换的坐标。",[20,5037,5038],{},[23,5039],{"alt":25,"src":5040},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1326.webp",[20,5042,5043],{},"除了用try catch处理转换异常，还可以用buffer底下的函数转换。",[20,5045,5046],{},[23,5047],{"alt":25,"src":5048},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1327.webp",[20,5050,5051],{},"比如这个cantransform可以判断是否可以正常转换。",[20,5053,5054],{},[23,5055],{"alt":25,"src":5056},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1328.webp",[20,5058,5059],{},[23,5060],{"alt":25,"src":5061},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1329.webp",[20,5063,5064],{},"这种报错要改为C风格字符串",[20,5066,5067],{},"启动三个终端，终端1输入如下命令发布雷达（laser）相对于底盘（base_link）的静态坐标变换：",[126,5069,5071],{"className":128,"code":5070,"language":130,"meta":25,"style":25},"ros2 run tf2_ros static_transform_publisher --frame-id base_link --child-frame-id camera --x -0.5 --z -0.4\n",[33,5072,5073],{"__ignoreMap":25},[134,5074,5075,5077,5079,5081,5083,5085,5087,5089,5092,5094,5096,5098],{"class":136,"line":137},[134,5076,292],{"class":154},[134,5078,319],{"class":158},[134,5080,884],{"class":158},[134,5082,944],{"class":158},[134,5084,980],{"class":524},[134,5086,1122],{"class":158},[134,5088,985],{"class":524},[134,5090,5091],{"class":158}," camera",[134,5093,947],{"class":524},[134,5095,1256],{"class":524},[134,5097,957],{"class":524},[134,5099,5100],{"class":524}," -0.4\n",[20,5102,1236],{},[126,5104,5106],{"className":128,"code":5105,"language":130,"meta":25,"style":25},"ros2 run tf2_ros static_transform_publisher --frame-id base_link --child-frame-id laser--x 0.4 --z 0.2\n",[33,5107,5108],{"__ignoreMap":25},[134,5109,5110,5112,5114,5116,5118,5120,5122,5124,5127,5129,5131],{"class":136,"line":137},[134,5111,292],{"class":154},[134,5113,319],{"class":158},[134,5115,884],{"class":158},[134,5117,944],{"class":158},[134,5119,980],{"class":524},[134,5121,1122],{"class":158},[134,5123,985],{"class":524},[134,5125,5126],{"class":158}," laser--x",[134,5128,1202],{"class":524},[134,5130,957],{"class":524},[134,5132,5133],{"class":524}," 0.2\n",[20,5135,5136],{},"终端3输入如下命令执行坐标系变换：",[126,5138,5140],{"className":128,"code":5139,"language":130,"meta":25,"style":25},". install\u002Fsetup.bash \nros2 run cpp04_tf_listener demo01_tf_listener\n",[33,5141,5142,5150],{"__ignoreMap":25},[134,5143,5144,5146,5148],{"class":136,"line":137},[134,5145,2414],{"class":524},[134,5147,2417],{"class":158},[134,5149,2420],{"class":1313},[134,5151,5152,5154,5156,5158],{"class":136,"line":144},[134,5153,292],{"class":154},[134,5155,319],{"class":158},[134,5157,4242],{"class":158},[134,5159,4262],{"class":158},[20,5161,5162],{},"终端3将输出 laser 相对于 camera 的坐标，具体结果请参考案例1。",[20,5164,5165],{},[23,5166],{"alt":25,"src":5167},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1330.webp",[20,5169,5170],{},[23,5171],{"alt":25,"src":5172},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1331.webp",[20,5174,5175],{},"当只运行一个广播，他会抛错。",[20,5177,5178],{},[23,5179],{"alt":25,"src":5180},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1332.webp",[20,5182,5183],{},[23,5184],{"alt":25,"src":5185},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1333.webp",[20,5187,5188],{},"当所有广播都跑起来时，才会正常转换。",[16,5190,4266,5192,4270],{"id":5191},"坐标-点-变换监听_c",[30,5193,5194],{},"点",[359,5196,5197],{"id":5197},"实现框架",[20,5199,5200],{},[23,5201],{"alt":25,"src":5202},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1334.webp",[20,5204,5205],{},"求laser测得的坐标点到base_link的距离",[20,5207,5208],{},[23,5209],{"alt":25,"src":5210},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1335.webp",[20,5212,5213],{},[23,5214],{"alt":25,"src":5215},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1336.webp",[20,5217,5218],{},"laser到point的坐标用的是point话题，与监听器用的话题不一样，所以不好订阅，要创建一个新的订阅对象。",[359,5220,1297],{"id":5221},"框架搭建-2",[20,5223,5224,5225,350],{},"package.xml在创建功能包时，所依赖的部分功能包已经自动配置了，不过为了实现坐标点变换，还需要添加依赖包",[33,5226,5227],{},"tf2_geometry_msgs",[20,5229,5230,5233],{},[33,5231,5232],{},"message_filters","，修改后的配置内容如下：",[126,5235,5239],{"className":5236,"code":5237,"language":5238,"meta":25,"style":25},"language-xml shiki shiki-themes github-light github-dark","\u003Cdepend>rclcpp\u003C\u002Fdepend>\n\u003Cdepend>tf2\u003C\u002Fdepend>\n\u003Cdepend>tf2_ros\u003C\u002Fdepend>\n\u003Cdepend>geometry_msgs\u003C\u002Fdepend>\n\u003Cdepend>tf2_geometry_msgs\u003C\u002Fdepend>\n\u003Cdepend>message_filters\u003C\u002Fdepend>\n","xml",[33,5240,5241,5257,5270,5283,5296,5309],{"__ignoreMap":25},[134,5242,5243,5245,5249,5252,5254],{"class":136,"line":137},[134,5244,1682],{"class":1313},[134,5246,5248],{"class":5247},"s9eBZ","depend",[134,5250,5251],{"class":1313},">rclcpp\u003C\u002F",[134,5253,5248],{"class":5247},[134,5255,5256],{"class":1313},">\n",[134,5258,5259,5261,5263,5266,5268],{"class":136,"line":144},[134,5260,1682],{"class":1313},[134,5262,5248],{"class":5247},[134,5264,5265],{"class":1313},">tf2\u003C\u002F",[134,5267,5248],{"class":5247},[134,5269,5256],{"class":1313},[134,5271,5272,5274,5276,5279,5281],{"class":136,"line":151},[134,5273,1682],{"class":1313},[134,5275,5248],{"class":5247},[134,5277,5278],{"class":1313},">tf2_ros\u003C\u002F",[134,5280,5248],{"class":5247},[134,5282,5256],{"class":1313},[134,5284,5285,5287,5289,5292,5294],{"class":136,"line":174},[134,5286,1682],{"class":1313},[134,5288,5248],{"class":5247},[134,5290,5291],{"class":1313},">geometry_msgs\u003C\u002F",[134,5293,5248],{"class":5247},[134,5295,5256],{"class":1313},[134,5297,5298,5300,5302,5305,5307],{"class":136,"line":179},[134,5299,1682],{"class":1313},[134,5301,5248],{"class":5247},[134,5303,5304],{"class":1313},">tf2_geometry_msgs\u003C\u002F",[134,5306,5248],{"class":5247},[134,5308,5256],{"class":1313},[134,5310,5311,5313,5315,5318,5320],{"class":136,"line":185},[134,5312,1682],{"class":1313},[134,5314,5248],{"class":5247},[134,5316,5317],{"class":1313},">message_filters\u003C\u002F",[134,5319,5248],{"class":5247},[134,5321,5256],{"class":1313},[20,5323,5324],{},"CMakeLists.txt 文件修改后的内容如下：",[126,5326,5328],{"className":1300,"code":5327,"language":1302,"meta":25,"style":25},"find dependencies\nfind_package(ament_cmake REQUIRED)\nfind_package(rclcpp REQUIRED)\nfind_package(tf2 REQUIRED)\nfind_package(tf2_ros REQUIRED)\nfind_package(geometry_msgs REQUIRED)\nfind_package(tf2_geometry_msgs REQUIRED)\nfind_package(message_filters REQUIRED)\n\nadd_executable(demo01_tf_listener src\u002Fdemo01_tf_listener.cpp)\nament_target_dependencies(\n  demo01_tf_listener\n  \"rclcpp\"\n  \"tf2\"\n  \"tf2_ros\"\n  \"geometry_msgs\"\n)\nadd_executable(demo02_message_filter src\u002Fdemo02_message_filter.cpp)\nament_target_dependencies(\n  demo02_message_filter\n  \"rclcpp\"\n  \"tf2\"\n  \"tf2_ros\"\n  \"geometry_msgs\"\n  \"tf2_geometry_msgs\"\n  \"message_filters\"\n)\ninstall(TARGETS demo01_tf_listener\n  demo02_message_filter\n  DESTINATION lib\u002F${PROJECT_NAME})\n",[33,5329,5330,5335,5341,5347,5353,5359,5365,5372,5379,5383,5390,5394,5399,5403,5407,5411,5415,5419,5426,5430,5435,5439,5443,5447,5451,5456,5461,5465,5472,5476],{"__ignoreMap":25},[134,5331,5332],{"class":136,"line":137},[134,5333,5334],{"class":1313},"find dependencies\n",[134,5336,5337,5339],{"class":136,"line":144},[134,5338,1310],{"class":1309},[134,5340,1314],{"class":1313},[134,5342,5343,5345],{"class":136,"line":151},[134,5344,1310],{"class":1309},[134,5346,1321],{"class":1313},[134,5348,5349,5351],{"class":136,"line":174},[134,5350,1310],{"class":1309},[134,5352,1328],{"class":1313},[134,5354,5355,5357],{"class":136,"line":179},[134,5356,1310],{"class":1309},[134,5358,1335],{"class":1313},[134,5360,5361,5363],{"class":136,"line":185},[134,5362,1310],{"class":1309},[134,5364,1342],{"class":1313},[134,5366,5367,5369],{"class":136,"line":265},[134,5368,1310],{"class":1309},[134,5370,5371],{"class":1313},"(tf2_geometry_msgs REQUIRED)\n",[134,5373,5374,5376],{"class":136,"line":467},[134,5375,1310],{"class":1309},[134,5377,5378],{"class":1313},"(message_filters REQUIRED)\n",[134,5380,5381],{"class":136,"line":479},[134,5382,141],{"emptyLinePlaceholder":140},[134,5384,5385,5387],{"class":136,"line":488},[134,5386,1358],{"class":1309},[134,5388,5389],{"class":1313},"(demo01_tf_listener src\u002Fdemo01_tf_listener.cpp)\n",[134,5391,5392],{"class":136,"line":496},[134,5393,1366],{"class":1313},[134,5395,5396],{"class":136,"line":504},[134,5397,5398],{"class":1313},"  demo01_tf_listener\n",[134,5400,5401],{"class":136,"line":516},[134,5402,1376],{"class":158},[134,5404,5405],{"class":136,"line":528},[134,5406,1381],{"class":158},[134,5408,5409],{"class":136,"line":538},[134,5410,1386],{"class":158},[134,5412,5413],{"class":136,"line":548},[134,5414,1391],{"class":158},[134,5416,5417],{"class":136,"line":1404},[134,5418,1401],{"class":1313},[134,5420,5421,5423],{"class":136,"line":1409},[134,5422,1358],{"class":1309},[134,5424,5425],{"class":1313},"(demo02_message_filter src\u002Fdemo02_message_filter.cpp)\n",[134,5427,5428],{"class":136,"line":1418},[134,5429,1366],{"class":1313},[134,5431,5432],{"class":136,"line":1536},[134,5433,5434],{"class":1313},"  demo02_message_filter\n",[134,5436,5437],{"class":136,"line":1544},[134,5438,1376],{"class":158},[134,5440,5441],{"class":136,"line":1552},[134,5442,1381],{"class":158},[134,5444,5445],{"class":136,"line":1557},[134,5446,1386],{"class":158},[134,5448,5449],{"class":136,"line":1575},[134,5450,1391],{"class":158},[134,5452,5453],{"class":136,"line":1580},[134,5454,5455],{"class":158},"  \"tf2_geometry_msgs\"\n",[134,5457,5458],{"class":136,"line":1586},[134,5459,5460],{"class":158},"  \"message_filters\"\n",[134,5462,5463],{"class":136,"line":1608},[134,5464,1401],{"class":1313},[134,5466,5467,5469],{"class":136,"line":1614},[134,5468,1412],{"class":1309},[134,5470,5471],{"class":1313},"(TARGETS demo01_tf_listener\n",[134,5473,5474],{"class":136,"line":1620},[134,5475,5434],{"class":1313},[134,5477,5478,5480,5482],{"class":136,"line":1654},[134,5479,1421],{"class":1313},[134,5481,1424],{"class":1309},[134,5483,1401],{"class":1313},[359,5485,3497],{"id":5486},"实现-2",[126,5488,5490],{"className":1432,"code":5489,"language":1434,"meta":25,"style":25},"\u002F*  \n  需求：将雷达感知到的障碍物的坐标点数据（相对于 laser 坐标系），\n       转换成相对于底盘坐标系（base_link）的坐标点。\n\n  步骤：\n    1.包含头文件；\n    2.初始化 ROS 客户端；\n    3.定义节点类；\n      3-1.创建tf缓存对象指针；\n      3-2.创建tf监听器；\n      3-3.创建坐标点订阅方并订阅指定话题；\n      3-4.创建消息过滤器过滤被处理的数据；\n      3-5.为消息过滤器注册转换坐标点数据的回调函数。\n    4.调用 spin 函数，并传入对象指针；\n    5.释放资源。\n\n*\u002F\u002F\u002F 1.包含头文件；#include \u003Cgeometry_msgs\u002Fmsg\u002Fpoint_stamped.hpp>#include \u003Cmessage_filters\u002Fsubscriber.h>#include \u003Crclcpp\u002Frclcpp.hpp>#include \u003Ctf2_ros\u002Fbuffer.h>#include \u003Ctf2_ros\u002Fcreate_timer_ros.h>#include \u003Ctf2_ros\u002Fmessage_filter.h>#include \u003Ctf2_ros\u002Ftransform_listener.h>\u002F\u002F #ifdef TF2_CPP_HEADERS\u002F\u002F   #include \u003Ctf2_geometry_msgs\u002Ftf2_geometry_msgs.hpp>\u002F\u002F #else\u002F\u002F   #include \u003Ctf2_geometry_msgs\u002Ftf2_geometry_msgs.h>\u002F\u002F #endif#include \u003Ctf2_geometry_msgs\u002Ftf2_geometry_msgs.hpp>using namespace std::chrono_literals;\n\n\u002F\u002F 3.定义节点类；class MessageFilterPointListener : public rclcpp::Node\n{\npublic:\n  MessageFilterPointListener(): Node(\"message_filter_point_listener\")\n  {\n\n    target_frame_ = \"base_link\";\n\n    typedef std::chrono::duration\u003Cint> seconds_type;\n    seconds_type buffer_timeout(1);\n    \u002F\u002F 3-1.创建tf缓存对象指针；\n    tf2_buffer_ = std::make_shared\u003Ctf2_ros::Buffer>(this->get_clock());\n    auto timer_interface = std::make_shared\u003Ctf2_ros::CreateTimerROS>(\n      this->get_node_base_interface(),\n      this->get_node_timers_interface());\n    tf2_buffer_->setCreateTimerInterface(timer_interface);\n    \u002F\u002F 3-2.创建tf监听器；\n    tf2_listener_ = std::make_shared\u003Ctf2_ros::TransformListener>(*tf2_buffer_);\n\n    \u002F\u002F 3-3.创建坐标点订阅方并订阅指定话题；\n    point_sub_.subscribe(this, \"point\");\n    \u002F\u002F 3-4.创建消息过滤器过滤被处理的数据；\n    tf2_filter_ = std::make_shared\u003Ctf2_ros::MessageFilter\u003Cgeometry_msgs::msg::PointStamped>>(\n      point_sub_, *tf2_buffer_, target_frame_, 100, this->get_node_logging_interface(),\n      this->get_node_clock_interface(), buffer_timeout);\n    \u002F\u002F 3-5.为消息过滤器注册转换坐标点数据的回调函数。\n    tf2_filter_->registerCallback(&MessageFilterPointListener::msgCallback, this);\n  }\n\nprivate:\n  void msgCallback(const geometry_msgs::msg::PointStamped::SharedPtr point_ptr){\n    geometry_msgs::msg::PointStamped point_out;\n    try {\n      tf2_buffer_->transform(*point_ptr, point_out, target_frame_);\n      RCLCPP_INFO(\n        this->get_logger(), \"坐标点相对于base_link的坐标:(%.2f,%.2f,%.2f)\",\n        point_out.point.x,\n        point_out.point.y,\n        point_out.point.z);\n    } catch (tf2::TransformException & ex) {\n      RCLCPP_WARN(\n        \u002F\u002F Print exception which was caughtthis->get_logger(), \"Failure %s\\n\", ex.what());\n    }\n  }\n  std::string target_frame_;\n  std::shared_ptr\u003Ctf2_ros::Buffer> tf2_buffer_;\n  std::shared_ptr\u003Ctf2_ros::TransformListener> tf2_listener_;\n  message_filters::Subscriber\u003Cgeometry_msgs::msg::PointStamped> point_sub_;\n  std::shared_ptr\u003Ctf2_ros::MessageFilter\u003Cgeometry_msgs::msg::PointStamped>> tf2_filter_;\n};\n\nint main(int argc, char * argv[]){\n  \u002F\u002F 2.初始化 ROS 客户端；\n  rclcpp::init(argc, argv);\n  \u002F\u002F 4.调用 spin 函数，并传入对象指针；\n  rclcpp::spin(std::make_shared\u003CMessageFilterPointListener>());\n  \u002F\u002F 5.释放资源。\n  rclcpp::shutdown();\n  return 0;\n}\n",[33,5491,5492,5496,5501,5506,5510,5514,5518,5522,5526,5531,5536,5541,5546,5551,5555,5559,5563,5568,5572,5577,5581,5585,5601,5605,5609,5621,5625,5646,5660,5665,5696,5724,5737,5748,5759,5764,5792,5796,5801,5819,5824,5861,5885,5897,5902,5924,5928,5932,5936,5960,5971,5978,5993,5999,6028,6033,6038,6043,6064,6071,6076,6080,6084,6091,6108,6125,6148,6177,6181,6185,6205,6209,6219,6223,6245,6249,6259,6267],{"__ignoreMap":25},[134,5493,5494],{"class":136,"line":137},[134,5495,1441],{"class":147},[134,5497,5498],{"class":136,"line":144},[134,5499,5500],{"class":147},"  需求：将雷达感知到的障碍物的坐标点数据（相对于 laser 坐标系），\n",[134,5502,5503],{"class":136,"line":151},[134,5504,5505],{"class":147},"       转换成相对于底盘坐标系（base_link）的坐标点。\n",[134,5507,5508],{"class":136,"line":174},[134,5509,141],{"emptyLinePlaceholder":140},[134,5511,5512],{"class":136,"line":179},[134,5513,1456],{"class":147},[134,5515,5516],{"class":136,"line":185},[134,5517,1461],{"class":147},[134,5519,5520],{"class":136,"line":265},[134,5521,2630],{"class":147},[134,5523,5524],{"class":136,"line":467},[134,5525,2635],{"class":147},[134,5527,5528],{"class":136,"line":479},[134,5529,5530],{"class":147},"      3-1.创建tf缓存对象指针；\n",[134,5532,5533],{"class":136,"line":488},[134,5534,5535],{"class":147},"      3-2.创建tf监听器；\n",[134,5537,5538],{"class":136,"line":496},[134,5539,5540],{"class":147},"      3-3.创建坐标点订阅方并订阅指定话题；\n",[134,5542,5543],{"class":136,"line":504},[134,5544,5545],{"class":147},"      3-4.创建消息过滤器过滤被处理的数据；\n",[134,5547,5548],{"class":136,"line":516},[134,5549,5550],{"class":147},"      3-5.为消息过滤器注册转换坐标点数据的回调函数。\n",[134,5552,5553],{"class":136,"line":528},[134,5554,2655],{"class":147},[134,5556,5557],{"class":136,"line":538},[134,5558,2660],{"class":147},[134,5560,5561],{"class":136,"line":548},[134,5562,141],{"emptyLinePlaceholder":140},[134,5564,5565],{"class":136,"line":1404},[134,5566,5567],{"class":147},"*\u002F\u002F\u002F 1.包含头文件；#include \u003Cgeometry_msgs\u002Fmsg\u002Fpoint_stamped.hpp>#include \u003Cmessage_filters\u002Fsubscriber.h>#include \u003Crclcpp\u002Frclcpp.hpp>#include \u003Ctf2_ros\u002Fbuffer.h>#include \u003Ctf2_ros\u002Fcreate_timer_ros.h>#include \u003Ctf2_ros\u002Fmessage_filter.h>#include \u003Ctf2_ros\u002Ftransform_listener.h>\u002F\u002F #ifdef TF2_CPP_HEADERS\u002F\u002F   #include \u003Ctf2_geometry_msgs\u002Ftf2_geometry_msgs.hpp>\u002F\u002F #else\u002F\u002F   #include \u003Ctf2_geometry_msgs\u002Ftf2_geometry_msgs.h>\u002F\u002F #endif#include \u003Ctf2_geometry_msgs\u002Ftf2_geometry_msgs.hpp>using namespace std::chrono_literals;\n",[134,5569,5570],{"class":136,"line":1409},[134,5571,141],{"emptyLinePlaceholder":140},[134,5573,5574],{"class":136,"line":1418},[134,5575,5576],{"class":147},"\u002F\u002F 3.定义节点类；class MessageFilterPointListener : public rclcpp::Node\n",[134,5578,5579],{"class":136,"line":1536},[134,5580,1611],{"class":1313},[134,5582,5583],{"class":136,"line":1544},[134,5584,1617],{"class":1309},[134,5586,5587,5590,5592,5594,5596,5599],{"class":136,"line":1552},[134,5588,5589],{"class":154},"  MessageFilterPointListener",[134,5591,2766],{"class":1313},[134,5593,1644],{"class":154},[134,5595,1628],{"class":1313},[134,5597,5598],{"class":158},"\"message_filter_point_listener\"",[134,5600,1401],{"class":1313},[134,5602,5603],{"class":136,"line":1557},[134,5604,1657],{"class":1313},[134,5606,5607],{"class":136,"line":1575},[134,5608,141],{"emptyLinePlaceholder":140},[134,5610,5611,5614,5616,5619],{"class":136,"line":1580},[134,5612,5613],{"class":1313},"    target_frame_ ",[134,5615,1672],{"class":1309},[134,5617,5618],{"class":158}," \"base_link\"",[134,5620,2221],{"class":1313},[134,5622,5623],{"class":136,"line":1586},[134,5624,141],{"emptyLinePlaceholder":140},[134,5626,5627,5630,5632,5634,5637,5640,5643],{"class":136,"line":1608},[134,5628,5629],{"class":1309},"    typedef",[134,5631,1563],{"class":154},[134,5633,1566],{"class":1313},[134,5635,5636],{"class":154},"chrono",[134,5638,5639],{"class":1313},"::duration",[134,5641,5642],{"class":1309},"\u003Cint>",[134,5644,5645],{"class":1313}," seconds_type;\n",[134,5647,5648,5651,5654,5656,5658],{"class":136,"line":1614},[134,5649,5650],{"class":1313},"    seconds_type ",[134,5652,5653],{"class":154},"buffer_timeout",[134,5655,1628],{"class":1313},[134,5657,1884],{"class":524},[134,5659,1698],{"class":1313},[134,5661,5662],{"class":136,"line":1620},[134,5663,5664],{"class":147},"    \u002F\u002F 3-1.创建tf缓存对象指针；\n",[134,5666,5667,5670,5672,5674,5676,5678,5680,5682,5684,5686,5688,5690,5692,5694],{"class":136,"line":1654},[134,5668,5669],{"class":1313},"    tf2_buffer_ ",[134,5671,1672],{"class":1309},[134,5673,1563],{"class":154},[134,5675,1566],{"class":1313},[134,5677,1679],{"class":154},[134,5679,1682],{"class":1313},[134,5681,915],{"class":154},[134,5683,1566],{"class":1313},[134,5685,4496],{"class":154},[134,5687,1692],{"class":1313},[134,5689,1695],{"class":524},[134,5691,1712],{"class":1313},[134,5693,1810],{"class":154},[134,5695,4507],{"class":1313},[134,5697,5698,5701,5704,5706,5708,5710,5712,5714,5716,5718,5721],{"class":136,"line":1660},[134,5699,5700],{"class":1309},"    auto",[134,5702,5703],{"class":1313}," timer_interface ",[134,5705,1672],{"class":1309},[134,5707,1563],{"class":154},[134,5709,1566],{"class":1313},[134,5711,1679],{"class":154},[134,5713,1682],{"class":1313},[134,5715,915],{"class":154},[134,5717,1566],{"class":1313},[134,5719,5720],{"class":154},"CreateTimerROS",[134,5722,5723],{"class":1313},">(\n",[134,5725,5726,5729,5731,5734],{"class":136,"line":1666},[134,5727,5728],{"class":524},"      this",[134,5730,1712],{"class":1313},[134,5732,5733],{"class":154},"get_node_base_interface",[134,5735,5736],{"class":1313},"(),\n",[134,5738,5739,5741,5743,5746],{"class":136,"line":1701},[134,5740,5728],{"class":524},[134,5742,1712],{"class":1313},[134,5744,5745],{"class":154},"get_node_timers_interface",[134,5747,4507],{"class":1313},[134,5749,5750,5753,5756],{"class":136,"line":1706},[134,5751,5752],{"class":1313},"    tf2_buffer_->",[134,5754,5755],{"class":154},"setCreateTimerInterface",[134,5757,5758],{"class":1313},"(timer_interface);\n",[134,5760,5761],{"class":136,"line":1721},[134,5762,5763],{"class":147},"    \u002F\u002F 3-2.创建tf监听器；\n",[134,5765,5766,5769,5771,5773,5775,5777,5779,5781,5783,5785,5787,5789],{"class":136,"line":1727},[134,5767,5768],{"class":1313},"    tf2_listener_ ",[134,5770,1672],{"class":1309},[134,5772,1563],{"class":154},[134,5774,1566],{"class":1313},[134,5776,1679],{"class":154},[134,5778,1682],{"class":1313},[134,5780,915],{"class":154},[134,5782,1566],{"class":1313},[134,5784,4529],{"class":154},[134,5786,1692],{"class":1313},[134,5788,2812],{"class":1309},[134,5790,5791],{"class":1313},"tf2_buffer_);\n",[134,5793,5794],{"class":136,"line":1732},[134,5795,141],{"emptyLinePlaceholder":140},[134,5797,5798],{"class":136,"line":1738},[134,5799,5800],{"class":147},"    \u002F\u002F 3-3.创建坐标点订阅方并订阅指定话题；\n",[134,5802,5803,5806,5809,5811,5813,5815,5817],{"class":136,"line":1744},[134,5804,5805],{"class":1313},"    point_sub_.",[134,5807,5808],{"class":154},"subscribe",[134,5810,1628],{"class":1313},[134,5812,1695],{"class":524},[134,5814,2122],{"class":1313},[134,5816,3698],{"class":158},[134,5818,1698],{"class":1313},[134,5820,5821],{"class":136,"line":1764},[134,5822,5823],{"class":147},"    \u002F\u002F 3-4.创建消息过滤器过滤被处理的数据；\n",[134,5825,5826,5829,5831,5833,5835,5837,5839,5841,5843,5846,5848,5850,5852,5854,5856,5858],{"class":136,"line":1769},[134,5827,5828],{"class":1313},"    tf2_filter_ ",[134,5830,1672],{"class":1309},[134,5832,1563],{"class":154},[134,5834,1566],{"class":1313},[134,5836,1679],{"class":154},[134,5838,1682],{"class":1313},[134,5840,915],{"class":154},[134,5842,1566],{"class":1313},[134,5844,5845],{"class":154},"MessageFilter",[134,5847,1682],{"class":1313},[134,5849,3684],{"class":154},[134,5851,1566],{"class":1313},[134,5853,1783],{"class":154},[134,5855,1566],{"class":1313},[134,5857,3902],{"class":154},[134,5859,5860],{"class":1313},">>(\n",[134,5862,5863,5866,5868,5871,5874,5876,5878,5880,5883],{"class":136,"line":1775},[134,5864,5865],{"class":1313},"      point_sub_, ",[134,5867,2812],{"class":1309},[134,5869,5870],{"class":1313},"tf2_buffer_, target_frame_, ",[134,5872,5873],{"class":524},"100",[134,5875,2122],{"class":1313},[134,5877,1695],{"class":524},[134,5879,1712],{"class":1313},[134,5881,5882],{"class":154},"get_node_logging_interface",[134,5884,5736],{"class":1313},[134,5886,5887,5889,5891,5894],{"class":136,"line":1789},[134,5888,5728],{"class":524},[134,5890,1712],{"class":1313},[134,5892,5893],{"class":154},"get_node_clock_interface",[134,5895,5896],{"class":1313},"(), buffer_timeout);\n",[134,5898,5899],{"class":136,"line":1794},[134,5900,5901],{"class":147},"    \u002F\u002F 3-5.为消息过滤器注册转换坐标点数据的回调函数。\n",[134,5903,5904,5907,5910,5912,5914,5917,5920,5922],{"class":136,"line":1822},[134,5905,5906],{"class":1313},"    tf2_filter_->",[134,5908,5909],{"class":154},"registerCallback",[134,5911,1628],{"class":1313},[134,5913,2898],{"class":1309},[134,5915,5916],{"class":154},"MessageFilterPointListener",[134,5918,5919],{"class":1313},"::msgCallback, ",[134,5921,1695],{"class":524},[134,5923,1698],{"class":1313},[134,5925,5926],{"class":136,"line":1833},[134,5927,1724],{"class":1313},[134,5929,5930],{"class":136,"line":1850},[134,5931,141],{"emptyLinePlaceholder":140},[134,5933,5934],{"class":136,"line":1865},[134,5935,1735],{"class":1309},[134,5937,5938,5940,5943,5945,5947,5949,5951,5953,5955,5957],{"class":136,"line":1870},[134,5939,1747],{"class":1309},[134,5941,5942],{"class":154}," msgCallback",[134,5944,1628],{"class":1313},[134,5946,2938],{"class":1309},[134,5948,887],{"class":154},[134,5950,1566],{"class":1313},[134,5952,1783],{"class":154},[134,5954,1566],{"class":1313},[134,5956,3902],{"class":154},[134,5958,5959],{"class":1313},"::SharedPtr point_ptr){\n",[134,5961,5962,5964,5966,5968],{"class":136,"line":1890},[134,5963,1778],{"class":154},[134,5965,1566],{"class":1313},[134,5967,1783],{"class":154},[134,5969,5970],{"class":1313},"::PointStamped point_out;\n",[134,5972,5973,5976],{"class":136,"line":1907},[134,5974,5975],{"class":1309},"    try",[134,5977,3631],{"class":1313},[134,5979,5980,5983,5986,5988,5990],{"class":136,"line":1924},[134,5981,5982],{"class":1313},"      tf2_buffer_->",[134,5984,5985],{"class":154},"transform",[134,5987,1628],{"class":1313},[134,5989,2812],{"class":1309},[134,5991,5992],{"class":1313},"point_ptr, point_out, target_frame_);\n",[134,5994,5995,5997],{"class":136,"line":1933},[134,5996,4646],{"class":154},[134,5998,1942],{"class":1313},[134,6000,6001,6004,6006,6008,6011,6014,6016,6018,6020,6022,6024,6026],{"class":136,"line":1945},[134,6002,6003],{"class":524},"        this",[134,6005,1712],{"class":1313},[134,6007,2160],{"class":154},[134,6009,6010],{"class":1313},"(), ",[134,6012,6013],{"class":158},"\"坐标点相对于base_link的坐标:(",[134,6015,4741],{"class":524},[134,6017,3701],{"class":158},[134,6019,4741],{"class":524},[134,6021,3701],{"class":158},[134,6023,4741],{"class":524},[134,6025,4752],{"class":158},[134,6027,2883],{"class":1313},[134,6029,6030],{"class":136,"line":1959},[134,6031,6032],{"class":1313},"        point_out.point.x,\n",[134,6034,6035],{"class":136,"line":1971},[134,6036,6037],{"class":1313},"        point_out.point.y,\n",[134,6039,6040],{"class":136,"line":1984},[134,6041,6042],{"class":1313},"        point_out.point.z);\n",[134,6044,6045,6048,6051,6054,6056,6059,6061],{"class":136,"line":2000},[134,6046,6047],{"class":1313},"    } ",[134,6049,6050],{"class":1309},"catch",[134,6052,6053],{"class":1313}," (",[134,6055,4638],{"class":154},[134,6057,6058],{"class":1313},"::TransformException ",[134,6060,2898],{"class":1309},[134,6062,6063],{"class":1313}," ex) {\n",[134,6065,6066,6069],{"class":136,"line":2015},[134,6067,6068],{"class":154},"      RCLCPP_WARN",[134,6070,1942],{"class":1313},[134,6072,6073],{"class":136,"line":2030},[134,6074,6075],{"class":147},"        \u002F\u002F Print exception which was caughtthis->get_logger(), \"Failure %s\\n\", ex.what());\n",[134,6077,6078],{"class":136,"line":2045},[134,6079,3759],{"class":1313},[134,6081,6082],{"class":136,"line":2050},[134,6083,1724],{"class":1313},[134,6085,6086,6088],{"class":136,"line":2056},[134,6087,2076],{"class":154},[134,6089,6090],{"class":1313},"::string target_frame_;\n",[134,6092,6093,6095,6097,6099,6101,6103,6105],{"class":136,"line":2068},[134,6094,2076],{"class":154},[134,6096,2079],{"class":1313},[134,6098,1682],{"class":1309},[134,6100,915],{"class":154},[134,6102,4882],{"class":1313},[134,6104,2089],{"class":1309},[134,6106,6107],{"class":1313}," tf2_buffer_;\n",[134,6109,6110,6112,6114,6116,6118,6120,6122],{"class":136,"line":2073},[134,6111,2076],{"class":154},[134,6113,2079],{"class":1313},[134,6115,1682],{"class":1309},[134,6117,915],{"class":154},[134,6119,4864],{"class":1313},[134,6121,2089],{"class":1309},[134,6123,6124],{"class":1313}," tf2_listener_;\n",[134,6126,6127,6130,6133,6135,6137,6139,6141,6143,6145],{"class":136,"line":2095},[134,6128,6129],{"class":154},"  message_filters",[134,6131,6132],{"class":1313},"::Subscriber",[134,6134,1682],{"class":1309},[134,6136,3684],{"class":154},[134,6138,1566],{"class":1313},[134,6140,1783],{"class":154},[134,6142,3691],{"class":1313},[134,6144,2089],{"class":1309},[134,6146,6147],{"class":1313}," point_sub_;\n",[134,6149,6150,6152,6154,6156,6158,6161,6163,6165,6167,6169,6171,6174],{"class":136,"line":2101},[134,6151,2076],{"class":154},[134,6153,2079],{"class":1313},[134,6155,1682],{"class":1309},[134,6157,915],{"class":154},[134,6159,6160],{"class":1313},"::MessageFilter",[134,6162,1682],{"class":1309},[134,6164,3684],{"class":154},[134,6166,1566],{"class":1313},[134,6168,1783],{"class":154},[134,6170,3691],{"class":1313},[134,6172,6173],{"class":1309},">>",[134,6175,6176],{"class":1313}," tf2_filter_;\n",[134,6178,6179],{"class":136,"line":2106},[134,6180,2098],{"class":1313},[134,6182,6183],{"class":136,"line":2134},[134,6184,141],{"emptyLinePlaceholder":140},[134,6186,6187,6189,6191,6193,6195,6198,6200,6202],{"class":136,"line":2139},[134,6188,2109],{"class":1309},[134,6190,2112],{"class":154},[134,6192,1628],{"class":1313},[134,6194,2109],{"class":1309},[134,6196,6197],{"class":1313}," argc, ",[134,6199,1631],{"class":1309},[134,6201,1634],{"class":1309},[134,6203,6204],{"class":1313}," argv[]){\n",[134,6206,6207],{"class":136,"line":2145},[134,6208,3255],{"class":147},[134,6210,6211,6213,6215,6217],{"class":136,"line":2170},[134,6212,2243],{"class":154},[134,6214,1566],{"class":1313},[134,6216,2248],{"class":154},[134,6218,2251],{"class":1313},[134,6220,6221],{"class":136,"line":2175},[134,6222,3270],{"class":147},[134,6224,6225,6227,6229,6231,6233,6235,6237,6239,6241,6243],{"class":136,"line":2193},[134,6226,2243],{"class":154},[134,6228,1566],{"class":1313},[134,6230,2267],{"class":154},[134,6232,1628],{"class":1313},[134,6234,2272],{"class":154},[134,6236,1566],{"class":1313},[134,6238,1679],{"class":154},[134,6240,1682],{"class":1313},[134,6242,5916],{"class":154},[134,6244,3293],{"class":1313},[134,6246,6247],{"class":136,"line":2201},[134,6248,3298],{"class":147},[134,6250,6251,6253,6255,6257],{"class":136,"line":2212},[134,6252,2243],{"class":154},[134,6254,1566],{"class":1313},[134,6256,2300],{"class":154},[134,6258,1819],{"class":1313},[134,6260,6261,6263,6265],{"class":136,"line":2224},[134,6262,2308],{"class":1309},[134,6264,1207],{"class":524},[134,6266,2221],{"class":1313},[134,6268,6269],{"class":136,"line":2229},[134,6270,2318],{"class":1313},[20,6272,6273],{},[23,6274],{"alt":25,"src":6275},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1337.webp",[20,6277,6278],{},"把上面此参数设置一下",[20,6280,6281],{},[23,6282],{"alt":25,"src":6283},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1338.webp",[20,6285,6286],{},[23,6287],{"alt":25,"src":6288},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1339.webp",[20,6290,6291],{},[23,6292],{"alt":25,"src":6293},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1340.webp",[20,6295,6296],{},"进行数据解析",[20,6298,6299],{},[23,6300],{"alt":25,"src":6301},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1341.webp",[20,6303,6304],{},"用第一个重载。",[20,6306,6307],{},"转换过程会抛异常，可以不管他。转化失败会在终端上自动抛异常。",[20,6309,6310],{},[23,6311],{"alt":25,"src":6312},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1342.webp",[20,6314,6315],{},"在当前工作空间下，启动三个终端，终端1输入如下命令发布雷达（laser）相对于底盘（base_link）的静态坐标变换：",[126,6317,6318],{"className":128,"code":2407,"language":130,"meta":25,"style":25},[33,6319,6320,6328],{"__ignoreMap":25},[134,6321,6322,6324,6326],{"class":136,"line":137},[134,6323,2414],{"class":524},[134,6325,2417],{"class":158},[134,6327,2420],{"class":1313},[134,6329,6330,6332,6334,6336,6338,6340,6342,6344,6346,6348,6350,6352],{"class":136,"line":144},[134,6331,292],{"class":154},[134,6333,319],{"class":158},[134,6335,866],{"class":158},[134,6337,2431],{"class":158},[134,6339,1202],{"class":524},[134,6341,1207],{"class":524},[134,6343,1212],{"class":524},[134,6345,1207],{"class":524},[134,6347,1207],{"class":524},[134,6349,1207],{"class":524},[134,6351,1122],{"class":158},[134,6353,1127],{"class":158},[20,6355,4093],{},[126,6357,6358],{"className":128,"code":4096,"language":130,"meta":25,"style":25},[33,6359,6360,6368],{"__ignoreMap":25},[134,6361,6362,6364,6366],{"class":136,"line":137},[134,6363,2414],{"class":524},[134,6365,2417],{"class":158},[134,6367,2420],{"class":1313},[134,6369,6370,6372,6374,6376],{"class":136,"line":144},[134,6371,292],{"class":154},[134,6373,319],{"class":158},[134,6375,866],{"class":158},[134,6377,4117],{"class":158},[20,6379,6380],{},"终端3输入如下命令执行坐标点变换：",[126,6382,6384],{"className":128,"code":6383,"language":130,"meta":25,"style":25},". install\u002Fsetup.bash \nros2 run cpp04_tf_listener demo02_message_filter\n",[33,6385,6386,6394],{"__ignoreMap":25},[134,6387,6388,6390,6392],{"class":136,"line":137},[134,6389,2414],{"class":524},[134,6391,2417],{"class":158},[134,6393,2420],{"class":1313},[134,6395,6396,6398,6400,6402],{"class":136,"line":144},[134,6397,292],{"class":154},[134,6399,319],{"class":158},[134,6401,4242],{"class":158},[134,6403,6404],{"class":158}," demo02_message_filter\n",[20,6406,6407],{},"终端3将输出坐标点相对于 base_link 的坐标，具体结果请参考案例2。",[20,6409,6410],{},"按顺序依次发布",[20,6412,6413],{},[23,6414],{"alt":25,"src":6415},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1343.webp",[20,6417,6418],{},[23,6419],{"alt":25,"src":6420},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1344.webp",[12,6422,6423],{"id":6423},"坐标变换工具",[20,6425,6426,6427,350,6429,354],{},"在 ROS2 的 TF 框架中除了封装了坐标广播与订阅功能外，还提供了一些工具，可以帮助我们提高开发、调试效率。本节主要介绍这些工具的使用，这些工具主要涉及到两个功能包：",[33,6428,915],{},[33,6430,6431],{},"tf2_tools",[20,6433,6434,6436],{},[33,6435,915],{},"包中提供的常用节点如下：",[6438,6439,6440,6443,6446],"ul",{},[806,6441,6442],{},"static_transform_publisher：该节点用于广播静态坐标变换；（用过很多次了）",[806,6444,6445],{},"tf2_monitor：该节点用于打印所有或特定坐标系的发布频率与网络延迟；",[806,6447,6448],{},"tf2_echo：该节点用于打印特定坐标系的平移旋转关系。",[20,6450,6451,6453],{},[33,6452,6431],{},"包中提供的节点如下：",[6438,6455,6456],{},[806,6457,6458],{},"view_frames：该节点可以生成显示坐标系关系的 pdf 文件，该文件包含树形结构的坐标系图谱。",[20,6460,6461,6462,6464,6465,6467,6468,6470],{},"上述诸多工具中，功能包",[33,6463,915],{},"中的",[33,6466,919],{},"节点在 ",[30,6469,2453],{}," 一节中已有详细说明，本节不再介绍。",[20,6472,6473],{},[30,6474,6475],{},"准备工作：",[20,6477,6478,6479,6481,6482,6485],{},"为了更好的演示工具的使用，请先启动若干坐标系广播节点，比如：可以按照 ",[30,6480,2453],{}," 和 ",[30,6483,6484],{},"动态广播器（C++）"," 广播一些坐标系消息。",[20,6487,6488],{},"第一个终端：",[126,6490,6491],{"className":128,"code":1185,"language":130,"meta":25,"style":25},[33,6492,6493],{"__ignoreMap":25},[134,6494,6495,6497,6499,6501,6503,6505,6507,6509,6511,6513,6515,6517,6519,6521,6523,6525,6527,6529,6531,6533],{"class":136,"line":137},[134,6496,292],{"class":154},[134,6498,319],{"class":158},[134,6500,884],{"class":158},[134,6502,944],{"class":158},[134,6504,947],{"class":524},[134,6506,1202],{"class":524},[134,6508,952],{"class":524},[134,6510,1207],{"class":524},[134,6512,957],{"class":524},[134,6514,1212],{"class":524},[134,6516,962],{"class":524},[134,6518,1217],{"class":524},[134,6520,974],{"class":524},[134,6522,1207],{"class":524},[134,6524,968],{"class":524},[134,6526,1207],{"class":524},[134,6528,980],{"class":524},[134,6530,1122],{"class":158},[134,6532,985],{"class":524},[134,6534,1127],{"class":158},[20,6536,6537],{},"第二个终端：",[126,6539,6540],{"className":128,"code":1239,"language":130,"meta":25,"style":25},[33,6541,6542],{"__ignoreMap":25},[134,6543,6544,6546,6548,6550,6552,6554,6556,6558,6560,6562,6564,6566,6568,6570,6572,6574,6576,6578,6580,6582],{"class":136,"line":137},[134,6545,292],{"class":154},[134,6547,319],{"class":158},[134,6549,884],{"class":158},[134,6551,944],{"class":158},[134,6553,947],{"class":524},[134,6555,1256],{"class":524},[134,6557,952],{"class":524},[134,6559,1207],{"class":524},[134,6561,957],{"class":524},[134,6563,1202],{"class":524},[134,6565,962],{"class":524},[134,6567,1207],{"class":524},[134,6569,974],{"class":524},[134,6571,1207],{"class":524},[134,6573,968],{"class":524},[134,6575,1207],{"class":524},[134,6577,980],{"class":524},[134,6579,1122],{"class":158},[134,6581,985],{"class":524},[134,6583,1285],{"class":158},[20,6585,6586],{},"第三个终端：",[126,6588,6590],{"className":128,"code":6589,"language":130,"meta":25,"style":25},"ros2 run turtlesim turtlesim_node\n",[33,6591,6592],{"__ignoreMap":25},[134,6593,6594,6596,6598,6600],{"class":136,"line":137},[134,6595,292],{"class":154},[134,6597,319],{"class":158},[134,6599,322],{"class":158},[134,6601,6602],{"class":158}," turtlesim_node\n",[20,6604,6605],{},"第四个终端：",[126,6607,6608],{"className":128,"code":310,"language":130,"meta":25,"style":25},[33,6609,6610],{"__ignoreMap":25},[134,6611,6612,6614,6616,6618],{"class":136,"line":137},[134,6613,292],{"class":154},[134,6615,319],{"class":158},[134,6617,322],{"class":158},[134,6619,325],{"class":158},[20,6621,6622],{},"第五个终端：",[126,6624,6626],{"className":128,"code":6625,"language":130,"meta":25,"style":25},"source install\u002Fsetup.bash\nros2 run cpp03_tf_broadcaster demo02_dynamic_tf_broadcaster\n",[33,6627,6628,6636],{"__ignoreMap":25},[134,6629,6630,6633],{"class":136,"line":137},[134,6631,6632],{"class":524},"source",[134,6634,6635],{"class":158}," install\u002Fsetup.bash\n",[134,6637,6638,6640,6642,6644],{"class":136,"line":144},[134,6639,292],{"class":154},[134,6641,319],{"class":158},[134,6643,866],{"class":158},[134,6645,6646],{"class":158}," demo02_dynamic_tf_broadcaster\n",[20,6648,6649],{},[23,6650],{"alt":25,"src":6651},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1345.webp",[20,6653,6654],{},"以上是准备工作",[359,6656,6658],{"id":6657},"_1tf2_monitor","1.tf2_monitor",[6660,6661,6663],"h6",{"id":6662},"_11打印所有坐标系的发布频率与网络延迟","1.1打印所有坐标系的发布频率与网络延迟",[20,6665,6666],{},"终端执行命令：",[126,6668,6670],{"className":128,"code":6669,"language":130,"meta":25,"style":25},"ros2 run tf2_ros tf2_monitor\n",[33,6671,6672],{"__ignoreMap":25},[134,6673,6674,6676,6678,6680],{"class":136,"line":137},[134,6675,292],{"class":154},[134,6677,319],{"class":158},[134,6679,884],{"class":158},[134,6681,6682],{"class":158}," tf2_monitor\n",[20,6684,6685],{},"运行结果：",[20,6687,6688],{},[23,6689],{"alt":25,"src":6690},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1346.webp",[20,6692,6693],{},"该命令有10s的阻塞时间，因为要在一个区间内测频率。",[20,6695,6696],{},"静态的没有变化，而动态的发布频率是有一些变化的。",[20,6698,6699],{},"该函数每隔10s会再发布一次。",[6660,6701,6703],{"id":6702},"_12打印指定坐标系的发布频率与网络延迟","1.2打印指定坐标系的发布频率与网络延迟",[20,6705,6666],{},[126,6707,6709],{"className":128,"code":6708,"language":130,"meta":25,"style":25},"ros2 run tf2_ros tf2_monitor camera laser\n",[33,6710,6711],{"__ignoreMap":25},[134,6712,6713,6715,6717,6719,6722,6724],{"class":136,"line":137},[134,6714,292],{"class":154},[134,6716,319],{"class":158},[134,6718,884],{"class":158},[134,6720,6721],{"class":158}," tf2_monitor",[134,6723,5091],{"class":158},[134,6725,1127],{"class":158},[20,6727,6685],{},[20,6729,6730],{},[23,6731],{"alt":25,"src":6732},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1347.webp",[20,6734,6735],{},"刚开始在缓存里拿不到数据抛错很正常。",[359,6737,6739],{"id":6738},"_2tf2_echo","2.tf2_echo",[20,6741,6742],{},"打印两个坐标系的平移旋转关系。",[20,6744,6666],{},[126,6746,6748],{"className":128,"code":6747,"language":130,"meta":25,"style":25},"ros2 run tf2_ros tf2_echo world turtle1\n",[33,6749,6750],{"__ignoreMap":25},[134,6751,6752,6754,6756,6758,6761,6764],{"class":136,"line":137},[134,6753,292],{"class":154},[134,6755,319],{"class":158},[134,6757,884],{"class":158},[134,6759,6760],{"class":158}," tf2_echo",[134,6762,6763],{"class":158}," world",[134,6765,6766],{"class":158}," turtle1\n",[20,6768,6685],{},[20,6770,6771],{},[23,6772],{"alt":25,"src":6773},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1348.webp",[20,6775,6776],{},"会出平移量和旋转量",[20,6778,6779,6780,6784],{},"会以好几种方式表现，如",[6781,6782,6783],"em",{},"平移距离，四元数，弧度欧拉角，角度欧拉角，矩阵","等。",[20,6786,6787],{},[23,6788],{"alt":25,"src":6789},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1349.webp",[20,6791,6792],{},"当龟男🐢🚹动弹的时候，数值也会发生改变。",[359,6794,6796],{"id":6795},"_3view_frames常用","3.view_frames（常用）",[20,6798,6799],{},"以图形化的方式显示坐标系关系。",[20,6801,6666],{},[126,6803,6805],{"className":128,"code":6804,"language":130,"meta":25,"style":25},"ros2 run tf2_tools view_frames\n",[33,6806,6807],{"__ignoreMap":25},[134,6808,6809,6811,6813,6816],{"class":136,"line":137},[134,6810,292],{"class":154},[134,6812,319],{"class":158},[134,6814,6815],{"class":158}," tf2_tools",[134,6817,6818],{"class":158}," view_frames\n",[20,6820,6821,6822,6825],{},"运行结果：将会在",[30,6823,6824],{},"当前目录","下生成 frames_xxxx.gv 与 frames_xxxx.pdf 文件，其中 xxxx 为时间戳。打开 pdf 文件显示如下内容：",[20,6827,6828],{},[23,6829],{"alt":25,"src":6830},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1350.webp",[20,6832,6833],{},"此节点会监听我们5秒钟，并生成对应的文件。",[20,6835,6836],{},[23,6837],{"alt":25,"src":6838},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1351.webp",[20,6840,6841],{},[23,6842],{"alt":25,"src":6843},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F12\u002F30\u002Fimage1352.webp",[20,6845,6846],{},"上图中有两棵坐标树，但是实际上的项目中，咱们只能设计一棵树，而不能设计两个坐标树。",[12,6848,6849],{"id":6849},"练习",[16,6851,6852],{"id":6852},"乌龟跟随",[16,6854,6855],{"id":6855},"乌龟护航",[12,6857,4144],{"id":6858},"小结-1",[6860,6861,6862],"style",{},"html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}",{"title":25,"searchDepth":144,"depth":144,"links":6864},[6865,6866,6867,6868,6869,6870],{"id":14,"depth":151,"text":14},{"id":737,"depth":151,"text":737},{"id":4161,"depth":151,"text":4161},{"id":6423,"depth":151,"text":6423},{"id":6849,"depth":151,"text":6849},{"id":6858,"depth":151,"text":4144},0,"0800","2023-12-30","2023-12-30-ros2-tutorial","\u002Fwiki\u002F2023-12-30-ros2-tutorial","Ros2 Tutorial","md",false,{},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F0800-zuo-biao-bian-huan-tf",{"title":5,"description":25},"wiki\u002F2023-12-30-ros2-tutorial\u002F0800-坐标变换TF","czEpX0UKhi8cX8gip3rGeBMdbZvu6Ryx3K-Gb6LlsXk",[6885,6891,6897,6903,6909,6915,6921,6927,6929,6935,6941,6947,6953,6959,6965,6971,6977,6983,6989,6995,7001,7007,7013,7019,7025,7031,7037,7043,7049,7055,7061,7067,7073,7079,7085,7090,7096,7101,7107,7113,7119,7125,7131,7137,7143,7149,7155,7161,7166,7172,7178,7184,7190,7196,7202,7208,7214,7220,7226,7232,7238,7244,7250,7256,7262,7268,7274,7280,7286],{"path":6886,"stem":6887,"title":6888,"authors":6889,"date":6873,"chapterOrder":6890,"chapterDepth":6871,"docKey":6874,"docRoot":6875,"docTitle":6876,"isWikiDoc":140,"isWikiIndex":6878},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F0100-ros2-jie-shao","wiki\u002F2023-12-30-ros2-tutorial\u002F0100-ROS2介绍","ROS2介绍",[7],"0100",{"path":6892,"stem":6893,"title":6894,"authors":6895,"date":6873,"chapterOrder":6896,"chapterDepth":6871,"docKey":6874,"docRoot":6875,"docTitle":6876,"isWikiDoc":140,"isWikiIndex":6878},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F0200-ru-men-cao-zuo","wiki\u002F2023-12-30-ros2-tutorial\u002F0200-入门操作","入门操作",[7],"0200",{"path":6898,"stem":6899,"title":6900,"authors":6901,"date":6873,"chapterOrder":6902,"chapterDepth":6871,"docKey":6874,"docRoot":6875,"docTitle":6876,"isWikiDoc":140,"isWikiIndex":6878},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F0300-gong-zuo-kong-jian-yu-gong-neng-bao","wiki\u002F2023-12-30-ros2-tutorial\u002F0300-工作空间与功能包","工作空间与功能包",[7],"0300",{"path":6904,"stem":6905,"title":6906,"authors":6907,"date":6873,"chapterOrder":6908,"chapterDepth":6871,"docKey":6874,"docRoot":6875,"docTitle":6876,"isWikiDoc":140,"isWikiIndex":6878},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F0400-si-da-tong-xin","wiki\u002F2023-12-30-ros2-tutorial\u002F0400-四大通信","四大通信",[7],"0400",{"path":6910,"stem":6911,"title":6912,"authors":6913,"date":6873,"chapterOrder":6914,"chapterDepth":6871,"docKey":6874,"docRoot":6875,"docTitle":6876,"isWikiDoc":140,"isWikiIndex":6878},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F0500-ros2-qi-ta-tong-xin-ji-zhi","wiki\u002F2023-12-30-ros2-tutorial\u002F0500-ROS2其他通信机制","ROS2其他通信机制",[7],"0500",{"path":6916,"stem":6917,"title":6918,"authors":6919,"date":6873,"chapterOrder":6920,"chapterDepth":6871,"docKey":6874,"docRoot":6875,"docTitle":6876,"isWikiDoc":140,"isWikiIndex":6878},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F0600-launch","wiki\u002F2023-12-30-ros2-tutorial\u002F0600-Launch","Launch",[7],"0600",{"path":6922,"stem":6923,"title":6924,"authors":6925,"date":6873,"chapterOrder":6926,"chapterDepth":6871,"docKey":6874,"docRoot":6875,"docTitle":6876,"isWikiDoc":140,"isWikiIndex":6878},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F0700-hui-su-rosbag2","wiki\u002F2023-12-30-ros2-tutorial\u002F0700-回溯rosbag2","回溯rosbag2",[7],"0700",{"path":6880,"stem":6882,"title":5,"authors":6928,"date":6873,"chapterOrder":6872,"chapterDepth":6871,"docKey":6874,"docRoot":6875,"docTitle":6876,"isWikiDoc":140,"isWikiIndex":6878},[7],{"path":6930,"stem":6931,"title":6932,"authors":6933,"date":6873,"chapterOrder":6934,"chapterDepth":6871,"docKey":6874,"docRoot":6875,"docTitle":6876,"isWikiDoc":140,"isWikiIndex":6878},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F0900-ke-shi-hua-ping-tai-rviz2-yu-urdf-jian-mo-yu-yan","wiki\u002F2023-12-30-ros2-tutorial\u002F0900-可视化平台RVIZ2与URDF建模语言","可视化平台RVIZ2与URDF建模语言",[7],"0900",{"path":6936,"stem":6937,"title":6938,"authors":6939,"date":6873,"chapterOrder":6940,"chapterDepth":6871,"docKey":6874,"docRoot":6875,"docTitle":6876,"isWikiDoc":140,"isWikiIndex":6878},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F1000-stage-ros2-fang-zhen-ping-tai","wiki\u002F2023-12-30-ros2-tutorial\u002F1000-Stage_Ros2仿真平台","Stage_Ros2仿真平台",[7],"1000",{"path":6942,"stem":6943,"title":6944,"authors":6945,"date":6873,"chapterOrder":6946,"chapterDepth":137,"docKey":6874,"docRoot":6875,"docTitle":6876,"isWikiDoc":140,"isWikiIndex":6878},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F1100-0100-gazeboclassic","wiki\u002F2023-12-30-ros2-tutorial\u002F1100-0100-GazeboClassic","Gezebo Classic",[7],"1100-0100",{"path":6948,"stem":6949,"title":6950,"authors":6951,"date":6873,"chapterOrder":6952,"chapterDepth":137,"docKey":6874,"docRoot":6875,"docTitle":6876,"isWikiDoc":140,"isWikiIndex":6878},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F1100-0200-ignitiongazebo","wiki\u002F2023-12-30-ros2-tutorial\u002F1100-0200-IgnitionGazebo","Ignition Gazebo（Gazebo Fortress）",[7],"1100-0200",{"path":6954,"stem":6955,"title":6956,"authors":6957,"date":6873,"chapterOrder":6958,"chapterDepth":137,"docKey":6874,"docRoot":6875,"docTitle":6876,"isWikiDoc":140,"isWikiIndex":6878},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F1100-0300-gazebosim","wiki\u002F2023-12-30-ros2-tutorial\u002F1100-0300-GazeboSim","Gz Sim（Gazebo Harmonic）",[7],"1100-0300",{"path":6960,"stem":6961,"title":6962,"authors":6963,"date":6873,"chapterOrder":6964,"chapterDepth":137,"docKey":6874,"docRoot":6875,"docTitle":6876,"isWikiDoc":140,"isWikiIndex":6878},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F1100-0400-igngz2gzsim","wiki\u002F2023-12-30-ros2-tutorial\u002F1100-0400-Igngz2gzsim","将Ign Gazebo迁移至Gz Sim",[7],"1100-0400",{"path":6966,"stem":6967,"title":6968,"authors":6969,"date":6873,"chapterOrder":6970,"chapterDepth":6871,"docKey":6874,"docRoot":6875,"docTitle":6876,"isWikiDoc":140,"isWikiIndex":6878},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F1100-gezebo-fang-zhen-ping-tai","wiki\u002F2023-12-30-ros2-tutorial\u002F1100-Gezebo仿真平台","Gezebo仿真平台",[7],"1100",{"path":6972,"stem":6973,"title":6974,"authors":6975,"date":6873,"chapterOrder":6976,"chapterDepth":137,"docKey":6874,"docRoot":6875,"docTitle":6876,"isWikiDoc":140,"isWikiIndex":6878},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F1200-0100-humble-ban-ben","wiki\u002F2023-12-30-ros2-tutorial\u002F1200-0100-Humble版本","Humble导航仿真",[7],"1200-0100",{"path":6978,"stem":6979,"title":6980,"authors":6981,"date":6873,"chapterOrder":6982,"chapterDepth":137,"docKey":6874,"docRoot":6875,"docTitle":6876,"isWikiDoc":140,"isWikiIndex":6878},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F1200-0200-jazzy-ban-ben","wiki\u002F2023-12-30-ros2-tutorial\u002F1200-0200-Jazzy版本","Jazzy导航仿真",[7],"1200-0200",{"path":6984,"stem":6985,"title":6986,"authors":6987,"date":6873,"chapterOrder":6988,"chapterDepth":137,"docKey":6874,"docRoot":6875,"docTitle":6876,"isWikiDoc":140,"isWikiIndex":6878},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F1200-0300-humble2jazzy","wiki\u002F2023-12-30-ros2-tutorial\u002F1200-0300-Humble2Jazzy","Humble与Jazzy导航的差异",[7],"1200-0300",{"path":6990,"stem":6991,"title":6992,"authors":6993,"date":6873,"chapterOrder":6994,"chapterDepth":144,"docKey":6874,"docRoot":6875,"docTitle":6876,"isWikiDoc":140,"isWikiIndex":6878},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F1200-0400-0100-you-xian-zhuang-tai-ji-fsm","wiki\u002F2023-12-30-ros2-tutorial\u002F1200-0400-0100-有限状态机FSM","有限状态机（Finite State Machine）",[7],"1200-0400-0100",{"path":6996,"stem":6997,"title":6998,"authors":6999,"date":6873,"chapterOrder":7000,"chapterDepth":151,"docKey":6874,"docRoot":6875,"docTitle":6876,"isWikiDoc":140,"isWikiIndex":6878},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F1200-0400-0200-0100-ji-ben-gai-nian","wiki\u002F2023-12-30-ros2-tutorial\u002F1200-0400-0200-0100-基本概念","基本概念",[7],"1200-0400-0200-0100",{"path":7002,"stem":7003,"title":7004,"authors":7005,"date":6873,"chapterOrder":7006,"chapterDepth":151,"docKey":6874,"docRoot":6875,"docTitle":6876,"isWikiDoc":140,"isWikiIndex":6878},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F1200-0400-0200-0200-kong-zhi-yu-zhuang-shi-gui-ze","wiki\u002F2023-12-30-ros2-tutorial\u002F1200-0400-0200-0200-控制与装饰规则","控制与装饰规则",[7],"1200-0400-0200-0200",{"path":7008,"stem":7009,"title":7010,"authors":7011,"date":6873,"chapterOrder":7012,"chapterDepth":151,"docKey":6874,"docRoot":6875,"docTitle":6876,"isWikiDoc":140,"isWikiIndex":6878},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F1200-0400-0200-0300-di-yi-ge-wan-zheng-cheng-xu","wiki\u002F2023-12-30-ros2-tutorial\u002F1200-0400-0200-0300-第一个完整程序","第一个完整程序",[7],"1200-0400-0200-0300",{"path":7014,"stem":7015,"title":7016,"authors":7017,"date":6873,"chapterOrder":7018,"chapterDepth":151,"docKey":6874,"docRoot":6875,"docTitle":6876,"isWikiDoc":140,"isWikiIndex":6878},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F1200-0400-0200-0400-jie-dian-zhi-jian-chuan-shu-ju","wiki\u002F2023-12-30-ros2-tutorial\u002F1200-0400-0200-0400-节点之间传数据","节点之间传数据",[7],"1200-0400-0200-0400",{"path":7020,"stem":7021,"title":7022,"authors":7023,"date":6873,"chapterOrder":7024,"chapterDepth":151,"docKey":6874,"docRoot":6875,"docTitle":6876,"isWikiDoc":140,"isWikiIndex":6878},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F1200-0400-0200-0500-chi-xu-ren-wu-yu-zhong-zhi","wiki\u002F2023-12-30-ros2-tutorial\u002F1200-0400-0200-0500-持续任务与中止","持续任务与中止",[7],"1200-0400-0200-0500",{"path":7026,"stem":7027,"title":7028,"authors":7029,"date":6873,"chapterOrder":7030,"chapterDepth":151,"docKey":6874,"docRoot":6875,"docTitle":6876,"isWikiDoc":140,"isWikiIndex":6878},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F1200-0400-0200-0600-zu-he-shi-ji-ren-wu","wiki\u002F2023-12-30-ros2-tutorial\u002F1200-0400-0200-0600-组合实际任务","组合实际任务",[7],"1200-0400-0200-0600",{"path":7032,"stem":7033,"title":7034,"authors":7035,"date":6873,"chapterOrder":7036,"chapterDepth":144,"docKey":6874,"docRoot":6875,"docTitle":6876,"isWikiDoc":140,"isWikiIndex":6878},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F1200-0400-0200-xing-wei-shu-bt","wiki\u002F2023-12-30-ros2-tutorial\u002F1200-0400-0200-行为树BT","行为树（BehaviorTree.CPP）",[7],"1200-0400-0200",{"path":7038,"stem":7039,"title":7040,"authors":7041,"date":6873,"chapterOrder":7042,"chapterDepth":137,"docKey":6874,"docRoot":6875,"docTitle":6876,"isWikiDoc":140,"isWikiIndex":6878},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F1200-0400-fsm-yu-bt","wiki\u002F2023-12-30-ros2-tutorial\u002F1200-0400-FSM与BT","有限状态机FSM与行为树BT",[7],"1200-0400",{"path":7044,"stem":7045,"title":7046,"authors":7047,"date":6873,"chapterOrder":7048,"chapterDepth":6871,"docKey":6874,"docRoot":6875,"docTitle":6876,"isWikiDoc":140,"isWikiIndex":6878},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F1200-ji-qi-ren-dao-hang-navigation2-fang-zhen-pian","wiki\u002F2023-12-30-ros2-tutorial\u002F1200-机器人导航Navigation2(仿真篇)","机器人导航Navigation2(仿真篇)",[7],"1200",{"path":7050,"stem":7051,"title":7052,"authors":7053,"date":6873,"chapterOrder":7054,"chapterDepth":144,"docKey":6874,"docRoot":6875,"docTitle":6876,"isWikiDoc":140,"isWikiIndex":6878},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F1300-0100-0100-boost-aiso","wiki\u002F2023-12-30-ros2-tutorial\u002F1300-0100-0100-Boost.Aiso","Boost.Asio库",[7],"1300-0100-0100",{"path":7056,"stem":7057,"title":7058,"authors":7059,"date":6873,"chapterOrder":7060,"chapterDepth":144,"docKey":6874,"docRoot":6875,"docTitle":6876,"isWikiDoc":140,"isWikiIndex":6878},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F1300-0100-0200-ros2-serial-driver","wiki\u002F2023-12-30-ros2-tutorial\u002F1300-0100-0200-ros2_serial_driver","ROS2 Serial Driver库",[7],"1300-0100-0200",{"path":7062,"stem":7063,"title":7064,"authors":7065,"date":6873,"chapterOrder":7066,"chapterDepth":137,"docKey":6874,"docRoot":6875,"docTitle":6876,"isWikiDoc":140,"isWikiIndex":6878},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F1300-0100-chuan-kou-tong-xin","wiki\u002F2023-12-30-ros2-tutorial\u002F1300-0100-串口通信","UART串口通信",[7],"1300-0100",{"path":7068,"stem":7069,"title":7070,"authors":7071,"date":6873,"chapterOrder":7072,"chapterDepth":144,"docKey":6874,"docRoot":6875,"docTitle":6876,"isWikiDoc":140,"isWikiIndex":6878},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F1300-0200-0100-socketcan","wiki\u002F2023-12-30-ros2-tutorial\u002F1300-0200-0100-socketcan","SocketCAN",[7],"1300-0200-0100",{"path":7074,"stem":7075,"title":7076,"authors":7077,"date":6873,"chapterOrder":7078,"chapterDepth":144,"docKey":6874,"docRoot":6875,"docTitle":6876,"isWikiDoc":140,"isWikiIndex":6878},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F1300-0200-0200-ros2-socketcan","wiki\u002F2023-12-30-ros2-tutorial\u002F1300-0200-0200-ros2_socketcan","ROS2_SocketCAN",[7],"1300-0200-0200",{"path":7080,"stem":7081,"title":7082,"authors":7083,"date":6873,"chapterOrder":7084,"chapterDepth":137,"docKey":6874,"docRoot":6875,"docTitle":6876,"isWikiDoc":140,"isWikiIndex":6878},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F1300-0200-can-tong-xin","wiki\u002F2023-12-30-ros2-tutorial\u002F1300-0200-CAN通信","CAN通信",[7],"1300-0200",{"path":7086,"stem":7087,"title":7052,"authors":7088,"date":6873,"chapterOrder":7089,"chapterDepth":144,"docKey":6874,"docRoot":6875,"docTitle":6876,"isWikiDoc":140,"isWikiIndex":6878},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F1300-0300-0100-boost-aiso","wiki\u002F2023-12-30-ros2-tutorial\u002F1300-0300-0100-Boost.Aiso",[7],"1300-0300-0100",{"path":7091,"stem":7092,"title":7093,"authors":7094,"date":6873,"chapterOrder":7095,"chapterDepth":137,"docKey":6874,"docRoot":6875,"docTitle":6876,"isWikiDoc":140,"isWikiIndex":6878},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F1300-0300-tcp-tong-xin","wiki\u002F2023-12-30-ros2-tutorial\u002F1300-0300-TCP通信","TCP通信",[7],"1300-0300",{"path":7097,"stem":7098,"title":7052,"authors":7099,"date":6873,"chapterOrder":7100,"chapterDepth":144,"docKey":6874,"docRoot":6875,"docTitle":6876,"isWikiDoc":140,"isWikiIndex":6878},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F1300-0400-0100-boost-aiso","wiki\u002F2023-12-30-ros2-tutorial\u002F1300-0400-0100-Boost.Aiso",[7],"1300-0400-0100",{"path":7102,"stem":7103,"title":7104,"authors":7105,"date":6873,"chapterOrder":7106,"chapterDepth":137,"docKey":6874,"docRoot":6875,"docTitle":6876,"isWikiDoc":140,"isWikiIndex":6878},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F1300-0400-udp-tong-xin","wiki\u002F2023-12-30-ros2-tutorial\u002F1300-0400-UDP通信","UDP通信",[7],"1300-0400",{"path":7108,"stem":7109,"title":7110,"authors":7111,"date":6873,"chapterOrder":7112,"chapterDepth":6871,"docKey":6874,"docRoot":6875,"docTitle":6876,"isWikiDoc":140,"isWikiIndex":6878},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F1300-linux-ying-jian-tong-xin","wiki\u002F2023-12-30-ros2-tutorial\u002F1300-Linux硬件通信","Linux硬件通信",[7],"1300",{"path":7114,"stem":7115,"title":7116,"authors":7117,"date":6873,"chapterOrder":7118,"chapterDepth":137,"docKey":6874,"docRoot":6875,"docTitle":6876,"isWikiDoc":140,"isWikiIndex":6878},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F1400-0100-ji-qi-ren-zu-cheng","wiki\u002F2023-12-30-ros2-tutorial\u002F1400-0100-机器人组成","机器人组成",[7],"1400-0100",{"path":7120,"stem":7121,"title":7122,"authors":7123,"date":6873,"chapterOrder":7124,"chapterDepth":144,"docKey":6874,"docRoot":6875,"docTitle":6876,"isWikiDoc":140,"isWikiIndex":6878},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F1400-0200-0100-yuan-cheng-kai-fa-ssh","wiki\u002F2023-12-30-ros2-tutorial\u002F1400-0200-0100-远程开发SSH","远程开发SSH",[7],"1400-0200-0100",{"path":7126,"stem":7127,"title":7128,"authors":7129,"date":6873,"chapterOrder":7130,"chapterDepth":144,"docKey":6874,"docRoot":6875,"docTitle":6876,"isWikiDoc":140,"isWikiIndex":6878},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F1400-0200-0200-yuan-cheng-fang-wen-zhuo-mian","wiki\u002F2023-12-30-ros2-tutorial\u002F1400-0200-0200-远程访问桌面","远程访问桌面",[7],"1400-0200-0200",{"path":7132,"stem":7133,"title":7134,"authors":7135,"date":6873,"chapterOrder":7136,"chapterDepth":137,"docKey":6874,"docRoot":6875,"docTitle":6876,"isWikiDoc":140,"isWikiIndex":6878},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F1400-0200-gong-kong-ji-zhi-yuan-cheng-kai-fa-huan-jing","wiki\u002F2023-12-30-ros2-tutorial\u002F1400-0200-工控机之远程开发环境","工控机之远程开发环境",[7],"1400-0200",{"path":7138,"stem":7139,"title":7140,"authors":7141,"date":6873,"chapterOrder":7142,"chapterDepth":137,"docKey":6874,"docRoot":6875,"docTitle":6876,"isWikiDoc":140,"isWikiIndex":6878},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F1400-0300-gong-kong-ji-zhi-wai-jie-usb-she-bei","wiki\u002F2023-12-30-ros2-tutorial\u002F1400-0300-工控机之外接USB设备","工控机之外接USB设备",[7],"1400-0300",{"path":7144,"stem":7145,"title":7146,"authors":7147,"date":6873,"chapterOrder":7148,"chapterDepth":137,"docKey":6874,"docRoot":6875,"docTitle":6876,"isWikiDoc":140,"isWikiIndex":6878},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F1400-0400-fen-bu-shi-da-jian","wiki\u002F2023-12-30-ros2-tutorial\u002F1400-0400-分布式搭建","分布式搭建",[7],"1400-0400",{"path":7150,"stem":7151,"title":7152,"authors":7153,"date":6873,"chapterOrder":7154,"chapterDepth":137,"docKey":6874,"docRoot":6875,"docTitle":6876,"isWikiDoc":140,"isWikiIndex":6878},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F1400-0500-you-hua-ri-zhi","wiki\u002F2023-12-30-ros2-tutorial\u002F1400-0500-优化日志","优化日志",[7],"1400-0500",{"path":7156,"stem":7157,"title":7158,"authors":7159,"date":6873,"chapterOrder":7160,"chapterDepth":144,"docKey":6874,"docRoot":6875,"docTitle":6876,"isWikiDoc":140,"isWikiIndex":6878},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F1400-0600-0100-li-cheng-ji-odom","wiki\u002F2023-12-30-ros2-tutorial\u002F1400-0600-0100-里程计Odom","里程计Odom",[7],"1400-0600-0100",{"path":7162,"stem":7163,"title":42,"authors":7164,"date":6873,"chapterOrder":7165,"chapterDepth":144,"docKey":6874,"docRoot":6875,"docTitle":6876,"isWikiDoc":140,"isWikiIndex":6878},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F1400-0600-0200-guan-xing-ji-imu","wiki\u002F2023-12-30-ros2-tutorial\u002F1400-0600-0200-惯性计IMU",[7],"1400-0600-0200",{"path":7167,"stem":7168,"title":7169,"authors":7170,"date":6873,"chapterOrder":7171,"chapterDepth":144,"docKey":6874,"docRoot":6875,"docTitle":6876,"isWikiDoc":140,"isWikiIndex":6878},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F1400-0600-0300-ji-guang-lei-da-lidar","wiki\u002F2023-12-30-ros2-tutorial\u002F1400-0600-0300-激光雷达LiDAR","激光雷达LiDAR",[7],"1400-0600-0300",{"path":7173,"stem":7174,"title":7175,"authors":7176,"date":6873,"chapterOrder":7177,"chapterDepth":144,"docKey":6874,"docRoot":6875,"docTitle":6876,"isWikiDoc":140,"isWikiIndex":6878},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F1400-0600-0400-xiang-ji-camera","wiki\u002F2023-12-30-ros2-tutorial\u002F1400-0600-0400-相机Camera","相机Camera",[7],"1400-0600-0400",{"path":7179,"stem":7180,"title":7181,"authors":7182,"date":6873,"chapterOrder":7183,"chapterDepth":144,"docKey":6874,"docRoot":6875,"docTitle":6876,"isWikiDoc":140,"isWikiIndex":6878},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F1400-0600-0500-quan-qiu-ding-wei-gnss","wiki\u002F2023-12-30-ros2-tutorial\u002F1400-0600-0500-全球定位GNSS","全球定位GNSS",[7],"1400-0600-0500",{"path":7185,"stem":7186,"title":7187,"authors":7188,"date":6873,"chapterOrder":7189,"chapterDepth":144,"docKey":6874,"docRoot":6875,"docTitle":6876,"isWikiDoc":140,"isWikiIndex":6878},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F1400-0600-0600-shou-bing-joy","wiki\u002F2023-12-30-ros2-tutorial\u002F1400-0600-0600-手柄joy","手柄JOY",[7],"1400-0600-0600",{"path":7191,"stem":7192,"title":7193,"authors":7194,"date":6873,"chapterOrder":7195,"chapterDepth":144,"docKey":6874,"docRoot":6875,"docTitle":6876,"isWikiDoc":140,"isWikiIndex":6878},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F1400-0600-0700-jian-pan-kong-zhi-jie-dian","wiki\u002F2023-12-30-ros2-tutorial\u002F1400-0600-0700-键盘控制节点","键盘控制节点",[7],"1400-0600-0700",{"path":7197,"stem":7198,"title":7199,"authors":7200,"date":6873,"chapterOrder":7201,"chapterDepth":137,"docKey":6874,"docRoot":6875,"docTitle":6876,"isWikiDoc":140,"isWikiIndex":6878},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F1400-0600-ying-jian-ping-tai","wiki\u002F2023-12-30-ros2-tutorial\u002F1400-0600-硬件平台","硬件平台",[7],"1400-0600",{"path":7203,"stem":7204,"title":7205,"authors":7206,"date":6873,"chapterOrder":7207,"chapterDepth":137,"docKey":6874,"docRoot":6875,"docTitle":6876,"isWikiDoc":140,"isWikiIndex":6878},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F1400-0700-zuo-biao-xi-yu-hua-ti-guan-xi","wiki\u002F2023-12-30-ros2-tutorial\u002F1400-0700-坐标系与话题关系","坐标系与话题关系",[7],"1400-0700",{"path":7209,"stem":7210,"title":7211,"authors":7212,"date":6873,"chapterOrder":7213,"chapterDepth":151,"docKey":6874,"docRoot":6875,"docTitle":6876,"isWikiDoc":140,"isWikiIndex":6878},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F1400-0800-0100-0100-lun-shi-li-cheng-ji-biao-ding","wiki\u002F2023-12-30-ros2-tutorial\u002F1400-0800-0100-0100-轮式里程计标定","轮式里程计标定",[7],"1400-0800-0100-0100",{"path":7215,"stem":7216,"title":7217,"authors":7218,"date":6873,"chapterOrder":7219,"chapterDepth":151,"docKey":6874,"docRoot":6875,"docTitle":6876,"isWikiDoc":140,"isWikiIndex":6878},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F1400-0800-0100-0200-lun-shi-li-cheng-ji-yu-imu-rong-he","wiki\u002F2023-12-30-ros2-tutorial\u002F1400-0800-0100-0200-轮式里程计与IMU融合","轮式里程计与IMU融合",[7],"1400-0800-0100-0200",{"path":7221,"stem":7222,"title":7223,"authors":7224,"date":6873,"chapterOrder":7225,"chapterDepth":144,"docKey":6874,"docRoot":6875,"docTitle":6876,"isWikiDoc":140,"isWikiIndex":6878},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F1400-0800-0100-lun-shi-li-cheng-ji-biao-ding-yu-rong-he","wiki\u002F2023-12-30-ros2-tutorial\u002F1400-0800-0100-轮式里程计标定与融合","轮式里程计标定与融合",[7],"1400-0800-0100",{"path":7227,"stem":7228,"title":7229,"authors":7230,"date":6873,"chapterOrder":7231,"chapterDepth":144,"docKey":6874,"docRoot":6875,"docTitle":6876,"isWikiDoc":140,"isWikiIndex":6878},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F1400-0800-0200-ji-guang-lei-da-gong-ju","wiki\u002F2023-12-30-ros2-tutorial\u002F1400-0800-0200-激光雷达工具","激光雷达工具",[7],"1400-0800-0200",{"path":7233,"stem":7234,"title":7235,"authors":7236,"date":6873,"chapterOrder":7237,"chapterDepth":144,"docKey":6874,"docRoot":6875,"docTitle":6876,"isWikiDoc":140,"isWikiIndex":6878},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F1400-0800-0300-xiang-ji-shi-yong-jin-jie","wiki\u002F2023-12-30-ros2-tutorial\u002F1400-0800-0300-相机使用进阶","相机使用进阶",[7],"1400-0800-0300",{"path":7239,"stem":7240,"title":7241,"authors":7242,"date":6873,"chapterOrder":7243,"chapterDepth":137,"docKey":6874,"docRoot":6875,"docTitle":6876,"isWikiDoc":140,"isWikiIndex":6878},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F1400-0800-ying-jian-ping-tai-jin-jie","wiki\u002F2023-12-30-ros2-tutorial\u002F1400-0800-硬件平台进阶","硬件平台进阶",[7],"1400-0800",{"path":7245,"stem":7246,"title":7247,"authors":7248,"date":6873,"chapterOrder":7249,"chapterDepth":6871,"docKey":6874,"docRoot":6875,"docTitle":6876,"isWikiDoc":140,"isWikiIndex":6878},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F1400-ji-qi-ren-ying-jian","wiki\u002F2023-12-30-ros2-tutorial\u002F1400-机器人硬件","机器人硬件",[7],"1400",{"path":7251,"stem":7252,"title":7253,"authors":7254,"date":6873,"chapterOrder":7255,"chapterDepth":6871,"docKey":6874,"docRoot":6875,"docTitle":6876,"isWikiDoc":140,"isWikiIndex":6878},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F1500-ros2-control","wiki\u002F2023-12-30-ros2-tutorial\u002F1500-ROS2_Control","ROS2_Control",[7],"1500",{"path":7257,"stem":7258,"title":7259,"authors":7260,"date":6873,"chapterOrder":7261,"chapterDepth":6871,"docKey":6874,"docRoot":6875,"docTitle":6876,"isWikiDoc":140,"isWikiIndex":6878},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F1600-moveit2-gong-ye-ji-qi-ren-ji-xie-bi","wiki\u002F2023-12-30-ros2-tutorial\u002F1600-Moveit2工业机器人机械臂","Moveit2工业机器人机械臂",[7],"1600",{"path":7263,"stem":7264,"title":7265,"authors":7266,"date":6873,"chapterOrder":7267,"chapterDepth":6871,"docKey":6874,"docRoot":6875,"docTitle":6876,"isWikiDoc":140,"isWikiIndex":6878},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F1700-ji-qi-ren-dao-hang-navigation2-shi-ti-pian","wiki\u002F2023-12-30-ros2-tutorial\u002F1700-机器人导航Navigation2(实体篇)","机器人导航Navigation2(实体篇)",[7],"1700",{"path":7269,"stem":7270,"title":7271,"authors":7272,"date":6873,"chapterOrder":7273,"chapterDepth":6871,"docKey":6874,"docRoot":6875,"docTitle":6876,"isWikiDoc":140,"isWikiIndex":6878},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F1800-microros","wiki\u002F2023-12-30-ros2-tutorial\u002F1800-MicroROS","MicroROS",[7],"1800",{"path":7275,"stem":7276,"title":7277,"authors":7278,"date":6873,"chapterOrder":7279,"chapterDepth":6871,"docKey":6874,"docRoot":6875,"docTitle":6876,"isWikiDoc":140,"isWikiIndex":6878},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F1900-webots-fang-zhen-ping-tai","wiki\u002F2023-12-30-ros2-tutorial\u002F1900-Webots仿真平台","Webots仿真平台",[7],"1900",{"path":7281,"stem":7282,"title":7283,"authors":7284,"date":6873,"chapterOrder":7285,"chapterDepth":6871,"docKey":6874,"docRoot":6875,"docTitle":6876,"isWikiDoc":140,"isWikiIndex":6878},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F2000-opencv","wiki\u002F2023-12-30-ros2-tutorial\u002F2000-OpenCV","OpenCV",[7],"2000",{"path":6875,"stem":7287,"title":7288,"authors":7289,"date":6873,"chapterOrder":7290,"chapterDepth":6871,"docKey":6874,"docRoot":6875,"docTitle":6876,"isWikiDoc":140,"isWikiIndex":140},"wiki\u002F2023-12-30-ros2-tutorial\u002Findex","ROS2机器人操作系统教程",[7],null,[7292,7294,7297,7300],{"name":7,"image":7293},"\u002Fimages\u002Fmember_photo\u002F董佳辉.jpg",{"name":7295,"image":7296},"宫金良","\u002Fimages\u002Fmember_photo\u002F宫金良.jpg",{"name":7298,"image":7299},"巩丽","\u002Fimages\u002Fmember_photo\u002F巩丽.png",{"name":7301,"image":7302},"张彦斐","\u002Fimages\u002Fmember_photo\u002F张彦斐.jpg",1792431901500]