[{"data":1,"prerenderedAt":3692},["ShallowReactive",2],{"wiki-page-\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F1400-0600-0700-jian-pan-kong-zhi-jie-dian":3,"wiki-doc-items-2023-12-30-ros2-tutorial":3271,"wiki:author-members":3680},{"id":4,"title":5,"authors":6,"body":8,"chapterDepth":92,"chapterOrder":3259,"date":3260,"description":57,"docKey":3261,"docRoot":3262,"docTitle":3263,"extension":3264,"isWikiDoc":88,"isWikiIndex":3265,"meta":3266,"navigation":88,"path":3267,"seo":3268,"stem":3269,"wikiDepth":64,"__hash__":3270},"wiki\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F1400-0600-0700-键盘控制节点.md","键盘控制节点",[7],"董佳辉",{"type":9,"value":10,"toc":3252},"minimark",[11,15,24,47,51,79,199,249,256,259,866,869,938,941,944,962,1097,1100,1103,1107,1144,1147,1153,1159,1165,1171,1176,1179,1501,1504,3248],[12,13,14],"h3",{"id":14},"简介",[16,17,18,19,23],"p",{},"要在 ROS2 中使用 ",[20,21,22],"code",{},"keyboard"," 节点控制底盘，我们需要实现以下步骤：",[25,26,27,35,41],"ol",{},[28,29,30,34],"li",{},[31,32,33],"strong",{},"创建 ROS2 包"," 创建一个新的 ROS2 包用于实现键盘控制功能。",[28,36,37,40],{},[31,38,39],{},"编写键盘控制节点"," 编写一个 C++ 节点，用于监听键盘输入并发布速度命令。",[28,42,43,46],{},[31,44,45],{},"与麦轮底盘通信"," 将发布的速度命令与底盘控制结合。",[12,48,50],{"id":49},"twist消息接口","Twist消息接口",[52,53,58],"pre",{"className":54,"code":55,"language":56,"meta":57,"style":57},"language-bash shiki shiki-themes github-light github-dark","ros2 interface show geometry_msgs\u002Fmsg\u002FTwist\n","bash","",[20,59,60],{"__ignoreMap":57},[61,62,65,69,73,76],"span",{"class":63,"line":64},"line",1,[61,66,68],{"class":67},"sScJk","ros2",[61,70,72],{"class":71},"sZZnC"," interface",[61,74,75],{"class":71}," show",[61,77,78],{"class":71}," geometry_msgs\u002Fmsg\u002FTwist\n",[52,80,82],{"className":54,"code":81,"language":56,"meta":57,"style":57},"\n# This expresses velocity in free space broken into its linear and angular parts.\n\n# 该消息表示自由空间中的速度，分为线速度和角速度两部分。\n\nVector3  linear\n        float64 x  # 线速度的 x 分量（通常表示前后方向的速度）\n        float64 y  # 线速度的 y 分量（通常表示左右方向的速度）\n        float64 z  # 线速度的 z 分量（通常表示上下方向的速度）\n\nVector3  angular\n        float64 x  # 角速度的 x 分量（绕 x 轴的旋转速度）\n        float64 y  # 角速度的 y 分量（绕 y 轴的旋转速度）\n        float64 z  # 角速度的 z 分量（绕 z 轴的旋转速度）\n\n",[20,83,84,90,97,102,108,113,122,134,145,156,161,169,179,189],{"__ignoreMap":57},[61,85,86],{"class":63,"line":64},[61,87,89],{"emptyLinePlaceholder":88},true,"\n",[61,91,93],{"class":63,"line":92},2,[61,94,96],{"class":95},"sJ8bj","# This expresses velocity in free space broken into its linear and angular parts.\n",[61,98,100],{"class":63,"line":99},3,[61,101,89],{"emptyLinePlaceholder":88},[61,103,105],{"class":63,"line":104},4,[61,106,107],{"class":95},"# 该消息表示自由空间中的速度，分为线速度和角速度两部分。\n",[61,109,111],{"class":63,"line":110},5,[61,112,89],{"emptyLinePlaceholder":88},[61,114,116,119],{"class":63,"line":115},6,[61,117,118],{"class":67},"Vector3",[61,120,121],{"class":71},"  linear\n",[61,123,125,128,131],{"class":63,"line":124},7,[61,126,127],{"class":67},"        float64",[61,129,130],{"class":71}," x",[61,132,133],{"class":95},"  # 线速度的 x 分量（通常表示前后方向的速度）\n",[61,135,137,139,142],{"class":63,"line":136},8,[61,138,127],{"class":67},[61,140,141],{"class":71}," y",[61,143,144],{"class":95},"  # 线速度的 y 分量（通常表示左右方向的速度）\n",[61,146,148,150,153],{"class":63,"line":147},9,[61,149,127],{"class":67},[61,151,152],{"class":71}," z",[61,154,155],{"class":95},"  # 线速度的 z 分量（通常表示上下方向的速度）\n",[61,157,159],{"class":63,"line":158},10,[61,160,89],{"emptyLinePlaceholder":88},[61,162,164,166],{"class":63,"line":163},11,[61,165,118],{"class":67},[61,167,168],{"class":71},"  angular\n",[61,170,172,174,176],{"class":63,"line":171},12,[61,173,127],{"class":67},[61,175,130],{"class":71},[61,177,178],{"class":95},"  # 角速度的 x 分量（绕 x 轴的旋转速度）\n",[61,180,182,184,186],{"class":63,"line":181},13,[61,183,127],{"class":67},[61,185,141],{"class":71},[61,187,188],{"class":95},"  # 角速度的 y 分量（绕 y 轴的旋转速度）\n",[61,190,192,194,196],{"class":63,"line":191},14,[61,193,127],{"class":67},[61,195,152],{"class":71},[61,197,198],{"class":95},"  # 角速度的 z 分量（绕 z 轴的旋转速度）\n",[200,201,202,228],"ul",{},[28,203,204,207,208],{},[31,205,206],{},"线速度（linear）"," ：描述物体在三维空间中沿直线运动的速度。通常在移动机器人中：",[200,209,210,216,222],{},[28,211,212,215],{},[20,213,214],{},"x"," 表示前进\u002F后退。",[28,217,218,221],{},[20,219,220],{},"y"," 表示左右平移。",[28,223,224,227],{},[20,225,226],{},"z"," 通常为 0，因为大部分地面机器人只在平面上运动。",[28,229,230,233,234],{},[31,231,232],{},"角速度（angular）"," ：描述物体在三维空间中绕某一轴旋转的速度。通常在移动机器人中：",[200,235,236,241],{},[28,237,238,240],{},[20,239,226],{}," 表示绕垂直轴的旋转（顺时针\u002F逆时针）。",[28,242,243,245,246,248],{},[20,244,214],{}," 和 ",[20,247,220],{}," 通常为 0，因为大多数地面机器人只需要在平面上旋转。",[16,250,251,252,255],{},"这个消息类型广泛用于控制机器人运动，也就是我们常说的DOF自由度，通过发布到 ",[20,253,254],{},"\u002Fcmd_vel"," 话题，可以为机器人提供运动指令。",[12,257,258],{"id":258},"发布cmd_vel给单片机",[52,260,264],{"className":261,"code":262,"language":263,"meta":57,"style":57},"language-cpp shiki shiki-themes github-light github-dark","\u002F\u002F初始化串口消息订阅\nrclcpp::Subscription\u003Cgeometry_msgs::msg::Twist>::SharedPtr cmd_vel_sub_;\ncmd_vel_sub_ = this->create_subscription\u003Cgeometry_msgs::msg::Twist(\"cmd_vel\",10,std::bind(&Serial_Node::cmd_vel_sub_callback,this,std::placeholders::_1));\n\n  void cmd_vel_sub_callback(const geometry_msgs::msg::Twist &cmd_msg)\n  {\n    \u002F\u002F bool bool_buffer[] = {1, 0, 1, 0};\n    \u002F\u002F int8_t int8_buffer[] = {0x11,0x22};\n    \u002F\u002F int16_t int16_buffer[] = {2000,6666};\n    \u002F\u002F int32_t int32_buffer[] = {305419896};\n    fp32 fp32_buffer[] = {(fp32)cmd_msg.linear.x,(fp32)cmd_msg.linear.y,(fp32)cmd_msg.linear.z,\n                          (fp32)cmd_msg.angular.x,(fp32)cmd_msg.angular.y,(fp32)cmd_msg.angular.z};\n\n    \u002F\u002F由于ROS2中node为局部变量，所以只能在node中调用send函数，所以Serial_Transmit只负责处理data_buffer。\n    serial_pack_.tx.Data_Pack(0x01, \n                                 nullptr, 0,\n                                 nullptr, 0,\n                                 nullptr, 0,\n                                 nullptr, 0,\n                                 fp32_buffer, sizeof(fp32_buffer) \u002F sizeof(fp32));\n\n    auto port = serial_driver_->port();\n\n    try\n    {\n      size_t bytes_size = port->send(data_buffer);\n      \u002F\u002F RCLCPP_INFO(this->get_logger(), \"Transmitted: \");\n      \u002F\u002F for (size_t i = 0; i \u003C data_buffer.size(); ++i) \n      \u002F\u002F {\n        \u002F\u002F RCLCPP_INFO(this->get_logger(), \"0x%02X \", data_buffer[i]);  \u002F\u002F以十六进制格式打印每个字节\n      \u002F\u002F }\n      RCLCPP_INFO(this->get_logger(), \"平动XYZ：%.6f,%.6f,%.6f\", fp32_buffer[0],fp32_buffer[1],fp32_buffer[2]);\n      RCLCPP_INFO(this->get_logger(), \"转动XYZ：%.6f,%.6f,%.6f\", fp32_buffer[3],fp32_buffer[4],fp32_buffer[5]);\n      RCLCPP_INFO(this->get_logger(), \"(%ld bytes)\", bytes_size);\n      \u002F\u002F (void)bytes_size;\n    }\n    catch(const std::exception &ex)\n    {\n      RCLCPP_ERROR(this->get_logger(), \"Error Transmiting from serial port:%s\",ex.what());\n    }\n  }\n};\n","cpp",[20,265,266,271,302,378,382,416,421,426,431,436,441,451,456,460,465,485,500,511,522,533,554,559,579,584,590,596,616,622,628,634,643,649,704,751,778,784,790,811,816,849,854,860],{"__ignoreMap":57},[61,267,268],{"class":63,"line":64},[61,269,270],{"class":95},"\u002F\u002F初始化串口消息订阅\n",[61,272,273,276,280,283,286,289,291,294,296,299],{"class":63,"line":92},[61,274,275],{"class":67},"rclcpp",[61,277,279],{"class":278},"sVt8B","::",[61,281,282],{"class":67},"Subscription",[61,284,285],{"class":278},"\u003C",[61,287,288],{"class":67},"geometry_msgs",[61,290,279],{"class":278},[61,292,293],{"class":67},"msg",[61,295,279],{"class":278},[61,297,298],{"class":67},"Twist",[61,300,301],{"class":278},">::SharedPtr cmd_vel_sub_;\n",[61,303,304,307,311,315,318,320,322,324,326,328,330,333,336,339,342,344,347,349,352,354,357,360,363,366,368,370,372,375],{"class":63,"line":99},[61,305,306],{"class":278},"cmd_vel_sub_ ",[61,308,310],{"class":309},"szBVR","=",[61,312,314],{"class":313},"sj4cs"," this",[61,316,317],{"class":278},"->create_subscription",[61,319,285],{"class":309},[61,321,288],{"class":67},[61,323,279],{"class":278},[61,325,293],{"class":67},[61,327,279],{"class":278},[61,329,298],{"class":67},[61,331,332],{"class":278},"(",[61,334,335],{"class":71},"\"cmd_vel\"",[61,337,338],{"class":278},",",[61,340,341],{"class":313},"10",[61,343,338],{"class":278},[61,345,346],{"class":67},"std",[61,348,279],{"class":278},[61,350,351],{"class":67},"bind",[61,353,332],{"class":278},[61,355,356],{"class":309},"&",[61,358,359],{"class":67},"Serial_Node",[61,361,362],{"class":278},"::cmd_vel_sub_callback,",[61,364,365],{"class":313},"this",[61,367,338],{"class":278},[61,369,346],{"class":67},[61,371,279],{"class":278},[61,373,374],{"class":67},"placeholders",[61,376,377],{"class":278},"::_1));\n",[61,379,380],{"class":63,"line":104},[61,381,89],{"emptyLinePlaceholder":88},[61,383,384,387,390,392,395,398,400,402,404,406,409,413],{"class":63,"line":110},[61,385,386],{"class":309},"  void",[61,388,389],{"class":67}," cmd_vel_sub_callback",[61,391,332],{"class":278},[61,393,394],{"class":309},"const",[61,396,397],{"class":67}," geometry_msgs",[61,399,279],{"class":278},[61,401,293],{"class":67},[61,403,279],{"class":278},[61,405,298],{"class":67},[61,407,408],{"class":309}," &",[61,410,412],{"class":411},"s4XuR","cmd_msg",[61,414,415],{"class":278},")\n",[61,417,418],{"class":63,"line":115},[61,419,420],{"class":278},"  {\n",[61,422,423],{"class":63,"line":124},[61,424,425],{"class":95},"    \u002F\u002F bool bool_buffer[] = {1, 0, 1, 0};\n",[61,427,428],{"class":63,"line":136},[61,429,430],{"class":95},"    \u002F\u002F int8_t int8_buffer[] = {0x11,0x22};\n",[61,432,433],{"class":63,"line":147},[61,434,435],{"class":95},"    \u002F\u002F int16_t int16_buffer[] = {2000,6666};\n",[61,437,438],{"class":63,"line":158},[61,439,440],{"class":95},"    \u002F\u002F int32_t int32_buffer[] = {305419896};\n",[61,442,443,446,448],{"class":63,"line":163},[61,444,445],{"class":278},"    fp32 fp32_buffer[] ",[61,447,310],{"class":309},[61,449,450],{"class":278}," {(fp32)cmd_msg.linear.x,(fp32)cmd_msg.linear.y,(fp32)cmd_msg.linear.z,\n",[61,452,453],{"class":63,"line":171},[61,454,455],{"class":278},"                          (fp32)cmd_msg.angular.x,(fp32)cmd_msg.angular.y,(fp32)cmd_msg.angular.z};\n",[61,457,458],{"class":63,"line":181},[61,459,89],{"emptyLinePlaceholder":88},[61,461,462],{"class":63,"line":191},[61,463,464],{"class":95},"    \u002F\u002F由于ROS2中node为局部变量，所以只能在node中调用send函数，所以Serial_Transmit只负责处理data_buffer。\n",[61,466,468,471,474,476,479,482],{"class":63,"line":467},15,[61,469,470],{"class":278},"    serial_pack_.tx.",[61,472,473],{"class":67},"Data_Pack",[61,475,332],{"class":278},[61,477,478],{"class":309},"0x",[61,480,481],{"class":313},"01",[61,483,484],{"class":278},", \n",[61,486,488,491,494,497],{"class":63,"line":487},16,[61,489,490],{"class":313},"                                 nullptr",[61,492,493],{"class":278},", ",[61,495,496],{"class":313},"0",[61,498,499],{"class":278},",\n",[61,501,503,505,507,509],{"class":63,"line":502},17,[61,504,490],{"class":313},[61,506,493],{"class":278},[61,508,496],{"class":313},[61,510,499],{"class":278},[61,512,514,516,518,520],{"class":63,"line":513},18,[61,515,490],{"class":313},[61,517,493],{"class":278},[61,519,496],{"class":313},[61,521,499],{"class":278},[61,523,525,527,529,531],{"class":63,"line":524},19,[61,526,490],{"class":313},[61,528,493],{"class":278},[61,530,496],{"class":313},[61,532,499],{"class":278},[61,534,536,539,542,545,548,551],{"class":63,"line":535},20,[61,537,538],{"class":278},"                                 fp32_buffer, ",[61,540,541],{"class":309},"sizeof",[61,543,544],{"class":278},"(fp32_buffer) ",[61,546,547],{"class":309},"\u002F",[61,549,550],{"class":309}," sizeof",[61,552,553],{"class":278},"(fp32));\n",[61,555,557],{"class":63,"line":556},21,[61,558,89],{"emptyLinePlaceholder":88},[61,560,562,565,568,570,573,576],{"class":63,"line":561},22,[61,563,564],{"class":309},"    auto",[61,566,567],{"class":278}," port ",[61,569,310],{"class":309},[61,571,572],{"class":278}," serial_driver_->",[61,574,575],{"class":67},"port",[61,577,578],{"class":278},"();\n",[61,580,582],{"class":63,"line":581},23,[61,583,89],{"emptyLinePlaceholder":88},[61,585,587],{"class":63,"line":586},24,[61,588,589],{"class":309},"    try\n",[61,591,593],{"class":63,"line":592},25,[61,594,595],{"class":278},"    {\n",[61,597,599,602,605,607,610,613],{"class":63,"line":598},26,[61,600,601],{"class":309},"      size_t",[61,603,604],{"class":278}," bytes_size ",[61,606,310],{"class":309},[61,608,609],{"class":278}," port->",[61,611,612],{"class":67},"send",[61,614,615],{"class":278},"(data_buffer);\n",[61,617,619],{"class":63,"line":618},27,[61,620,621],{"class":95},"      \u002F\u002F RCLCPP_INFO(this->get_logger(), \"Transmitted: \");\n",[61,623,625],{"class":63,"line":624},28,[61,626,627],{"class":95},"      \u002F\u002F for (size_t i = 0; i \u003C data_buffer.size(); ++i) \n",[61,629,631],{"class":63,"line":630},29,[61,632,633],{"class":95},"      \u002F\u002F {\n",[61,635,637,640],{"class":63,"line":636},30,[61,638,639],{"class":95},"        \u002F\u002F RCLCPP_INFO(this->get_logger(), \"0x%02X \", data_buffer[i]);",[61,641,642],{"class":95},"  \u002F\u002F以十六进制格式打印每个字节\n",[61,644,646],{"class":63,"line":645},31,[61,647,648],{"class":95},"      \u002F\u002F }\n",[61,650,652,655,657,659,662,665,668,671,674,676,678,680,682,685,688,690,693,696,698,701],{"class":63,"line":651},32,[61,653,654],{"class":67},"      RCLCPP_INFO",[61,656,332],{"class":278},[61,658,365],{"class":313},[61,660,661],{"class":278},"->",[61,663,664],{"class":67},"get_logger",[61,666,667],{"class":278},"(), ",[61,669,670],{"class":71},"\"平动XYZ：",[61,672,673],{"class":313},"%.6f",[61,675,338],{"class":71},[61,677,673],{"class":313},[61,679,338],{"class":71},[61,681,673],{"class":313},[61,683,684],{"class":71},"\"",[61,686,687],{"class":278},", fp32_buffer[",[61,689,496],{"class":313},[61,691,692],{"class":278},"],fp32_buffer[",[61,694,695],{"class":313},"1",[61,697,692],{"class":278},[61,699,700],{"class":313},"2",[61,702,703],{"class":278},"]);\n",[61,705,707,709,711,713,715,717,719,722,724,726,728,730,732,734,736,739,741,744,746,749],{"class":63,"line":706},33,[61,708,654],{"class":67},[61,710,332],{"class":278},[61,712,365],{"class":313},[61,714,661],{"class":278},[61,716,664],{"class":67},[61,718,667],{"class":278},[61,720,721],{"class":71},"\"转动XYZ：",[61,723,673],{"class":313},[61,725,338],{"class":71},[61,727,673],{"class":313},[61,729,338],{"class":71},[61,731,673],{"class":313},[61,733,684],{"class":71},[61,735,687],{"class":278},[61,737,738],{"class":313},"3",[61,740,692],{"class":278},[61,742,743],{"class":313},"4",[61,745,692],{"class":278},[61,747,748],{"class":313},"5",[61,750,703],{"class":278},[61,752,754,756,758,760,762,764,766,769,772,775],{"class":63,"line":753},34,[61,755,654],{"class":67},[61,757,332],{"class":278},[61,759,365],{"class":313},[61,761,661],{"class":278},[61,763,664],{"class":67},[61,765,667],{"class":278},[61,767,768],{"class":71},"\"(",[61,770,771],{"class":313},"%ld",[61,773,774],{"class":71}," bytes)\"",[61,776,777],{"class":278},", bytes_size);\n",[61,779,781],{"class":63,"line":780},35,[61,782,783],{"class":95},"      \u002F\u002F (void)bytes_size;\n",[61,785,787],{"class":63,"line":786},36,[61,788,789],{"class":278},"    }\n",[61,791,793,796,798,800,803,806,808],{"class":63,"line":792},37,[61,794,795],{"class":309},"    catch",[61,797,332],{"class":278},[61,799,394],{"class":309},[61,801,802],{"class":67}," std",[61,804,805],{"class":278},"::exception ",[61,807,356],{"class":309},[61,809,810],{"class":278},"ex)\n",[61,812,814],{"class":63,"line":813},38,[61,815,595],{"class":278},[61,817,819,822,824,826,828,830,832,835,838,840,843,846],{"class":63,"line":818},39,[61,820,821],{"class":67},"      RCLCPP_ERROR",[61,823,332],{"class":278},[61,825,365],{"class":313},[61,827,661],{"class":278},[61,829,664],{"class":67},[61,831,667],{"class":278},[61,833,834],{"class":71},"\"Error Transmiting from serial port:",[61,836,837],{"class":313},"%s",[61,839,684],{"class":71},[61,841,842],{"class":278},",ex.",[61,844,845],{"class":67},"what",[61,847,848],{"class":278},"());\n",[61,850,852],{"class":63,"line":851},40,[61,853,789],{"class":278},[61,855,857],{"class":63,"line":856},41,[61,858,859],{"class":278},"  }\n",[61,861,863],{"class":63,"line":862},42,[61,864,865],{"class":278},"};\n",[16,867,868],{},"STM32部分代码：",[52,870,872],{"className":261,"code":871,"language":263,"meta":57,"style":57},"    case CHASSIS_ROS2_CMD: \u002F\u002FROS2接管模式\n        \u002F\u002F单位就是m\u002Fs和rad\u002Fs\n        this->oriChassis.Speed.vx =   cmd_vel_.Linear.Y;\n        this->oriChassis.Speed.vy =   cmd_vel_.Linear.X;\n        this->oriChassis.Speed.vw = - cmd_vel_.Angular.Z;\n        break;\n",[20,873,874,885,890,903,915,930],{"__ignoreMap":57},[61,875,876,879,882],{"class":63,"line":64},[61,877,878],{"class":309},"    case",[61,880,881],{"class":278}," CHASSIS_ROS2_CMD:",[61,883,884],{"class":95}," \u002F\u002FROS2接管模式\n",[61,886,887],{"class":63,"line":92},[61,888,889],{"class":95},"        \u002F\u002F单位就是m\u002Fs和rad\u002Fs\n",[61,891,892,895,898,900],{"class":63,"line":99},[61,893,894],{"class":313},"        this",[61,896,897],{"class":278},"->oriChassis.Speed.vx ",[61,899,310],{"class":309},[61,901,902],{"class":278},"   cmd_vel_.Linear.Y;\n",[61,904,905,907,910,912],{"class":63,"line":104},[61,906,894],{"class":313},[61,908,909],{"class":278},"->oriChassis.Speed.vy ",[61,911,310],{"class":309},[61,913,914],{"class":278},"   cmd_vel_.Linear.X;\n",[61,916,917,919,922,924,927],{"class":63,"line":110},[61,918,894],{"class":313},[61,920,921],{"class":278},"->oriChassis.Speed.vw ",[61,923,310],{"class":309},[61,925,926],{"class":309}," -",[61,928,929],{"class":278}," cmd_vel_.Angular.Z;\n",[61,931,932,935],{"class":63,"line":115},[61,933,934],{"class":309},"        break",[61,936,937],{"class":278},";\n",[16,939,940],{},"由于我的STM32以Y为底盘前后方向，ROS2以X为底盘前后方向，所以我这里并不是完全对应的。",[12,942,943],{"id":943},"官方节点",[52,945,947],{"className":54,"code":946,"language":56,"meta":57,"style":57},"ros2 run teleop_twist_keyboard teleop_twist_keyboard\n",[20,948,949],{"__ignoreMap":57},[61,950,951,953,956,959],{"class":63,"line":64},[61,952,68],{"class":67},[61,954,955],{"class":71}," run",[61,957,958],{"class":71}," teleop_twist_keyboard",[61,960,961],{"class":71}," teleop_twist_keyboard\n",[200,963,964,974,985,995,1004,1010,1021,1031,1042,1055,1072,1087],{},[28,965,966,969,970,973],{},[20,967,968],{},"i",": 向前移动（增加线速度 ",[20,971,972],{},"linear.x","）",[28,975,976,978,979,982,983,973],{},[20,977,338],{}," ",[31,980,981],{},"(逗号)"," : 向后移动（减少线速度 ",[20,984,972],{},[28,986,987,990,991,994],{},[20,988,989],{},"j",": 左转（增加角速度 ",[20,992,993],{},"angular.z","，逆时针）",[28,996,997,1000,1001,1003],{},[20,998,999],{},"l",": 右转（减少角速度 ",[20,1002,993],{},"，顺时针）",[28,1005,1006,1009],{},[20,1007,1008],{},"k",": 紧急停止（将线速度和角速度归零）",[28,1011,1012,1015,1016,1018,1019,973],{},[20,1013,1014],{},"u",": 向前左转（组合运动：",[20,1017,972],{}," + ",[20,1020,993],{},[28,1022,1023,1026,1027,1018,1029,973],{},[20,1024,1025],{},"o",": 向前右转（组合运动：",[20,1028,972],{},[20,1030,993],{},[28,1032,1033,1036,1037,1018,1040,973],{},[20,1034,1035],{},"m",": 向后左转（组合运动：",[20,1038,1039],{},"-linear.x",[20,1041,993],{},[28,1043,1044,978,1047,1050,1051,1018,1053,973],{},[20,1045,1046],{},".",[31,1048,1049],{},"(句号)"," : 向后右转（组合运动：",[20,1052,1039],{},[20,1054,993],{},[28,1056,1057,1060,1062,1064,1065,1068,1069,1071],{},[20,1058,1059],{},"w",[31,1061,547],{},[20,1063,214],{},": 增加\u002F减少 ",[31,1066,1067],{},"线速度"," （",[20,1070,972],{}," 的增量步长）",[28,1073,1074,1077,1079,1064,1082,1068,1085,1071],{},[20,1075,1076],{},"a",[31,1078,547],{},[20,1080,1081],{},"d",[31,1083,1084],{},"角速度",[20,1086,993],{},[28,1088,1089,1092,1094,1009],{},[20,1090,1091],{},"s",[31,1093,547],{},[20,1095,1096],{},"S",[16,1098,1099],{},"建议可以使用官方的节点。记得跑之前，先将步长降低。",[12,1101,1102],{"id":1102},"自定义节点",[1104,1105,1106],"h4",{"id":1106},"功能包创建",[52,1108,1110],{"className":54,"code":1109,"language":56,"meta":57,"style":57},"ros2 pkg create cyber_teleop_twist_keyboard --build-type ament_cmake --dependencies rclcpp geometry_msgs --node-name teleop_twist_keyboard\n",[20,1111,1112],{"__ignoreMap":57},[61,1113,1114,1116,1119,1122,1125,1128,1131,1134,1137,1139,1142],{"class":63,"line":64},[61,1115,68],{"class":67},[61,1117,1118],{"class":71}," pkg",[61,1120,1121],{"class":71}," create",[61,1123,1124],{"class":71}," cyber_teleop_twist_keyboard",[61,1126,1127],{"class":313}," --build-type",[61,1129,1130],{"class":71}," ament_cmake",[61,1132,1133],{"class":313}," --dependencies",[61,1135,1136],{"class":71}," rclcpp",[61,1138,397],{"class":71},[61,1140,1141],{"class":313}," --node-name",[61,1143,961],{"class":71},[1104,1145,1146],{"id":1146},"节点主逻辑",[16,1148,1149,1152],{},[20,1150,1151],{},"w\u002Fs\u002Fa\u002Fd","：控制机器人前进\u002F后退\u002F左平移\u002F右平移。",[16,1154,1155,1158],{},[20,1156,1157],{},"q\u002Fe","：控制机器人逆时针\u002F顺时针旋转。",[16,1160,1161,1164],{},[20,1162,1163],{},"i\u002F,","：调整线速度步长（加速\u002F减速步长）。",[16,1166,1167,1170],{},[20,1168,1169],{},"j\u002Fl","：调整角速度步长（减速\u002F加速步长）。",[16,1172,1173,1175],{},[20,1174,1008],{},"：停止所有运动。",[16,1177,1178],{},"下方是一个核心函数，用于检测按键。",[52,1180,1182],{"className":261,"code":1181,"language":263,"meta":57,"style":57},"#include \u003Ctermios.h>\n#include \u003Cunistd.h>\n#include \u003Cfcntl.h>\n\n    \u002F\u002F查键盘输入的函数，它不需要按回车就能返回键盘输入。它通过修改终端设置，使得可以直接获取按键的值。\n    int kbhit(void)\n    {\n      struct termios oldt, newt;\n      int ch;\n      int oldf;\n\n      tcgetattr(STDIN_FILENO, &oldt);        \u002F\u002F 获取当前终端的设置\n      newt = oldt;\n      newt.c_lflag &= ~(ICANON | ECHO);       \u002F\u002F 禁用缓冲模式和回显\n      newt.c_cc[VMIN] = 1;\n      newt.c_cc[VTIME] = 0;\n      tcsetattr(STDIN_FILENO, TCSANOW, &newt); \u002F\u002F 设置新的终端设置\n\n      oldf = fcntl(STDIN_FILENO, F_GETFL, 0);\n      fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK); \u002F\u002F 设置为非阻塞模式\n\n      ch = getchar(); \u002F\u002F 获取字符\n      tcsetattr(STDIN_FILENO, TCSANOW, &oldt);   \u002F\u002F 恢复终端设置\n      fcntl(STDIN_FILENO, F_SETFL, oldf);         \u002F\u002F 恢复文件描述符设置\n\n      if(ch != EOF) { \n          ungetc(ch, stdin);  \u002F\u002F 将字符放回标准输入流\n          return 1;           \u002F\u002F 如果读取了字符，返回 1\n      }\n\n      return 0;   \u002F\u002F 没有读取到字符\n    }\n",[20,1183,1184,1192,1199,1206,1210,1215,1230,1234,1245,1253,1260,1264,1280,1290,1313,1325,1337,1353,1357,1375,1391,1395,1411,1424,1434,1438,1452,1463,1476,1481,1485,1497],{"__ignoreMap":57},[61,1185,1186,1189],{"class":63,"line":64},[61,1187,1188],{"class":309},"#include",[61,1190,1191],{"class":71}," \u003Ctermios.h>\n",[61,1193,1194,1196],{"class":63,"line":92},[61,1195,1188],{"class":309},[61,1197,1198],{"class":71}," \u003Cunistd.h>\n",[61,1200,1201,1203],{"class":63,"line":99},[61,1202,1188],{"class":309},[61,1204,1205],{"class":71}," \u003Cfcntl.h>\n",[61,1207,1208],{"class":63,"line":104},[61,1209,89],{"emptyLinePlaceholder":88},[61,1211,1212],{"class":63,"line":110},[61,1213,1214],{"class":95},"    \u002F\u002F查键盘输入的函数，它不需要按回车就能返回键盘输入。它通过修改终端设置，使得可以直接获取按键的值。\n",[61,1216,1217,1220,1223,1225,1228],{"class":63,"line":115},[61,1218,1219],{"class":309},"    int",[61,1221,1222],{"class":67}," kbhit",[61,1224,332],{"class":278},[61,1226,1227],{"class":309},"void",[61,1229,415],{"class":278},[61,1231,1232],{"class":63,"line":124},[61,1233,595],{"class":278},[61,1235,1236,1239,1242],{"class":63,"line":136},[61,1237,1238],{"class":309},"      struct",[61,1240,1241],{"class":67}," termios",[61,1243,1244],{"class":278}," oldt, newt;\n",[61,1246,1247,1250],{"class":63,"line":147},[61,1248,1249],{"class":309},"      int",[61,1251,1252],{"class":278}," ch;\n",[61,1254,1255,1257],{"class":63,"line":158},[61,1256,1249],{"class":309},[61,1258,1259],{"class":278}," oldf;\n",[61,1261,1262],{"class":63,"line":163},[61,1263,89],{"emptyLinePlaceholder":88},[61,1265,1266,1269,1272,1274,1277],{"class":63,"line":171},[61,1267,1268],{"class":67},"      tcgetattr",[61,1270,1271],{"class":278},"(STDIN_FILENO, ",[61,1273,356],{"class":309},[61,1275,1276],{"class":278},"oldt);",[61,1278,1279],{"class":95},"        \u002F\u002F 获取当前终端的设置\n",[61,1281,1282,1285,1287],{"class":63,"line":181},[61,1283,1284],{"class":278},"      newt ",[61,1286,310],{"class":309},[61,1288,1289],{"class":278}," oldt;\n",[61,1291,1292,1295,1298,1301,1304,1307,1310],{"class":63,"line":191},[61,1293,1294],{"class":278},"      newt.c_lflag ",[61,1296,1297],{"class":309},"&=",[61,1299,1300],{"class":309}," ~",[61,1302,1303],{"class":278},"(ICANON ",[61,1305,1306],{"class":309},"|",[61,1308,1309],{"class":278}," ECHO);",[61,1311,1312],{"class":95},"       \u002F\u002F 禁用缓冲模式和回显\n",[61,1314,1315,1318,1320,1323],{"class":63,"line":467},[61,1316,1317],{"class":278},"      newt.c_cc[VMIN] ",[61,1319,310],{"class":309},[61,1321,1322],{"class":313}," 1",[61,1324,937],{"class":278},[61,1326,1327,1330,1332,1335],{"class":63,"line":487},[61,1328,1329],{"class":278},"      newt.c_cc[VTIME] ",[61,1331,310],{"class":309},[61,1333,1334],{"class":313}," 0",[61,1336,937],{"class":278},[61,1338,1339,1342,1345,1347,1350],{"class":63,"line":502},[61,1340,1341],{"class":67},"      tcsetattr",[61,1343,1344],{"class":278},"(STDIN_FILENO, TCSANOW, ",[61,1346,356],{"class":309},[61,1348,1349],{"class":278},"newt);",[61,1351,1352],{"class":95}," \u002F\u002F 设置新的终端设置\n",[61,1354,1355],{"class":63,"line":513},[61,1356,89],{"emptyLinePlaceholder":88},[61,1358,1359,1362,1364,1367,1370,1372],{"class":63,"line":524},[61,1360,1361],{"class":278},"      oldf ",[61,1363,310],{"class":309},[61,1365,1366],{"class":67}," fcntl",[61,1368,1369],{"class":278},"(STDIN_FILENO, F_GETFL, ",[61,1371,496],{"class":313},[61,1373,1374],{"class":278},");\n",[61,1376,1377,1380,1383,1385,1388],{"class":63,"line":535},[61,1378,1379],{"class":67},"      fcntl",[61,1381,1382],{"class":278},"(STDIN_FILENO, F_SETFL, oldf ",[61,1384,1306],{"class":309},[61,1386,1387],{"class":278}," O_NONBLOCK);",[61,1389,1390],{"class":95}," \u002F\u002F 设置为非阻塞模式\n",[61,1392,1393],{"class":63,"line":556},[61,1394,89],{"emptyLinePlaceholder":88},[61,1396,1397,1400,1402,1405,1408],{"class":63,"line":561},[61,1398,1399],{"class":278},"      ch ",[61,1401,310],{"class":309},[61,1403,1404],{"class":67}," getchar",[61,1406,1407],{"class":278},"();",[61,1409,1410],{"class":95}," \u002F\u002F 获取字符\n",[61,1412,1413,1415,1417,1419,1421],{"class":63,"line":581},[61,1414,1341],{"class":67},[61,1416,1344],{"class":278},[61,1418,356],{"class":309},[61,1420,1276],{"class":278},[61,1422,1423],{"class":95},"   \u002F\u002F 恢复终端设置\n",[61,1425,1426,1428,1431],{"class":63,"line":586},[61,1427,1379],{"class":67},[61,1429,1430],{"class":278},"(STDIN_FILENO, F_SETFL, oldf);",[61,1432,1433],{"class":95},"         \u002F\u002F 恢复文件描述符设置\n",[61,1435,1436],{"class":63,"line":592},[61,1437,89],{"emptyLinePlaceholder":88},[61,1439,1440,1443,1446,1449],{"class":63,"line":598},[61,1441,1442],{"class":309},"      if",[61,1444,1445],{"class":278},"(ch ",[61,1447,1448],{"class":309},"!=",[61,1450,1451],{"class":278}," EOF) { \n",[61,1453,1454,1457,1460],{"class":63,"line":618},[61,1455,1456],{"class":67},"          ungetc",[61,1458,1459],{"class":278},"(ch, stdin);",[61,1461,1462],{"class":95},"  \u002F\u002F 将字符放回标准输入流\n",[61,1464,1465,1468,1470,1473],{"class":63,"line":624},[61,1466,1467],{"class":309},"          return",[61,1469,1322],{"class":313},[61,1471,1472],{"class":278},";",[61,1474,1475],{"class":95},"           \u002F\u002F 如果读取了字符，返回 1\n",[61,1477,1478],{"class":63,"line":630},[61,1479,1480],{"class":278},"      }\n",[61,1482,1483],{"class":63,"line":636},[61,1484,89],{"emptyLinePlaceholder":88},[61,1486,1487,1490,1492,1494],{"class":63,"line":645},[61,1488,1489],{"class":309},"      return",[61,1491,1334],{"class":313},[61,1493,1472],{"class":278},[61,1495,1496],{"class":95},"   \u002F\u002F 没有读取到字符\n",[61,1498,1499],{"class":63,"line":651},[61,1500,789],{"class":278},[16,1502,1503],{},"以下代码未经验证，谨慎使用，本人直接采用了官方的节点，并未使用自定义节点。",[52,1505,1507],{"className":261,"code":1506,"language":263,"meta":57,"style":57},"#include \"rclcpp\u002Frclcpp.hpp\"\n#include \"geometry_msgs\u002Fmsg\u002Ftwist.hpp\"\n#include \u003Cgeometry_msgs\u002Fmsg\u002Fdetail\u002Ftwist__struct.hpp>\n#include \u003Ctermios.h>\n#include \u003Cunistd.h>\n#include \u003Cfcntl.h>\n#include \"cyber_teleop_twist_keyboard\u002Fstruct_typedef.h\"\n\nclass TeleopTwistKeyboardNode: public rclcpp::Node\n{\n  public:\n    TeleopTwistKeyboardNode():Node(\"CyberTeleopTwistKeyboardNode_cpp\")\n    {\n      RCLCPP_INFO(this->get_logger(),\"TeleopTwistKeyboardNode Running!\");\n      RCLCPP_INFO(this->get_logger(),\"键盘控制机器人节点已启动！\");\n      \u002F\u002F 创建一个发布者，类型是 geometry_msgs\u002Fmsg\u002FTwist，发布到 \"cmd_vel\" 话题\n      keyboard_control_pub_ = this->create_publisher\u003Cgeometry_msgs::msg::Twist>(\"cmd_vel\", 10);\n\n      \u002F\u002F 定时器，周期性调用发布函数\n      keyboard_control_pub_timer_ = this->create_wall_timer(\n          std::chrono::milliseconds(100), \n          std::bind(&TeleopTwistKeyboardNode::cmd_vel_publish_timer_callback, this)\n        );\n\n    }\n\n  private:\n    rclcpp::Publisher\u003Cgeometry_msgs::msg::Twist>::SharedPtr keyboard_control_pub_;\n    rclcpp::TimerBase::SharedPtr keyboard_control_pub_timer_;\n\n    \u002F\u002F 步长\n    fp64 linear_step_ = 0.1;\n    fp64 angular_step_ = 0.1;\n\n    \u002F\u002F 当前线速度和角速度\n    fp64 linear_speed_ = 0.0;\n    fp64 angular_speed_ = 0.0;\n\n    \u002F\u002F 最大速度限制\n    fp64 max_linear_speed_ = 0.5;\n    fp64 max_angular_speed_ = 0.2;\n\n    \u002F\u002F 最小速度限制\n    fp64 min_linear_speed_ = 0.0;\n    fp64 min_angular_speed_ = 0.0;\n\n    geometry_msgs::msg::Twist cmd_msg;\n\n    \u002F\u002F查键盘输入的函数，它不需要按回车就能返回键盘输入。它通过修改终端设置，使得可以直接获取按键的值。\n    int kbhit(void)\n    {\n      struct termios oldt, newt;\n      int ch;\n      int oldf;\n\n      tcgetattr(STDIN_FILENO, &oldt);        \u002F\u002F 获取当前终端的设置\n      newt = oldt;\n      newt.c_lflag &= ~(ICANON | ECHO);       \u002F\u002F 禁用缓冲模式和回显\n      newt.c_cc[VMIN] = 1;\n      newt.c_cc[VTIME] = 0;\n      tcsetattr(STDIN_FILENO, TCSANOW, &newt); \u002F\u002F 设置新的终端设置\n\n      oldf = fcntl(STDIN_FILENO, F_GETFL, 0);\n      fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK); \u002F\u002F 设置为非阻塞模式\n\n      ch = getchar(); \u002F\u002F 获取字符\n      tcsetattr(STDIN_FILENO, TCSANOW, &oldt);   \u002F\u002F 恢复终端设置\n      fcntl(STDIN_FILENO, F_SETFL, oldf);         \u002F\u002F 恢复文件描述符设置\n\n      if(ch != EOF) { \n          ungetc(ch, stdin);  \u002F\u002F 将字符放回标准输入流\n          return 1;           \u002F\u002F 如果读取了字符，返回 1\n      }\n\n      return 0;   \u002F\u002F 没有读取到字符\n    }\n\n  void cmd_vel_publish_timer_callback()\n  {\n\n    cmd_msg.linear.y = 0.0;\n    cmd_msg.linear.x = 0.0;\n    cmd_msg.angular.z = 0.0;\n\n    \u002F\u002F 当有键盘输入时，处理它\n    if (kbhit()) \n    {\n      char key = getchar();  \u002F\u002F 获取键盘输入的字符\n\n      if(key == EOF)\n      {\n        return;\n      }\n      RCLCPP_INFO(this->get_logger(),\"按下了:%c\",key);\n      \u002F\u002F 根据按键决定机器人运动方向\n      switch(key)\n      {\n        case 'w': \u002F\u002F 前进\n          cmd_msg.linear.y = linear_speed_;\n          cmd_msg.linear.x = 0.0;\n          cmd_msg.angular.z = 0.0;\n          break;\n        case 's': \u002F\u002F 后退\n          cmd_msg.linear.y = - linear_speed_;\n          cmd_msg.linear.x = 0.0;\n          cmd_msg.angular.z = 0.0;\n          break;\n        case 'a': \u002F\u002F 左平移\n          cmd_msg.linear.y = 0.0;\n          cmd_msg.linear.x = - linear_speed_;\n          cmd_msg.angular.z = 0.0;\n          break;\n        case 'd': \u002F\u002F 右平移\n          cmd_msg.linear.y = 0.0;\n          cmd_msg.linear.x = linear_speed_;\n          cmd_msg.angular.z = 0.0;\n          break;\n        case 'q': \u002F\u002F 逆时针旋转\n          cmd_msg.linear.y = 0.0;\n          cmd_msg.linear.x = 0.0;\n          cmd_msg.angular.z = - angular_speed_;\n          break;\n        case 'e': \u002F\u002F 顺时针旋转\n          cmd_msg.angular.z = angular_speed_;\n          break;\n        case 'i': \u002F\u002F 增加线速度\n          linear_speed_ = std::clamp(linear_speed_ + linear_step_, min_linear_speed_, max_linear_speed_);\n          RCLCPP_INFO(this->get_logger(), \"Linear increased to: %.2f\", linear_speed_);\n          break;\n        case ',': \u002F\u002F 减小线速度\n          linear_speed_ = std::clamp(linear_speed_ - linear_step_, min_linear_speed_, max_linear_speed_);\n          RCLCPP_INFO(this->get_logger(), \"Linear decreased to: %.2f\", linear_speed_);\n          break;\n        case 'l': \u002F\u002F 增加角速度\n          angular_speed_ = std::clamp(angular_speed_ + angular_step_, min_angular_speed_, max_angular_speed_);\n          RCLCPP_INFO(this->get_logger(), \"Angular increased to: %.2f\", angular_speed_);\n          break;\n        case 'j': \u002F\u002F 减小角速度\n          angular_speed_ = std::clamp(angular_speed_ - angular_step_, min_angular_speed_, max_angular_speed_);\n          RCLCPP_INFO(this->get_logger(), \"Angular decreased to: %.2f\", angular_speed_);\n          break;\n        case 'k': \u002F\u002F 停止\n          cmd_msg.linear.y = 0.0;\n          cmd_msg.linear.x = 0.0;\n          cmd_msg.angular.z = 0.0;\n          break;\n        default:\n          RCLCPP_WARN(this->get_logger(), \"Unknown key pressed!\");\n      }\n    }\n    keyboard_control_pub_->publish(cmd_msg);\n  }\n\n};\n\nint main(int argc, char ** argv)\n{\n  rclcpp::init(argc,argv);\n\n  auto node = std::make_shared\u003CTeleopTwistKeyboardNode>();\n\n  rclcpp::spin(node);\n\n  rclcpp::shutdown();\n  return 0;\n}\n",[20,1508,1509,1516,1523,1530,1536,1542,1548,1555,1559,1580,1585,1590,1608,1612,1632,1651,1656,1692,1696,1701,1718,1741,1763,1768,1772,1776,1780,1785,1810,1822,1826,1831,1843,1854,1858,1863,1875,1886,1890,1895,1907,1919,1923,1929,1941,1953,1958,1971,1976,1981,1994,1999,2008,2015,2022,2027,2040,2049,2066,2077,2088,2101,2106,2121,2134,2139,2152,2165,2174,2179,2190,2199,2210,2215,2220,2231,2236,2241,2252,2257,2262,2274,2286,2298,2303,2309,2324,2329,2347,2352,2366,2372,2380,2385,2411,2417,2426,2431,2446,2457,2469,2481,2489,2502,2513,2524,2535,2542,2555,2566,2577,2588,2595,2608,2619,2628,2639,2646,2659,2670,2681,2693,2700,2713,2722,2729,2742,2766,2793,2800,2813,2833,2857,2864,2877,2899,2924,2931,2944,2963,2987,2994,3007,3018,3029,3040,3047,3056,3077,3082,3087,3099,3104,3109,3114,3119,3148,3153,3167,3172,3197,3202,3215,3220,3232,3242],{"__ignoreMap":57},[61,1510,1511,1513],{"class":63,"line":64},[61,1512,1188],{"class":309},[61,1514,1515],{"class":71}," \"rclcpp\u002Frclcpp.hpp\"\n",[61,1517,1518,1520],{"class":63,"line":92},[61,1519,1188],{"class":309},[61,1521,1522],{"class":71}," \"geometry_msgs\u002Fmsg\u002Ftwist.hpp\"\n",[61,1524,1525,1527],{"class":63,"line":99},[61,1526,1188],{"class":309},[61,1528,1529],{"class":71}," \u003Cgeometry_msgs\u002Fmsg\u002Fdetail\u002Ftwist__struct.hpp>\n",[61,1531,1532,1534],{"class":63,"line":104},[61,1533,1188],{"class":309},[61,1535,1191],{"class":71},[61,1537,1538,1540],{"class":63,"line":110},[61,1539,1188],{"class":309},[61,1541,1198],{"class":71},[61,1543,1544,1546],{"class":63,"line":115},[61,1545,1188],{"class":309},[61,1547,1205],{"class":71},[61,1549,1550,1552],{"class":63,"line":124},[61,1551,1188],{"class":309},[61,1553,1554],{"class":71}," \"cyber_teleop_twist_keyboard\u002Fstruct_typedef.h\"\n",[61,1556,1557],{"class":63,"line":136},[61,1558,89],{"emptyLinePlaceholder":88},[61,1560,1561,1564,1567,1570,1573,1575,1577],{"class":63,"line":147},[61,1562,1563],{"class":309},"class",[61,1565,1566],{"class":67}," TeleopTwistKeyboardNode",[61,1568,1569],{"class":278},": ",[61,1571,1572],{"class":309},"public",[61,1574,1136],{"class":67},[61,1576,279],{"class":278},[61,1578,1579],{"class":67},"Node\n",[61,1581,1582],{"class":63,"line":158},[61,1583,1584],{"class":278},"{\n",[61,1586,1587],{"class":63,"line":163},[61,1588,1589],{"class":309},"  public:\n",[61,1591,1592,1595,1598,1601,1603,1606],{"class":63,"line":171},[61,1593,1594],{"class":67},"    TeleopTwistKeyboardNode",[61,1596,1597],{"class":278},"():",[61,1599,1600],{"class":67},"Node",[61,1602,332],{"class":278},[61,1604,1605],{"class":71},"\"CyberTeleopTwistKeyboardNode_cpp\"",[61,1607,415],{"class":278},[61,1609,1610],{"class":63,"line":181},[61,1611,595],{"class":278},[61,1613,1614,1616,1618,1620,1622,1624,1627,1630],{"class":63,"line":191},[61,1615,654],{"class":67},[61,1617,332],{"class":278},[61,1619,365],{"class":313},[61,1621,661],{"class":278},[61,1623,664],{"class":67},[61,1625,1626],{"class":278},"(),",[61,1628,1629],{"class":71},"\"TeleopTwistKeyboardNode Running!\"",[61,1631,1374],{"class":278},[61,1633,1634,1636,1638,1640,1642,1644,1646,1649],{"class":63,"line":467},[61,1635,654],{"class":67},[61,1637,332],{"class":278},[61,1639,365],{"class":313},[61,1641,661],{"class":278},[61,1643,664],{"class":67},[61,1645,1626],{"class":278},[61,1647,1648],{"class":71},"\"键盘控制机器人节点已启动！\"",[61,1650,1374],{"class":278},[61,1652,1653],{"class":63,"line":487},[61,1654,1655],{"class":95},"      \u002F\u002F 创建一个发布者，类型是 geometry_msgs\u002Fmsg\u002FTwist，发布到 \"cmd_vel\" 话题\n",[61,1657,1658,1661,1663,1665,1668,1670,1672,1674,1676,1679,1682,1684,1686,1688,1690],{"class":63,"line":502},[61,1659,1660],{"class":278},"      keyboard_control_pub_ ",[61,1662,310],{"class":309},[61,1664,314],{"class":313},[61,1666,1667],{"class":278},"->create_publisher",[61,1669,285],{"class":309},[61,1671,288],{"class":67},[61,1673,279],{"class":278},[61,1675,293],{"class":67},[61,1677,1678],{"class":278},"::Twist",[61,1680,1681],{"class":309},">",[61,1683,332],{"class":278},[61,1685,335],{"class":71},[61,1687,493],{"class":278},[61,1689,341],{"class":313},[61,1691,1374],{"class":278},[61,1693,1694],{"class":63,"line":513},[61,1695,89],{"emptyLinePlaceholder":88},[61,1697,1698],{"class":63,"line":524},[61,1699,1700],{"class":95},"      \u002F\u002F 定时器，周期性调用发布函数\n",[61,1702,1703,1706,1708,1710,1712,1715],{"class":63,"line":535},[61,1704,1705],{"class":278},"      keyboard_control_pub_timer_ ",[61,1707,310],{"class":309},[61,1709,314],{"class":313},[61,1711,661],{"class":278},[61,1713,1714],{"class":67},"create_wall_timer",[61,1716,1717],{"class":278},"(\n",[61,1719,1720,1723,1725,1728,1730,1733,1735,1738],{"class":63,"line":556},[61,1721,1722],{"class":67},"          std",[61,1724,279],{"class":278},[61,1726,1727],{"class":67},"chrono",[61,1729,279],{"class":278},[61,1731,1732],{"class":67},"milliseconds",[61,1734,332],{"class":278},[61,1736,1737],{"class":313},"100",[61,1739,1740],{"class":278},"), \n",[61,1742,1743,1745,1747,1749,1751,1753,1756,1759,1761],{"class":63,"line":561},[61,1744,1722],{"class":67},[61,1746,279],{"class":278},[61,1748,351],{"class":67},[61,1750,332],{"class":278},[61,1752,356],{"class":309},[61,1754,1755],{"class":67},"TeleopTwistKeyboardNode",[61,1757,1758],{"class":278},"::cmd_vel_publish_timer_callback, ",[61,1760,365],{"class":313},[61,1762,415],{"class":278},[61,1764,1765],{"class":63,"line":581},[61,1766,1767],{"class":278},"        );\n",[61,1769,1770],{"class":63,"line":586},[61,1771,89],{"emptyLinePlaceholder":88},[61,1773,1774],{"class":63,"line":592},[61,1775,789],{"class":278},[61,1777,1778],{"class":63,"line":598},[61,1779,89],{"emptyLinePlaceholder":88},[61,1781,1782],{"class":63,"line":618},[61,1783,1784],{"class":309},"  private:\n",[61,1786,1787,1790,1792,1795,1797,1799,1801,1803,1805,1807],{"class":63,"line":624},[61,1788,1789],{"class":67},"    rclcpp",[61,1791,279],{"class":278},[61,1793,1794],{"class":67},"Publisher",[61,1796,285],{"class":278},[61,1798,288],{"class":67},[61,1800,279],{"class":278},[61,1802,293],{"class":67},[61,1804,279],{"class":278},[61,1806,298],{"class":67},[61,1808,1809],{"class":278},">::SharedPtr keyboard_control_pub_;\n",[61,1811,1812,1814,1816,1819],{"class":63,"line":630},[61,1813,1789],{"class":67},[61,1815,279],{"class":278},[61,1817,1818],{"class":67},"TimerBase",[61,1820,1821],{"class":278},"::SharedPtr keyboard_control_pub_timer_;\n",[61,1823,1824],{"class":63,"line":636},[61,1825,89],{"emptyLinePlaceholder":88},[61,1827,1828],{"class":63,"line":645},[61,1829,1830],{"class":95},"    \u002F\u002F 步长\n",[61,1832,1833,1836,1838,1841],{"class":63,"line":651},[61,1834,1835],{"class":278},"    fp64 linear_step_ ",[61,1837,310],{"class":309},[61,1839,1840],{"class":313}," 0.1",[61,1842,937],{"class":278},[61,1844,1845,1848,1850,1852],{"class":63,"line":706},[61,1846,1847],{"class":278},"    fp64 angular_step_ ",[61,1849,310],{"class":309},[61,1851,1840],{"class":313},[61,1853,937],{"class":278},[61,1855,1856],{"class":63,"line":753},[61,1857,89],{"emptyLinePlaceholder":88},[61,1859,1860],{"class":63,"line":780},[61,1861,1862],{"class":95},"    \u002F\u002F 当前线速度和角速度\n",[61,1864,1865,1868,1870,1873],{"class":63,"line":786},[61,1866,1867],{"class":278},"    fp64 linear_speed_ ",[61,1869,310],{"class":309},[61,1871,1872],{"class":313}," 0.0",[61,1874,937],{"class":278},[61,1876,1877,1880,1882,1884],{"class":63,"line":792},[61,1878,1879],{"class":278},"    fp64 angular_speed_ ",[61,1881,310],{"class":309},[61,1883,1872],{"class":313},[61,1885,937],{"class":278},[61,1887,1888],{"class":63,"line":813},[61,1889,89],{"emptyLinePlaceholder":88},[61,1891,1892],{"class":63,"line":818},[61,1893,1894],{"class":95},"    \u002F\u002F 最大速度限制\n",[61,1896,1897,1900,1902,1905],{"class":63,"line":851},[61,1898,1899],{"class":278},"    fp64 max_linear_speed_ ",[61,1901,310],{"class":309},[61,1903,1904],{"class":313}," 0.5",[61,1906,937],{"class":278},[61,1908,1909,1912,1914,1917],{"class":63,"line":856},[61,1910,1911],{"class":278},"    fp64 max_angular_speed_ ",[61,1913,310],{"class":309},[61,1915,1916],{"class":313}," 0.2",[61,1918,937],{"class":278},[61,1920,1921],{"class":63,"line":862},[61,1922,89],{"emptyLinePlaceholder":88},[61,1924,1926],{"class":63,"line":1925},43,[61,1927,1928],{"class":95},"    \u002F\u002F 最小速度限制\n",[61,1930,1932,1935,1937,1939],{"class":63,"line":1931},44,[61,1933,1934],{"class":278},"    fp64 min_linear_speed_ ",[61,1936,310],{"class":309},[61,1938,1872],{"class":313},[61,1940,937],{"class":278},[61,1942,1944,1947,1949,1951],{"class":63,"line":1943},45,[61,1945,1946],{"class":278},"    fp64 min_angular_speed_ ",[61,1948,310],{"class":309},[61,1950,1872],{"class":313},[61,1952,937],{"class":278},[61,1954,1956],{"class":63,"line":1955},46,[61,1957,89],{"emptyLinePlaceholder":88},[61,1959,1961,1964,1966,1968],{"class":63,"line":1960},47,[61,1962,1963],{"class":67},"    geometry_msgs",[61,1965,279],{"class":278},[61,1967,293],{"class":67},[61,1969,1970],{"class":278},"::Twist cmd_msg;\n",[61,1972,1974],{"class":63,"line":1973},48,[61,1975,89],{"emptyLinePlaceholder":88},[61,1977,1979],{"class":63,"line":1978},49,[61,1980,1214],{"class":95},[61,1982,1984,1986,1988,1990,1992],{"class":63,"line":1983},50,[61,1985,1219],{"class":309},[61,1987,1222],{"class":67},[61,1989,332],{"class":278},[61,1991,1227],{"class":309},[61,1993,415],{"class":278},[61,1995,1997],{"class":63,"line":1996},51,[61,1998,595],{"class":278},[61,2000,2002,2004,2006],{"class":63,"line":2001},52,[61,2003,1238],{"class":309},[61,2005,1241],{"class":67},[61,2007,1244],{"class":278},[61,2009,2011,2013],{"class":63,"line":2010},53,[61,2012,1249],{"class":309},[61,2014,1252],{"class":278},[61,2016,2018,2020],{"class":63,"line":2017},54,[61,2019,1249],{"class":309},[61,2021,1259],{"class":278},[61,2023,2025],{"class":63,"line":2024},55,[61,2026,89],{"emptyLinePlaceholder":88},[61,2028,2030,2032,2034,2036,2038],{"class":63,"line":2029},56,[61,2031,1268],{"class":67},[61,2033,1271],{"class":278},[61,2035,356],{"class":309},[61,2037,1276],{"class":278},[61,2039,1279],{"class":95},[61,2041,2043,2045,2047],{"class":63,"line":2042},57,[61,2044,1284],{"class":278},[61,2046,310],{"class":309},[61,2048,1289],{"class":278},[61,2050,2052,2054,2056,2058,2060,2062,2064],{"class":63,"line":2051},58,[61,2053,1294],{"class":278},[61,2055,1297],{"class":309},[61,2057,1300],{"class":309},[61,2059,1303],{"class":278},[61,2061,1306],{"class":309},[61,2063,1309],{"class":278},[61,2065,1312],{"class":95},[61,2067,2069,2071,2073,2075],{"class":63,"line":2068},59,[61,2070,1317],{"class":278},[61,2072,310],{"class":309},[61,2074,1322],{"class":313},[61,2076,937],{"class":278},[61,2078,2080,2082,2084,2086],{"class":63,"line":2079},60,[61,2081,1329],{"class":278},[61,2083,310],{"class":309},[61,2085,1334],{"class":313},[61,2087,937],{"class":278},[61,2089,2091,2093,2095,2097,2099],{"class":63,"line":2090},61,[61,2092,1341],{"class":67},[61,2094,1344],{"class":278},[61,2096,356],{"class":309},[61,2098,1349],{"class":278},[61,2100,1352],{"class":95},[61,2102,2104],{"class":63,"line":2103},62,[61,2105,89],{"emptyLinePlaceholder":88},[61,2107,2109,2111,2113,2115,2117,2119],{"class":63,"line":2108},63,[61,2110,1361],{"class":278},[61,2112,310],{"class":309},[61,2114,1366],{"class":67},[61,2116,1369],{"class":278},[61,2118,496],{"class":313},[61,2120,1374],{"class":278},[61,2122,2124,2126,2128,2130,2132],{"class":63,"line":2123},64,[61,2125,1379],{"class":67},[61,2127,1382],{"class":278},[61,2129,1306],{"class":309},[61,2131,1387],{"class":278},[61,2133,1390],{"class":95},[61,2135,2137],{"class":63,"line":2136},65,[61,2138,89],{"emptyLinePlaceholder":88},[61,2140,2142,2144,2146,2148,2150],{"class":63,"line":2141},66,[61,2143,1399],{"class":278},[61,2145,310],{"class":309},[61,2147,1404],{"class":67},[61,2149,1407],{"class":278},[61,2151,1410],{"class":95},[61,2153,2155,2157,2159,2161,2163],{"class":63,"line":2154},67,[61,2156,1341],{"class":67},[61,2158,1344],{"class":278},[61,2160,356],{"class":309},[61,2162,1276],{"class":278},[61,2164,1423],{"class":95},[61,2166,2168,2170,2172],{"class":63,"line":2167},68,[61,2169,1379],{"class":67},[61,2171,1430],{"class":278},[61,2173,1433],{"class":95},[61,2175,2177],{"class":63,"line":2176},69,[61,2178,89],{"emptyLinePlaceholder":88},[61,2180,2182,2184,2186,2188],{"class":63,"line":2181},70,[61,2183,1442],{"class":309},[61,2185,1445],{"class":278},[61,2187,1448],{"class":309},[61,2189,1451],{"class":278},[61,2191,2193,2195,2197],{"class":63,"line":2192},71,[61,2194,1456],{"class":67},[61,2196,1459],{"class":278},[61,2198,1462],{"class":95},[61,2200,2202,2204,2206,2208],{"class":63,"line":2201},72,[61,2203,1467],{"class":309},[61,2205,1322],{"class":313},[61,2207,1472],{"class":278},[61,2209,1475],{"class":95},[61,2211,2213],{"class":63,"line":2212},73,[61,2214,1480],{"class":278},[61,2216,2218],{"class":63,"line":2217},74,[61,2219,89],{"emptyLinePlaceholder":88},[61,2221,2223,2225,2227,2229],{"class":63,"line":2222},75,[61,2224,1489],{"class":309},[61,2226,1334],{"class":313},[61,2228,1472],{"class":278},[61,2230,1496],{"class":95},[61,2232,2234],{"class":63,"line":2233},76,[61,2235,789],{"class":278},[61,2237,2239],{"class":63,"line":2238},77,[61,2240,89],{"emptyLinePlaceholder":88},[61,2242,2244,2246,2249],{"class":63,"line":2243},78,[61,2245,386],{"class":309},[61,2247,2248],{"class":67}," cmd_vel_publish_timer_callback",[61,2250,2251],{"class":278},"()\n",[61,2253,2255],{"class":63,"line":2254},79,[61,2256,420],{"class":278},[61,2258,2260],{"class":63,"line":2259},80,[61,2261,89],{"emptyLinePlaceholder":88},[61,2263,2265,2268,2270,2272],{"class":63,"line":2264},81,[61,2266,2267],{"class":278},"    cmd_msg.linear.y ",[61,2269,310],{"class":309},[61,2271,1872],{"class":313},[61,2273,937],{"class":278},[61,2275,2277,2280,2282,2284],{"class":63,"line":2276},82,[61,2278,2279],{"class":278},"    cmd_msg.linear.x ",[61,2281,310],{"class":309},[61,2283,1872],{"class":313},[61,2285,937],{"class":278},[61,2287,2289,2292,2294,2296],{"class":63,"line":2288},83,[61,2290,2291],{"class":278},"    cmd_msg.angular.z ",[61,2293,310],{"class":309},[61,2295,1872],{"class":313},[61,2297,937],{"class":278},[61,2299,2301],{"class":63,"line":2300},84,[61,2302,89],{"emptyLinePlaceholder":88},[61,2304,2306],{"class":63,"line":2305},85,[61,2307,2308],{"class":95},"    \u002F\u002F 当有键盘输入时，处理它\n",[61,2310,2312,2315,2318,2321],{"class":63,"line":2311},86,[61,2313,2314],{"class":309},"    if",[61,2316,2317],{"class":278}," (",[61,2319,2320],{"class":67},"kbhit",[61,2322,2323],{"class":278},"()) \n",[61,2325,2327],{"class":63,"line":2326},87,[61,2328,595],{"class":278},[61,2330,2332,2335,2338,2340,2342,2344],{"class":63,"line":2331},88,[61,2333,2334],{"class":309},"      char",[61,2336,2337],{"class":278}," key ",[61,2339,310],{"class":309},[61,2341,1404],{"class":67},[61,2343,1407],{"class":278},[61,2345,2346],{"class":95},"  \u002F\u002F 获取键盘输入的字符\n",[61,2348,2350],{"class":63,"line":2349},89,[61,2351,89],{"emptyLinePlaceholder":88},[61,2353,2355,2357,2360,2363],{"class":63,"line":2354},90,[61,2356,1442],{"class":309},[61,2358,2359],{"class":278},"(key ",[61,2361,2362],{"class":309},"==",[61,2364,2365],{"class":278}," EOF)\n",[61,2367,2369],{"class":63,"line":2368},91,[61,2370,2371],{"class":278},"      {\n",[61,2373,2375,2378],{"class":63,"line":2374},92,[61,2376,2377],{"class":309},"        return",[61,2379,937],{"class":278},[61,2381,2383],{"class":63,"line":2382},93,[61,2384,1480],{"class":278},[61,2386,2388,2390,2392,2394,2396,2398,2400,2403,2406,2408],{"class":63,"line":2387},94,[61,2389,654],{"class":67},[61,2391,332],{"class":278},[61,2393,365],{"class":313},[61,2395,661],{"class":278},[61,2397,664],{"class":67},[61,2399,1626],{"class":278},[61,2401,2402],{"class":71},"\"按下了:",[61,2404,2405],{"class":313},"%c",[61,2407,684],{"class":71},[61,2409,2410],{"class":278},",key);\n",[61,2412,2414],{"class":63,"line":2413},95,[61,2415,2416],{"class":95},"      \u002F\u002F 根据按键决定机器人运动方向\n",[61,2418,2420,2423],{"class":63,"line":2419},96,[61,2421,2422],{"class":309},"      switch",[61,2424,2425],{"class":278},"(key)\n",[61,2427,2429],{"class":63,"line":2428},97,[61,2430,2371],{"class":278},[61,2432,2434,2437,2440,2443],{"class":63,"line":2433},98,[61,2435,2436],{"class":309},"        case",[61,2438,2439],{"class":71}," 'w'",[61,2441,2442],{"class":278},":",[61,2444,2445],{"class":95}," \u002F\u002F 前进\n",[61,2447,2449,2452,2454],{"class":63,"line":2448},99,[61,2450,2451],{"class":278},"          cmd_msg.linear.y ",[61,2453,310],{"class":309},[61,2455,2456],{"class":278}," linear_speed_;\n",[61,2458,2460,2463,2465,2467],{"class":63,"line":2459},100,[61,2461,2462],{"class":278},"          cmd_msg.linear.x ",[61,2464,310],{"class":309},[61,2466,1872],{"class":313},[61,2468,937],{"class":278},[61,2470,2472,2475,2477,2479],{"class":63,"line":2471},101,[61,2473,2474],{"class":278},"          cmd_msg.angular.z ",[61,2476,310],{"class":309},[61,2478,1872],{"class":313},[61,2480,937],{"class":278},[61,2482,2484,2487],{"class":63,"line":2483},102,[61,2485,2486],{"class":309},"          break",[61,2488,937],{"class":278},[61,2490,2492,2494,2497,2499],{"class":63,"line":2491},103,[61,2493,2436],{"class":309},[61,2495,2496],{"class":71}," 's'",[61,2498,2442],{"class":278},[61,2500,2501],{"class":95}," \u002F\u002F 后退\n",[61,2503,2505,2507,2509,2511],{"class":63,"line":2504},104,[61,2506,2451],{"class":278},[61,2508,310],{"class":309},[61,2510,926],{"class":309},[61,2512,2456],{"class":278},[61,2514,2516,2518,2520,2522],{"class":63,"line":2515},105,[61,2517,2462],{"class":278},[61,2519,310],{"class":309},[61,2521,1872],{"class":313},[61,2523,937],{"class":278},[61,2525,2527,2529,2531,2533],{"class":63,"line":2526},106,[61,2528,2474],{"class":278},[61,2530,310],{"class":309},[61,2532,1872],{"class":313},[61,2534,937],{"class":278},[61,2536,2538,2540],{"class":63,"line":2537},107,[61,2539,2486],{"class":309},[61,2541,937],{"class":278},[61,2543,2545,2547,2550,2552],{"class":63,"line":2544},108,[61,2546,2436],{"class":309},[61,2548,2549],{"class":71}," 'a'",[61,2551,2442],{"class":278},[61,2553,2554],{"class":95}," \u002F\u002F 左平移\n",[61,2556,2558,2560,2562,2564],{"class":63,"line":2557},109,[61,2559,2451],{"class":278},[61,2561,310],{"class":309},[61,2563,1872],{"class":313},[61,2565,937],{"class":278},[61,2567,2569,2571,2573,2575],{"class":63,"line":2568},110,[61,2570,2462],{"class":278},[61,2572,310],{"class":309},[61,2574,926],{"class":309},[61,2576,2456],{"class":278},[61,2578,2580,2582,2584,2586],{"class":63,"line":2579},111,[61,2581,2474],{"class":278},[61,2583,310],{"class":309},[61,2585,1872],{"class":313},[61,2587,937],{"class":278},[61,2589,2591,2593],{"class":63,"line":2590},112,[61,2592,2486],{"class":309},[61,2594,937],{"class":278},[61,2596,2598,2600,2603,2605],{"class":63,"line":2597},113,[61,2599,2436],{"class":309},[61,2601,2602],{"class":71}," 'd'",[61,2604,2442],{"class":278},[61,2606,2607],{"class":95}," \u002F\u002F 右平移\n",[61,2609,2611,2613,2615,2617],{"class":63,"line":2610},114,[61,2612,2451],{"class":278},[61,2614,310],{"class":309},[61,2616,1872],{"class":313},[61,2618,937],{"class":278},[61,2620,2622,2624,2626],{"class":63,"line":2621},115,[61,2623,2462],{"class":278},[61,2625,310],{"class":309},[61,2627,2456],{"class":278},[61,2629,2631,2633,2635,2637],{"class":63,"line":2630},116,[61,2632,2474],{"class":278},[61,2634,310],{"class":309},[61,2636,1872],{"class":313},[61,2638,937],{"class":278},[61,2640,2642,2644],{"class":63,"line":2641},117,[61,2643,2486],{"class":309},[61,2645,937],{"class":278},[61,2647,2649,2651,2654,2656],{"class":63,"line":2648},118,[61,2650,2436],{"class":309},[61,2652,2653],{"class":71}," 'q'",[61,2655,2442],{"class":278},[61,2657,2658],{"class":95}," \u002F\u002F 逆时针旋转\n",[61,2660,2662,2664,2666,2668],{"class":63,"line":2661},119,[61,2663,2451],{"class":278},[61,2665,310],{"class":309},[61,2667,1872],{"class":313},[61,2669,937],{"class":278},[61,2671,2673,2675,2677,2679],{"class":63,"line":2672},120,[61,2674,2462],{"class":278},[61,2676,310],{"class":309},[61,2678,1872],{"class":313},[61,2680,937],{"class":278},[61,2682,2684,2686,2688,2690],{"class":63,"line":2683},121,[61,2685,2474],{"class":278},[61,2687,310],{"class":309},[61,2689,926],{"class":309},[61,2691,2692],{"class":278}," angular_speed_;\n",[61,2694,2696,2698],{"class":63,"line":2695},122,[61,2697,2486],{"class":309},[61,2699,937],{"class":278},[61,2701,2703,2705,2708,2710],{"class":63,"line":2702},123,[61,2704,2436],{"class":309},[61,2706,2707],{"class":71}," 'e'",[61,2709,2442],{"class":278},[61,2711,2712],{"class":95}," \u002F\u002F 顺时针旋转\n",[61,2714,2716,2718,2720],{"class":63,"line":2715},124,[61,2717,2474],{"class":278},[61,2719,310],{"class":309},[61,2721,2692],{"class":278},[61,2723,2725,2727],{"class":63,"line":2724},125,[61,2726,2486],{"class":309},[61,2728,937],{"class":278},[61,2730,2732,2734,2737,2739],{"class":63,"line":2731},126,[61,2733,2436],{"class":309},[61,2735,2736],{"class":71}," 'i'",[61,2738,2442],{"class":278},[61,2740,2741],{"class":95}," \u002F\u002F 增加线速度\n",[61,2743,2745,2748,2750,2752,2754,2757,2760,2763],{"class":63,"line":2744},127,[61,2746,2747],{"class":278},"          linear_speed_ ",[61,2749,310],{"class":309},[61,2751,802],{"class":67},[61,2753,279],{"class":278},[61,2755,2756],{"class":67},"clamp",[61,2758,2759],{"class":278},"(linear_speed_ ",[61,2761,2762],{"class":309},"+",[61,2764,2765],{"class":278}," linear_step_, min_linear_speed_, max_linear_speed_);\n",[61,2767,2769,2772,2774,2776,2778,2780,2782,2785,2788,2790],{"class":63,"line":2768},128,[61,2770,2771],{"class":67},"          RCLCPP_INFO",[61,2773,332],{"class":278},[61,2775,365],{"class":313},[61,2777,661],{"class":278},[61,2779,664],{"class":67},[61,2781,667],{"class":278},[61,2783,2784],{"class":71},"\"Linear increased to: ",[61,2786,2787],{"class":313},"%.2f",[61,2789,684],{"class":71},[61,2791,2792],{"class":278},", linear_speed_);\n",[61,2794,2796,2798],{"class":63,"line":2795},129,[61,2797,2486],{"class":309},[61,2799,937],{"class":278},[61,2801,2803,2805,2808,2810],{"class":63,"line":2802},130,[61,2804,2436],{"class":309},[61,2806,2807],{"class":71}," ','",[61,2809,2442],{"class":278},[61,2811,2812],{"class":95}," \u002F\u002F 减小线速度\n",[61,2814,2816,2818,2820,2822,2824,2826,2828,2831],{"class":63,"line":2815},131,[61,2817,2747],{"class":278},[61,2819,310],{"class":309},[61,2821,802],{"class":67},[61,2823,279],{"class":278},[61,2825,2756],{"class":67},[61,2827,2759],{"class":278},[61,2829,2830],{"class":309},"-",[61,2832,2765],{"class":278},[61,2834,2836,2838,2840,2842,2844,2846,2848,2851,2853,2855],{"class":63,"line":2835},132,[61,2837,2771],{"class":67},[61,2839,332],{"class":278},[61,2841,365],{"class":313},[61,2843,661],{"class":278},[61,2845,664],{"class":67},[61,2847,667],{"class":278},[61,2849,2850],{"class":71},"\"Linear decreased to: ",[61,2852,2787],{"class":313},[61,2854,684],{"class":71},[61,2856,2792],{"class":278},[61,2858,2860,2862],{"class":63,"line":2859},133,[61,2861,2486],{"class":309},[61,2863,937],{"class":278},[61,2865,2867,2869,2872,2874],{"class":63,"line":2866},134,[61,2868,2436],{"class":309},[61,2870,2871],{"class":71}," 'l'",[61,2873,2442],{"class":278},[61,2875,2876],{"class":95}," \u002F\u002F 增加角速度\n",[61,2878,2880,2883,2885,2887,2889,2891,2894,2896],{"class":63,"line":2879},135,[61,2881,2882],{"class":278},"          angular_speed_ ",[61,2884,310],{"class":309},[61,2886,802],{"class":67},[61,2888,279],{"class":278},[61,2890,2756],{"class":67},[61,2892,2893],{"class":278},"(angular_speed_ ",[61,2895,2762],{"class":309},[61,2897,2898],{"class":278}," angular_step_, min_angular_speed_, max_angular_speed_);\n",[61,2900,2902,2904,2906,2908,2910,2912,2914,2917,2919,2921],{"class":63,"line":2901},136,[61,2903,2771],{"class":67},[61,2905,332],{"class":278},[61,2907,365],{"class":313},[61,2909,661],{"class":278},[61,2911,664],{"class":67},[61,2913,667],{"class":278},[61,2915,2916],{"class":71},"\"Angular increased to: ",[61,2918,2787],{"class":313},[61,2920,684],{"class":71},[61,2922,2923],{"class":278},", angular_speed_);\n",[61,2925,2927,2929],{"class":63,"line":2926},137,[61,2928,2486],{"class":309},[61,2930,937],{"class":278},[61,2932,2934,2936,2939,2941],{"class":63,"line":2933},138,[61,2935,2436],{"class":309},[61,2937,2938],{"class":71}," 'j'",[61,2940,2442],{"class":278},[61,2942,2943],{"class":95}," \u002F\u002F 减小角速度\n",[61,2945,2947,2949,2951,2953,2955,2957,2959,2961],{"class":63,"line":2946},139,[61,2948,2882],{"class":278},[61,2950,310],{"class":309},[61,2952,802],{"class":67},[61,2954,279],{"class":278},[61,2956,2756],{"class":67},[61,2958,2893],{"class":278},[61,2960,2830],{"class":309},[61,2962,2898],{"class":278},[61,2964,2966,2968,2970,2972,2974,2976,2978,2981,2983,2985],{"class":63,"line":2965},140,[61,2967,2771],{"class":67},[61,2969,332],{"class":278},[61,2971,365],{"class":313},[61,2973,661],{"class":278},[61,2975,664],{"class":67},[61,2977,667],{"class":278},[61,2979,2980],{"class":71},"\"Angular decreased to: ",[61,2982,2787],{"class":313},[61,2984,684],{"class":71},[61,2986,2923],{"class":278},[61,2988,2990,2992],{"class":63,"line":2989},141,[61,2991,2486],{"class":309},[61,2993,937],{"class":278},[61,2995,2997,2999,3002,3004],{"class":63,"line":2996},142,[61,2998,2436],{"class":309},[61,3000,3001],{"class":71}," 'k'",[61,3003,2442],{"class":278},[61,3005,3006],{"class":95}," \u002F\u002F 停止\n",[61,3008,3010,3012,3014,3016],{"class":63,"line":3009},143,[61,3011,2451],{"class":278},[61,3013,310],{"class":309},[61,3015,1872],{"class":313},[61,3017,937],{"class":278},[61,3019,3021,3023,3025,3027],{"class":63,"line":3020},144,[61,3022,2462],{"class":278},[61,3024,310],{"class":309},[61,3026,1872],{"class":313},[61,3028,937],{"class":278},[61,3030,3032,3034,3036,3038],{"class":63,"line":3031},145,[61,3033,2474],{"class":278},[61,3035,310],{"class":309},[61,3037,1872],{"class":313},[61,3039,937],{"class":278},[61,3041,3043,3045],{"class":63,"line":3042},146,[61,3044,2486],{"class":309},[61,3046,937],{"class":278},[61,3048,3050,3053],{"class":63,"line":3049},147,[61,3051,3052],{"class":309},"        default",[61,3054,3055],{"class":278},":\n",[61,3057,3059,3062,3064,3066,3068,3070,3072,3075],{"class":63,"line":3058},148,[61,3060,3061],{"class":67},"          RCLCPP_WARN",[61,3063,332],{"class":278},[61,3065,365],{"class":313},[61,3067,661],{"class":278},[61,3069,664],{"class":67},[61,3071,667],{"class":278},[61,3073,3074],{"class":71},"\"Unknown key pressed!\"",[61,3076,1374],{"class":278},[61,3078,3080],{"class":63,"line":3079},149,[61,3081,1480],{"class":278},[61,3083,3085],{"class":63,"line":3084},150,[61,3086,789],{"class":278},[61,3088,3090,3093,3096],{"class":63,"line":3089},151,[61,3091,3092],{"class":278},"    keyboard_control_pub_->",[61,3094,3095],{"class":67},"publish",[61,3097,3098],{"class":278},"(cmd_msg);\n",[61,3100,3102],{"class":63,"line":3101},152,[61,3103,859],{"class":278},[61,3105,3107],{"class":63,"line":3106},153,[61,3108,89],{"emptyLinePlaceholder":88},[61,3110,3112],{"class":63,"line":3111},154,[61,3113,865],{"class":278},[61,3115,3117],{"class":63,"line":3116},155,[61,3118,89],{"emptyLinePlaceholder":88},[61,3120,3122,3125,3128,3130,3132,3135,3137,3140,3143,3146],{"class":63,"line":3121},156,[61,3123,3124],{"class":309},"int",[61,3126,3127],{"class":67}," main",[61,3129,332],{"class":278},[61,3131,3124],{"class":309},[61,3133,3134],{"class":411}," argc",[61,3136,493],{"class":278},[61,3138,3139],{"class":309},"char",[61,3141,3142],{"class":309}," **",[61,3144,3145],{"class":411}," argv",[61,3147,415],{"class":278},[61,3149,3151],{"class":63,"line":3150},157,[61,3152,1584],{"class":278},[61,3154,3156,3159,3161,3164],{"class":63,"line":3155},158,[61,3157,3158],{"class":67},"  rclcpp",[61,3160,279],{"class":278},[61,3162,3163],{"class":67},"init",[61,3165,3166],{"class":278},"(argc,argv);\n",[61,3168,3170],{"class":63,"line":3169},159,[61,3171,89],{"emptyLinePlaceholder":88},[61,3173,3175,3178,3181,3183,3185,3187,3190,3192,3194],{"class":63,"line":3174},160,[61,3176,3177],{"class":309},"  auto",[61,3179,3180],{"class":278}," node ",[61,3182,310],{"class":309},[61,3184,802],{"class":67},[61,3186,279],{"class":278},[61,3188,3189],{"class":67},"make_shared",[61,3191,285],{"class":278},[61,3193,1755],{"class":67},[61,3195,3196],{"class":278},">();\n",[61,3198,3200],{"class":63,"line":3199},161,[61,3201,89],{"emptyLinePlaceholder":88},[61,3203,3205,3207,3209,3212],{"class":63,"line":3204},162,[61,3206,3158],{"class":67},[61,3208,279],{"class":278},[61,3210,3211],{"class":67},"spin",[61,3213,3214],{"class":278},"(node);\n",[61,3216,3218],{"class":63,"line":3217},163,[61,3219,89],{"emptyLinePlaceholder":88},[61,3221,3223,3225,3227,3230],{"class":63,"line":3222},164,[61,3224,3158],{"class":67},[61,3226,279],{"class":278},[61,3228,3229],{"class":67},"shutdown",[61,3231,578],{"class":278},[61,3233,3235,3238,3240],{"class":63,"line":3234},165,[61,3236,3237],{"class":309},"  return",[61,3239,1334],{"class":313},[61,3241,937],{"class":278},[61,3243,3245],{"class":63,"line":3244},166,[61,3246,3247],{"class":278},"}\n",[3249,3250,3251],"style",{},"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 .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}",{"title":57,"searchDepth":92,"depth":92,"links":3253},[3254,3255,3256,3257,3258],{"id":14,"depth":99,"text":14},{"id":49,"depth":99,"text":50},{"id":258,"depth":99,"text":258},{"id":943,"depth":99,"text":943},{"id":1102,"depth":99,"text":1102},"1400-0600-0700","2023-12-30","2023-12-30-ros2-tutorial","\u002Fwiki\u002F2023-12-30-ros2-tutorial","Ros2 Tutorial","md",false,{},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F1400-0600-0700-jian-pan-kong-zhi-jie-dian",{"title":5,"description":57},"wiki\u002F2023-12-30-ros2-tutorial\u002F1400-0600-0700-键盘控制节点","lGBDlUHWh4MuvBAHCYjA1QFM4DwZtm-UO8LN2KOb7rI",[3272,3279,3285,3291,3297,3303,3309,3315,3321,3327,3333,3339,3345,3351,3357,3363,3369,3375,3381,3387,3393,3399,3405,3411,3417,3423,3429,3435,3441,3447,3453,3459,3465,3471,3477,3482,3488,3493,3499,3505,3511,3517,3523,3529,3535,3541,3547,3553,3559,3565,3571,3577,3583,3585,3591,3597,3603,3609,3615,3621,3627,3633,3639,3645,3651,3657,3663,3669,3675],{"path":3273,"stem":3274,"title":3275,"authors":3276,"date":3260,"chapterOrder":3277,"chapterDepth":3278,"docKey":3261,"docRoot":3262,"docTitle":3263,"isWikiDoc":88,"isWikiIndex":3265},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F0100-ros2-jie-shao","wiki\u002F2023-12-30-ros2-tutorial\u002F0100-ROS2介绍","ROS2介绍",[7],"0100",0,{"path":3280,"stem":3281,"title":3282,"authors":3283,"date":3260,"chapterOrder":3284,"chapterDepth":3278,"docKey":3261,"docRoot":3262,"docTitle":3263,"isWikiDoc":88,"isWikiIndex":3265},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F0200-ru-men-cao-zuo","wiki\u002F2023-12-30-ros2-tutorial\u002F0200-入门操作","入门操作",[7],"0200",{"path":3286,"stem":3287,"title":3288,"authors":3289,"date":3260,"chapterOrder":3290,"chapterDepth":3278,"docKey":3261,"docRoot":3262,"docTitle":3263,"isWikiDoc":88,"isWikiIndex":3265},"\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":3292,"stem":3293,"title":3294,"authors":3295,"date":3260,"chapterOrder":3296,"chapterDepth":3278,"docKey":3261,"docRoot":3262,"docTitle":3263,"isWikiDoc":88,"isWikiIndex":3265},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F0400-si-da-tong-xin","wiki\u002F2023-12-30-ros2-tutorial\u002F0400-四大通信","四大通信",[7],"0400",{"path":3298,"stem":3299,"title":3300,"authors":3301,"date":3260,"chapterOrder":3302,"chapterDepth":3278,"docKey":3261,"docRoot":3262,"docTitle":3263,"isWikiDoc":88,"isWikiIndex":3265},"\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":3304,"stem":3305,"title":3306,"authors":3307,"date":3260,"chapterOrder":3308,"chapterDepth":3278,"docKey":3261,"docRoot":3262,"docTitle":3263,"isWikiDoc":88,"isWikiIndex":3265},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F0600-launch","wiki\u002F2023-12-30-ros2-tutorial\u002F0600-Launch","Launch",[7],"0600",{"path":3310,"stem":3311,"title":3312,"authors":3313,"date":3260,"chapterOrder":3314,"chapterDepth":3278,"docKey":3261,"docRoot":3262,"docTitle":3263,"isWikiDoc":88,"isWikiIndex":3265},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F0700-hui-su-rosbag2","wiki\u002F2023-12-30-ros2-tutorial\u002F0700-回溯rosbag2","回溯rosbag2",[7],"0700",{"path":3316,"stem":3317,"title":3318,"authors":3319,"date":3260,"chapterOrder":3320,"chapterDepth":3278,"docKey":3261,"docRoot":3262,"docTitle":3263,"isWikiDoc":88,"isWikiIndex":3265},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F0800-zuo-biao-bian-huan-tf","wiki\u002F2023-12-30-ros2-tutorial\u002F0800-坐标变换TF","坐标变换TF",[7],"0800",{"path":3322,"stem":3323,"title":3324,"authors":3325,"date":3260,"chapterOrder":3326,"chapterDepth":3278,"docKey":3261,"docRoot":3262,"docTitle":3263,"isWikiDoc":88,"isWikiIndex":3265},"\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":3328,"stem":3329,"title":3330,"authors":3331,"date":3260,"chapterOrder":3332,"chapterDepth":3278,"docKey":3261,"docRoot":3262,"docTitle":3263,"isWikiDoc":88,"isWikiIndex":3265},"\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":3334,"stem":3335,"title":3336,"authors":3337,"date":3260,"chapterOrder":3338,"chapterDepth":64,"docKey":3261,"docRoot":3262,"docTitle":3263,"isWikiDoc":88,"isWikiIndex":3265},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F1100-0100-gazeboclassic","wiki\u002F2023-12-30-ros2-tutorial\u002F1100-0100-GazeboClassic","Gezebo Classic",[7],"1100-0100",{"path":3340,"stem":3341,"title":3342,"authors":3343,"date":3260,"chapterOrder":3344,"chapterDepth":64,"docKey":3261,"docRoot":3262,"docTitle":3263,"isWikiDoc":88,"isWikiIndex":3265},"\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":3346,"stem":3347,"title":3348,"authors":3349,"date":3260,"chapterOrder":3350,"chapterDepth":64,"docKey":3261,"docRoot":3262,"docTitle":3263,"isWikiDoc":88,"isWikiIndex":3265},"\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":3352,"stem":3353,"title":3354,"authors":3355,"date":3260,"chapterOrder":3356,"chapterDepth":64,"docKey":3261,"docRoot":3262,"docTitle":3263,"isWikiDoc":88,"isWikiIndex":3265},"\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":3358,"stem":3359,"title":3360,"authors":3361,"date":3260,"chapterOrder":3362,"chapterDepth":3278,"docKey":3261,"docRoot":3262,"docTitle":3263,"isWikiDoc":88,"isWikiIndex":3265},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F1100-gezebo-fang-zhen-ping-tai","wiki\u002F2023-12-30-ros2-tutorial\u002F1100-Gezebo仿真平台","Gezebo仿真平台",[7],"1100",{"path":3364,"stem":3365,"title":3366,"authors":3367,"date":3260,"chapterOrder":3368,"chapterDepth":64,"docKey":3261,"docRoot":3262,"docTitle":3263,"isWikiDoc":88,"isWikiIndex":3265},"\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":3370,"stem":3371,"title":3372,"authors":3373,"date":3260,"chapterOrder":3374,"chapterDepth":64,"docKey":3261,"docRoot":3262,"docTitle":3263,"isWikiDoc":88,"isWikiIndex":3265},"\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":3376,"stem":3377,"title":3378,"authors":3379,"date":3260,"chapterOrder":3380,"chapterDepth":64,"docKey":3261,"docRoot":3262,"docTitle":3263,"isWikiDoc":88,"isWikiIndex":3265},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F1200-0300-humble2jazzy","wiki\u002F2023-12-30-ros2-tutorial\u002F1200-0300-Humble2Jazzy","Humble与Jazzy导航的差异",[7],"1200-0300",{"path":3382,"stem":3383,"title":3384,"authors":3385,"date":3260,"chapterOrder":3386,"chapterDepth":92,"docKey":3261,"docRoot":3262,"docTitle":3263,"isWikiDoc":88,"isWikiIndex":3265},"\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":3388,"stem":3389,"title":3390,"authors":3391,"date":3260,"chapterOrder":3392,"chapterDepth":99,"docKey":3261,"docRoot":3262,"docTitle":3263,"isWikiDoc":88,"isWikiIndex":3265},"\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":3394,"stem":3395,"title":3396,"authors":3397,"date":3260,"chapterOrder":3398,"chapterDepth":99,"docKey":3261,"docRoot":3262,"docTitle":3263,"isWikiDoc":88,"isWikiIndex":3265},"\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":3400,"stem":3401,"title":3402,"authors":3403,"date":3260,"chapterOrder":3404,"chapterDepth":99,"docKey":3261,"docRoot":3262,"docTitle":3263,"isWikiDoc":88,"isWikiIndex":3265},"\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":3406,"stem":3407,"title":3408,"authors":3409,"date":3260,"chapterOrder":3410,"chapterDepth":99,"docKey":3261,"docRoot":3262,"docTitle":3263,"isWikiDoc":88,"isWikiIndex":3265},"\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":3412,"stem":3413,"title":3414,"authors":3415,"date":3260,"chapterOrder":3416,"chapterDepth":99,"docKey":3261,"docRoot":3262,"docTitle":3263,"isWikiDoc":88,"isWikiIndex":3265},"\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":3418,"stem":3419,"title":3420,"authors":3421,"date":3260,"chapterOrder":3422,"chapterDepth":99,"docKey":3261,"docRoot":3262,"docTitle":3263,"isWikiDoc":88,"isWikiIndex":3265},"\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":3424,"stem":3425,"title":3426,"authors":3427,"date":3260,"chapterOrder":3428,"chapterDepth":92,"docKey":3261,"docRoot":3262,"docTitle":3263,"isWikiDoc":88,"isWikiIndex":3265},"\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":3430,"stem":3431,"title":3432,"authors":3433,"date":3260,"chapterOrder":3434,"chapterDepth":64,"docKey":3261,"docRoot":3262,"docTitle":3263,"isWikiDoc":88,"isWikiIndex":3265},"\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":3436,"stem":3437,"title":3438,"authors":3439,"date":3260,"chapterOrder":3440,"chapterDepth":3278,"docKey":3261,"docRoot":3262,"docTitle":3263,"isWikiDoc":88,"isWikiIndex":3265},"\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":3442,"stem":3443,"title":3444,"authors":3445,"date":3260,"chapterOrder":3446,"chapterDepth":92,"docKey":3261,"docRoot":3262,"docTitle":3263,"isWikiDoc":88,"isWikiIndex":3265},"\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":3448,"stem":3449,"title":3450,"authors":3451,"date":3260,"chapterOrder":3452,"chapterDepth":92,"docKey":3261,"docRoot":3262,"docTitle":3263,"isWikiDoc":88,"isWikiIndex":3265},"\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":3454,"stem":3455,"title":3456,"authors":3457,"date":3260,"chapterOrder":3458,"chapterDepth":64,"docKey":3261,"docRoot":3262,"docTitle":3263,"isWikiDoc":88,"isWikiIndex":3265},"\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":3460,"stem":3461,"title":3462,"authors":3463,"date":3260,"chapterOrder":3464,"chapterDepth":92,"docKey":3261,"docRoot":3262,"docTitle":3263,"isWikiDoc":88,"isWikiIndex":3265},"\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":3466,"stem":3467,"title":3468,"authors":3469,"date":3260,"chapterOrder":3470,"chapterDepth":92,"docKey":3261,"docRoot":3262,"docTitle":3263,"isWikiDoc":88,"isWikiIndex":3265},"\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":3472,"stem":3473,"title":3474,"authors":3475,"date":3260,"chapterOrder":3476,"chapterDepth":64,"docKey":3261,"docRoot":3262,"docTitle":3263,"isWikiDoc":88,"isWikiIndex":3265},"\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":3478,"stem":3479,"title":3444,"authors":3480,"date":3260,"chapterOrder":3481,"chapterDepth":92,"docKey":3261,"docRoot":3262,"docTitle":3263,"isWikiDoc":88,"isWikiIndex":3265},"\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":3483,"stem":3484,"title":3485,"authors":3486,"date":3260,"chapterOrder":3487,"chapterDepth":64,"docKey":3261,"docRoot":3262,"docTitle":3263,"isWikiDoc":88,"isWikiIndex":3265},"\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":3489,"stem":3490,"title":3444,"authors":3491,"date":3260,"chapterOrder":3492,"chapterDepth":92,"docKey":3261,"docRoot":3262,"docTitle":3263,"isWikiDoc":88,"isWikiIndex":3265},"\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":3494,"stem":3495,"title":3496,"authors":3497,"date":3260,"chapterOrder":3498,"chapterDepth":64,"docKey":3261,"docRoot":3262,"docTitle":3263,"isWikiDoc":88,"isWikiIndex":3265},"\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":3500,"stem":3501,"title":3502,"authors":3503,"date":3260,"chapterOrder":3504,"chapterDepth":3278,"docKey":3261,"docRoot":3262,"docTitle":3263,"isWikiDoc":88,"isWikiIndex":3265},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F1300-linux-ying-jian-tong-xin","wiki\u002F2023-12-30-ros2-tutorial\u002F1300-Linux硬件通信","Linux硬件通信",[7],"1300",{"path":3506,"stem":3507,"title":3508,"authors":3509,"date":3260,"chapterOrder":3510,"chapterDepth":64,"docKey":3261,"docRoot":3262,"docTitle":3263,"isWikiDoc":88,"isWikiIndex":3265},"\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":3512,"stem":3513,"title":3514,"authors":3515,"date":3260,"chapterOrder":3516,"chapterDepth":92,"docKey":3261,"docRoot":3262,"docTitle":3263,"isWikiDoc":88,"isWikiIndex":3265},"\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":3518,"stem":3519,"title":3520,"authors":3521,"date":3260,"chapterOrder":3522,"chapterDepth":92,"docKey":3261,"docRoot":3262,"docTitle":3263,"isWikiDoc":88,"isWikiIndex":3265},"\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":3524,"stem":3525,"title":3526,"authors":3527,"date":3260,"chapterOrder":3528,"chapterDepth":64,"docKey":3261,"docRoot":3262,"docTitle":3263,"isWikiDoc":88,"isWikiIndex":3265},"\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":3530,"stem":3531,"title":3532,"authors":3533,"date":3260,"chapterOrder":3534,"chapterDepth":64,"docKey":3261,"docRoot":3262,"docTitle":3263,"isWikiDoc":88,"isWikiIndex":3265},"\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":3536,"stem":3537,"title":3538,"authors":3539,"date":3260,"chapterOrder":3540,"chapterDepth":64,"docKey":3261,"docRoot":3262,"docTitle":3263,"isWikiDoc":88,"isWikiIndex":3265},"\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":3542,"stem":3543,"title":3544,"authors":3545,"date":3260,"chapterOrder":3546,"chapterDepth":64,"docKey":3261,"docRoot":3262,"docTitle":3263,"isWikiDoc":88,"isWikiIndex":3265},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F1400-0500-you-hua-ri-zhi","wiki\u002F2023-12-30-ros2-tutorial\u002F1400-0500-优化日志","优化日志",[7],"1400-0500",{"path":3548,"stem":3549,"title":3550,"authors":3551,"date":3260,"chapterOrder":3552,"chapterDepth":92,"docKey":3261,"docRoot":3262,"docTitle":3263,"isWikiDoc":88,"isWikiIndex":3265},"\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":3554,"stem":3555,"title":3556,"authors":3557,"date":3260,"chapterOrder":3558,"chapterDepth":92,"docKey":3261,"docRoot":3262,"docTitle":3263,"isWikiDoc":88,"isWikiIndex":3265},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F1400-0600-0200-guan-xing-ji-imu","wiki\u002F2023-12-30-ros2-tutorial\u002F1400-0600-0200-惯性计IMU","惯性计IMU",[7],"1400-0600-0200",{"path":3560,"stem":3561,"title":3562,"authors":3563,"date":3260,"chapterOrder":3564,"chapterDepth":92,"docKey":3261,"docRoot":3262,"docTitle":3263,"isWikiDoc":88,"isWikiIndex":3265},"\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":3566,"stem":3567,"title":3568,"authors":3569,"date":3260,"chapterOrder":3570,"chapterDepth":92,"docKey":3261,"docRoot":3262,"docTitle":3263,"isWikiDoc":88,"isWikiIndex":3265},"\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":3572,"stem":3573,"title":3574,"authors":3575,"date":3260,"chapterOrder":3576,"chapterDepth":92,"docKey":3261,"docRoot":3262,"docTitle":3263,"isWikiDoc":88,"isWikiIndex":3265},"\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":3578,"stem":3579,"title":3580,"authors":3581,"date":3260,"chapterOrder":3582,"chapterDepth":92,"docKey":3261,"docRoot":3262,"docTitle":3263,"isWikiDoc":88,"isWikiIndex":3265},"\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":3267,"stem":3269,"title":5,"authors":3584,"date":3260,"chapterOrder":3259,"chapterDepth":92,"docKey":3261,"docRoot":3262,"docTitle":3263,"isWikiDoc":88,"isWikiIndex":3265},[7],{"path":3586,"stem":3587,"title":3588,"authors":3589,"date":3260,"chapterOrder":3590,"chapterDepth":64,"docKey":3261,"docRoot":3262,"docTitle":3263,"isWikiDoc":88,"isWikiIndex":3265},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F1400-0600-ying-jian-ping-tai","wiki\u002F2023-12-30-ros2-tutorial\u002F1400-0600-硬件平台","硬件平台",[7],"1400-0600",{"path":3592,"stem":3593,"title":3594,"authors":3595,"date":3260,"chapterOrder":3596,"chapterDepth":64,"docKey":3261,"docRoot":3262,"docTitle":3263,"isWikiDoc":88,"isWikiIndex":3265},"\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":3598,"stem":3599,"title":3600,"authors":3601,"date":3260,"chapterOrder":3602,"chapterDepth":99,"docKey":3261,"docRoot":3262,"docTitle":3263,"isWikiDoc":88,"isWikiIndex":3265},"\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":3604,"stem":3605,"title":3606,"authors":3607,"date":3260,"chapterOrder":3608,"chapterDepth":99,"docKey":3261,"docRoot":3262,"docTitle":3263,"isWikiDoc":88,"isWikiIndex":3265},"\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":3610,"stem":3611,"title":3612,"authors":3613,"date":3260,"chapterOrder":3614,"chapterDepth":92,"docKey":3261,"docRoot":3262,"docTitle":3263,"isWikiDoc":88,"isWikiIndex":3265},"\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":3616,"stem":3617,"title":3618,"authors":3619,"date":3260,"chapterOrder":3620,"chapterDepth":92,"docKey":3261,"docRoot":3262,"docTitle":3263,"isWikiDoc":88,"isWikiIndex":3265},"\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":3622,"stem":3623,"title":3624,"authors":3625,"date":3260,"chapterOrder":3626,"chapterDepth":92,"docKey":3261,"docRoot":3262,"docTitle":3263,"isWikiDoc":88,"isWikiIndex":3265},"\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":3628,"stem":3629,"title":3630,"authors":3631,"date":3260,"chapterOrder":3632,"chapterDepth":64,"docKey":3261,"docRoot":3262,"docTitle":3263,"isWikiDoc":88,"isWikiIndex":3265},"\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":3634,"stem":3635,"title":3636,"authors":3637,"date":3260,"chapterOrder":3638,"chapterDepth":3278,"docKey":3261,"docRoot":3262,"docTitle":3263,"isWikiDoc":88,"isWikiIndex":3265},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F1400-ji-qi-ren-ying-jian","wiki\u002F2023-12-30-ros2-tutorial\u002F1400-机器人硬件","机器人硬件",[7],"1400",{"path":3640,"stem":3641,"title":3642,"authors":3643,"date":3260,"chapterOrder":3644,"chapterDepth":3278,"docKey":3261,"docRoot":3262,"docTitle":3263,"isWikiDoc":88,"isWikiIndex":3265},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F1500-ros2-control","wiki\u002F2023-12-30-ros2-tutorial\u002F1500-ROS2_Control","ROS2_Control",[7],"1500",{"path":3646,"stem":3647,"title":3648,"authors":3649,"date":3260,"chapterOrder":3650,"chapterDepth":3278,"docKey":3261,"docRoot":3262,"docTitle":3263,"isWikiDoc":88,"isWikiIndex":3265},"\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":3652,"stem":3653,"title":3654,"authors":3655,"date":3260,"chapterOrder":3656,"chapterDepth":3278,"docKey":3261,"docRoot":3262,"docTitle":3263,"isWikiDoc":88,"isWikiIndex":3265},"\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":3658,"stem":3659,"title":3660,"authors":3661,"date":3260,"chapterOrder":3662,"chapterDepth":3278,"docKey":3261,"docRoot":3262,"docTitle":3263,"isWikiDoc":88,"isWikiIndex":3265},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F1800-microros","wiki\u002F2023-12-30-ros2-tutorial\u002F1800-MicroROS","MicroROS",[7],"1800",{"path":3664,"stem":3665,"title":3666,"authors":3667,"date":3260,"chapterOrder":3668,"chapterDepth":3278,"docKey":3261,"docRoot":3262,"docTitle":3263,"isWikiDoc":88,"isWikiIndex":3265},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F1900-webots-fang-zhen-ping-tai","wiki\u002F2023-12-30-ros2-tutorial\u002F1900-Webots仿真平台","Webots仿真平台",[7],"1900",{"path":3670,"stem":3671,"title":3672,"authors":3673,"date":3260,"chapterOrder":3674,"chapterDepth":3278,"docKey":3261,"docRoot":3262,"docTitle":3263,"isWikiDoc":88,"isWikiIndex":3265},"\u002Fwiki\u002F2023-12-30-ros2-tutorial\u002F2000-opencv","wiki\u002F2023-12-30-ros2-tutorial\u002F2000-OpenCV","OpenCV",[7],"2000",{"path":3262,"stem":3676,"title":3677,"authors":3678,"date":3260,"chapterOrder":3679,"chapterDepth":3278,"docKey":3261,"docRoot":3262,"docTitle":3263,"isWikiDoc":88,"isWikiIndex":88},"wiki\u002F2023-12-30-ros2-tutorial\u002Findex","ROS2机器人操作系统教程",[7],null,[3681,3683,3686,3689],{"name":7,"image":3682},"\u002Fimages\u002Fmember_photo\u002F董佳辉.jpg",{"name":3684,"image":3685},"宫金良","\u002Fimages\u002Fmember_photo\u002F宫金良.jpg",{"name":3687,"image":3688},"巩丽","\u002Fimages\u002Fmember_photo\u002F巩丽.png",{"name":3690,"image":3691},"张彦斐","\u002Fimages\u002Fmember_photo\u002F张彦斐.jpg",1792431904242]