☰
TS30/TS50测量机器人GeoCom二次开发与联调避坑指南
2026/10/29 21:34:10 网站建设 项目流程

简介:《TS30、TS50系列测量机器人Geocom中文说明书》面向从事徕卡测量机器人二次开发的工程师与编程学习者,重点解决GEOCOM接口理解、通信协议调用和程序框架搭建等问题。压缩包内共1个docx文件,大小约1.49MB,以中文说明书形式集中呈现开发目录与关键要点。内容围绕地理数据通讯接口、TPS1200系统软件、GEOCOM一般概念、ASCII协议语法与数据类型展开,并给出C/C++及VBA中的函数调用协议、基础应用框架、开发系统支持和编程提示,还涉及联合值、仪器操作方式与常见通信错误,便于读者按章节查阅接口定义、理解数据交互规则并排查调用问题。已有2426人学习,适合具备一定编程基础、希望从协议入门过渡到实际二次开发,并借助示例组织测量机器人采集与传输程序的读者参考。

1. 从一条“测不回数”的串口日志说起:TS30/TS50 的 GeoCom 中文说明书到底解决什么

TS30/TS50 系列测量机器人的 GeoCom 中文说明书,拿在手里不像一本教程,更像一张二次开发的接口地图。现场最常见的翻车不是算法写错,而是 PC 端发出一条自认为正确的 ASCII 命令,仪器却只回一个超时;或者望远镜转过去了,测距值却因为棱镜常数和角度单位对不上而整体偏掉。

这份中文资料把 GeoCom 的通信设置、ASCII 协议、C/C++ 与 VBA 调用框架,以及 AUS、AUT、BAP、CSV、FTR、IMG 等子系统按函数条目拆开,适合做自动化监测、工业测量集成、测量机器人程序二次开发的从业者。它不教你从零写测绘算法,但能把“函数名是什么、参数往哪填、返回码怎么看”这些黑匣子打开。同系列 TS60 若使用同一代 GeoCom,函数分组思路接近,但 RPC 号与枚举值仍要以对应版本手册为准,别拿一份文档硬套所有固件。

2. 把 GeoCom 通信链路搭起来:从串口/TCP 参数到 ASCII 请求响应

通信链路是二次开发的第一道门槛,也是最容易被“我觉得应该这样”带偏的地方。GeoCom 本质上是一套远程调用接口:测量机器人是服务器,PC 是客户端,客户端发一条带函数号和参数的命令,服务器执行后回结果。你可以走串口,也可以走 TCP 网关;可以用 ASCII 文本,也可以走二进制或 C/C++、VBA 的函数调用封装。选型不需要炫技,脚本联调优先 ASCII,生产环境再用一层类型安全的封装把字符串细节吃掉。

2.1 先分清客户端/服务器与三个协议层

GeoCom 手册的目录结构很能说明问题:前面讲 TPS 系统软件的组织、ASCII 协议语法、C/C++ 与 VBA 的函数调用协议,后面才按 AUS、AUT、BAP、BMM、COM、CSV、EDM、FTR、IMG 分子系统列函数。这个顺序不是排版习惯,而是二次开发的依赖顺序——协议层没打通,后面所有自动化命令都是空谈。

ASCII 协议层负责把函数号、参数、事务号封成一段可读文本。常见请求形态是%R1Q,<RPC号>,<参数>:<事务号>,响应形态是%R1P,<返回码>,<事务号>:<结果>,具体分隔符和终止符以手册的 ASCII 语法一节为准。C/C++ 与 VBA 的函数调用协议则是在这层文本外面再包一层,让你用COM_NullProc()、AUT_Search()这样的函数名调用,底层仍然落回 RPC 号和参数序列。

RPC 描述的结构一般包含子系统、函数号、参数方向、返回类型和错误码。看手册时不要只抄函数名,先把那一页的“常数和类型”看清楚:哪个参数是输入,哪个是输出,角度用度、gon 还是弧度,距离单位是米还是毫米。很多“命令发了没反应”的问题,最后都落在参数类型和单位上,而不是通信本身。

