[{"data":1,"prerenderedAt":3681},["ShallowReactive",2],{"wiki-page-\u002Fwiki\u002F2026-09-20-dao-hang\u002F0600-kai-fa-wen-ti-yu-pai-cha":3,"wiki-doc-items-2026-09-20-dao-hang":3445,"wiki:author-members":3669},{"id":4,"title":5,"authors":6,"body":8,"chapterDepth":3432,"chapterOrder":3433,"date":3434,"description":285,"docKey":3435,"docRoot":3436,"docTitle":3437,"extension":3438,"isWikiDoc":891,"isWikiIndex":3439,"meta":3440,"navigation":891,"path":3441,"seo":3442,"stem":3443,"wikiDepth":292,"__hash__":3444},"wiki\u002Fwiki\u002F2026-09-20-导航\u002F0600-开发问题与排查.md","开发问题与排查",[7],"董佳辉",{"type":9,"value":10,"toc":3426},"minimark",[11,14,19,23,44,47,115,133,144,201,229,235,252,263,267,272,279,301,304,342,351,357,362,369,398,410,415,418,447,450,458,465,471,484,495,500,503,526,529,556,570,575,608,617,620,644,656,659,662,733,752,756,764,792,795,800,826,838,843,846,858,869,2149,2155,2160,2163,2175,2178,2243,2246,2258,2260,2349,2352,2400,2408,2417,2422,2428,2457,2460,2471,2474,2480,2488,2501,2504,2507,2556,2577,2580,2595,2598,2603,2633,2650,2653,2659,2664,2667,2761,2768,2772,2775,2782,2785,2844,2854,2861,2864,2869,2876,2894,2897,2910,2913,2925,2936,2939,2954,2969,2974,2977,2982,2985,2991,3001,3008,3028,3045,3104,3110,3113,3172,3196,3202,3209,3214,3217,3241,3244,3249,3252,3261,3264,3288,3297,3305,3311,3342,3346,3356,3362,3365,3368,3406,3409,3419,3422],[12,13,5],"h2",{"id":5},[15,16,18],"h3",{"id":17},"ssh-连接-ysulocal-时解析到-mid360-网口地址","SSH 连接 ysu.local 时解析到 MID360 网口地址",[20,21,22],"h4",{"id":22},"原因",[24,25,26,27,31,32,35,36,39,40,43],"p",{},"现象是：电脑与工控机连接同一个 Wi-Fi，直接 ping 工控机的 Wi-Fi 地址 ",[28,29,30],"code",{},"192.168.2.183"," 正常，也能通过这个地址 SSH 登录；但使用 ",[28,33,34],{},"ssh ysu@ysu.local"," 时，主机名却解析到 ",[28,37,38],{},"192.168.1.50","，提示 ",[28,41,42],{},"Connection closed by 192.168.1.50 port 22","。\n此前拔掉 MID360 网线并重启工控机后，主机名又能解析到 Wi-Fi 地址，但保留两张网卡时问题再次出现。",[24,45,46],{},"工控机同时使用 Wi-Fi 和有线网口，两张网卡的用途不同：",[48,49,50,66],"table",{},[51,52,53],"thead",{},[54,55,56,60,63],"tr",{},[57,58,59],"th",{},"接口或设备",[57,61,62],{},"本次地址",[57,64,65],{},"用途",[67,68,69,86,102],"tbody",{},[54,70,71,78,83],{},[72,73,74,75],"td",{},"工控机 Wi-Fi ",[28,76,77],{},"wlp4s0",[72,79,80],{},[28,81,82],{},"192.168.2.183\u002F24",[72,84,85],{},"SSH、局域网通信和联网，地址由 DHCP 分配",[54,87,88,94,99],{},[72,89,90,91],{},"工控机雷达有线口 ",[28,92,93],{},"enp3s0",[72,95,96],{},[28,97,98],{},"192.168.1.50\u002F24",[72,100,101],{},"接收 MID360 点云和 IMU 数据",[54,103,104,107,112],{},[72,105,106],{},"MID360",[72,108,109],{},[28,110,111],{},"192.168.1.107",[72,113,114],{},"向配置的上位机地址发送数据",[24,116,117,118,120,121,124,125,128,129,132],{},"**",[28,119,38],{}," 是雷达数据的接收端地址，不是 MID360 的默认网关。\n**该地址填写在驱动配置的 ",[28,122,123],{},"host_net_info"," 中，雷达自身地址填写在 ",[28,126,127],{},"lidar_configs"," 中。\nWi-Fi 和雷达使用不同的 ",[28,130,131],{},"\u002F24"," 网段，本次故障不是这两个网段重叠造成的。",[24,134,135,136],{},"2026-10-19 保留两张网卡复现后，抓包和进程跟踪确认：",[137,138,139,140,143],"strong",{},"工控机上的 NoMachine 9.7.3 在 Wi-Fi 上错误发布了 ",[28,141,142],{},"ysu.local → 192.168.1.50","，与 Avahi 发布的正确地址冲突。",[48,145,146,159],{},[51,147,148],{},[54,149,150,153,156],{},[57,151,152],{},"发布进程",[57,154,155],{},"在 Wi-Fi 上返回的 A 记录",[57,157,158],{},"记录有效期 TTL",[67,160,161,180],{},[54,162,163,172,177],{},[72,164,165,168,169],{},[28,166,167],{},"avahi-daemon","，PID ",[28,170,171],{},"735",[72,173,174],{},[28,175,176],{},"ysu.local → 192.168.2.183",[72,178,179],{},"120 秒",[54,181,182,194,198],{},[72,183,184,168,187,190,191],{},[28,185,186],{},"nxserver.bin",[28,188,189],{},"3955","，发送线程 ",[28,192,193],{},"4400",[72,195,196],{},[28,197,142],{},[72,199,200],{},"600 秒",[24,202,203,204,206,207,210,211,214,215,218,219,221,222,224,225,228],{},"在工控机 ",[28,205,77],{}," 上抓到的响应均来自 ",[28,208,209],{},"192.168.2.183:5353","，但记录内容分别为 ",[28,212,213],{},".183"," 和 ",[28,216,217],{},".50","。进一步跟踪系统调用，确认 NoMachine 的发送线程将包含 ",[28,220,217],{}," 的记录从 Wi-Fi socket 发出，而 Avahi 发出的是 ",[28,223,213],{},"。因此不是单凭“哪个进程监听了 5353 端口”推测原因，",[137,226,227],{},"已经定位到错误记录的实际发送进程","。",[24,230,231,232,234],{},"两个服务使用同一个主机名给出不同的地址，电脑收到并缓存错误记录后，就会把 SSH 发往雷达网段。\n600 秒表示记录有效期，并不是地址优先级；实际解析结果还受响应先后和缓存更新影响，所以会出现有时正常、有时指向 ",[28,233,217],{}," 的现象。",[24,236,237,238,240,241,243,244,247,248,251],{},"本次电脑去往 ",[28,239,217],{}," 的实际路由还进入了 FlClash TUN，去往 ",[28,242,213],{}," 则直接经过 Wi-Fi。\n",[137,245,246],{},"错误地址来自工控机 NoMachine 的 mDNS 发布；FlClash 接管去往错误地址的连接，是后续路径问题。","\n不能仅凭 ",[28,249,250],{},"Connection closed"," 判断工控机的 SSH 服务故障。",[24,253,254,255,258,259,262],{},"Avahi 当时已正确回答 Wi-Fi 地址，systemd-resolved 的 mDNS 未启用，两端检查的 hosts 文件中也没有静态配置 ",[28,256,257],{},"ysu.local → .50","。先关闭 NoMachine 自带的局域网发现后，主机名立即恢复正常，验证了故障来源；单独重启 Avahi 或限制其接口，无法阻止 NoMachine 继续发送错误记录。随后进一步通过 NoMachine 自身的 ",[28,260,261],{},"NXDListenAddress"," 配置绑定 Wi-Fi 地址，恢复原生自动发现，并补上 DHCP 地址变化时的同步。下面先记录临时方案，再说明本机最终采用的完整修复。",[20,264,266],{"id":265},"临时方案关闭-nomachine-自动发现","临时方案：关闭 NoMachine 自动发现",[24,268,269],{},[137,270,271],{},"1. 临时连接：使用工控机当前的 Wi-Fi 地址。（前提是你得知道它的 IP 地址）",[24,273,274,275,278],{},"以下命令在",[137,276,277],{},"电脑端","执行，本次地址为：",[280,281,286],"pre",{"className":282,"code":283,"language":284,"meta":285,"style":285},"language-bash shiki shiki-themes github-light github-dark","ssh ysu@192.168.2.183\n","bash","",[28,287,288],{"__ignoreMap":285},[289,290,293,297],"span",{"class":291,"line":292},"line",1,[289,294,296],{"class":295},"sScJk","ssh",[289,298,300],{"class":299},"sZZnC"," ysu@192.168.2.183\n",[24,302,303],{},"Wi-Fi 地址可能随 DHCP 租约变化，可以在工控机本地或路由器客户端列表中查询。工控机上也可以执行：",[280,305,307],{"className":282,"code":306,"language":284,"meta":285,"style":285},"nmcli -f DEVICE,TYPE,STATE,CONNECTION device status\nip -br -4 addr\n",[28,308,309,327],{"__ignoreMap":285},[289,310,311,314,318,321,324],{"class":291,"line":292},[289,312,313],{"class":295},"nmcli",[289,315,317],{"class":316},"sj4cs"," -f",[289,319,320],{"class":299}," DEVICE,TYPE,STATE,CONNECTION",[289,322,323],{"class":299}," device",[289,325,326],{"class":299}," status\n",[289,328,330,333,336,339],{"class":291,"line":329},2,[289,331,332],{"class":295},"ip",[289,334,335],{"class":316}," -br",[289,337,338],{"class":316}," -4",[289,340,341],{"class":299}," addr\n",[24,343,344,345,347,348,350],{},"本次工控机 Wi-Fi 接口为 ",[28,346,77],{},"，雷达有线接口为 ",[28,349,93],{},"。排查其他机器时，以实际输出为准。",[24,352,353],{},[354,355],"img",{"alt":285,"src":356},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2026\u002F09\u002F20\u002F1792326507031-a8325a6b.webp",[24,358,359],{},[137,360,361],{},"2. 工控机：确认 NoMachine 也在使用 mDNS。",[24,363,364,365,368],{},"以下操作在",[137,366,367],{},"工控机上","执行，不是在用于远程连接的电脑上执行：",[280,370,372],{"className":282,"code":371,"language":284,"meta":285,"style":285},"sudo ss -ulpn 'sport = :5353'\nsudo \u002Fetc\u002FNX\u002Fnxserver --version\n",[28,373,374,388],{"__ignoreMap":285},[289,375,376,379,382,385],{"class":291,"line":292},[289,377,378],{"class":295},"sudo",[289,380,381],{"class":299}," ss",[289,383,384],{"class":316}," -ulpn",[289,386,387],{"class":299}," 'sport = :5353'\n",[289,389,390,392,395],{"class":291,"line":329},[289,391,378],{"class":295},[289,393,394],{"class":299}," \u002Fetc\u002FNX\u002Fnxserver",[289,396,397],{"class":316}," --version\n",[24,399,400,401,214,403,405,406,409],{},"修复前，5353 UDP 端口同时由 ",[28,402,167],{},[28,404,186],{}," 使用。本次 NoMachine 版本为 ",[28,407,408],{},"9.7.3","。多个进程监听同一端口本身不代表一定故障，应结合实际回答的地址判断；本次已通过抓包和进程跟踪确认 NoMachine 发布错误记录。",[24,411,412],{},[137,413,414],{},"3. 工控机：关闭 NoMachine 的局域网自动发现。",[24,416,417],{},"先备份配置。下面的备份文件名用于本次排查；再次操作时换一个文件名，保留已有备份：",[280,419,421],{"className":282,"code":420,"language":284,"meta":285,"style":285},"sudo cp -a \u002Fusr\u002FNX\u002Fetc\u002Fserver.cfg \u002Fusr\u002FNX\u002Fetc\u002Fserver.cfg.before-mdns-fix-20261019\nsudoedit \u002Fusr\u002FNX\u002Fetc\u002Fserver.cfg\n",[28,422,423,439],{"__ignoreMap":285},[289,424,425,427,430,433,436],{"class":291,"line":292},[289,426,378],{"class":295},[289,428,429],{"class":299}," cp",[289,431,432],{"class":316}," -a",[289,434,435],{"class":299}," \u002Fusr\u002FNX\u002Fetc\u002Fserver.cfg",[289,437,438],{"class":299}," \u002Fusr\u002FNX\u002Fetc\u002Fserver.cfg.before-mdns-fix-20261019\n",[289,440,441,444],{"class":291,"line":329},[289,442,443],{"class":295},"sudoedit",[289,445,446],{"class":299}," \u002Fusr\u002FNX\u002Fetc\u002Fserver.cfg\n",[24,448,449],{},"找到本次安装版本中的配置项：",[280,451,456],{"className":452,"code":454,"language":455,"meta":285},[453],"language-text","#EnableLocalNetworkBroadcast 1\n","text",[28,457,454],{"__ignoreMap":285},[24,459,460,461,464],{},"去掉开头的 ",[28,462,463],{},"#"," 并改为：",[280,466,469],{"className":467,"code":468,"language":455,"meta":285},[453],"EnableLocalNetworkBroadcast 0\n",[28,470,468],{"__ignoreMap":285},[24,472,473,474,477],{},"这会关闭 NoMachine 的局域网自动发现，其他电脑不再通过它的广播自动发现该工控机；仍可通过 IP 或能够正常解析的主机名手动连接 NoMachine。\n",[137,475,476],{},"无需卸载 NoMachine，也无需停掉 Avahi。",[478,479,483],"a",{"href":480,"rel":481},"https:\u002F\u002Fkb.nomachine.com\u002FDT04U00275",[482],"nofollow","NoMachine 官方端口与配置说明",[24,485,486,487,490,491,494],{},"不同版本的配置项可能不同，旧资料中还会出现 ",[28,488,489],{},"EnableNetworkBroadcast","。应以安装版本的 ",[28,492,493],{},"server.cfg"," 注释和对应文档为准，不能把旧名称直接添加到本次 9.7.3 的配置中。",[24,496,497],{},[137,498,499],{},"4. 工控机：重启 NoMachine，使配置生效。",[24,501,502],{},"先结束正在使用的 NoMachine 远程桌面会话，再执行；重启会暂时中断该服务：",[280,504,506],{"className":282,"code":505,"language":284,"meta":285,"style":285},"sudo \u002Fetc\u002FNX\u002Fnxserver --restart\nsudo \u002Fetc\u002FNX\u002Fnxserver --status\n",[28,507,508,517],{"__ignoreMap":285},[289,509,510,512,514],{"class":291,"line":292},[289,511,378],{"class":295},[289,513,394],{"class":299},[289,515,516],{"class":316}," --restart\n",[289,518,519,521,523],{"class":291,"line":329},[289,520,378],{"class":295},[289,522,394],{"class":299},[289,524,525],{"class":316}," --status\n",[24,527,528],{},"随后检查：",[280,530,532],{"className":282,"code":531,"language":284,"meta":285,"style":285},"sudo ss -ulpn 'sport = :5353'\nsudo ss -ltnp 'sport = :4000'\n",[28,533,534,544],{"__ignoreMap":285},[289,535,536,538,540,542],{"class":291,"line":292},[289,537,378],{"class":295},[289,539,381],{"class":299},[289,541,384],{"class":316},[289,543,387],{"class":299},[289,545,546,548,550,553],{"class":291,"line":329},[289,547,378],{"class":295},[289,549,381],{"class":299},[289,551,552],{"class":316}," -ltnp",[289,554,555],{"class":299}," 'sport = :4000'\n",[24,557,558,559,562,563,214,566,569],{},"临时方案生效后，5353 端口只剩 Avahi，NoMachine 的 ",[28,560,561],{},"nxserver","、",[28,564,565],{},"nxnode",[28,567,568],{},"nxd"," 服务恢复运行，4000 TCP 端口继续监听。配置保存在文件中，系统重启后仍会读取；本次没有修改 Avahi 配置，也没有修改 Wi-Fi、雷达 IP 或路由。",[24,571,572],{},[137,573,574],{},"5. 电脑端：验证主机名和 SSH。",[280,576,578],{"className":282,"code":577,"language":284,"meta":285,"style":285},"getent ahostsv4 ysu.local\navahi-resolve-host-name -4 ysu.local\nssh ysu@ysu.local\n",[28,579,580,591,600],{"__ignoreMap":285},[289,581,582,585,588],{"class":291,"line":292},[289,583,584],{"class":295},"getent",[289,586,587],{"class":299}," ahostsv4",[289,589,590],{"class":299}," ysu.local\n",[289,592,593,596,598],{"class":291,"line":329},[289,594,595],{"class":295},"avahi-resolve-host-name",[289,597,338],{"class":316},[289,599,590],{"class":299},[289,601,603,605],{"class":291,"line":602},3,[289,604,296],{"class":295},[289,606,607],{"class":299}," ysu@ysu.local\n",[24,609,610,611,613,614,616],{},"预期解析到工控机当前的 Wi-Fi 地址，本次为 ",[28,612,30],{},"，并且可以正常登录。已经缓存的错误记录可能需要等待过期或被正确记录更新；若仍返回 ",[28,615,217],{},"，应继续抓包确认是否还有错误发布源，不能仅凭服务状态认定修复完成。",[24,618,619],{},"如需抓包，在工控机执行以下命令，将接口名换成实际 Wi-Fi 接口：",[280,621,623],{"className":282,"code":622,"language":284,"meta":285,"style":285},"sudo tcpdump -ni wlp4s0 -vv 'udp port 5353'\n",[28,624,625],{"__ignoreMap":285},[289,626,627,629,632,635,638,641],{"class":291,"line":292},[289,628,378],{"class":295},[289,630,631],{"class":299}," tcpdump",[289,633,634],{"class":316}," -ni",[289,636,637],{"class":299}," wlp4s0",[289,639,640],{"class":316}," -vv",[289,642,643],{"class":299}," 'udp port 5353'\n",[24,645,646,647,650,651,653,654,228],{},"观察 ",[28,648,649],{},"ysu.local"," 的 A 记录内容，而不只是数据包的源 IP。本次错误响应的数据包源 IP 也是 ",[28,652,213],{},"，真正错误的是其中的 A 记录指向了 ",[28,655,217],{},[20,657,658],{"id":658},"临时方案验证结果",[24,660,661],{},"2026-10-19 完成上述修改并重启 NoMachine 后：",[48,663,664,674],{},[51,665,666],{},[54,667,668,671],{},[57,669,670],{},"检查项目",[57,672,673],{},"结果",[67,675,676,686,699,715,723],{},[54,677,678,681],{},[72,679,680],{},"电脑端三次名称查询",[72,682,683,684],{},"均得到 ",[28,685,30],{},[54,687,688,691],{},[72,689,690],{},"工控机 Wi-Fi 上的三次 mDNS 查询响应",[72,692,693,694,696,697],{},"均为 Avahi 返回的 ",[28,695,213],{},"，该轮抓包未再出现 ",[28,698,217],{},[54,700,701,705],{},[72,702,703],{},[28,704,34],{},[72,706,707,708,711,712],{},"密码登录成功，远端 ",[28,709,710],{},"hostname"," 返回 ",[28,713,714],{},"ysu",[54,716,717,720],{},[72,718,719],{},"NoMachine 状态",[72,721,722],{},"服务正常，4000 TCP 端口继续监听",[54,724,725,728],{},[72,726,727],{},"电脑断开并重新连接原 Wi-Fi 后",[72,729,730,731],{},"主机名仍解析到 ",[28,732,213],{},[24,734,735,736,739,740,743,744,747,748,751],{},"临时方案只将 ",[28,737,738],{},"\u002Fusr\u002FNX\u002Fetc\u002Fserver.cfg"," 中的 ",[28,741,742],{},"EnableLocalNetworkBroadcast"," 设为 ",[28,745,746],{},"0","，原配置备份在同目录的 ",[28,749,750],{},"server.cfg.before-mdns-fix-20261019","。后续已恢复自动发现，最终状态以下面的完整修复为准。",[20,753,755],{"id":754},"完整修复让-nomachine-自动跟随-wi-fi-当前-ip","完整修复：让 NoMachine 自动跟随 Wi-Fi 当前 IP",[24,757,758,761,763],{},[137,759,760],{},"这里固定的是用于远程连接的 Wi-Fi 接口，不是某一个 IP。",[28,762,261],{}," 本身需要填写具体地址，不能靠写一行配置就自动追踪 DHCP。动态效果来自下面的同步程序：每次读取 Wi-Fi 当前地址，再把它写入 NoMachine 配置。",[24,765,766,767,769,770,772,773,787],{},"例如当前地址为 ",[28,768,213],{},"，程序就写入 ",[28,771,213],{},"；以后 DHCP 分配了其他地址，程序会用新地址替换它。",[137,774,775,776,778,779,781,782,784,785,228],{},"不要手动把 ",[28,777,261],{}," 永久写成 ",[28,780,30],{},"，也不要把 ",[28,783,649],{}," 填进这个字段来解析自己；电脑端连接时才使用 ",[28,786,649],{},[478,788,791],{"href":789,"rel":790},"https:\u002F\u002Fkb.nomachine.com\u002FTR10T10648",[482],"NoMachine 监听和广播地址配置说明",[24,793,794],{},"本机已完成下面的部署，现有工控机无需重复安装。下面给出完整步骤，方便在其他机器复用；首次部署会重启 NoMachine，应先结束正在使用的远程桌面会话。",[24,796,797],{},[137,798,799],{},"1. 工控机：确认需要跟随的 Wi-Fi 接口。",[280,801,802],{"className":282,"code":306,"language":284,"meta":285,"style":285},[28,803,804,816],{"__ignoreMap":285},[289,805,806,808,810,812,814],{"class":291,"line":292},[289,807,313],{"class":295},[289,809,317],{"class":316},[289,811,320],{"class":299},[289,813,323],{"class":299},[289,815,326],{"class":299},[289,817,818,820,822,824],{"class":291,"line":329},[289,819,332],{"class":295},[289,821,335],{"class":316},[289,823,338],{"class":316},[289,825,341],{"class":299},[24,827,828,829,831,832,834,835,837],{},"本机 Wi-Fi 为 ",[28,830,77],{},"，雷达网口为 ",[28,833,93],{},"。后面的 Python 脚本和 NetworkManager 事件脚本中各有一处接口设置，其他机器应把两处 ",[28,836,77],{}," 都换成实际 Wi-Fi 接口名。Wi-Fi 继续使用 DHCP，无需固定 IP，也无需修改雷达网口。",[24,839,840],{},[137,841,842],{},"2. 工控机：安装读取当前 IP 的同步程序。",[24,844,845],{},"创建文件：",[280,847,849],{"className":282,"code":848,"language":284,"meta":285,"style":285},"sudoedit \u002Fusr\u002Flocal\u002Fsbin\u002Fnomachine-wifi-sync\n",[28,850,851],{"__ignoreMap":285},[289,852,853,855],{"class":291,"line":292},[289,854,443],{"class":295},[289,856,857],{"class":299}," \u002Fusr\u002Flocal\u002Fsbin\u002Fnomachine-wifi-sync\n",[24,859,860,861,864,865,868],{},"填入下面的内容。脚本中只指定接口名 ",[28,862,863],{},"INTERFACE","，没有写死 Wi-Fi IP；",[28,866,867],{},"PORT"," 对应本机 NoMachine 默认的 4000 端口。",[280,870,874],{"className":871,"code":872,"language":873,"meta":285,"style":285},"language-python shiki shiki-themes github-light github-dark","#!\u002Fusr\u002Fbin\u002Fpython3\n\"\"\"Keep NoMachine bound to the robot's management Wi-Fi IPv4 address.\"\"\"\n\nimport fcntl\nimport json\nimport os\nfrom pathlib import Path\nimport re\nimport stat\nimport subprocess\nimport tempfile\n\n\nINTERFACE = \"wlp4s0\"\nCONFIG = Path(\"\u002Fusr\u002FNX\u002Fetc\u002Fserver.cfg\")\nPORT = 4000\n\n\ndef run(*args):\n    return subprocess.check_output(args, text=True, timeout=10)\n\n\ndef replace_config(content):\n    metadata = CONFIG.stat()\n    temporary = None\n    try:\n        with tempfile.NamedTemporaryFile(mode=\"w\", dir=CONFIG.parent, delete=False) as output:\n            temporary = Path(output.name)\n            output.write(content)\n            output.flush()\n            os.fchown(output.fileno(), metadata.st_uid, metadata.st_gid)\n            os.fchmod(output.fileno(), stat.S_IMODE(metadata.st_mode))\n            os.fsync(output.fileno())\n        os.replace(temporary, CONFIG)\n    finally:\n        if temporary is not None and temporary.exists():\n            temporary.unlink()\n\n\ndef main():\n    with open(\"\u002Frun\u002Fnomachine-wifi-sync.lock\", \"w\") as lock:\n        fcntl.flock(lock, fcntl.LOCK_EX)\n        interfaces = json.loads(run(\"\u002Fusr\u002Fsbin\u002Fip\", \"-j\", \"-4\", \"address\", \"show\", \"dev\", INTERFACE))\n        addresses = [\n            address[\"local\"]\n            for interface in interfaces\n            for address in interface.get(\"addr_info\", [])\n            if address.get(\"scope\") == \"global\" and address.get(\"valid_life_time\") != 0\n        ]\n        if not addresses:\n            print(f\"{INTERFACE} has no IPv4 address; leaving configuration unchanged.\", flush=True)\n            return\n        if len(addresses) != 1:\n            raise RuntimeError(f\"Expected one Wi-Fi IPv4 address; got {addresses!r}\")\n        address = addresses[0]\n        old = CONFIG.read_text()\n        updated, count = re.subn(\n            r\"(?m)^[ \\t]*#?NXDListenAddress[^\\S\\n]+[^\\n]*$\",\n            f'NXDListenAddress \"{address}\"',\n            old,\n        )\n        if count != 1:\n            raise RuntimeError(f\"Expected one NXDListenAddress entry; got {count}\")\n        listeners = run(\"\u002Fusr\u002Fbin\u002Fss\", \"-H\", \"-ltn\", f\"sport = :{PORT}\")\n        bound = any(line.split()[3] == f\"{address}:{PORT}\" for line in listeners.splitlines())\n        if updated == old and bound:\n            print(f\"NoMachine already bound to {INTERFACE} {address}:{PORT}; no restart.\", flush=True)\n            return\n        if updated != old:\n            replace_config(updated)\n        print(f\"Synchronizing NoMachine to {INTERFACE} {address}:{PORT}.\", flush=True)\n        subprocess.run([\"\u002Fetc\u002FNX\u002Fnxserver\", \"--restart\"], check=True, timeout=75)\n        listeners = run(\"\u002Fusr\u002Fbin\u002Fss\", \"-H\", \"-ltn\", f\"sport = :{PORT}\")\n        if not any(line.split()[3] == f\"{address}:{PORT}\" for line in listeners.splitlines()):\n            raise RuntimeError(f\"NoMachine is not listening on {address}:{PORT} after restart\")\n        print(f\"Verified NoMachine listener {address}:{PORT}.\", flush=True)\n\n\nif __name__ == \"__main__\":\n    main()\n","python",[28,875,876,882,887,893,904,912,920,934,942,950,958,966,971,976,987,1004,1014,1019,1024,1042,1073,1078,1083,1094,1108,1119,1128,1174,1185,1191,1197,1203,1209,1215,1225,1233,1257,1263,1268,1273,1284,1309,1320,1366,1377,1389,1404,1423,1458,1464,1474,1505,1511,1529,1561,1576,1589,1600,1666,1687,1693,1699,1713,1738,1776,1827,1846,1884,1889,1901,1907,1945,1980,2011,2053,2082,2116,2121,2126,2143],{"__ignoreMap":285},[289,877,878],{"class":291,"line":292},[289,879,881],{"class":880},"sJ8bj","#!\u002Fusr\u002Fbin\u002Fpython3\n",[289,883,884],{"class":291,"line":329},[289,885,886],{"class":299},"\"\"\"Keep NoMachine bound to the robot's management Wi-Fi IPv4 address.\"\"\"\n",[289,888,889],{"class":291,"line":602},[289,890,892],{"emptyLinePlaceholder":891},true,"\n",[289,894,896,900],{"class":291,"line":895},4,[289,897,899],{"class":898},"szBVR","import",[289,901,903],{"class":902},"sVt8B"," fcntl\n",[289,905,907,909],{"class":291,"line":906},5,[289,908,899],{"class":898},[289,910,911],{"class":902}," json\n",[289,913,915,917],{"class":291,"line":914},6,[289,916,899],{"class":898},[289,918,919],{"class":902}," os\n",[289,921,923,926,929,931],{"class":291,"line":922},7,[289,924,925],{"class":898},"from",[289,927,928],{"class":902}," pathlib ",[289,930,899],{"class":898},[289,932,933],{"class":902}," Path\n",[289,935,937,939],{"class":291,"line":936},8,[289,938,899],{"class":898},[289,940,941],{"class":902}," re\n",[289,943,945,947],{"class":291,"line":944},9,[289,946,899],{"class":898},[289,948,949],{"class":902}," stat\n",[289,951,953,955],{"class":291,"line":952},10,[289,954,899],{"class":898},[289,956,957],{"class":902}," subprocess\n",[289,959,961,963],{"class":291,"line":960},11,[289,962,899],{"class":898},[289,964,965],{"class":902}," tempfile\n",[289,967,969],{"class":291,"line":968},12,[289,970,892],{"emptyLinePlaceholder":891},[289,972,974],{"class":291,"line":973},13,[289,975,892],{"emptyLinePlaceholder":891},[289,977,979,981,984],{"class":291,"line":978},14,[289,980,863],{"class":316},[289,982,983],{"class":898}," =",[289,985,986],{"class":299}," \"wlp4s0\"\n",[289,988,990,993,995,998,1001],{"class":291,"line":989},15,[289,991,992],{"class":316},"CONFIG",[289,994,983],{"class":898},[289,996,997],{"class":902}," Path(",[289,999,1000],{"class":299},"\"\u002Fusr\u002FNX\u002Fetc\u002Fserver.cfg\"",[289,1002,1003],{"class":902},")\n",[289,1005,1007,1009,1011],{"class":291,"line":1006},16,[289,1008,867],{"class":316},[289,1010,983],{"class":898},[289,1012,1013],{"class":316}," 4000\n",[289,1015,1017],{"class":291,"line":1016},17,[289,1018,892],{"emptyLinePlaceholder":891},[289,1020,1022],{"class":291,"line":1021},18,[289,1023,892],{"emptyLinePlaceholder":891},[289,1025,1027,1030,1033,1036,1039],{"class":291,"line":1026},19,[289,1028,1029],{"class":898},"def",[289,1031,1032],{"class":295}," run",[289,1034,1035],{"class":902},"(",[289,1037,1038],{"class":898},"*",[289,1040,1041],{"class":902},"args):\n",[289,1043,1045,1048,1051,1054,1057,1060,1063,1066,1068,1071],{"class":291,"line":1044},20,[289,1046,1047],{"class":898},"    return",[289,1049,1050],{"class":902}," subprocess.check_output(args, ",[289,1052,455],{"class":1053},"s4XuR",[289,1055,1056],{"class":898},"=",[289,1058,1059],{"class":316},"True",[289,1061,1062],{"class":902},", ",[289,1064,1065],{"class":1053},"timeout",[289,1067,1056],{"class":898},[289,1069,1070],{"class":316},"10",[289,1072,1003],{"class":902},[289,1074,1076],{"class":291,"line":1075},21,[289,1077,892],{"emptyLinePlaceholder":891},[289,1079,1081],{"class":291,"line":1080},22,[289,1082,892],{"emptyLinePlaceholder":891},[289,1084,1086,1088,1091],{"class":291,"line":1085},23,[289,1087,1029],{"class":898},[289,1089,1090],{"class":295}," replace_config",[289,1092,1093],{"class":902},"(content):\n",[289,1095,1097,1100,1102,1105],{"class":291,"line":1096},24,[289,1098,1099],{"class":902},"    metadata ",[289,1101,1056],{"class":898},[289,1103,1104],{"class":316}," CONFIG",[289,1106,1107],{"class":902},".stat()\n",[289,1109,1111,1114,1116],{"class":291,"line":1110},25,[289,1112,1113],{"class":902},"    temporary ",[289,1115,1056],{"class":898},[289,1117,1118],{"class":316}," None\n",[289,1120,1122,1125],{"class":291,"line":1121},26,[289,1123,1124],{"class":898},"    try",[289,1126,1127],{"class":902},":\n",[289,1129,1131,1134,1137,1140,1142,1145,1147,1150,1152,1154,1157,1160,1162,1165,1168,1171],{"class":291,"line":1130},27,[289,1132,1133],{"class":898},"        with",[289,1135,1136],{"class":902}," tempfile.NamedTemporaryFile(",[289,1138,1139],{"class":1053},"mode",[289,1141,1056],{"class":898},[289,1143,1144],{"class":299},"\"w\"",[289,1146,1062],{"class":902},[289,1148,1149],{"class":1053},"dir",[289,1151,1056],{"class":898},[289,1153,992],{"class":316},[289,1155,1156],{"class":902},".parent, ",[289,1158,1159],{"class":1053},"delete",[289,1161,1056],{"class":898},[289,1163,1164],{"class":316},"False",[289,1166,1167],{"class":902},") ",[289,1169,1170],{"class":898},"as",[289,1172,1173],{"class":902}," output:\n",[289,1175,1177,1180,1182],{"class":291,"line":1176},28,[289,1178,1179],{"class":902},"            temporary ",[289,1181,1056],{"class":898},[289,1183,1184],{"class":902}," Path(output.name)\n",[289,1186,1188],{"class":291,"line":1187},29,[289,1189,1190],{"class":902},"            output.write(content)\n",[289,1192,1194],{"class":291,"line":1193},30,[289,1195,1196],{"class":902},"            output.flush()\n",[289,1198,1200],{"class":291,"line":1199},31,[289,1201,1202],{"class":902},"            os.fchown(output.fileno(), metadata.st_uid, metadata.st_gid)\n",[289,1204,1206],{"class":291,"line":1205},32,[289,1207,1208],{"class":902},"            os.fchmod(output.fileno(), stat.S_IMODE(metadata.st_mode))\n",[289,1210,1212],{"class":291,"line":1211},33,[289,1213,1214],{"class":902},"            os.fsync(output.fileno())\n",[289,1216,1218,1221,1223],{"class":291,"line":1217},34,[289,1219,1220],{"class":902},"        os.replace(temporary, ",[289,1222,992],{"class":316},[289,1224,1003],{"class":902},[289,1226,1228,1231],{"class":291,"line":1227},35,[289,1229,1230],{"class":898},"    finally",[289,1232,1127],{"class":902},[289,1234,1236,1239,1242,1245,1248,1251,1254],{"class":291,"line":1235},36,[289,1237,1238],{"class":898},"        if",[289,1240,1241],{"class":902}," temporary ",[289,1243,1244],{"class":898},"is",[289,1246,1247],{"class":898}," not",[289,1249,1250],{"class":316}," None",[289,1252,1253],{"class":898}," and",[289,1255,1256],{"class":902}," temporary.exists():\n",[289,1258,1260],{"class":291,"line":1259},37,[289,1261,1262],{"class":902},"            temporary.unlink()\n",[289,1264,1266],{"class":291,"line":1265},38,[289,1267,892],{"emptyLinePlaceholder":891},[289,1269,1271],{"class":291,"line":1270},39,[289,1272,892],{"emptyLinePlaceholder":891},[289,1274,1276,1278,1281],{"class":291,"line":1275},40,[289,1277,1029],{"class":898},[289,1279,1280],{"class":295}," main",[289,1282,1283],{"class":902},"():\n",[289,1285,1287,1290,1293,1295,1298,1300,1302,1304,1306],{"class":291,"line":1286},41,[289,1288,1289],{"class":898},"    with",[289,1291,1292],{"class":316}," open",[289,1294,1035],{"class":902},[289,1296,1297],{"class":299},"\"\u002Frun\u002Fnomachine-wifi-sync.lock\"",[289,1299,1062],{"class":902},[289,1301,1144],{"class":299},[289,1303,1167],{"class":902},[289,1305,1170],{"class":898},[289,1307,1308],{"class":902}," lock:\n",[289,1310,1312,1315,1318],{"class":291,"line":1311},42,[289,1313,1314],{"class":902},"        fcntl.flock(lock, fcntl.",[289,1316,1317],{"class":316},"LOCK_EX",[289,1319,1003],{"class":902},[289,1321,1323,1326,1328,1331,1334,1336,1339,1341,1344,1346,1349,1351,1354,1356,1359,1361,1363],{"class":291,"line":1322},43,[289,1324,1325],{"class":902},"        interfaces ",[289,1327,1056],{"class":898},[289,1329,1330],{"class":902}," json.loads(run(",[289,1332,1333],{"class":299},"\"\u002Fusr\u002Fsbin\u002Fip\"",[289,1335,1062],{"class":902},[289,1337,1338],{"class":299},"\"-j\"",[289,1340,1062],{"class":902},[289,1342,1343],{"class":299},"\"-4\"",[289,1345,1062],{"class":902},[289,1347,1348],{"class":299},"\"address\"",[289,1350,1062],{"class":902},[289,1352,1353],{"class":299},"\"show\"",[289,1355,1062],{"class":902},[289,1357,1358],{"class":299},"\"dev\"",[289,1360,1062],{"class":902},[289,1362,863],{"class":316},[289,1364,1365],{"class":902},"))\n",[289,1367,1369,1372,1374],{"class":291,"line":1368},44,[289,1370,1371],{"class":902},"        addresses ",[289,1373,1056],{"class":898},[289,1375,1376],{"class":902}," [\n",[289,1378,1380,1383,1386],{"class":291,"line":1379},45,[289,1381,1382],{"class":902},"            address[",[289,1384,1385],{"class":299},"\"local\"",[289,1387,1388],{"class":902},"]\n",[289,1390,1392,1395,1398,1401],{"class":291,"line":1391},46,[289,1393,1394],{"class":898},"            for",[289,1396,1397],{"class":902}," interface ",[289,1399,1400],{"class":898},"in",[289,1402,1403],{"class":902}," interfaces\n",[289,1405,1407,1409,1412,1414,1417,1420],{"class":291,"line":1406},47,[289,1408,1394],{"class":898},[289,1410,1411],{"class":902}," address ",[289,1413,1400],{"class":898},[289,1415,1416],{"class":902}," interface.get(",[289,1418,1419],{"class":299},"\"addr_info\"",[289,1421,1422],{"class":902},", [])\n",[289,1424,1426,1429,1432,1435,1437,1440,1443,1445,1447,1450,1452,1455],{"class":291,"line":1425},48,[289,1427,1428],{"class":898},"            if",[289,1430,1431],{"class":902}," address.get(",[289,1433,1434],{"class":299},"\"scope\"",[289,1436,1167],{"class":902},[289,1438,1439],{"class":898},"==",[289,1441,1442],{"class":299}," \"global\"",[289,1444,1253],{"class":898},[289,1446,1431],{"class":902},[289,1448,1449],{"class":299},"\"valid_life_time\"",[289,1451,1167],{"class":902},[289,1453,1454],{"class":898},"!=",[289,1456,1457],{"class":316}," 0\n",[289,1459,1461],{"class":291,"line":1460},49,[289,1462,1463],{"class":902},"        ]\n",[289,1465,1467,1469,1471],{"class":291,"line":1466},50,[289,1468,1238],{"class":898},[289,1470,1247],{"class":898},[289,1472,1473],{"class":902}," addresses:\n",[289,1475,1477,1480,1482,1485,1488,1491,1494,1496,1499,1501,1503],{"class":291,"line":1476},51,[289,1478,1479],{"class":316},"            print",[289,1481,1035],{"class":902},[289,1483,1484],{"class":898},"f",[289,1486,1487],{"class":299},"\"",[289,1489,1490],{"class":316},"{INTERFACE}",[289,1492,1493],{"class":299}," has no IPv4 address; leaving configuration unchanged.\"",[289,1495,1062],{"class":902},[289,1497,1498],{"class":1053},"flush",[289,1500,1056],{"class":898},[289,1502,1059],{"class":316},[289,1504,1003],{"class":902},[289,1506,1508],{"class":291,"line":1507},52,[289,1509,1510],{"class":898},"            return\n",[289,1512,1514,1516,1519,1522,1524,1527],{"class":291,"line":1513},53,[289,1515,1238],{"class":898},[289,1517,1518],{"class":316}," len",[289,1520,1521],{"class":902},"(addresses) ",[289,1523,1454],{"class":898},[289,1525,1526],{"class":316}," 1",[289,1528,1127],{"class":902},[289,1530,1532,1535,1538,1540,1542,1545,1548,1551,1554,1557,1559],{"class":291,"line":1531},54,[289,1533,1534],{"class":898},"            raise",[289,1536,1537],{"class":316}," RuntimeError",[289,1539,1035],{"class":902},[289,1541,1484],{"class":898},[289,1543,1544],{"class":299},"\"Expected one Wi-Fi IPv4 address; got ",[289,1546,1547],{"class":316},"{",[289,1549,1550],{"class":902},"addresses",[289,1552,1553],{"class":898},"!r",[289,1555,1556],{"class":316},"}",[289,1558,1487],{"class":299},[289,1560,1003],{"class":902},[289,1562,1564,1567,1569,1572,1574],{"class":291,"line":1563},55,[289,1565,1566],{"class":902},"        address ",[289,1568,1056],{"class":898},[289,1570,1571],{"class":902}," addresses[",[289,1573,746],{"class":316},[289,1575,1388],{"class":902},[289,1577,1579,1582,1584,1586],{"class":291,"line":1578},56,[289,1580,1581],{"class":902},"        old ",[289,1583,1056],{"class":898},[289,1585,1104],{"class":316},[289,1587,1588],{"class":902},".read_text()\n",[289,1590,1592,1595,1597],{"class":291,"line":1591},57,[289,1593,1594],{"class":902},"        updated, count ",[289,1596,1056],{"class":898},[289,1598,1599],{"class":902}," re.subn(\n",[289,1601,1603,1606,1608,1611,1614,1618,1621,1623,1626,1629,1631,1634,1637,1640,1643,1645,1648,1650,1652,1654,1656,1658,1661,1663],{"class":291,"line":1602},58,[289,1604,1605],{"class":898},"            r",[289,1607,1487],{"class":299},[289,1609,1610],{"class":898},"(?m)",[289,1612,1613],{"class":316},"^[ ",[289,1615,1617],{"class":1616},"snhLl","\\t",[289,1619,1620],{"class":316},"]",[289,1622,1038],{"class":898},[289,1624,463],{"class":1625},"sA_wV",[289,1627,1628],{"class":898},"?",[289,1630,261],{"class":1625},[289,1632,1633],{"class":316},"[",[289,1635,1636],{"class":898},"^",[289,1638,1639],{"class":316},"\\S",[289,1641,1642],{"class":1616},"\\n",[289,1644,1620],{"class":316},[289,1646,1647],{"class":898},"+",[289,1649,1633],{"class":316},[289,1651,1636],{"class":898},[289,1653,1642],{"class":1616},[289,1655,1620],{"class":316},[289,1657,1038],{"class":898},[289,1659,1660],{"class":316},"$",[289,1662,1487],{"class":299},[289,1664,1665],{"class":902},",\n",[289,1667,1669,1672,1675,1677,1680,1682,1685],{"class":291,"line":1668},59,[289,1670,1671],{"class":898},"            f",[289,1673,1674],{"class":299},"'NXDListenAddress \"",[289,1676,1547],{"class":316},[289,1678,1679],{"class":902},"address",[289,1681,1556],{"class":316},[289,1683,1684],{"class":299},"\"'",[289,1686,1665],{"class":902},[289,1688,1690],{"class":291,"line":1689},60,[289,1691,1692],{"class":902},"            old,\n",[289,1694,1696],{"class":291,"line":1695},61,[289,1697,1698],{"class":902},"        )\n",[289,1700,1702,1704,1707,1709,1711],{"class":291,"line":1701},62,[289,1703,1238],{"class":898},[289,1705,1706],{"class":902}," count ",[289,1708,1454],{"class":898},[289,1710,1526],{"class":316},[289,1712,1127],{"class":902},[289,1714,1716,1718,1720,1722,1724,1727,1729,1732,1734,1736],{"class":291,"line":1715},63,[289,1717,1534],{"class":898},[289,1719,1537],{"class":316},[289,1721,1035],{"class":902},[289,1723,1484],{"class":898},[289,1725,1726],{"class":299},"\"Expected one NXDListenAddress entry; got ",[289,1728,1547],{"class":316},[289,1730,1731],{"class":902},"count",[289,1733,1556],{"class":316},[289,1735,1487],{"class":299},[289,1737,1003],{"class":902},[289,1739,1741,1744,1746,1749,1752,1754,1757,1759,1762,1764,1766,1769,1772,1774],{"class":291,"line":1740},64,[289,1742,1743],{"class":902},"        listeners ",[289,1745,1056],{"class":898},[289,1747,1748],{"class":902}," run(",[289,1750,1751],{"class":299},"\"\u002Fusr\u002Fbin\u002Fss\"",[289,1753,1062],{"class":902},[289,1755,1756],{"class":299},"\"-H\"",[289,1758,1062],{"class":902},[289,1760,1761],{"class":299},"\"-ltn\"",[289,1763,1062],{"class":902},[289,1765,1484],{"class":898},[289,1767,1768],{"class":299},"\"sport = :",[289,1770,1771],{"class":316},"{PORT}",[289,1773,1487],{"class":299},[289,1775,1003],{"class":902},[289,1777,1779,1782,1784,1787,1790,1793,1796,1798,1801,1803,1805,1807,1809,1812,1814,1816,1819,1822,1824],{"class":291,"line":1778},65,[289,1780,1781],{"class":902},"        bound ",[289,1783,1056],{"class":898},[289,1785,1786],{"class":316}," any",[289,1788,1789],{"class":902},"(line.split()[",[289,1791,1792],{"class":316},"3",[289,1794,1795],{"class":902},"] ",[289,1797,1439],{"class":898},[289,1799,1800],{"class":898}," f",[289,1802,1487],{"class":299},[289,1804,1547],{"class":316},[289,1806,1679],{"class":902},[289,1808,1556],{"class":316},[289,1810,1811],{"class":299},":",[289,1813,1771],{"class":316},[289,1815,1487],{"class":299},[289,1817,1818],{"class":898}," for",[289,1820,1821],{"class":902}," line ",[289,1823,1400],{"class":898},[289,1825,1826],{"class":902}," listeners.splitlines())\n",[289,1828,1830,1832,1835,1837,1840,1843],{"class":291,"line":1829},66,[289,1831,1238],{"class":898},[289,1833,1834],{"class":902}," updated ",[289,1836,1439],{"class":898},[289,1838,1839],{"class":902}," old ",[289,1841,1842],{"class":898},"and",[289,1844,1845],{"class":902}," bound:\n",[289,1847,1849,1851,1853,1855,1858,1860,1863,1865,1867,1869,1871,1874,1876,1878,1880,1882],{"class":291,"line":1848},67,[289,1850,1479],{"class":316},[289,1852,1035],{"class":902},[289,1854,1484],{"class":898},[289,1856,1857],{"class":299},"\"NoMachine already bound to ",[289,1859,1490],{"class":316},[289,1861,1862],{"class":316}," {",[289,1864,1679],{"class":902},[289,1866,1556],{"class":316},[289,1868,1811],{"class":299},[289,1870,1771],{"class":316},[289,1872,1873],{"class":299},"; no restart.\"",[289,1875,1062],{"class":902},[289,1877,1498],{"class":1053},[289,1879,1056],{"class":898},[289,1881,1059],{"class":316},[289,1883,1003],{"class":902},[289,1885,1887],{"class":291,"line":1886},68,[289,1888,1510],{"class":898},[289,1890,1892,1894,1896,1898],{"class":291,"line":1891},69,[289,1893,1238],{"class":898},[289,1895,1834],{"class":902},[289,1897,1454],{"class":898},[289,1899,1900],{"class":902}," old:\n",[289,1902,1904],{"class":291,"line":1903},70,[289,1905,1906],{"class":902},"            replace_config(updated)\n",[289,1908,1910,1913,1915,1917,1920,1922,1924,1926,1928,1930,1932,1935,1937,1939,1941,1943],{"class":291,"line":1909},71,[289,1911,1912],{"class":316},"        print",[289,1914,1035],{"class":902},[289,1916,1484],{"class":898},[289,1918,1919],{"class":299},"\"Synchronizing NoMachine to ",[289,1921,1490],{"class":316},[289,1923,1862],{"class":316},[289,1925,1679],{"class":902},[289,1927,1556],{"class":316},[289,1929,1811],{"class":299},[289,1931,1771],{"class":316},[289,1933,1934],{"class":299},".\"",[289,1936,1062],{"class":902},[289,1938,1498],{"class":1053},[289,1940,1056],{"class":898},[289,1942,1059],{"class":316},[289,1944,1003],{"class":902},[289,1946,1948,1951,1954,1956,1959,1962,1965,1967,1969,1971,1973,1975,1978],{"class":291,"line":1947},72,[289,1949,1950],{"class":902},"        subprocess.run([",[289,1952,1953],{"class":299},"\"\u002Fetc\u002FNX\u002Fnxserver\"",[289,1955,1062],{"class":902},[289,1957,1958],{"class":299},"\"--restart\"",[289,1960,1961],{"class":902},"], ",[289,1963,1964],{"class":1053},"check",[289,1966,1056],{"class":898},[289,1968,1059],{"class":316},[289,1970,1062],{"class":902},[289,1972,1065],{"class":1053},[289,1974,1056],{"class":898},[289,1976,1977],{"class":316},"75",[289,1979,1003],{"class":902},[289,1981,1983,1985,1987,1989,1991,1993,1995,1997,1999,2001,2003,2005,2007,2009],{"class":291,"line":1982},73,[289,1984,1743],{"class":902},[289,1986,1056],{"class":898},[289,1988,1748],{"class":902},[289,1990,1751],{"class":299},[289,1992,1062],{"class":902},[289,1994,1756],{"class":299},[289,1996,1062],{"class":902},[289,1998,1761],{"class":299},[289,2000,1062],{"class":902},[289,2002,1484],{"class":898},[289,2004,1768],{"class":299},[289,2006,1771],{"class":316},[289,2008,1487],{"class":299},[289,2010,1003],{"class":902},[289,2012,2014,2016,2018,2020,2022,2024,2026,2028,2030,2032,2034,2036,2038,2040,2042,2044,2046,2048,2050],{"class":291,"line":2013},74,[289,2015,1238],{"class":898},[289,2017,1247],{"class":898},[289,2019,1786],{"class":316},[289,2021,1789],{"class":902},[289,2023,1792],{"class":316},[289,2025,1795],{"class":902},[289,2027,1439],{"class":898},[289,2029,1800],{"class":898},[289,2031,1487],{"class":299},[289,2033,1547],{"class":316},[289,2035,1679],{"class":902},[289,2037,1556],{"class":316},[289,2039,1811],{"class":299},[289,2041,1771],{"class":316},[289,2043,1487],{"class":299},[289,2045,1818],{"class":898},[289,2047,1821],{"class":902},[289,2049,1400],{"class":898},[289,2051,2052],{"class":902}," listeners.splitlines()):\n",[289,2054,2056,2058,2060,2062,2064,2067,2069,2071,2073,2075,2077,2080],{"class":291,"line":2055},75,[289,2057,1534],{"class":898},[289,2059,1537],{"class":316},[289,2061,1035],{"class":902},[289,2063,1484],{"class":898},[289,2065,2066],{"class":299},"\"NoMachine is not listening on ",[289,2068,1547],{"class":316},[289,2070,1679],{"class":902},[289,2072,1556],{"class":316},[289,2074,1811],{"class":299},[289,2076,1771],{"class":316},[289,2078,2079],{"class":299}," after restart\"",[289,2081,1003],{"class":902},[289,2083,2085,2087,2089,2091,2094,2096,2098,2100,2102,2104,2106,2108,2110,2112,2114],{"class":291,"line":2084},76,[289,2086,1912],{"class":316},[289,2088,1035],{"class":902},[289,2090,1484],{"class":898},[289,2092,2093],{"class":299},"\"Verified NoMachine listener ",[289,2095,1547],{"class":316},[289,2097,1679],{"class":902},[289,2099,1556],{"class":316},[289,2101,1811],{"class":299},[289,2103,1771],{"class":316},[289,2105,1934],{"class":299},[289,2107,1062],{"class":902},[289,2109,1498],{"class":1053},[289,2111,1056],{"class":898},[289,2113,1059],{"class":316},[289,2115,1003],{"class":902},[289,2117,2119],{"class":291,"line":2118},77,[289,2120,892],{"emptyLinePlaceholder":891},[289,2122,2124],{"class":291,"line":2123},78,[289,2125,892],{"emptyLinePlaceholder":891},[289,2127,2129,2132,2135,2138,2141],{"class":291,"line":2128},79,[289,2130,2131],{"class":898},"if",[289,2133,2134],{"class":316}," __name__",[289,2136,2137],{"class":898}," ==",[289,2139,2140],{"class":299}," \"__main__\"",[289,2142,1127],{"class":902},[289,2144,2146],{"class":291,"line":2145},80,[289,2147,2148],{"class":902},"    main()\n",[24,2150,2151,2152,2154],{},"这个程序读取接口当前的唯一全局 IPv4，更新现有的 ",[28,2153,261],{}," 配置项。当前地址和监听都正确时直接退出；地址改变或监听未恢复时，才重启 NoMachine 并检查结果。接口暂时没有 IPv4 时不修改配置，存在多个 IPv4 时明确报错，避免随意选择地址。",[24,2156,2157],{},[137,2158,2159],{},"3. 工控机：设置开机同步和网络变化触发。",[24,2161,2162],{},"创建一次性同步服务：",[280,2164,2166],{"className":282,"code":2165,"language":284,"meta":285,"style":285},"sudoedit \u002Fetc\u002Fsystemd\u002Fsystem\u002Fnomachine-wifi-sync.service\n",[28,2167,2168],{"__ignoreMap":285},[289,2169,2170,2172],{"class":291,"line":292},[289,2171,443],{"class":295},[289,2173,2174],{"class":299}," \u002Fetc\u002Fsystemd\u002Fsystem\u002Fnomachine-wifi-sync.service\n",[24,2176,2177],{},"填入：",[280,2179,2183],{"className":2180,"code":2181,"language":2182,"meta":285,"style":285},"language-ini shiki shiki-themes github-light github-dark","[Unit]\nDescription=Bind NoMachine to the current management Wi-Fi IPv4 address\nWants=network-online.target\nAfter=network-online.target nxserver.service\n\n[Service]\nType=oneshot\nExecStart=\u002Fusr\u002Flocal\u002Fsbin\u002Fnomachine-wifi-sync\nTimeoutStartSec=100\n\n[Install]\nWantedBy=multi-user.target\n","ini",[28,2184,2185,2190,2195,2200,2205,2209,2214,2219,2224,2229,2233,2238],{"__ignoreMap":285},[289,2186,2187],{"class":291,"line":292},[289,2188,2189],{},"[Unit]\n",[289,2191,2192],{"class":291,"line":329},[289,2193,2194],{},"Description=Bind NoMachine to the current management Wi-Fi IPv4 address\n",[289,2196,2197],{"class":291,"line":602},[289,2198,2199],{},"Wants=network-online.target\n",[289,2201,2202],{"class":291,"line":895},[289,2203,2204],{},"After=network-online.target nxserver.service\n",[289,2206,2207],{"class":291,"line":906},[289,2208,892],{"emptyLinePlaceholder":891},[289,2210,2211],{"class":291,"line":914},[289,2212,2213],{},"[Service]\n",[289,2215,2216],{"class":291,"line":922},[289,2217,2218],{},"Type=oneshot\n",[289,2220,2221],{"class":291,"line":936},[289,2222,2223],{},"ExecStart=\u002Fusr\u002Flocal\u002Fsbin\u002Fnomachine-wifi-sync\n",[289,2225,2226],{"class":291,"line":944},[289,2227,2228],{},"TimeoutStartSec=100\n",[289,2230,2231],{"class":291,"line":952},[289,2232,892],{"emptyLinePlaceholder":891},[289,2234,2235],{"class":291,"line":960},[289,2236,2237],{},"[Install]\n",[289,2239,2240],{"class":291,"line":968},[289,2241,2242],{},"WantedBy=multi-user.target\n",[24,2244,2245],{},"再创建 NetworkManager 事件脚本：",[280,2247,2249],{"className":282,"code":2248,"language":284,"meta":285,"style":285},"sudoedit \u002Fetc\u002FNetworkManager\u002Fdispatcher.d\u002F90-nomachine-wifi\n",[28,2250,2251],{"__ignoreMap":285},[289,2252,2253,2255],{"class":291,"line":292},[289,2254,443],{"class":295},[289,2256,2257],{"class":299}," \u002Fetc\u002FNetworkManager\u002Fdispatcher.d\u002F90-nomachine-wifi\n",[24,2259,2177],{},[280,2261,2265],{"className":2262,"code":2263,"language":2264,"meta":285,"style":285},"language-sh shiki shiki-themes github-light github-dark","#!\u002Fbin\u002Fsh\n# NetworkManager runs this as root after connection\u002Faddress changes.\ncase \"${1:-}:${2:-}\" in\n    wlp4s0:up|wlp4s0:dhcp4-change|wlp4s0:reapply)\n        \u002Fusr\u002Fbin\u002Fsystemctl --no-block start nomachine-wifi-sync.service\n        ;;\nesac\n","sh",[28,2266,2267,2272,2277,2307,2325,2339,2344],{"__ignoreMap":285},[289,2268,2269],{"class":291,"line":292},[289,2270,2271],{"class":880},"#!\u002Fbin\u002Fsh\n",[289,2273,2274],{"class":291,"line":329},[289,2275,2276],{"class":880},"# NetworkManager runs this as root after connection\u002Faddress changes.\n",[289,2278,2279,2282,2285,2288,2291,2293,2295,2298,2300,2302,2304],{"class":291,"line":602},[289,2280,2281],{"class":898},"case",[289,2283,2284],{"class":299}," \"",[289,2286,2287],{"class":316},"${1",[289,2289,2290],{"class":898},":-",[289,2292,1556],{"class":316},[289,2294,1811],{"class":299},[289,2296,2297],{"class":316},"${2",[289,2299,2290],{"class":898},[289,2301,1556],{"class":316},[289,2303,1487],{"class":299},[289,2305,2306],{"class":898}," in\n",[289,2308,2309,2312,2315,2318,2320,2323],{"class":291,"line":895},[289,2310,2311],{"class":1625},"    wlp4s0:up",[289,2313,2314],{"class":898},"|",[289,2316,2317],{"class":1625},"wlp4s0:dhcp4-change",[289,2319,2314],{"class":898},[289,2321,2322],{"class":1625},"wlp4s0:reapply",[289,2324,1003],{"class":898},[289,2326,2327,2330,2333,2336],{"class":291,"line":906},[289,2328,2329],{"class":295},"        \u002Fusr\u002Fbin\u002Fsystemctl",[289,2331,2332],{"class":316}," --no-block",[289,2334,2335],{"class":299}," start",[289,2337,2338],{"class":299}," nomachine-wifi-sync.service\n",[289,2340,2341],{"class":291,"line":914},[289,2342,2343],{"class":902},"        ;;\n",[289,2345,2346],{"class":291,"line":922},[289,2347,2348],{"class":898},"esac\n",[24,2350,2351],{},"设置文件所有者和执行权限：",[280,2353,2355],{"className":282,"code":2354,"language":284,"meta":285,"style":285},"sudo chown root:root \u002Fusr\u002Flocal\u002Fsbin\u002Fnomachine-wifi-sync \u002Fetc\u002Fsystemd\u002Fsystem\u002Fnomachine-wifi-sync.service \u002Fetc\u002FNetworkManager\u002Fdispatcher.d\u002F90-nomachine-wifi\nsudo chmod 755 \u002Fusr\u002Flocal\u002Fsbin\u002Fnomachine-wifi-sync \u002Fetc\u002FNetworkManager\u002Fdispatcher.d\u002F90-nomachine-wifi\nsudo chmod 644 \u002Fetc\u002Fsystemd\u002Fsystem\u002Fnomachine-wifi-sync.service\n",[28,2356,2357,2375,2389],{"__ignoreMap":285},[289,2358,2359,2361,2364,2367,2370,2373],{"class":291,"line":292},[289,2360,378],{"class":295},[289,2362,2363],{"class":299}," chown",[289,2365,2366],{"class":299}," root:root",[289,2368,2369],{"class":299}," \u002Fusr\u002Flocal\u002Fsbin\u002Fnomachine-wifi-sync",[289,2371,2372],{"class":299}," \u002Fetc\u002Fsystemd\u002Fsystem\u002Fnomachine-wifi-sync.service",[289,2374,2257],{"class":299},[289,2376,2377,2379,2382,2385,2387],{"class":291,"line":329},[289,2378,378],{"class":295},[289,2380,2381],{"class":299}," chmod",[289,2383,2384],{"class":316}," 755",[289,2386,2369],{"class":299},[289,2388,2257],{"class":299},[289,2390,2391,2393,2395,2398],{"class":291,"line":602},[289,2392,378],{"class":295},[289,2394,2381],{"class":299},[289,2396,2397],{"class":316}," 644",[289,2399,2174],{"class":299},[24,2401,2402,2403],{},"这样，Wi-Fi 连接、DHCPv4 租约变化或重新应用连接配置时，系统都会触发同步。",[478,2404,2407],{"href":2405,"rel":2406},"https:\u002F\u002Fnetworkmanager.pages.freedesktop.org\u002FNetworkManager\u002FNetworkManager\u002FNetworkManager-dispatcher.html",[482],"NetworkManager 官方事件说明",[24,2409,2410,2411],{},"上述三个文件是本次部署的辅助配置，不是 NoMachine 自带功能；",[137,2412,2413,2414,2416],{},"只修改 ",[28,2415,493],{},"、没有安装事件脚本，地址就不会自动跟随 DHCP。",[24,2418,2419],{},[137,2420,2421],{},"4. 工控机：启用同步，再恢复 NoMachine 自动发现。",[24,2423,2424,2425,2427],{},"先加载并启用同步服务，让程序根据当前 Wi-Fi 地址生成 ",[28,2426,261],{},"：",[280,2429,2431],{"className":282,"code":2430,"language":284,"meta":285,"style":285},"sudo systemctl daemon-reload\nsudo systemctl enable --now nomachine-wifi-sync.service\n",[28,2432,2433,2443],{"__ignoreMap":285},[289,2434,2435,2437,2440],{"class":291,"line":292},[289,2436,378],{"class":295},[289,2438,2439],{"class":299}," systemctl",[289,2441,2442],{"class":299}," daemon-reload\n",[289,2444,2445,2447,2449,2452,2455],{"class":291,"line":329},[289,2446,378],{"class":295},[289,2448,2439],{"class":299},[289,2450,2451],{"class":299}," enable",[289,2453,2454],{"class":316}," --now",[289,2456,2338],{"class":299},[24,2458,2459],{},"然后编辑 NoMachine 配置：",[280,2461,2463],{"className":282,"code":2462,"language":284,"meta":285,"style":285},"sudoedit \u002Fusr\u002FNX\u002Fetc\u002Fserver.cfg\n",[28,2464,2465],{"__ignoreMap":285},[289,2466,2467,2469],{"class":291,"line":292},[289,2468,443],{"class":295},[289,2470,446],{"class":299},[24,2472,2473],{},"将局域网自动发现配置项改为：",[280,2475,2478],{"className":2476,"code":2477,"language":455,"meta":285},[453],"EnableLocalNetworkBroadcast 1\n",[28,2479,2477],{"__ignoreMap":285},[24,2481,117,2482,2484,2485,2487],{},[28,2483,261],{}," 这一行交给同步程序维护，不手动填写 ",[28,2486,213],{},"。**首次打开自动发现后，重启 NoMachine，使该开关生效：",[280,2489,2491],{"className":282,"code":2490,"language":284,"meta":285,"style":285},"sudo \u002Fetc\u002FNX\u002Fnxserver --restart\n",[28,2492,2493],{"__ignoreMap":285},[289,2494,2495,2497,2499],{"class":291,"line":292},[289,2496,378],{"class":295},[289,2498,394],{"class":299},[289,2500,516],{"class":316},[24,2502,2503],{},"后续 IP 变化由同步服务自动处理，无需再手动修改配置或重启；地址发生变化时的服务重启会中断原有 NoMachine 会话。",[24,2505,2506],{},"可以检查程序生成的地址和日志：",[280,2508,2510],{"className":282,"code":2509,"language":284,"meta":285,"style":285},"sudo grep '^NXDListenAddress' \u002Fusr\u002FNX\u002Fetc\u002Fserver.cfg\nsystemctl is-enabled nomachine-wifi-sync.service\nsudo journalctl -u nomachine-wifi-sync.service -n 30 --no-pager\n",[28,2511,2512,2524,2534],{"__ignoreMap":285},[289,2513,2514,2516,2519,2522],{"class":291,"line":292},[289,2515,378],{"class":295},[289,2517,2518],{"class":299}," grep",[289,2520,2521],{"class":299}," '^NXDListenAddress'",[289,2523,446],{"class":299},[289,2525,2526,2529,2532],{"class":291,"line":329},[289,2527,2528],{"class":295},"systemctl",[289,2530,2531],{"class":299}," is-enabled",[289,2533,2338],{"class":299},[289,2535,2536,2538,2541,2544,2547,2550,2553],{"class":291,"line":602},[289,2537,378],{"class":295},[289,2539,2540],{"class":299}," journalctl",[289,2542,2543],{"class":316}," -u",[289,2545,2546],{"class":299}," nomachine-wifi-sync.service",[289,2548,2549],{"class":316}," -n",[289,2551,2552],{"class":316}," 30",[289,2554,2555],{"class":316}," --no-pager\n",[24,2557,2558,2559,2562,2563,2565,2566,2569,2570,2573,2574,228],{},"这里看到的是",[137,2560,2561],{},"程序最后一次同步的具体地址","，应与 ",[28,2564,77],{}," 当前 IPv4 一致，不代表给网卡设置了静态 IP。服务是一次性任务，执行成功后显示 ",[28,2567,2568],{},"inactive"," 属于正常情况，应看日志和 ",[28,2571,2572],{},"Result","，不要求它一直处于 ",[28,2575,2576],{},"active",[24,2578,2579],{},"需要手动重新同步时执行：",[280,2581,2583],{"className":282,"code":2582,"language":284,"meta":285,"style":285},"sudo systemctl start nomachine-wifi-sync.service\n",[28,2584,2585],{"__ignoreMap":285},[289,2586,2587,2589,2591,2593],{"class":291,"line":292},[289,2588,378],{"class":295},[289,2590,2439],{"class":299},[289,2592,2335],{"class":299},[289,2594,2338],{"class":299},[24,2596,2597],{},"NoMachine 恢复自动发现后仍会使用 5353 UDP 端口。此时不能把“看到 nxserver.bin 监听 5353”直接当作故障，应检查它发布的地址是否与当前 Wi-Fi IP 一致。",[24,2599,2600],{},[137,2601,2602],{},"5. 电脑端：始终使用主机名连接。",[280,2604,2606],{"className":282,"code":2605,"language":284,"meta":285,"style":285},"avahi-browse -rt _nomachine._tcp\ngetent ahostsv4 ysu.local\nssh ysu@ysu.local\n",[28,2607,2608,2619,2627],{"__ignoreMap":285},[289,2609,2610,2613,2616],{"class":291,"line":292},[289,2611,2612],{"class":295},"avahi-browse",[289,2614,2615],{"class":316}," -rt",[289,2617,2618],{"class":299}," _nomachine._tcp\n",[289,2620,2621,2623,2625],{"class":291,"line":329},[289,2622,584],{"class":295},[289,2624,587],{"class":299},[289,2626,590],{"class":299},[289,2628,2629,2631],{"class":291,"line":602},[289,2630,296],{"class":295},[289,2632,607],{"class":299},[24,2634,2635,2636,2639,2640,2642,2643,2645,2646,2649],{},"自动发现的 A 记录和 TXT 中的 ",[28,2637,2638],{},"ip="," 应等于工控机此时的 Wi-Fi IPv4，而不是永远等于本次排查时的 ",[28,2641,213],{},"。本次 NoMachine 的 SRV 记录端口为 ",[28,2644,746],{},"，实际 NX 连接端口由 TXT 中的 ",[28,2647,2648],{},"service=nx:4000"," 给出，不能据此误判服务没有监听。",[24,2651,2652],{},"手动创建 NoMachine 连接时使用主机名：",[280,2654,2657],{"className":2655,"code":2656,"language":455,"meta":285},[453],"协议：NX\n主机：ysu.local\n端口：4000\n用户名：ysu\n",[28,2658,2656],{"__ignoreMap":285},[24,2660,2661,2662,228],{},"电脑仍需与工控机处于能够进行局域网发现和互访的网络中。IP 变化时，由 Avahi 更新主机名记录、同步程序更新 NoMachine 绑定地址，电脑端继续使用 ",[28,2663,649],{},[20,2665,2666],{"id":2666},"完整修复验证结果",[48,2668,2669,2677],{},[51,2670,2671],{},[54,2672,2673,2675],{},[57,2674,670],{},[57,2676,673],{},[67,2678,2679,2692,2705,2717,2730,2745,2753],{},[54,2680,2681,2684],{},[72,2682,2683],{},"原生 NoMachine 自动发现",[72,2685,2686,2687,2689,2690],{},"已恢复，能发现 ",[28,2688,714],{},"，A 记录和 TXT 的 IP 均为 ",[28,2691,213],{},[54,2693,2694,2697],{},[72,2695,2696],{},"Wi-Fi 抓包",[72,2698,2699,2700,2702,2703],{},"Avahi 和 NoMachine 都回答 ",[28,2701,213],{},"，该轮未再出现 ",[28,2704,217],{},[54,2706,2707,2710],{},[72,2708,2709],{},"4000 TCP 端口",[72,2711,2712,2713,2716],{},"绑定 ",[28,2714,2715],{},"192.168.2.183:4000","，电脑端实际 TCP 连接成功",[54,2718,2719,2722],{},[72,2720,2721],{},"SSH 主机名连接",[72,2723,2724,2727,2728],{},[28,2725,2726],{},"ssh ysu@ysu.local hostname"," 密码登录成功，返回 ",[28,2729,714],{},[54,2731,2732,2735],{},[72,2733,2734],{},"配置残留旧 IP 的模拟",[72,2736,2737,2738,2741,2742,2744],{},"将保存地址临时改成 ",[28,2739,2740],{},".254"," 后触发 DHCP 变化处理，同步任务自动恢复 ",[28,2743,213],{},"、重启服务并验证监听成功",[54,2746,2747,2750],{},[72,2748,2749],{},"地址未变化的事件",[72,2751,2752],{},"同步任务直接退出，不重启 NoMachine",[54,2754,2755,2758],{},[72,2756,2757],{},"开机同步",[72,2759,2760],{},"服务已启用",[24,2762,2763,2764,2767],{},"完整修复前的配置备份为 ",[28,2765,2766],{},"\u002Fusr\u002FNX\u002Fetc\u002Fserver.cfg.before-wifi-binding-20261019","。本次没有改变工控机实际 Wi-Fi IP，也没有做整机重启或图形桌面登录测试；模拟旧配置验证了同步处理流程，真实换 IP 和完整图形会话仍应在实际使用时确认。",[15,2769,2771],{"id":2770},"ros-2-远端查看-mid360-点云导致降频延迟和-rviz-不显示","ROS 2 远端查看 MID360 点云导致降频、延迟和 RViz 不显示",[20,2773,22],{"id":2774},"原因-1",[24,2776,2777,2778,2781],{},"现象是：电脑通过 Wi-Fi 打开 RViz，或者仅运行远端 ",[28,2779,2780],{},"ros2 topic hz","，工控机上的 MID360 点云和 IMU 就明显降频，连工控机本地测频也受到影响；关闭远端订阅后恢复。切换手机热点和其他 Wi-Fi 都未直接解决问题。",[24,2783,2784],{},"本次排查发现了两个独立问题：",[2786,2787,2788,2820],"ol",{},[2789,2790,2791,2794,2797,2798,2801,2802,2805,2806,2809,2810,2813,2814,2816,2817,228],"li",{},[137,2792,2793],{},"电脑端 DDS 公布了不适合本次跨机通信的地址。",[2795,2796],"br",{},"电脑端 DDS 同时公布了 Wi-Fi 地址、Docker 网桥地址 ",[28,2799,2800],{},"172.17.0.1"," 和 Clash TUN 虚拟网卡地址 ",[28,2803,2804],{},"198.20.0.1","。工控机根据这些地址发送数据，其中发往 Clash TUN 地址的数据被路由到雷达网口的网关 ",[28,2807,2808],{},"192.168.1.1","，邻居解析未完成。实测部分 UDP 发送调用阻塞约 ",[137,2811,2812],{},"250～330 毫秒","，发送阻塞拖慢发布，点云和 IMU 出现积压。",[2795,2815],{},"本次定位到的明显阻塞与 Clash TUN 地址有关，没有单独验证 Docker 地址是否造成同样阻塞。不过，电脑 Docker 网桥地址也不适合作为本次跨机接收地址，应一并排除。选择接口的原则是：",[137,2818,2819],{},"只使用 ROS 对端实际可达、并且本次通信确实需要的接口",[2789,2821,2822,2825,2827,2828,2831,2832,2835,2836,2838,2839],{},[137,2823,2824],{},"电脑端 UDP 接收缓冲不足以承受本次点云突发流量。",[2795,2826],{},"修正接口并重建电脑端 daemon 后，工控机已恢复点云约 20 Hz、IMU 约 200 Hz，但电脑端点云仍只有约 12.8 Hz，接收 socket 仍有缓冲丢包。此时默认接收缓冲约为 ",[137,2829,2830],{},"208 KiB","；将请求值增大到 ",[137,2833,2834],{},"4 MiB"," 后，电脑端点云恢复约 20 Hz，测试期间该 socket 的缓冲丢包计数为零。",[2795,2837],{},"因此，缓冲丢包不能全部归因于选错网卡。大点云的分片集中到达、接收线程短暂来不及处理时，正确接口也可能出现缓冲溢出。增大接收缓冲是按数据量选择的优化；本次 MID360 接收环境有实测依据，建议保留 4 MiB。",[478,2840,2843],{"href":2841,"rel":2842},"https:\u002F\u002Ffast-dds.docs.eprosima.com\u002Fen\u002F2.6.x\u002Ffastdds\u002Fuse_cases\u002Flarge_data\u002Flarge_data.html",[482],"Fast DDS 大数据传输说明",[24,2845,2846,2848,2849],{},[28,2847,2780],{}," 会订阅完整消息来统计频率，同样需要接收整帧点云，因此仅开启远端测频也可能触发上述问题。",[478,2850,2853],{"href":2851,"rel":2852},"https:\u002F\u002Fgithub.com\u002Fros2\u002Fros2cli\u002Fblob\u002Fhumble\u002Fros2topic\u002Fros2topic\u002Fverb\u002Fhz.py",[482],"ROS 2 Humble 测频实现",[24,2855,2856,2857,2860],{},"点云延迟到十几秒甚至几十秒后，点云时间戳可能早于 RViz 保存的 TF 历史。即使 TF 树连通、最新变换正常，RViz 仍无法完成点云时间戳对应的坐标变换，表现为不显示点云。本次将 Fixed Frame 临时改为点云自身的 ",[28,2858,2859],{},"front_mid360"," 后出现点云，验证了这个方向；解决传输积压后，就可以使用正常的显示坐标系。",[20,2862,2863],{"id":2863},"解决方法",[24,2865,2866],{},[137,2867,2868],{},"1. 工控机：建议保留异步发布。",[24,2870,2871,2872,2875],{},"在实际运行 ROS 的用户的 ",[28,2873,2874],{},"~\u002F.bashrc"," 中加入。",[280,2877,2879],{"className":282,"code":2878,"language":284,"meta":285,"style":285},"export RMW_FASTRTPS_PUBLICATION_MODE=ASYNCHRONOUS\n",[28,2880,2881],{"__ignoreMap":285},[289,2882,2883,2886,2889,2891],{"class":291,"line":292},[289,2884,2885],{"class":898},"export",[289,2887,2888],{"class":902}," RMW_FASTRTPS_PUBLICATION_MODE",[289,2890,1056],{"class":898},[289,2892,2893],{"class":902},"ASYNCHRONOUS\n",[24,2895,2896],{},"修改后执行：",[280,2898,2900],{"className":282,"code":2899,"language":284,"meta":285,"style":285},"source ~\u002F.bashrc\n",[28,2901,2902],{"__ignoreMap":285},[289,2903,2904,2907],{"class":291,"line":292},[289,2905,2906],{"class":316},"source",[289,2908,2909],{"class":299}," ~\u002F.bashrc\n",[24,2911,2912],{},"然后在加载了该环境的终端中重新启动 MID360 驱动，使新进程继承设置。",[24,2914,2915,2916,2919,2920],{},"异步发布将实际发送交给后台线程，可以减轻网络发送对驱动发布线程的直接影响；",[137,2917,2918],{},"单独设置它未能解决本次问题","，仍需配合下面的电脑端配置。",[478,2921,2924],{"href":2922,"rel":2923},"https:\u002F\u002Fgithub.com\u002Fros2\u002Frmw_fastrtps\u002Ftree\u002Fhumble#change-publication-mode",[482],"Fast DDS 在 ROS 2 Humble 中的发布模式说明",[24,2926,2927],{},[137,2928,2929,2930,2932,2933,228],{},"2. 电脑端：通过 ",[28,2931,2906],{}," 加载工程内的 ",[28,2934,2935],{},"dds_env.bash",[24,2937,2938],{},"先查询自己网络网卡：",[280,2940,2942],{"className":282,"code":2941,"language":284,"meta":285,"style":285},"ip -br -4 addr\n",[28,2943,2944],{"__ignoreMap":285},[289,2945,2946,2948,2950,2952],{"class":291,"line":292},[289,2947,332],{"class":295},[289,2949,335],{"class":316},[289,2951,338],{"class":316},[289,2953,341],{"class":299},[24,2955,2956,2957,2960,2961,2964,2965,2968],{},"看ip就能看出来，只有",[28,2958,2959],{},"10.xx.xx.xx","和",[28,2962,2963],{},"192.168.xx.xx","这种才是NAT4下发的ip。\n所以这个",[28,2966,2967],{},"wlp0s20f3","才是你和ROS用于局域网通信的网卡。",[24,2970,2971],{},[354,2972],{"alt":285,"src":2973},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2026\u002F09\u002F20\u002F1791768552425-a1dc45c9.webp",[24,2975,2976],{},"也可以点击WIFI按钮确认一下ip，和上方说的一模一样：",[24,2978,2979],{},[354,2980],{"alt":285,"src":2981},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2026\u002F09\u002F20\u002F1791768696430-c68935b3.webp",[24,2983,2984],{},"当前脚本位于工程根目录：",[280,2986,2989],{"className":2987,"code":2988,"language":455,"meta":285},[453],"\u002Fysu2026_rm_sentry_nav\u002Fdds_env.bash\n",[28,2990,2988],{"__ignoreMap":285},[24,2992,2993,2994,214,2997,3000],{},"现在初始化当前终端后即可正常使用 ",[28,2995,2996],{},"rviz2",[28,2998,2999],{},"ros2"," 命令。",[24,3002,3003,3004,3007],{},"这份配置应首先加载到电脑端，因为",[137,3005,3006],{},"接收地址由电脑 DDS 公布，接收缓冲也属于电脑上的接收进程","。工控机使用电脑公布的地址发送点云；增大工控机的接收缓冲不能替代电脑端设置。",[24,3009,3010,3011,3014,3015,3018,3019,3022,3023],{},"脚本读取所选接口当前的 IPv4，生成 XML，并导出 ",[28,3012,3013],{},"FASTRTPS_DEFAULT_PROFILES_FILE","。UDP 使用所选地址和本机回环地址 ",[28,3016,3017],{},"127.0.0.1","，同时保留本机 SHM 通信。XML 保存在工程根目录，文件名为 ",[28,3020,3021],{},".dds-env-\u003C用户ID>-\u003C配置摘要>.xml","，已加入 Git 忽略规则。",[478,3024,3027],{"href":3025,"rel":3026},"https:\u002F\u002Ffast-dds.docs.eprosima.com\u002Fen\u002F2.6.x\u002Ffastdds\u002Ftransport\u002Fwhitelist.html",[482],"Fast DDS 接口白名单",[24,3029,274,3030,3033,3034,3037,3038,3041,3042,3044],{},[137,3031,3032],{},"电脑的 ROS 终端","执行。两端 ",[28,3035,3036],{},"ROS_DOMAIN_ID"," 必须一致，本次为 ",[28,3039,3040],{},"6","；网卡名 ",[28,3043,2967],{}," 应按实际接口修改：",[280,3046,3048],{"className":282,"code":3047,"language":284,"meta":285,"style":285},"source \u002Fopt\u002Fros\u002Fhumble\u002Fsetup.bash\nexport ROS_DOMAIN_ID=6\n\nexport DDS_INTERFACE=wlp0s20f3\nexport DDS_RECV_BUFFER=4MiB\nsource \u002F你的存放工程的路径\u002Fysu2026_rm_sentry_nav\u002Fdds_env.bash\n",[28,3049,3050,3057,3069,3073,3085,3097],{"__ignoreMap":285},[289,3051,3052,3054],{"class":291,"line":292},[289,3053,2906],{"class":316},[289,3055,3056],{"class":299}," \u002Fopt\u002Fros\u002Fhumble\u002Fsetup.bash\n",[289,3058,3059,3061,3064,3066],{"class":291,"line":329},[289,3060,2885],{"class":898},[289,3062,3063],{"class":902}," ROS_DOMAIN_ID",[289,3065,1056],{"class":898},[289,3067,3068],{"class":316},"6\n",[289,3070,3071],{"class":291,"line":602},[289,3072,892],{"emptyLinePlaceholder":891},[289,3074,3075,3077,3080,3082],{"class":291,"line":895},[289,3076,2885],{"class":898},[289,3078,3079],{"class":902}," DDS_INTERFACE",[289,3081,1056],{"class":898},[289,3083,3084],{"class":902},"wlp0s20f3\n",[289,3086,3087,3089,3092,3094],{"class":291,"line":906},[289,3088,2885],{"class":898},[289,3090,3091],{"class":902}," DDS_RECV_BUFFER",[289,3093,1056],{"class":898},[289,3095,3096],{"class":902},"4MiB\n",[289,3098,3099,3101],{"class":291,"line":914},[289,3100,2906],{"class":316},[289,3102,3103],{"class":299}," \u002F你的存放工程的路径\u002Fysu2026_rm_sentry_nav\u002Fdds_env.bash\n",[24,3105,3106,3107],{},"比如：",[28,3108,3109],{},"source \u002Fhome\u002Ftungchiahui\u002FUserFolder\u002FMySource\u002Fysu2026_rm_sentry\u002Fysu2026_rm_sentry_nav\u002Fdds_env.bash",[24,3111,3112],{},"两个参数可以分别配置：",[48,3114,3115,3125],{},[51,3116,3117],{},[54,3118,3119,3122],{},[57,3120,3121],{},"参数",[57,3123,3124],{},"用法",[67,3126,3127,3137],{},[54,3128,3129,3134],{},[72,3130,3131],{},[28,3132,3133],{},"DDS_INTERFACE",[72,3135,3136],{},"指定网卡名称，支持逗号分隔的多个接口；未设置时自动选择唯一处于 UP 状态且有 IPv4 的物理网卡，多个候选时返回错误，要求明确选择",[54,3138,3139,3144],{},[72,3140,3141],{},[28,3142,3143],{},"DDS_RECV_BUFFER",[72,3145,3146,3147,3149,3150,562,3153,562,3156,562,3159,562,3162,562,3165,562,3168,3171],{},"不设置或 ",[28,3148,746],{}," 表示系统默认；纯整数表示字节；支持 ",[28,3151,3152],{},"B",[28,3154,3155],{},"KB",[28,3157,3158],{},"MB",[28,3160,3161],{},"GB",[28,3163,3164],{},"KiB",[28,3166,3167],{},"MiB",[28,3169,3170],{},"GiB"," 单位，数值须为非负整数",[24,3173,3174,3177,3178,3181,3182,3177,3185,3188,3189,3191,3192,3195],{},[28,3175,3176],{},"4MiB"," 等于 ",[28,3179,3180],{},"4194304"," 字节，",[28,3183,3184],{},"4MB",[28,3186,3187],{},"4000000"," 字节。缓冲参数是脚本定义的选项，最终会转换为字节写入 Fast DDS XML。本次接收 MID360 点云建议使用已验证有效的 ",[28,3190,3176],{},"。请求值还受系统 ",[28,3193,3194],{},"net.core.rmem_max"," 上限约束，超出上限时脚本会提示，但不会自动修改系统参数。",[24,3197,3198,3199,3201],{},"脚本成功加载时不打印，出错或系统上限不足时给出提示。它仅配置 Fast DDS，不改变 ",[28,3200,3036],{},"、消息 QoS 或当前 shell 的选项。",[24,3203,3204,3205,3208],{},"我电脑容器使用 host 网络，可以访问宿主 Wi-Fi 接口。其他 Docker 网络模式应选择容器实际可见且对端可达的接口；\n接口白名单不能替代 bridge 网络所需的 NAT 或发现配置。跨容器使用 SHM 还取决于 IPC 配置。（一劳永逸，直接",[28,3206,3207],{},"host","即可）",[24,3210,3211],{},[137,3212,3213],{},"3. 首次启用或切换网络后，重建电脑端 daemon。",[24,3215,3216],{},"先关闭旧的 RViz 和远端测频进程，在已加载上述 DDS 配置的终端执行：",[280,3218,3220],{"className":282,"code":3219,"language":284,"meta":285,"style":285},"ros2 daemon stop\nros2 daemon start\n",[28,3221,3222,3232],{"__ignoreMap":285},[289,3223,3224,3226,3229],{"class":291,"line":292},[289,3225,2999],{"class":295},[289,3227,3228],{"class":299}," daemon",[289,3230,3231],{"class":299}," stop\n",[289,3233,3234,3236,3238],{"class":291,"line":329},[289,3235,2999],{"class":295},[289,3237,3228],{"class":299},[289,3239,3240],{"class":299}," start\n",[24,3242,3243],{},"daemon 本身也会创建 DDS Participant，应继承相同的接口配置，避免保留原先的虚拟网卡地址。本次排查中，重建 daemon 是恢复正常通信的一步；不必每次测频都重启它。",[24,3245,3246],{},[137,3247,3248],{},"4. 直接打开 RViz 和测频。",[24,3250,3251],{},"在已加载配置的电脑终端中打开 RViz：",[280,3253,3255],{"className":282,"code":3254,"language":284,"meta":285,"style":285},"rviz2\n",[28,3256,3257],{"__ignoreMap":285},[289,3258,3259],{"class":291,"line":292},[289,3260,3254],{"class":295},[24,3262,3263],{},"另一个终端也先加载第 2 步相同的 ROS 和 DDS 环境，再运行：",[280,3265,3267],{"className":282,"code":3266,"language":284,"meta":285,"style":285},"ros2 topic hz \u002Flivox\u002Flidar\u002Fpointcloud --window 40\n",[28,3268,3269],{"__ignoreMap":285},[289,3270,3271,3273,3276,3279,3282,3285],{"class":291,"line":292},[289,3272,2999],{"class":295},[289,3274,3275],{"class":299}," topic",[289,3277,3278],{"class":299}," hz",[289,3280,3281],{"class":299}," \u002Flivox\u002Flidar\u002Fpointcloud",[289,3283,3284],{"class":316}," --window",[289,3286,3287],{"class":316}," 40\n",[24,3289,3290,3293,3294,228],{},[28,3291,3292],{},"--window 40"," 只是缩短统计窗口，方便观察近期变化；真正起作用的是",[137,3295,3296],{},"网卡白名单和接收缓冲设置",[24,3298,3299],{},[137,3300,3301,3302,228],{},"5. 日常使用：可加入电脑 ROS 用户的 ",[28,3303,3304],{},".bashrc",[24,3306,3307,3308,2427],{},"将以下三行放在已有 ROS 环境加载语句之后。当前电脑容器使用 root，对应 ",[28,3309,3310],{},"\u002Froot\u002F.bashrc",[280,3312,3314],{"className":282,"code":3313,"language":284,"meta":285,"style":285},"export DDS_INTERFACE=wlp0s20f3\nexport DDS_RECV_BUFFER=4MiB\nsource \u002F你的存放工程的路径\u002Fysu2026_rm_sentry_nav\u002Fdds_env.bash\n",[28,3315,3316,3326,3336],{"__ignoreMap":285},[289,3317,3318,3320,3322,3324],{"class":291,"line":292},[289,3319,2885],{"class":898},[289,3321,3079],{"class":902},[289,3323,1056],{"class":898},[289,3325,3084],{"class":902},[289,3327,3328,3330,3332,3334],{"class":291,"line":329},[289,3329,2885],{"class":898},[289,3331,3091],{"class":902},[289,3333,1056],{"class":898},[289,3335,3096],{"class":902},[289,3337,3338,3340],{"class":291,"line":602},[289,3339,2906],{"class":316},[289,3341,3103],{"class":299},[24,3343,3106,3344],{},[28,3345,3109],{},[24,3347,3348,3349,3351,3352,3355],{},"这样，新打开并读取 ",[28,3350,3304],{}," 的终端会自动初始化 DDS。通过服务或非交互方式启动的 ROS 程序，需要在其启动环境中主动加载配置。脚本位于个人工程中，加载现有 ",[28,3353,3354],{},"\u002Fopt\u002Fros\u002Fhumble\u002Fsetup.bash"," 不会修改 ROS 安装文件。",[24,3357,3358,3359,3361],{},"切换 Wi-Fi、改变所选接口或接收缓冲后，应重新 ",[28,3360,2906],{}," 脚本，重建 daemon，并重新启动相关 ROS 程序；已经运行的进程不会自动读取新的环境变量或 XML。脚本本身不会重启这些进程。",[20,3363,3364],{"id":3364},"本次验证结果",[24,3366,3367],{},"完成接口限制、daemon 重建和 4 MiB 接收缓冲配置后的现场远端实测结果如下：",[48,3369,3370,3384],{},[51,3371,3372],{},[54,3373,3374,3377,3381],{},[57,3375,3376],{},"测量位置",[57,3378,3380],{"align":3379},"right","点云频率",[57,3382,3383],{"align":3379},"IMU 频率",[67,3385,3386,3397],{},[54,3387,3388,3391,3394],{},[72,3389,3390],{},"工控机本地",[72,3392,3393],{"align":3379},"约 20 Hz",[72,3395,3396],{"align":3379},"约 200 Hz",[54,3398,3399,3401,3403],{},[72,3400,277],{},[72,3402,3393],{"align":3379},[72,3404,3405],{"align":3379},"约 197～199 Hz",[24,3407,3408],{},"放大缓冲后的测试节点接收缓冲丢包计数为零。打开 RViz 后，工控机仍保持正常频率，点云持续显示，延迟不再增长到几十秒。这是本次测试期间的结果。",[24,3410,3411,3412,3414,3415,3418],{},"上表来自整理新脚本之前的现场远端测试。后续新增 ",[28,3413,2935],{},"，在 ",[28,3416,3417],{},"ysu_ros_humble"," 中验证了 XML 加载、接收缓冲生效、本机约 262 KB 点云接收 20\u002F20 帧，以及单位转换、静默加载和参数错误时保留原环境。新版脚本的验证范围包含这些项目；上述远端频率仍引用此前现场实测。",[24,3420,3421],{},"配置整理在工程中新增了 DDS 环境脚本和生成 XML 的 Git 忽略规则；本次排查未修改 MID360 驱动、SLAM 或控制节点的业务代码。",[3423,3424,3425],"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 .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}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 .snhLl, html code.shiki .snhLl{--shiki-default:#22863A;--shiki-default-font-weight:bold;--shiki-dark:#85E89D;--shiki-dark-font-weight:bold}html pre.shiki code .sA_wV, html code.shiki .sA_wV{--shiki-default:#032F62;--shiki-dark:#DBEDFF}",{"title":285,"searchDepth":329,"depth":329,"links":3427},[3428],{"id":5,"depth":329,"text":5,"children":3429},[3430,3431],{"id":17,"depth":602,"text":18},{"id":2770,"depth":602,"text":2771},0,"0600","2026-09-20","2026-09-20-dao-hang","\u002Fwiki\u002F2026-09-20-dao-hang","导航","md",false,{},"\u002Fwiki\u002F2026-09-20-dao-hang\u002F0600-kai-fa-wen-ti-yu-pai-cha",{"title":5,"description":285},"wiki\u002F2026-09-20-导航\u002F0600-开发问题与排查","ARKwA6LATlz9YwcHXqXao19gMAa7GdPzZv_DeQJjHlc",[3446,3452,3458,3464,3470,3476,3482,3488,3494,3500,3506,3512,3518,3524,3530,3536,3542,3548,3554,3560,3566,3572,3578,3584,3590,3596,3602,3608,3614,3620,3626,3632,3638,3644,3650,3656,3658,3664],{"path":3447,"stem":3448,"title":3449,"authors":3450,"date":3434,"chapterOrder":3451,"chapterDepth":3432,"docKey":3435,"docRoot":3436,"docTitle":3437,"isWikiDoc":891,"isWikiIndex":3439},"\u002Fwiki\u002F2026-09-20-dao-hang\u002F0100-jian-jie","wiki\u002F2026-09-20-导航\u002F0100-简介","简介",[7],"0100",{"path":3453,"stem":3454,"title":3455,"authors":3456,"date":3434,"chapterOrder":3457,"chapterDepth":3432,"docKey":3435,"docRoot":3436,"docTitle":3437,"isWikiDoc":891,"isWikiIndex":3439},"\u002Fwiki\u002F2026-09-20-dao-hang\u002F0200-huan-jing-pei-zhi-yu-yun-xing","wiki\u002F2026-09-20-导航\u002F0200-环境配置与运行","环境配置与运行",[7],"0200",{"path":3459,"stem":3460,"title":3461,"authors":3462,"date":3434,"chapterOrder":3463,"chapterDepth":292,"docKey":3435,"docRoot":3436,"docTitle":3437,"isWikiDoc":891,"isWikiIndex":3439},"\u002Fwiki\u002F2026-09-20-dao-hang\u002F0300-0100-robot-description","wiki\u002F2026-09-20-导航\u002F0300-0100-robot_description","robot_description（机器人模型与关节定义）",[7],"0300-0100",{"path":3465,"stem":3466,"title":3467,"authors":3468,"date":3434,"chapterOrder":3469,"chapterDepth":292,"docKey":3435,"docRoot":3436,"docTitle":3437,"isWikiDoc":891,"isWikiIndex":3439},"\u002Fwiki\u002F2026-09-20-dao-hang\u002F0300-0200-mid360-an-zhuang-wei-zhi","wiki\u002F2026-09-20-导航\u002F0300-0200-MID360安装位置","MID360安装位置",[7],"0300-0200",{"path":3471,"stem":3472,"title":3473,"authors":3474,"date":3434,"chapterOrder":3475,"chapterDepth":292,"docKey":3435,"docRoot":3436,"docTitle":3437,"isWikiDoc":891,"isWikiIndex":3439},"\u002Fwiki\u002F2026-09-20-dao-hang\u002F0300-0300-launch-yu-bao-yi-lai-pei-zhi","wiki\u002F2026-09-20-导航\u002F0300-0300-Launch与包依赖配置","Launch与包依赖配置",[7],"0300-0300",{"path":3477,"stem":3478,"title":3479,"authors":3480,"date":3434,"chapterOrder":3481,"chapterDepth":292,"docKey":3435,"docRoot":3436,"docTitle":3437,"isWikiDoc":891,"isWikiIndex":3439},"\u002Fwiki\u002F2026-09-20-dao-hang\u002F0300-0400-fang-zhen-shi-jue-you-hua","wiki\u002F2026-09-20-导航\u002F0300-0400-仿真视觉优化","仿真视觉优化（可选）",[7],"0300-0400",{"path":3483,"stem":3484,"title":3485,"authors":3486,"date":3434,"chapterOrder":3487,"chapterDepth":292,"docKey":3435,"docRoot":3436,"docTitle":3437,"isWikiDoc":891,"isWikiIndex":3439},"\u002Fwiki\u002F2026-09-20-dao-hang\u002F0300-0500-tian-jia-di-tu","wiki\u002F2026-09-20-导航\u002F0300-0500-添加地图","添加地图",[7],"0300-0500",{"path":3489,"stem":3490,"title":3491,"authors":3492,"date":3434,"chapterOrder":3493,"chapterDepth":3432,"docKey":3435,"docRoot":3436,"docTitle":3437,"isWikiDoc":891,"isWikiIndex":3439},"\u002Fwiki\u002F2026-09-20-dao-hang\u002F0300-ji-qi-ren-mo-xing-yu-fang-zhen","wiki\u002F2026-09-20-导航\u002F0300-机器人模型与仿真","机器人模型与仿真",[7],"0300",{"path":3495,"stem":3496,"title":3497,"authors":3498,"date":3434,"chapterOrder":3499,"chapterDepth":292,"docKey":3435,"docRoot":3436,"docTitle":3437,"isWikiDoc":891,"isWikiIndex":3439},"\u002Fwiki\u002F2026-09-20-dao-hang\u002F0400-0100-linux-yu-mcu-shu-ju-dui-jie","wiki\u002F2026-09-20-导航\u002F0400-0100-Linux与MCU数据对接","Linux与MCU数据对接",[7],"0400-0100",{"path":3501,"stem":3502,"title":3503,"authors":3504,"date":3434,"chapterOrder":3505,"chapterDepth":292,"docKey":3435,"docRoot":3436,"docTitle":3437,"isWikiDoc":891,"isWikiIndex":3439},"\u002Fwiki\u002F2026-09-20-dao-hang\u002F0400-0200-chuan-kou-tong-xin","wiki\u002F2026-09-20-导航\u002F0400-0200-串口通信","Serial_Comm（串口通信）",[7],"0400-0200",{"path":3507,"stem":3508,"title":3509,"authors":3510,"date":3434,"chapterOrder":3511,"chapterDepth":292,"docKey":3435,"docRoot":3436,"docTitle":3437,"isWikiDoc":891,"isWikiIndex":3439},"\u002Fwiki\u002F2026-09-20-dao-hang\u002F0400-0300-shou-bing-kong-zhi","wiki\u002F2026-09-20-导航\u002F0400-0300-手柄控制","Joy（手柄控制）",[7],"0400-0300",{"path":3513,"stem":3514,"title":3515,"authors":3516,"date":3434,"chapterOrder":3517,"chapterDepth":292,"docKey":3435,"docRoot":3436,"docTitle":3437,"isWikiDoc":891,"isWikiIndex":3439},"\u002Fwiki\u002F2026-09-20-dao-hang\u002F0400-0400-mid360-yu-tf-lian-tiao","wiki\u002F2026-09-20-导航\u002F0400-0400-MID360与TF联调","MID360与TF联调",[7],"0400-0400",{"path":3519,"stem":3520,"title":3521,"authors":3522,"date":3434,"chapterOrder":3523,"chapterDepth":3432,"docKey":3435,"docRoot":3436,"docTitle":3437,"isWikiDoc":891,"isWikiIndex":3439},"\u002Fwiki\u002F2026-09-20-dao-hang\u002F0400-ying-jian-dui-jie-yu-kong-zhi","wiki\u002F2026-09-20-导航\u002F0400-硬件对接与控制","硬件对接与控制",[7],"0400",{"path":3525,"stem":3526,"title":3527,"authors":3528,"date":3434,"chapterOrder":3529,"chapterDepth":292,"docKey":3435,"docRoot":3436,"docTitle":3437,"isWikiDoc":891,"isWikiIndex":3439},"\u002Fwiki\u002F2026-09-20-dao-hang\u002F0500-0100-point-lio","wiki\u002F2026-09-20-导航\u002F0500-0100-Point_LIO","Point_LIO（激光与IMU融合里程计，建图与定位算法）",[7],"0500-0100",{"path":3531,"stem":3532,"title":3533,"authors":3534,"date":3434,"chapterOrder":3535,"chapterDepth":292,"docKey":3435,"docRoot":3436,"docTitle":3437,"isWikiDoc":891,"isWikiIndex":3439},"\u002Fwiki\u002F2026-09-20-dao-hang\u002F0500-0200-loam-interface","wiki\u002F2026-09-20-导航\u002F0500-0200-loam_interface","loam_interface（Point-LIO输出的坐标与话题适配）",[7],"0500-0200",{"path":3537,"stem":3538,"title":3539,"authors":3540,"date":3434,"chapterOrder":3541,"chapterDepth":292,"docKey":3435,"docRoot":3436,"docTitle":3437,"isWikiDoc":891,"isWikiIndex":3439},"\u002Fwiki\u002F2026-09-20-dao-hang\u002F0500-0300-sensor-scan-generation","wiki\u002F2026-09-20-导航\u002F0500-0300-sensor_scan_generation","sensor_scan_generation（雷达点云换系与底盘、云台位姿转换）",[7],"0500-0300",{"path":3543,"stem":3544,"title":3545,"authors":3546,"date":3434,"chapterOrder":3547,"chapterDepth":292,"docKey":3435,"docRoot":3436,"docTitle":3437,"isWikiDoc":891,"isWikiIndex":3439},"\u002Fwiki\u002F2026-09-20-dao-hang\u002F0500-0400-terrain-analysis","wiki\u002F2026-09-20-导航\u002F0500-0400-terrain_analysis","terrain_analysis（近场地面与障碍高差分析）",[7],"0500-0400",{"path":3549,"stem":3550,"title":3551,"authors":3552,"date":3434,"chapterOrder":3553,"chapterDepth":292,"docKey":3435,"docRoot":3436,"docTitle":3437,"isWikiDoc":891,"isWikiIndex":3439},"\u002Fwiki\u002F2026-09-20-dao-hang\u002F0500-0500-terrain-analysis-ext","wiki\u002F2026-09-20-导航\u002F0500-0500-terrain_analysis_ext","terrain_analysis_ext（扩展远场地形与近远场结果合并）",[7],"0500-0500",{"path":3555,"stem":3556,"title":3557,"authors":3558,"date":3434,"chapterOrder":3559,"chapterDepth":292,"docKey":3435,"docRoot":3436,"docTitle":3437,"isWikiDoc":891,"isWikiIndex":3439},"\u002Fwiki\u002F2026-09-20-dao-hang\u002F0500-0600-fake-vel-transform","wiki\u002F2026-09-20-导航\u002F0500-0600-fake_vel_transform","fake_vel_transform（云台系速度转换与底盘自旋）",[7],"0500-0600",{"path":3561,"stem":3562,"title":3563,"authors":3564,"date":3434,"chapterOrder":3565,"chapterDepth":292,"docKey":3435,"docRoot":3436,"docTitle":3437,"isWikiDoc":891,"isWikiIndex":3439},"\u002Fwiki\u002F2026-09-20-dao-hang\u002F0500-0700-small-gicp-relocalization","wiki\u002F2026-09-20-导航\u002F0500-0700-small_gicp_relocalization","small_gicp_relocalization（先验点云地图重定位）",[7],"0500-0700",{"path":3567,"stem":3568,"title":3569,"authors":3570,"date":3434,"chapterOrder":3571,"chapterDepth":292,"docKey":3435,"docRoot":3436,"docTitle":3437,"isWikiDoc":891,"isWikiIndex":3439},"\u002Fwiki\u002F2026-09-20-dao-hang\u002F0500-0800-pointcloud-to-laserscan","wiki\u002F2026-09-20-导航\u002F0500-0800-pointcloud_to_laserscan","pointcloud_to_laserscan（三维地形点云转二维扫描）",[7],"0500-0800",{"path":3573,"stem":3574,"title":3575,"authors":3576,"date":3434,"chapterOrder":3577,"chapterDepth":292,"docKey":3435,"docRoot":3436,"docTitle":3437,"isWikiDoc":891,"isWikiIndex":3439},"\u002Fwiki\u002F2026-09-20-dao-hang\u002F0500-0900-slam-toolbox","wiki\u002F2026-09-20-导航\u002F0500-0900-slam_toolbox","slam_toolbox（二维地图生成与轨迹优化）",[7],"0500-0900",{"path":3579,"stem":3580,"title":3581,"authors":3582,"date":3434,"chapterOrder":3583,"chapterDepth":292,"docKey":3435,"docRoot":3436,"docTitle":3437,"isWikiDoc":891,"isWikiIndex":3439},"\u002Fwiki\u002F2026-09-20-dao-hang\u002F0500-1000-bt-navigator","wiki\u002F2026-09-20-导航\u002F0500-1000-bt_navigator","bt_navigator（行为树导航任务调度）",[7],"0500-1000",{"path":3585,"stem":3586,"title":3587,"authors":3588,"date":3434,"chapterOrder":3589,"chapterDepth":292,"docKey":3435,"docRoot":3436,"docTitle":3437,"isWikiDoc":891,"isWikiIndex":3439},"\u002Fwiki\u002F2026-09-20-dao-hang\u002F0500-1100-controller-server","wiki\u002F2026-09-20-导航\u002F0500-1100-controller_server","controller_server（路径跟踪、进度检查与到达判定）",[7],"0500-1100",{"path":3591,"stem":3592,"title":3593,"authors":3594,"date":3434,"chapterOrder":3595,"chapterDepth":292,"docKey":3435,"docRoot":3436,"docTitle":3437,"isWikiDoc":891,"isWikiIndex":3439},"\u002Fwiki\u002F2026-09-20-dao-hang\u002F0500-1200-local-costmap","wiki\u002F2026-09-20-导航\u002F0500-1200-local_costmap","local_costmap（局部障碍代价地图）",[7],"0500-1200",{"path":3597,"stem":3598,"title":3599,"authors":3600,"date":3434,"chapterOrder":3601,"chapterDepth":292,"docKey":3435,"docRoot":3436,"docTitle":3437,"isWikiDoc":891,"isWikiIndex":3439},"\u002Fwiki\u002F2026-09-20-dao-hang\u002F0500-1300-global-costmap","wiki\u002F2026-09-20-导航\u002F0500-1300-global_costmap","global_costmap（全局规划代价地图）",[7],"0500-1300",{"path":3603,"stem":3604,"title":3605,"authors":3606,"date":3434,"chapterOrder":3607,"chapterDepth":292,"docKey":3435,"docRoot":3436,"docTitle":3437,"isWikiDoc":891,"isWikiIndex":3439},"\u002Fwiki\u002F2026-09-20-dao-hang\u002F0500-1400-map-server","wiki\u002F2026-09-20-导航\u002F0500-1400-map_server","map_server（已有二维地图加载与发布）",[7],"0500-1400",{"path":3609,"stem":3610,"title":3611,"authors":3612,"date":3434,"chapterOrder":3613,"chapterDepth":292,"docKey":3435,"docRoot":3436,"docTitle":3437,"isWikiDoc":891,"isWikiIndex":3439},"\u002Fwiki\u002F2026-09-20-dao-hang\u002F0500-1500-map-saver","wiki\u002F2026-09-20-导航\u002F0500-1500-map_saver","map_saver（二维栅格地图保存）",[7],"0500-1500",{"path":3615,"stem":3616,"title":3617,"authors":3618,"date":3434,"chapterOrder":3619,"chapterDepth":292,"docKey":3435,"docRoot":3436,"docTitle":3437,"isWikiDoc":891,"isWikiIndex":3439},"\u002Fwiki\u002F2026-09-20-dao-hang\u002F0500-1600-planner-server","wiki\u002F2026-09-20-导航\u002F0500-1600-planner_server","planner_server（Theta*全局路径规划）",[7],"0500-1600",{"path":3621,"stem":3622,"title":3623,"authors":3624,"date":3434,"chapterOrder":3625,"chapterDepth":292,"docKey":3435,"docRoot":3436,"docTitle":3437,"isWikiDoc":891,"isWikiIndex":3439},"\u002Fwiki\u002F2026-09-20-dao-hang\u002F0500-1700-smoother-server","wiki\u002F2026-09-20-导航\u002F0500-1700-smoother_server","smoother_server（全局路径平滑）",[7],"0500-1700",{"path":3627,"stem":3628,"title":3629,"authors":3630,"date":3434,"chapterOrder":3631,"chapterDepth":292,"docKey":3435,"docRoot":3436,"docTitle":3437,"isWikiDoc":891,"isWikiIndex":3439},"\u002Fwiki\u002F2026-09-20-dao-hang\u002F0500-1800-behavior-server","wiki\u002F2026-09-20-导航\u002F0500-1800-behavior_server","behavior_server（恢复行为与空闲方向移动）",[7],"0500-1800",{"path":3633,"stem":3634,"title":3635,"authors":3636,"date":3434,"chapterOrder":3637,"chapterDepth":292,"docKey":3435,"docRoot":3436,"docTitle":3437,"isWikiDoc":891,"isWikiIndex":3439},"\u002Fwiki\u002F2026-09-20-dao-hang\u002F0500-1900-waypoint-follower","wiki\u002F2026-09-20-导航\u002F0500-1900-waypoint_follower","waypoint_follower（逐点导航与到点等待）",[7],"0500-1900",{"path":3639,"stem":3640,"title":3641,"authors":3642,"date":3434,"chapterOrder":3643,"chapterDepth":292,"docKey":3435,"docRoot":3436,"docTitle":3437,"isWikiDoc":891,"isWikiIndex":3439},"\u002Fwiki\u002F2026-09-20-dao-hang\u002F0500-2000-velocity-smoother","wiki\u002F2026-09-20-导航\u002F0500-2000-velocity_smoother","velocity_smoother（速度限幅与加减速平滑）",[7],"0500-2000",{"path":3645,"stem":3646,"title":3647,"authors":3648,"date":3434,"chapterOrder":3649,"chapterDepth":292,"docKey":3435,"docRoot":3436,"docTitle":3437,"isWikiDoc":891,"isWikiIndex":3439},"\u002Fwiki\u002F2026-09-20-dao-hang\u002F0500-2100-pb-teleop-twist-joy-node","wiki\u002F2026-09-20-导航\u002F0500-2100-pb_teleop_twist_joy_node","pb_teleop_twist_joy_node（手柄输入与可替换控制入口）",[7],"0500-2100",{"path":3651,"stem":3652,"title":3653,"authors":3654,"date":3434,"chapterOrder":3655,"chapterDepth":3432,"docKey":3435,"docRoot":3436,"docTitle":3437,"isWikiDoc":891,"isWikiIndex":3439},"\u002Fwiki\u002F2026-09-20-dao-hang\u002F0500-dao-hang-can-shu","wiki\u002F2026-09-20-导航\u002F0500-导航参数","导航参数",[7],"0500",{"path":3441,"stem":3443,"title":5,"authors":3657,"date":3434,"chapterOrder":3433,"chapterDepth":3432,"docKey":3435,"docRoot":3436,"docTitle":3437,"isWikiDoc":891,"isWikiIndex":3439},[7],{"path":3659,"stem":3660,"title":3661,"authors":3662,"date":3434,"chapterOrder":3663,"chapterDepth":3432,"docKey":3435,"docRoot":3436,"docTitle":3437,"isWikiDoc":891,"isWikiIndex":3439},"\u002Fwiki\u002F2026-09-20-dao-hang\u002F0700-jue-ce","wiki\u002F2026-09-20-导航\u002F0700-决策","决策",[7],"0700",{"path":3436,"stem":3665,"title":3666,"authors":3667,"date":3434,"chapterOrder":3668,"chapterDepth":3432,"docKey":3435,"docRoot":3436,"docTitle":3437,"isWikiDoc":891,"isWikiIndex":891},"wiki\u002F2026-09-20-导航\u002Findex","北极熊导航复现日志",[7],null,[3670,3672,3675,3678],{"name":7,"image":3671},"\u002Fimages\u002Fmember_photo\u002F董佳辉.jpg",{"name":3673,"image":3674},"宫金良","\u002Fimages\u002Fmember_photo\u002F宫金良.jpg",{"name":3676,"image":3677},"巩丽","\u002Fimages\u002Fmember_photo\u002F巩丽.png",{"name":3679,"image":3680},"张彦斐","\u002Fimages\u002Fmember_photo\u002F张彦斐.jpg",1792431906729]