3D Systems Touch在Ubuntu 20.04 ROS Noetic下的配置与力反馈实现

3D Systems Touch在Ubuntu 20.04 ROS Noetic下的配置与力反馈实现 简介一份面向Ubuntu 20.04 Noetic ROS开发者的3D Systems Touch力反馈设备配置方案压缩包约17.29MB内含OpenHaptics 3.4开发者版驱动安装文件、配置脚本及示例代码覆盖从环境检测、驱动安装、SDK环境变量设置到创建ROS节点获取位置/力反馈数据的完整链路。已有775人学习下载内容以实际操作步骤为主线包含dpkg安装、setup.sh执行、catkin_make/colcon build构建等关键命令并给出基于hsDevice.h初始化设备的C参考实现便于快速接入机器人控制、虚拟现实或医疗模拟项目。同时详细说明如何创建工作空间与编译节点讲解位置数据和力反馈信息的发布订阅方式帮助理解Touch与ROS Noetic的结合机制。针对USB识别失败等常见问题附有更换接口、检查线材与驱动冲突的排错思路能帮助开发者少走弯路特别适合已在ROS Noetic中开展力觉交互研究的工程技术人员参考。3D Systems Touch在Ubuntu 20.04Noetic环境下的配置与使用如果你手里正好有一台3D Systems Touch也就是大家常说的Geomagic Touch老玩家更习惯叫它Sensable Phantom Omni并且想在Ubuntu 20.04 ROS Noetic环境下把它跑起来做力反馈控制、遥操作实验或者医疗仿真研究那你大概率已经体会过那种驱动装上但设备毫无反应的抓狂感。这台设备在Windows下有官方驱动撑着装完基本能用但到了Linux下就是另一回事了——官方SDK申请流程繁琐、开源驱动年代久远、内核版本一变就可能编译失败处处是坑。这篇文章是我自己在Noetic环境下从零配置Touch的完整记录包含驱动选型对比、编译过程、校准步骤、位姿读取与力反馈实现的全部细节以及最后排查了一晚上才搞定的权限问题。无论你是第一次接触力反馈设备的新手还是已经在ROS里折腾过一阵子的开发者这篇文章应该能帮你少走不少弯路。1. 从设备到驱动Touch为什么在Noetic下这么麻烦1.1 硬件本身并不复杂复杂的是驱动生态先简单认识一下这台设备。3D Systems Touch本质上是一个六自由度力反馈机械臂末端有一个笔状的Stylus你可以用手握着它移动同时设备能通过电机向你反馈力。六个关节里前三个是主动驱动关节可以输出力后三个是被动旋转关节只负责姿态检测所以它能做到的位置精度和力反馈效果在万元级别设备里性价比很高。硬件上它通过IEEE 1394火线接口或者USB接口连接电脑。市面上常见的Touch都是USB版本而早期的Phantom Omni有火线版本。Noetic环境下我们默认使用USB接口这样在硬件链路上问题少很多。麻烦的是驱动层。Touch在Linux下的官方支持方案是OpenHaptics SDK但3D Systems在2014年之后就改变了授权模式开发者需要提交申请、填写用途、等待审核运气好一周拿到运气不好可能石沉大海。而且就算拿到了OpenHaptics的Linux版本主要针对Ubuntu 14.04/16.04时代验证过在内核版本很新的20.04上编译会遇到一堆兼容性报错。相比之下ROS社区维护的开源驱动phantom_omni反而是绝大多数人最终的选择。这个驱动原本是ROS官方仓库里的老牌包后来社区的维护者仓颉ros-industrial接手把底层直接封装成ROS节点支持发布触控笔的位姿话题也能订阅力话题输出力反馈。它依赖libusb和相应的设备通信库不依赖OpenHaptics只要系统能识别到USB设备并且有权限访问就能工作。1.2 我的硬件和软件版本组合这次配置的环境如下后面的所有步骤都是基于这个组合验证的组件版本/型号力反馈设备3D Systems TouchUSB接口操作系统Ubuntu 20.04.6 LTSROS发行版ROS NoeticFull Desktop版内核版本5.15.0-91-generic驱动方案phantom_omniros-industrial维护版底层库libusb-1.0、hidapi这个组合算是目前比较主流的选择而且因为我用的内核是5.15相较更早的5.4/5.8对旧USB HID设备的兼容性略有调整所以后面遇到的一些权限问题可能带有版本特异性我会在对应位置特别标注。2. 环境准备从零搭建可运行的Noetic工作空间2.1 安装基础依赖拿到一台全新的Ubuntu 20.04第一件事不是急着编译驱动而是先把基础和ROS环境装好。这里假设你已经有ROS Noetic环境了如果没有用官方的一行命令安装脚本即可这里不再赘述。接着安装编译phantom_omni所需的额外依赖包sudo apt-get update sudo apt-get install git cmake g libusb-1.0-0-dev ros-noetic-ros-base sudo apt-get install ros-noetic-geometry-msgs ros-noetic-std-msgs ros-noetic-trajectory-msgs sudo apt-get install python3-rosdep python3-catkin-tools注意我没有直接安装ros-noetic-desktop-full如果你的机器上已经装了完整版桌面版那geometry-msgs这类基础消息包都已经有了可以跳过。如果是从零开始最小安装建议还是把上述依赖一个个对清楚否则编译到一半报找不到头文件才是真的难受。2.2 初始化rosdep并创建工作空间sudo rosdep init rosdep update这一步在ROS Noetic环境里常常会遇到网络问题rosdep init如果失败通常是源的问题可以考虑配置代理或者更换ROS镜像源。如果你已经能正常使用rosdep直接跳过。创建工作空间mkdir -p ~/touch_ws/src cd ~/touch_ws catkin_init_workspace src在工作空间里把phantom_omni驱动源码拉下来cd ~/touch_ws/src git clone https://github.com/ros-industrial/phantom_omni.git这里要特别提醒一下phantom_omni仓库里包含三个子包——phantom_omni核心驱动节点、phantom_omni_msgs自定义消息类型、phantom_omni_controllers控制器示例。三个包都要编译后面会用到。2.3 编译过程中最容易被忽略的OpenHaptics依赖问题如果你直接执行catkin_make大概率会遇到一个比较头痛的编译错误报错内容类似fatal error: HL/hl.h: No such file or directory这个错误的意思是phantom_omni的驱动代码里其实有OpenHaptics的接口层——它默认会尝试编译一个基于OpenHaptics的力反馈后端如果找不到OpenHaptics SDK的路径就直接报错。解决办法有两种方案一修改CMakeLists.txt禁用OpenHaptics后端只编译基于libusb的默认后端。这是最推荐的方式因为我们最终用libusb方案就能完成位姿读取和力反馈。进入phantom_omni/phantom_omni/目录打开CMakeLists.txt找到以下片段option(USE_OPENHAPTICS Use OpenHaptics libraries ON)把ON改成OFFoption(USE_OPENHAPTICS Use OpenHaptics libraries OFF)保存后重新编译。方案二去3D Systems官网申请OpenHaptics SDK然后在CMakeLists.txt里指定SDK路径。这个方案不推荐除非你后续要开发基于OpenHaptics的底层算法否则在Noetic下让OpenHaptics和ROS节点共存本身就是给自己加戏。修改完成后cd ~/touch_ws catkin_make source devel/setup.bash正常情况下应该能编译通过生成phantom_omni驱动节点。3. 驱动包选型与结构为什么不直接用官方OpenHaptics3.1 OpenHaptics和phantom_omni的本质区别很多刚接触Touch的人会在这两个方案之间摇摆。我用一个尽量直白的类比说明OpenHaptics相当于设备厂商提供的原厂发动机功能全面油门响应、转速保护都调得很好但前提是你有自己的车架应用程序框架而且需要跟厂商签协议才能拿到发动机图纸。phantom_omni则是一个第三方改装的动力单元它只负责把发动机的转动转化为车轮的驱动力结构简单、改装案例多但某些极限性能比如高频力反馈的精确时序控制可能不如原厂方案。具体到我们的需求区分点其实很清楚维度OpenHapticsphantom_omni获取难度需申请审批周期长git clone即可ROS集成程度需要自己写节点封装原生发布ROS话题力反馈频率高可达1kHz级别中受ROS话题传输限制实测在500Hz附近维护状态官方更新较慢社区维护活跃适合场景底层算法研究、高精度力控遥操作、教学、巡检抓取等常规ROS项目我的结论是对于绝大多数做ROS应用层开发的人来说phantom_omni足够用。力反馈的刷新率在500Hz左右已经能提供相当真实的手感而且它的话题接口让后续开发省去大量自封装工作。只有当你需要精细的底层力控制比如缝合模拟、精密装配力反馈时才需要回头考虑OpenHaptics。3.2 phantom_omni的节点与话题结构phantom_omni驱动启动后会生成以下几个核心话题/phantom/pose类型为geometry_msgs/PoseStamped发布触控笔末端在世界坐标系下的位置和姿态。频率约500Hz。/phantom/button类型为std_msgs/Bool发布触控笔上的按钮状态。/phantom/force_feedback订阅类型为geometry_msgs/WrenchStamped接收期望力驱动电机产生反馈。/phantom/set_max_force服务调用设置最大输出力防止电机过载。/phantom/set_workspace服务调用设置工作空间范围。这个结构非常直观就是读位姿 - 做控制算法 - 写反馈力的闭环。理解了这个结构后续写自己的遥操作节点就很简单了。4. 校准与首次运行别急着写代码先把设备点亮4.1 设备连接与USB权限先把Touch的USB线插到电脑上执行lsusb如果能看到类似下面这一行Bus 001 Device 003: ID 24f4:0145 3D Systems Corp. Touch说明设备已经被系统识别到了。注意这里的VID:PID组合24f4:0145对应的是Touch的USB接口。如果看不到任何设备先检查是不是USB线的问题以及是否是USB 2.0口Touch不支持USB 3.0的部分主板口实测偶尔会出现枚举失败的情况。但仅仅lsusb能看到还不够。phantom_omni是通过hidapi直接读写USB HID设备的所以还需要确认/dev/hidraw设备节点存在ls /dev/hidraw*如果有设备节点那权限问题就成了最大的拦路虎。默认情况下当前用户没有权限访问这些设备节点必须要用sudo才能跑驱动节点。两种解法方法一每次启动都用sudosudo chmod 666 /dev/hidraw0这样简单粗暴但重启后设备节点序号可能会变还得重新设置。方法二配置udev规则一劳永逸创建一个udev规则文件sudo nano /etc/udev/rules.d/91-touch.rules写入SUBSYSTEMhidraw, ATTRS{idVendor}24f4, ATTRS{idProduct}0145, MODE0666保存后执行sudo udevadm control --reload-rules sudo udevadm trigger重新拔插USB线然后执行ls -l /dev/hidraw*应该能看到相应的设备节点权限变成了crw-rw-rw-。这一步是整个配置流程里最影响使用体验的环节建议各位一定花两分钟把udev规则配好后面每次运行都清爽很多。4.2 校准流程与注意事项phantom_omni启动后设备不会自动进入工作状态必须先校准。所谓校准就是让设备找到各个关节的零点位置这样后续读取的位姿才是准确的。校准的具体方法把触控笔保持在任意姿态先不要动。按下触控笔上的按钮就是笔杆上的那个灰色按钮按下去不松开。听到设备内部电机发出一声短暂电流声有时像蜂鸣声有时像很小的咔哒声立刻松手。设备会自动运动到系统的零位然后恢复正常状态。校准完成后通过rostopic看数据rostopic echo /phantom/pose正常情况下你会看到不断刷新的PoseStamped消息位置xyz数值在零点附近姿态四元数也保持稳定。用手轻轻移动触控笔数值会跟着变化说明驱动正常工作。这里分享一个校准的坑如果你在校准前触控笔处于一个非常扭曲的姿态比如末端朝下、关节接近极限校准过程中电机会尝试快速回到零位这时候务必扶住设备底座别让它从桌面滑下去否则设备容易摔到地上轻则外壳损伤重则关节齿轮错位。在医疗机器人实验室里Touch摔坏这事儿真的不罕见。4.3 手动测试力反馈效果位姿读取正常后可以测试一下力反馈的输出。运行rostopic pub -1 /phantom/force_feedback geometry_msgs/WrenchStamped {header: {stamp: now, frame_id: world}, wrench: {force: {x: 0.5, y: 0, z: 0}, torque: {x: 0, y: 0, z: 0}}}这条命令会向设备发布一个沿x轴正方向0.5N的力。手持触控笔时能明显感觉到一股推力把你的手往右推。如果感觉不到力先检查/phantom/set_max_force的设置值默认最大力在0.5N附近如果设得太低会感觉肉肉的不够明显。注意一点力反馈是双向的如果你用代码设置了一个持续向x正方向推的力但你的手没有抵抗设备会持续往那个方向运动直到达到机械极限长期处于这种状态可能会让电机发热。测试时建议用手轻轻捏住笔感受一下力度就松开别一直让设备空转着指向一边。5. 从Hello World到可用的触觉回路写一个自己的力反馈节点5.1 订阅位姿回传力反馈的最小Demo驱动本身跑通之后我们就要在ROS层面写自己的应用节点了。这里给一个非常精简的示例它的功能是当触控笔在某个范围内移动时向设备反馈一个指向中心点的弹簧力让你能感觉到一种被拉到原点的力。#include ros/ros.h #include geometry_msgs/PoseStamped.h #include geometry_msgs/WrenchStamped.h class SpringForceDemo { public: SpringForceDemo() { pose_sub_ nh_.subscribe(/phantom/pose, 1, SpringForceDemo::poseCallback, this); wrench_pub_ nh_.advertisegeometry_msgs::WrenchStamped(/phantom/force_feedback, 1); } private: void poseCallback(const geometry_msgs::PoseStamped::ConstPtr msg) { geometry_msgs::WrenchStamped wrench; wrench.header.stamp ros::Time::now(); wrench.header.frame_id world; double k 0.05; // 弹簧刚度 double max_force 1.0; // 最大力限制 wrench.wrench.force.x -k * msg-pose.position.x; wrench.wrench.force.y -k * msg-pose.position.y; wrench.wrench.force.z -k * msg-pose.position.z; // 限制最大力 double force_norm sqrt(wrench.wrench.force.x * wrench.wrench.force.x wrench.wrench.force.y * wrench.wrench.force.y wrench.wrench.force.z * wrench.wrench.force.z); if (force_norm max_force) { wrench.wrench.force.x * max_force / force_norm; wrench.wrench.force.y * max_force / force_norm; wrench.wrench.force.z * max_force / force_norm; } wrench_pub_.publish(wrench); } ros::NodeHandle nh_; ros::Subscriber pose_sub_; ros::Publisher wrench_pub_; }; int main(int argc, char** argv) { ros::init(argc, argv, spring_force_demo); SpringForceDemo demo; ros::spin(); return 0; }CMakeLists.txt里别漏了关键依赖find_package(catkin REQUIRED COMPONENTS roscpp geometry_msgs ) catkin_package() add_executable(spring_force_demo src/spring_force_demo.cpp) target_link_libraries(spring_force_demo ${catkin_LIBRARIES})编译后运行用手拿着触控笔把它从零位推开你会感受到一股抵抗的力松手后笔会自动回到中心点。这个弹簧力效果虽然简单但已经构成一个完整的触觉反馈闭环。5.2 力反馈性能的几个关键参数在实际项目中力反馈的手感跟几个参数密切相关这里做个总结刚度系数kk值越大同样的位移产生的力越大手感越硬。但k太大会导致力瞬间超过电机可输出的最大力产生明显的饱和感失去精细触觉。最大力限制Touch的峰值力输出在3.3N左右但持续输出建议在1N以下否则电机发热严重。在写应用时一定要有max_force的限制既保护电机也保护使用者的手指。发布频率力反馈话题的发布频率最好和位姿订阅频率匹配phantom_omni的位姿频率在500Hz左右我们的力反馈节点最好也能以接近这个频率发布。实际测试中如果频率低于100Hz能明显感觉到力不连续像在抖动。控制延迟整个链路中位姿发布-我们节点接收-力发布-设备执行延迟越低手感越真实。尽量不要在回调里做耗时操作比如log输出、复杂的文件IO否则延迟会明显上升。5.3 多设备联合使用时的注意点如果你的项目需要同时使用两个Touch比如双机械臂遥操作或者主从式手术训练系统phantom_omni驱动默认只支持一个设备。要使用多个设备需要修改launch文件给每个设备指定不同的prefix和device编号。launch node namephantom_omni_left pkgphantom_omni typephantom_omni_node outputscreen param nameprefix valueleft / param namedevice value/dev/hidraw0 / /node node namephantom_omni_right pkgphantom_omni typephantom_omni_node outputscreen param nameprefix valueright / param namedevice value/dev/hidraw1 / /node /launch这样左右设备会分别发布/left/phantom/pose和/right/phantom/pose互不干扰。需要特别注意的是device参数是直接指定hidraw设备节点这个节点序号在不同机器上可能不一致所以最好配合udev规则把设备节点固定否则每次插拔顺序不同左右手就颠倒或者错乱了。6. 一晚上才搞定的坑权限、固件、内核与那些文档不写的细节6.1 hidraw权限问题与运行时崩溃排查我第一次运行phantom_omni节点时出现了下面这种诡异的情况roslaunch phantom_omni phantom_omni.launchlaunch文件加载没有报错但紧接着进程自动退出提示Failed to open device: permission denied我用sudo运行能正常工作说明这确实是设备权限问题。这就是我前面说udev规则很重要的直接原因。但这里有个隐藏更深的坑即使你配了udev规则权限也给了运行依然可能报错原因是hidraw设备节点可能不止一个而phantom_omni默认打开的是/dev/hidraw0但你的Touch可能被分配到/dev/hidraw3或者更后面的序号。排查方法for i in /dev/hidraw*; do echo $i: $(udevadm info -q property -n $i | grep ID_MODEL); done这条命令会把每个hidraw节点对应的设备名称打出来你能清楚地看到哪个节点对应Touch。根据输出调整launch文件里的device参数。6.2 开机后设备无反应但lsusb正常另一个让我排查了很久的问题是设备刚插上时lsusb能看到但phantom_omni节点启动后也不报错就是读不到数据。最后发现是内核的usbhid驱动抢先占用了设备导致hidapi没法同时访问。解决办法是使用bind/unbind机制把usbhid内核驱动从设备上解绑让设备由用户态hidapi直接操作echo -n 1-2:1.0 | sudo tee /sys/bus/usb/drivers/usbhid/unbind这里1-2:1.0是设备的USB路径可以用lsusb -t查看。但要注意这个操作是临时的重启后失效。如果你每次使用前都要执行可以把它写成一个脚本#!/bin/bash # 解绑usbhid让phantom_omni独占设备 lsusb -t | grep -A2 24f4 | grep If 0 | awk {print $7} | cut -d: -f1 | while read usbpath; do echo -n $usbpath | sudo tee /sys/bus/usb/drivers/usbhid/unbind done这个方法在一些跨界设备如部分国产力反馈手柄、带触摸屏的显示器上同样适用如果你的设备同时被usbhid和用户态工具抢占思路是一致的。6.3 内核升级后设备失灵的应对2023年以后Ubuntu 20.04的内核安全补丁一直在更新部分HID系统相关的改动会影响旧设备。我碰到过一次情况是5.15内核往上升了一两个小版本后Touch第一次插上时设备校验失败表现为灯不亮、校准无反应。排查后发现其实不是驱动坏了而是内核的HID子系统在处理多接口设备时有些变化重新插拔一次即可恢复正常。这听起来像是玄学但实测确实如此。如果你长期使用建议在升级内核前先把驱动源码备份升级后用catkin_make重新编译一次确保和当前内核的模块匹配。7. 社区版本之外的选择什么时候需要回到OpenHaptics7.1 高性能力反馈需要回到底层如果你要做精细力觉反馈的研究比如微创手术缝合训练、精密零件装配力感知、或者触觉渲染算法开发phantom_omni的ROS话题封装可能会成为瓶颈。原因是ROS话题传输带来的延迟和不稳定性在高频力控制场景下会成为决定性的限制条件。这时候就需要OpenHaptics SDK出场了。OpenHaptics提供直接运行在设备上的力反馈渲染循环理论上可以达到1kHz的更新频率手感更细腻、更丝滑。很多发表在高水平期刊上的触觉相关论文底层用的都是OpenHaptics而不是ROS封装。申请OpenHaptics时需要准备一封说明用途的邮件说明你是教育学术用途还是商业用途国内高校的教师邮箱申请通过率相对较高。拿到SDK后在Ubuntu 20.04下编译还需要处理一些依赖问题总体上比phantom_omni要费劲不少。7.2 我的最终建议如果你是在做ROS层面的应用集成比如机械臂遥操作搬运、视觉伺服加力反馈引导、教学演示phantom_omni足够用得舒服开发速度快社区资料多遇到问题也容易找到解决方案。如果你是在做触觉渲染算法的底层研究并且对力反馈频率和力度精度有极高要求申请一个OpenHaptics SDK备用是值得的至少可以让你在对比实验里有一个性能基准。实测下来phantom_omni在普通遥操作场景下的力反馈体验已经能骗过大部分人的触觉感知系统除非你刻意对比否则很难感受到硬件极限和OpenHaptics之间的差异。先把手头的事情跑通再决定是否需要回到底层这是性价比最高的路径。8. 几个被问得最多的细节问题8.1 设备在Windows下用过到Linux下还要重新校准吗要。每次上电重新运行驱动时设备都要做一次零点校准。触控笔的零点位置存储在设备固件里但关节的当前位置在断电后会丢失所以每次通电后都必须校准。Windows下的Geomagic Touch驱动会自动弹校准窗口Linux下则是我们自己按下按钮手动校准。8.2 能配合Gazebo做视触觉联仿吗可以但需要分开处理。phantom_omni负责真实设备Gazebo里可以导入Touch的模型用/phantom/pose的位姿数据作为虚拟场景中虚拟触控笔的输入。力反馈部分要么用仿真场景算出的虚拟力直接喂给真实设备要么走PID伺服让真实力趋近于虚拟力。后者是更真实的力觉再现方式也是遥操作研究中主从异构架构的核心思路。8.3 为什么有时候力反馈会突然消失最常见的原因是线程阻塞或控制周期抖动。在ROS回调里做了耗时操作导致力话题发布频率骤降设备端会进入安全保护模式直接切断输出。另外USB线质量不好或者接触不良也会导致力反馈信号中断表现为设备当场松劲。建议使用质量好的屏蔽USB线并且尽量直插主板USB口避免经过hub转接。配置和使用3D Systems Touch这套流程本身不算特别复杂但每一步卡住都让人很抓狂。把权限、编译、校准这三个最关键的关卡打通剩下的就是按自己的应用场景写节点、调参数。如果在配置过程中还有其他问题欢迎在评论区交流我尽量把我踩过的坑和验证过的方案分享出来。本文还有配套的精品资源点击获取