提示:第一次联调不要直接上 AUT 运动命令。先用 COM_NullProc 这类空过程确认链路,再读仪器名、版本、电源和温度,把“能通信”和“能控制”分开验证。

2.2 通信参数表:波特率、超时、双精度、数据格式

通信设置这一章通常包含内存使用、常数和类型、一般 GeoCom 功能、客户端特定功能。对二次开发最有用的是几组“设置后要回读”的参数:双精度设置、超时、传输数据格式、错误弹窗行为。下面这张表是现场联调时我一般会先对齐的项,具体取值范围以手册为准。

参数常见设置手册对应条目注意
端口与波特率串口按仪器端配置,TCP 网关按网关参数打开/关闭通信端口、获取当前波特率波特率不一致时可能收到乱码而不是超时
超时首轮联调不小于 2 s,运动类命令单独放大获取/设置当前超时值单位按手册,改完用 Get 回读
双精度联调阶段固定一种精度获取/设置双精度设置客户端解析位数要与返回值一致
传输数据格式固定分隔符和小数点规则获取传输数据格式不要一边改格式一边解析旧日志
错误弹窗后台服务关闭弹窗声明父窗口句柄、设置弹出错误消息框无人值守时弹窗会把采集线程卡住

COM_SetDoublePrecision这类函数不要设完就完事,紧接着用对应的 Get 函数回读一次。现场有过这样的情况:客户端以为设成了高精度,服务端返回的字符串却按另一种格式截断,最后距离值看起来只差一点点,排查半天才发现是格式层的问题。超时也一样,COM_SetTimeout改小能让异常快速返回,但自动定位和 PowerSearch 这类动作需要更长时间,统一设一个很小的值会把正常运动判成失败。

COM_UseWindow和弹出错误消息框是 Windows 客户端才关心的东西。做后台采集服务时,我一般会把弹窗关掉,把错误码写进日志,让上层状态机决定重试还是停机。现场无人值守时,一个模态弹窗比一个超时更难恢复,因为程序看起来“还在跑”,实际上已经停在某个错误提示上。

2.3 用 Python 写最小 ASCII 收发闭环

脚本联调阶段,Python 加串口库足够把链路跑通。下面这段不是完整产品代码,而是我一般用来验证“发得出去、收得回来、事务号对得上”的最小闭环。RPC 号不要猜,从中文手册对应函数条目里抄;下面的环境变量就是逼自己别把占位值写死。

import os import time import serial PORT = os.environ.get("GEOCOM_PORT", "COM3") # 串口端口;TCP 网关则换成 socket 连接 BAUD = int(os.environ.get("GEOCOM_BAUD", "115200")) TIMEOUT = float(os.environ.get("GEOCOM_TIMEOUT", "2.0")) RPC_NULL = int(os.environ["RPC_NULL"]) # 从手册 COM_NullProc 条目抄,不要照抄示例 def build_ascii(rpc_id: int, args: str = "", tid: int = 1) -> bytes: # ASCII 请求:%R1Q,<RPC号>,<参数>:<事务号>\r\n # 分隔符和终止符以手册 ASCII 语法为准,这里按常见形态写 return f"%R1Q,{rpc_id},{args}:{tid}\r\n".encode("ascii") def read_reply(ser: serial.Serial) -> str: # 先按行读;正式代码要加总超时、最大长度和十六进制原始日志 raw = ser.readline() return raw.decode("ascii", errors="replace").strip() ser = serial.Serial(PORT, BAUD, timeout=TIMEOUT) ser.reset_input_buffer() ser.write(build_ascii(RPC_NULL, "", 1)) time.sleep(0.2) reply = read_reply(ser) print(repr(reply)) ser.close()

逻辑说明:先打开端口并清空输入缓冲,避免上一次残留数据混进响应;发送时带上事务号,响应回来先看事务号是否一致,再看返回码是否为成功值。参数说明:PORT和BAUD必须与仪器端或 TCP 网关一致;TIMEOUT是读超时,不是业务超时,运动类命令要在上层单独设更长的等待;RPC_NULL必须从手册抄,不能凭记忆填。若返回乱码,先把原始字节打成十六进制看终止符,不要急着怀疑协议。

2.4 用 C++/VBA 包一层函数调用框架

生产代码里我一般不会到处拼字符串,而是先做一个 Transport 抽象,串口和 TCP 各实现一份,再把 GeoCom 的调用、事务号、返回码解析收进一个客户端类。这样换链路时业务代码不用动,错误码也能统一进日志。下面只保留骨架,重点是分层,不是让你照抄每一个类型。

class Transport { public: virtual ~Transport() = default; virtual bool open(const std::string& target, int timeoutMs) = 0; virtual bool send(const std::string& bytes) = 0; virtual std::string recvLine(int timeoutMs) = 0; virtual void close() = 0; }; class GeoComClient { public: explicit GeoComClient(Transport& t) : transport_(t) {} // rpcId 和 args 来自手册函数条目;tid 用于匹配请求与响应 std::string call(int rpcId, const std::string& args, int tid) { std::string req = "%R1Q," + std::to_string(rpcId) + "," + args + ":" + std::to_string(tid) + "\r\n"; if (!transport_.send(req)) return ""; return transport_.recvLine(2000); // 业务层应把超时做成可配置 } private: Transport& transport_; };

逻辑说明:Transport 只负责字节进出,GeoComClient 只负责协议封装,业务层只关心函数名和参数。参数说明:timeoutMs要区分“读一行”的超时和“等一个动作完成”的超时;tid建议自增并回写日志,便于把请求和响应串起来。C/C++ 里尤其注意字符串长度、结构体对齐和返回缓冲区的生命周期,别把临时字符串的指针传到异步线程里。

VBA 侧常见做法是用 MSComm 或 WinSock 控件做传输,再把调用包成函数。VBA 的 Long 是 32 位、Double 是 8 字节,和 C/C++ 的结构体对齐规则不一样,手册里“VBA 中的数据类型——派生的一般规则”那一节就是给这个场景用的。下面这段只表达调用和返回码检查的写法,控件初始化按你手头的开发环境来。

Dim reply As String reply = GeoComCall(RPC_ID:=GetRpcId("COM_NullProc"), Args:="", Tid:=1) If Left$(reply, 6) <> "%R1P,0" Then Debug.Print "GeoCom 返回异常: " & reply ' 这里应写入日志并交给状态机,不要只弹 MsgBox End If

逻辑说明:先按返回前缀判断是否成功,再把完整响应写日志;VBA 里不要用On Error Resume Next把通信错误吞掉。参数说明:GetRpcId应该从配置表或手册生成的常量表里取,不要把函数号散落在每个按钮事件里;Tid要能对应到具体调用,否则多线程或定时器并发时无法判断响应属于谁。

2.5 第一次联调先跑哪几条命令

链路打通后,不要急着写自动测量流程。我一般按下面顺序跑一遍,任何一步失败就停在那里查,不往后带病运行。

顺序调用通过标准失败先看
1COM_NullProc返回成功码,事务号一致端口、波特率、终止符、流控
2CSV_GetInstrumentName返回可读仪器名字符串长度、编码、返回格式
3CSV_GetSWVersion返回版本信息是否连到了正确的服务器
4CSV_CheckPower返回电源状态电池、外接电源、仪器是否开机
5CSV_GetIntTemp返回内部温度长时间连续测量前的健康检查
6CSV_GetDateTime返回日期时间文件时间戳和日志对齐

这几条命令没有运动风险,适合反复跑。电源和温度看着不起眼,但连续监测项目里,很多“偶发通信失败”最后都指向供电不稳或内部温度过高。先把健康检查做成固定步骤,后面 AUT 和 BAP 出问题时,你才能确定是控制层的问题还是链路层的问题。

3. 让望远镜动起来:AUT 自动定位、ATR 搜索与 PowerSearch 参数落地

AUT 子系统是二次开发里最容易让人产生“它会自己动”错觉的部分。实际上自动定位不是一条命令把望远镜丢过去就完事,它涉及角度单位、定位公差、定位超时、面转换、ATR 搜索窗口和微调模式。手册把 AUT 拆成读公差、设公差、读超时、设超时、自动定位、自动转换面、自动微调、自动搜索、目标跟踪、PowerSearch 窗口和范围等条目,就是提醒你:运动控制是一串状态,不是单次调用。

3.1 AUT 的定位模型:Hz/V 角、面、公差与超时

自动定位函数通常接收水平角 Hz 和垂直角 V,把望远镜转到指定位置。这里的第一个坑是角度单位:手册里可能同时出现度、gon、弧度,COM_SetDoublePrecision和传输格式又会改变返回值的小数位数。客户端如果用一个全局double接所有角度,却不记录单位,后面做限差判断时就会出“明明只差几毫米,程序却报超限”的玄学问题。

第二个坑是“面”。测量机器人有盘左、盘右两个面,自动转换面函数不是简单地把角度加 180 度,它涉及仪器当前面和目标面的关系。工业测量里如果只用一个面做测距,问题不大;做高精度角度交会或需要消除照准误差时,面转换就要和定位、微调、测距一起编排。我的习惯是把“当前面”作为状态机的一个字段,每次转换面后回读状态,不靠猜。

第三个坑是“定位”和“测量”不是一回事。AUT_GotoPosition这类函数只保证望远镜转到指定角度附近,目标是否在视场里、ATR 是否锁住,要靠 AUS 和 AUT_Search 去确认。定位成功后立刻测距,可能测到的是背景或错误棱镜。正确顺序通常是:设 ATR 模式、设锁定状态、设搜索窗口、定位、搜索、微调、测距。

3.2 定位公差与超时:先设边界再发运动命令

AUT 子系统里有读取和设置定位公差、读取和设置定位超时的函数。公差决定“转到多近算到位”,超时决定“等多久算失败”。这两个参数不是越小越好。公差设得比仪器分辨率还小,望远镜会在目标附近反复微调,日志看起来一直在动,实际永远到不了“到位”状态;超时设得太短,长距离转动还没稳定就被判失败,重试几次后状态机就乱了。

我一般的做法是先按手册推荐值起步,再根据现场距离和目标类型放大。近距离、小角度转动可以收紧一点;长距离、大角度转动要把超时放宽,并且把“粗定位”和“微调”分成两步。手册里 AUT 的微调模式函数就是给第二步用的:先让望远镜快速转到目标附近,再切到微调模式慢慢收。这样比一条命令死等更稳,也更容易在日志里定位失败发生在哪一段。

参数作用调整建议失败表现
定位公差判断是否到位不小于手册推荐值,按目标距离放大反复微调、迟迟不返回
定位超时判断动作是否失败按转动角度和现场温度留余量长距离转动被提前判失败
微调模式控制末段收敛方式粗定位后切微调过冲、来回摆
面状态盘左/盘右转换后回读,不靠假设角度差 180 度附近异常

注意:公差和超时的单位、取值范围以手册为准。不要拿其他型号的经验值直接套到 TS30/TS50 上,固件版本不同,枚举和默认值都可能变。

3.3 ATR 与锁定模式:AUS 子系统的状态机

AUS 子系统管的是 ATR 模式、锁定模式这类“看得见目标”的状态。ATR 没开,自动搜索和自动定位后的测距都可能落空;锁定模式没设对,目标稍微动一下,跟踪就断了。手册里 AUS 的函数不多,但每一条都影响后面 AUT 和 BAP 的行为,所以联调时我一般把 AUS 的状态查询放在运动命令之前。

常见做法是:先读 ATR 模式状态,确认当前是关闭、开启还是某种自动模式;再读锁定模式状态,确认用户锁定是开还是关;然后设置搜索窗口。ATR 搜索窗口不是越大越好,窗口太大容易把旁边反光物当目标,窗口太小又会在目标稍微偏离时搜不到。PowerSearch 窗口和 ATR 搜索窗口是两套参数,不要混用:前者用于大范围找目标,后者用于精确定位后的确认。

还有低可视模式和缩小 ATR 视场这类参数,BAP 子系统里有对应条目。现场光线复杂、背景有反光板或玻璃时,这些参数会影响锁定稳定性。我的习惯是先在标准目标上把 ATR 和锁定跑通,再去调低可视和视场参数;否则一开始就调一堆补偿,出了问题不知道是哪一项在起作用。

3.4 PowerSearch:窗口、范围与搜索下一个目标

PowerSearch 解决的是“目标不在当前视场里”的问题。AUT 子系统里有获取和设置 PowerSearch 窗口尺寸、启用窗口和范围、设置范围、启动 PowerSearch、搜索下一个目标的函数。它的基本逻辑是:先给一个搜索窗口和范围,再启动搜索,找到目标后锁定;如果有多个目标,用“搜索下一个”依次取。

这里的坑在“范围”和“窗口”的单位及坐标定义。窗口尺寸通常和距离、视场角有关,范围则限制搜索的物理区域。参数设得太大,搜索时间变长,还可能锁到错误目标;设得太小,目标稍微偏出就搜不到。我一般会先用一个中等窗口做首轮搜索,锁定后再用 ATR 窗口做精确认;如果现场有多个棱镜,给每个棱镜一个可区分的搜索顺序,不要依赖“它应该先找到最近那个”。

# 仅表达调用顺序,函数名和 RPC 号以中文手册对应条目为准 set_atr_mode(1) # 枚举值按手册,不要用 0/1 猜 set_user_lock_state(1) # 锁定模式同样按手册枚举 set_ps_window(width=..., height=...) # 窗口尺寸单位看手册 enable_ps_range(True) set_ps_range(...) # 范围参数按现场布点设置 start_power_search() target = search_next_target() # 多目标时循环调用,直到拿到期望目标 if target is None: raise RuntimeError("PowerSearch 未找到目标,先查窗口、范围和棱镜类型")

逻辑说明:先把 ATR 和锁定状态设好,再给 PowerSearch 窗口和范围,最后启动搜索并取目标;不要跳过状态设置直接搜。参数说明:窗口和范围的单位、坐标系以手册为准;search_next_target的循环要有上限,避免在无目标时无限搜索。失败时先看窗口是否覆盖目标可能出现的区域,再看棱镜类型和低可视模式,不要一上来就改通信超时。

3.5 一段“转到目标并测距”的编排

把上面的东西串起来,一次完整的“转到目标并测距”大概是:打开端口、设双精度和超时、读 ATR 和锁定状态、设定位公差和超时、自动定位、自动搜索、微调、测距、读结果、关端口。下面这段只保留业务顺序,具体函数名和 RPC 号从手册抄。

# 业务编排示例:每一步都要检查返回码,失败时记录当前步骤 open_port() set_double_precision(...) set_timeout(...) atr_mode = get_atr_mode() if atr_mode != EXPECTED_ATR: set_atr_mode(EXPECTED_ATR) set_user_lock_state(EXPECTED_LOCK) set_position_tolerance(hz_tol=..., v_tol=...) # 单位按手册 set_position_timeout(seconds=...) # 长距离转动要留余量 goto_position(hz=..., v=...) search_target() fine_adjust() hz, v, dist = meas_distance_angle() log_result(hz, v, dist) close_port()

逻辑说明:每个函数调用后都要看返回码,不能只捕获异常;运动类命令失败时记录当前角度、公差、超时和 ATR 状态,方便复现。参数说明:EXPECTED_ATR和EXPECTED_LOCK从手册枚举里取;公差和超时的单位不要凭经验填。测距结果回来先看棱镜常数和 EDM 类型,再看数值本身,否则系统性偏差会被当成偶然误差。

4. 从角度到文件:BAP 测距、EDM 配置、FTR 传输与 IMG 图像抓取

BAP 是基本应用子系统,管 EDM 类型、棱镜类型、距离测量程序和搜索目标;EDM 管激光指示和电子导光强度;FTR 管文件列表、下载、中止和删除;IMG 管望远镜图像配置和抓图。这几块看起来分散,但在一个完整的二次开发流程里是连着的:定位搜到目标,BAP 测距,EDM 控制激光和强度,FTR 把结果文件取回,IMG 抓现场图像做留档。任何一块参数不对,最后的数据都不算数。

4.1 BAP 测距链路:EDM 类型、棱镜类型与测量程序

BAP 子系统里先要看的是 EDM 类型和棱镜类型。EDM 类型决定测距模式,棱镜类型决定棱镜常数和测距信号处理方式。手册里有获取和设置 EDM 类型、获取和设置默认棱镜类型、获取默认或用户棱镜类型、获取和设置用户棱镜定义的条目。顺序上,我一般先读当前 EDM 和棱镜类型,再改,再回读,最后才发测距命令。

BAP_MeasDistanceAngle这类函数一次返回水平角、垂直角和距离,看起来很方便,但它依赖前面的配置。如果棱镜类型还是默认的圆棱镜,现场用的是用户自定义棱镜,距离就会带一个固定偏差。这个偏差在小范围里可能被当成“仪器误差”,在大范围里会直接让限差判断失效。所以测距前回读棱镜类型不是多余动作,是必要的防呆。

配置项手册对应影响检查方式
EDM 类型获取/设置 EDM 类型测距模式、速度、精度设置后回读
默认棱镜类型获取/设置默认棱镜类型棱镜常数与现场棱镜铭牌核对
用户棱镜定义获取/设置用户棱镜定义自定义常数单位按手册,改完回读
距离测量程序设置距离测量程序单次/连续/跟踪按业务节奏选,别混用
搜索目标BAP_SearchTarget目标确认搜完再看 ATR 状态

提示:棱镜常数不要靠“差不多”记。现场换棱镜、换适配器、换基座,都可能改变有效常数;每次换完重新回读一次用户棱镜定义,比事后修数据便宜得多。

4.2 棱镜常数与用户自定义棱镜:不统一就会系统性偏差

棱镜常数是二次开发里最典型的“血泪经验”之一。仪器里默认棱镜类型和用户棱镜定义是两套东西:默认类型通常对应常见棱镜,用户定义则允许你填自定义常数。手册里既有获取默认棱镜定义,也有获取和设置用户棱镜定义,说明这两条路径都要走通。我的习惯是:现场用什么棱镜,就在配置表里建一条记录,写清楚型号、常数、单位、适用距离段;程序启动时按记录设用户棱镜定义,设完回读,写进日志。

如果只改默认棱镜类型,不改用户定义,有些固件会在切换测量程序时回落到默认值;如果只改用户定义,不确认当前选择的是用户棱镜还是默认棱镜,测距仍然按默认常数算。这两种情况都会表现为“数据整体偏一个固定值”,而且换目标后偏差不变,很容易被误判为仪器需要校准。先查棱镜配置,再怀疑硬件。

4.3 FTR 文件传输:列表、下载、中止、删除的状态顺序

FTR 子系统管文件传输,手册里有设置列表、列表文件、中止列表、设置下载、下载文件、中止下载、删除文件等条目。它的状态顺序比函数本身更重要:先建列表会话,再列文件或选文件,再建下载会话,再下载,结束后释放会话;任何一步失败,都要走对应的中止函数,不能直接重来。

我一般把 FTR 调用包在一个上下文里,异常分支强制中止。下面这段是顺序示意,不是完整实现。

# FTR 顺序示意:SetupList -> 列表/选择 -> SetupDownload -> Download -> 释放 ftr_setup_list(remote_dir="/data") try: files = ftr_list_files() if not files: raise RuntimeError("仪器端没有可下载文件") ftr_setup_download(filename=files[0]) try: ftr_download() except Exception: ftr_abort_download() # 下载失败先中止下载会话 raise finally: ftr_abort_list() # 列表会话必须释放,避免下次列不出文件

逻辑说明:列表会话和下载会话是两层资源,外层finally释放列表,内层异常释放下载;不要只写成功路径。参数说明:remote_dir的路径规则以手册为准,不要假设和 PC 路径一样;文件名大小写和扩展名要按仪器端返回的原样传,不要自己拼。下载中断后不要立刻删文件,先中止会话、重新列列表,确认文件句柄释放后再操作。

4.4 IMG 图像抓取:TCC 配置与抓图前后顺序

IMG 子系统管望远镜图像,手册里有读取实际映像配置、设置实际映像配置、抓取望远镜图像等条目。图像配置通常包含曝光、增益、白平衡这类参数,具体字段以手册结构体为准。我的习惯是“先读后改再抓再恢复”:先读当前配置,基于当前值改一两项,设完回读,抓图,最后恢复原配置。这样不会把仪器留在某个奇怪的曝光状态,影响下一次测量。

抓图前要确认望远镜已经对准目标、ATR 状态正常,否则抓到的可能是一片背景。抓图函数和测距函数不要并发抢仪器资源,很多型号的 GeoCom 服务端是串行处理命令的,并发调用只会让超时更难排查。图像文件通常走 FTR 下载,抓图只是生成文件,别把“抓图成功”当成“文件已经到 PC”。

4.5 CSV 中央服务做健康检查:版本、电源、温度、时间

CSV 是中央服务子系统,管仪器号、仪器名、设备配置、日期时间、软件版本、电源、内部温度这些信息。它不直接参与测量,但非常适合做启动自检和定时巡检。我一般会在采集程序启动时读一次仪器名和版本,写进日志头;每轮采集前读电源和温度,超过手册范围就降频或停机;文件下载后用仪器时间给文件打标签,避免 PC 时间和仪器时间不一致导致追溯困难。

这些函数还有一个用处:区分“通信断了”和“仪器关了”。COM_NullProc能通但CSV_CheckPower报电源异常,说明链路在、仪器状态不对;两个都不通,才回去查端口和线缆。把健康检查做成固定顺序,排错时就不用靠猜。

5. 避坑与排查:GeoCom 二次开发里最容易翻车的五类问题

GeoCom 的坑大多不是“不会调函数”,而是“调了但不知道哪一层不对”。下面五类问题是我在联调和现场排查里见得最多的,每一条都按现象、原因、解决写,方便你直接对照日志。

5.1 通信能通但返回超时:先查终止符和流控

现象:串口打开成功,发送命令后有时能回、有时超时;换个波特率又能回几帧。原因通常不是协议错,而是终止符不一致、流控没开对,或者读函数按行读但响应里混了回显。ASCII 协议对\r\n敏感,文本模式还可能把\r吃掉。解决:先用十六进制打印原始收发,确认请求末尾和响应末尾的字节;串口参数里把流控、数据位、停止位逐项对齐;读响应加最大长度保护,别让一行脏数据把缓冲区撑爆。

5.2 角度单位/双精度设置不一致:数据差一个数量级

现象:测距值正常,角度值却差一个固定倍数;或者同一目标两次测量差很多。原因常见于角度单位混用:手册里可能用度、gon 或弧度,客户端解析时按另一种单位理解;COM_SetDoublePrecision改了精度但解析代码没跟着改,字符串被截断。解决:联调第一步固定单位,把所有角度转换收进一个函数,禁止在业务代码里直接乘系数;每次改双精度和传输格式后回读,并用一个已知角度做闭环验证。

5.3 ATR 不锁目标:窗口、低可视模式、棱镜类型

现象:AUT_Search返回成功,但随后测距失败或锁不住;换一个目标又正常。原因可能是 ATR 模式没开、锁定状态没设、搜索窗口太小、低可视模式不适合当前光线,或者棱镜类型和现场棱镜不匹配。解决:先读 AUS 的 ATR 和锁定状态,再设搜索窗口,再用 BAP 回读棱镜类型;光线复杂时先关掉不必要的补偿参数,用标准棱镜跑通,再逐项加回低可视和视场设置。

5.4 自动定位过冲或反复微调:公差与超时太小

现象:望远镜在目标附近来回动,日志里一直有微调,但状态机等不到到位;或者长距离转动刚启动就被判超时。原因多半是定位公差小于仪器实际分辨率,或超时没有按转动角度放大。解决:公差按手册推荐值起步,按距离分段设置;把粗定位和微调拆成两步,粗定位用较宽公差和较长超时,微调再收紧;每次失败记录当前角度、公差、超时和面状态,别只记一个“失败”。

5.5 文件下载中断后列表异常:没走 Abort

现象:FTR 下载中途断线,重连后列不出文件,或者删除文件报占用。原因是列表会话或下载会话没有释放,服务端还占着资源。解决:FTR 调用必须写异常分支,下载失败先FTR_AbortDownload,再FTR_AbortList;重连后先列列表确认状态,不要直接重试下载;删除文件前确认没有下载会话,删除后重新列一次列表验证。

6. 进阶验证:把“能跑”变成“可复现”的一条自检链

二次开发最怕“昨天能跑,今天不行”。我一般会给每台仪器留一条固定自检链,从链路到运动到文件,每一步都有通过标准和失败先看项。下面这张表可以直接抄进你的启动脚本,字段按项目改,顺序别乱。

步骤调用通过标准失败先看
1COM_NullProc返回成功,事务号一致端口、波特率、终止符
2CSV_GetInstrumentName / GetSWVersion返回可读名称和版本是否连错服务器
3CSV_CheckPower / GetIntTemp电源正常、温度在手册范围供电、连续测量时长
4AUS_GetATRMode / GetUserLockState状态与配置一致ATR 是否开启、锁定是否设置
5AUT_ReadTol / ReadTimeout与配置表一致是否被其他客户端改过
6AUT_GotoPosition + AUT_Search到位并锁定目标公差、超时、搜索窗口
7BAP_MeasDistanceAngle角度距离在限差内棱镜类型、EDM 类型
8FTR_SetupList + AbortList能列文件并正常释放会话是否残留
9IMG_TakeTccImage抓图成功且文件可下载图像配置、ATR 状态

自检链跑完后,把关键返回写进一份 JSON 日志,后面出问题可以直接对比。下面这段只记录几个字段,实际项目可以加原始响应和耗时。

import json import time def run_self_check(client): report = {"ts": time.strftime("%Y-%m-%d %H:%M:%S"), "steps": []} for name, fn in [ ("null_proc", client.com_null_proc), ("instrument_name", client.csv_get_instrument_name), ("power", client.csv_check_power), ("temperature", client.csv_get_int_temp), ]: t0 = time.time() try: value = fn() report["steps"].append({"name": name, "ok": True, "value": str(value), "ms": int((time.time() - t0) * 1000)}) except Exception as exc: report["steps"].append({"name": name, "ok": False, "error": str(exc), "ms": int((time.time() - t0) * 1000)}) break # 链路或健康检查失败,后面的运动步骤不再执行 return json.dumps(report, ensure_ascii=False, indent=2)

逻辑说明:每一步都记录耗时和结果,失败就中断,避免在链路不稳时继续发运动命令;日志用 JSON 方便后续比对。参数说明:client是你自己的封装对象,函数名对应手册条目;break的位置可以根据项目调整,但通信和电源失败时我一般不允许继续。

从那以后我每次接新仪器,都强制走一遍这条自检链,哪怕现场催得再紧也不跳过通信和电源两项。运动命令可以少跑,链路和健康检查不能省,因为后面所有“玄学问题”都能从这份日志里找到入口。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询