一、硬件和驱动
蔷薇包括两个App。一个是安装在机器人端的Launcher,另一个是kDesktop,安装在控制端,像手机、电脑、平板。

机器人端软件分三层。底层是操作系统,像Android、Windows。中间层是Launcher,一个普通app,在Android,就是以着用户级apk安装进系统。Launcher实现了机器人须要的核心模块,包括建图,导航,机械臂,远程桌面Server,自动化,小程序框架,以及DNN模型本地推理。但只有Launcher,机器人就像没有安装第三方App的手机,是运行在Launcher之上的第三方小程序在实现各种场景下功能。
对安装在手机的kDesktop,因为用了远程桌面,手机就是机器人屏幕。接下看搭载蔷薇后,机器人的可使用场景。
1.1 机器人
ros机器人,常用于教学。这是轮趣的。这是亚博的。这是小R的。要用于学习,厂家会公开相关资料,像如何控制底盘,知道怎么控制,就能写底盘驱动,Launcher已能在这三家一些型号产品上运行。
教育机器人是一种应用场景,改外壳,增器件,就能用在其它地方了。这是扫地机,雷达和底盘放得更紧凑,底盘做成既能行走,又能清扫。
家用看护机器人。能识别老人、小孩行为。加个4G电话模块,当发现异常行为,可向外拨打紧急电话。
宠物智能陪伴机器人。跟拍猫、狗。
接待机器人。带客户去指定位置。放在超市,就是导购机器人。
饭店机器人。送菜,问询上菜进度。
替代蓝牙Mesh中枢网关加智能音箱。用机器人组建家用物联网,控制智能家居。
家用投影仪。个人比较怀疑可行性,主要是怎么解决用电池给投影仪供电。不过产品结构做得不错。
亚马逊机器人。后面有个拖斗,东西是人手动放进去。设想下,如果拖斗前有个机械臂,那是不是就可以去哪里夹起物体,放进拖斗,再送到某个位置。
这是launcher实现的单机械臂加深度相机方案。能做到夹取物体,然后放到后面拖斗。
以上机器人的共同特点是须要自主导航,Launcher也能用在不动的。下棋机器人,陪伴机器人。
要支持的机器人种类这么多,Launcher怎么做到都能用?
1.2 硬件和驱动
对不含机械臂的,需要一块主板、一个包含驱动板的底盘,一个激光雷达、一个相机,以及一个喇叭和一个麦克风。
目前支持的主板有野火的鲁班猫4、萤火虫的ROC-RK3588S-PC。如果要用其它主板,硬件至少提供一个UART,四个USB。深度相机往往会超过500毫安,当中至少一个USB3.0。软件需Android12或以上,并对android源码作些修改,主要是让支持远程桌面,以及赋与com.kos.launcher这个普通app一些系统级权限,如何修改参考“定制Android内核(Android-12)”。
底盘一般包括一块驱动板、电机、轮子、底座。为支持众多厂家的底盘,使用了底盘驱动。驱动由小程序实现。兰栖科技提供的Basic小程序支持5种底盘。Ros Serial是用rosserial协议控制速度的机器人,小R机器人就在用这个。YahBoom对应亚博的。
其它三种都是轮趣。A1是轮趣这种封盒安装的。把它对比轮趣店的,为减少灰尘,把主板放进底下大盒,驱动板给罩了个盒子。把相机放上面,同时多加IMU、喇叭和麦克风。兰栖科技不做硬件,从这里下单,也是直接交给轮趣。轮趣发货,并负责硬件售后。
C1是轮趣敞开安装。MC1是轮趣敞开安装,并带有机械臂。这个带机械臂的,需要定制相机支架。
激光雷达作为SLAM传感器,用于建图和定位。Launcher使用cartographer算法。Baisc小程序支持两种雷达,镭神N10,以及思岚RPLIDAR A1M8。
相机用于拍照,以及识别物体。只是这两个功能,不用深度,普通RGB就行。
在连接上,麦克风和喇叭先汇合到一根音频线,音频线另一头以3.5mm接入到主板。
导航时需要知道实时偏航角,如果驱动板上IMU不符合要求,需要外接一个UART IMU。外接IMU时,是以着底盘驱动中一模块融入系统,在Baisc小程序实现的底盘驱动中,支持IM600。
对要支持机械臂机器人,需要再增加一个机械臂,以及把RGB相机换成深度相机,这两设备都需要编写驱动。对机械臂,Basic支持轮趣这种六轴的。硬件上,是由底盘控制,因而在设置机械臂串口、波特率值时,要和底盘一样。
对深度相机,Basic支持奥比中光的Gemini 2。这种相机的深度图像分辨率可到1280x720,盲区标称15cm。相机是安装在机械臂上,但得用个向后伸的支架,原因是要避免待识别物体落入相机盲区。
二、基础操作
2.1 远程桌面
Launcher内置了远程桌面Server,它基于微软RDP协议。由于使用RDP,现有一些RDP客户端就可访问机器人,像Windows内置的“远程桌面连接”。
远程桌面要访问机器人,需要知道机器人IP。要查询机器人IP,或连接向其它Wifi,可使用安装在Android或iOS上的kDesktop。
2.2 设置
运行机器人,大多用不到C洼账号。只在一些必须联网应用,比如抓拍到图像,要把这图像即时发到用户手机。
设置6个驱动。底盘、雷达、深度相机、机械臂都和硬件有关,IoT用于接收IoT事件,语音则用于识别语音、以及聊天服务。类似Windows中的显卡驱动,一旦在这里设置驱动,驱动就运行了,并一直运行。
一旦设置了底盘驱动,而且告知用了外置IMU,就会出现这个“外置IMU”按钮。单击它,设置这IMU连向主板哪个串口。
设了充电任务后,机器人检测到需要充电了,就会导航到“充电”位置,然后运行这里的充电任务。充电任务的目标是要让机器人对准充电桩。这里是设置充电桩宽度,要定位充电桩,往往必须有这个参数。
“地图”、“地图位置”和接下要说的导航有关。
2.3 建图、添加位置、导航
自主导航是机器人核心模块,分三个阶段,依次是建图、添加位置和导航。进入“地图”,选择“建图”,点击“运行”,机器人便开始建图了。
左键长按某个坐标,松开,机器人便会移动去那里,多次重复这操作,建出整张地图。认为建好图了,点击“保存”,地图就会保存到一个文件。切到“导航”,可以看到新建地图map0002.rsp,点击“去噪”,让改善地图质量,以便增加后面导航成功率。在导航页,点击“运行”,地图上长按一坐标,机器人便会去移动去那里,并满足朝向。这种导航操作一般只测试用,实用的还是得继续第二阶段:添加位置。
在“设置”,把新建地图“map0002.rsp”选择为当前地图,这意味着后面的添加位置或导航都会发生在这地图。点击地图位置行的“进入”。
肯定会存在个叫“充电”位置,用于指示充电桩放哪。让添加两个新位置“门口”、“窗台”。
长按“门口”,会出现“大头针”图标,这里拖动到地图,松开,就是“门口”位置的新坐标。除坐标,还可以设角度,一旦设了角度,要求导航时,除满足移动到门口坐标外,要还满足朝向这个角度。至此添加位置阶段结束,接下导航。
进入“中心”。选择“只移动”,位置选“门口”。这时机器人会自主导航到“门口”。
刚才导航位置是手动选,更多是放在哪任务中。进入“任务”,选择报时,在执行单任务,位置1选“窗台”。然后回到中心,选“只任务”,任务选“报时”,机器人会去“门口”,到了后,播报上午几点几分几秒。
上面只是自主导航三阶段的简单演示,要更复杂的,看这视频。
2.4 DNN
“DNN”作用是让快速运行DNN模型本地推理。Launcher内置的本地推理框架是Tensorflow Lite。可看到将用的测试模型是mobilenet_quant_v1_224.tflite,这是个TensorflowLite自带的免费模型。点击运行,便会启动相机,把收到视频帧送给这模型进行识别,识别结果是前面百分之90概率存在个塑料杯、
在用“中心”也能实现同样功能。进入“中心”,“只任务”,选择“图像识别”。“图像识别”是kHome小程序提供的一个相机任务,启动相机后,视频帧同样送给mobilenet_quant_v1_224.tflite。当有相机开着时,右上角会显示“相机”图标,进入便可看相机实际图像。
2.5 深度相机
如果“深度相机”驱动是空,那进入“深度相机”,是以着UVC规范去找普通RGB相机。这里可实时显示相机视频。当系统中有多个相机时,右下角会出现“切换”。在这里切换后,后面会用到的相机地方就都用此相机了。
设了个有效“深度相机”驱动,那进入“深度相机”,是以着深度相机规范去找相机。在这里,有个“抓拍深度”功能,它能从视频流抓出一张深度和RGB叠加的图像。
打开,每个像素点有红、绿、蓝三个数值,分别对应在该像素上,由深度相机测出的(x, y, z)坐标。可看到,相机中心点距离塑料袋1052毫米。
2.6 机械臂
进入“机械臂”。每条横向滑块对应机械臂一个关节,调整滑块便可控制对应舵机转向。
在机械臂,有个重要问题是运动学求逆解,即给出个笛卡尔坐标,要算出各关节的旋转值。Launche目前只支持不会左右移动的机械臂。对这种机械臂,有个特点是可逆解范围是个连贯的环状区域。这张图的白色部分显示了可逆解范围,纵轴是z,即高度,0值在中间。横轴是x,0值在最右端。绿线是针对每个z,x可逆解范围的中间点。
单击“ik_range”,可生成上面这张可逆解范围图像。点击“Loop up table”,可生成zx查找表movei.rsp,这表存储着上面可逆解范围。launcher要求逆解了,是以(z, x)为参数,查询zx查找表,由这表得到各关节应该值。简单说,用查表法解决运动学求逆解。
三、kLink(自动化)
kLink是Launcher处理自动化的模块,自动化要解决机器人怎么处理五花八门工作。顶层逻辑是小程序写出子任务,任务编辑器由这些子任务生成数个复合任务,然后用户根据自个需要,以恰当条件触发执行这些复合任务。(视频)如果产品是这么个台灯机器人,看如何用kLink规划后台任务。
3.1 智能家居触发
每条自动化归结为触发哪条件后,机器人去执行哪任务。对第一条,是当烟雾报警器触发后,去执行一个叫“处理IoT事件”的任务。烟雾报警器是个紧急报警,给了最高优先级,也就是说,它能抢占掉下面任何一条任务。
第二条是当门口门铃按下后,执行的也是“处理IoT事件”任务。
去“处理IoT事件”任务,看做了什么。每个智能家居设备都有个硬件ID,当硬件ID是6c38这一串字符时,表示触发硬件设备是门铃,于是进去门铃播报状态,否则触发这任务就是烟雾报警器,进入烟雾报警器播报状态。
在门铃播报状态,播放“有人在按下门铃”。
在烟雾报警器播报状态,会执行Basic小程序中一个叫“重复说话”任务。该任务行为是让机器人重复播放输入变量msg指示的那句话。也就是说,当触发烟雾报警器后,机器人将一直重复播放“厨房发生烟雾报警”。
3.2 坐姿检测、陪伴做操
台灯机器人要实现坐姿不端正提醒,是用Mediapipe模块。
Mediapipe会得到人的33个关键点,这里用到5个。要让不能靠得太近,那两肩宽度不能超过某个值。脸不能太歪,则两耳高度差不能过大。头不能太低,意味着鼻子距离两肩中点的高度不能太小。只要不满足一个条件,认为坐姿不端正。如果不端正持续了一段时间,像10秒,那上报坐姿不端正事件,上报方法是往环境变量basesubtask写入事件码1。离坐、久坐,也以着似类方法去检测,上报码依次是2和3。
在klink增加个变量触发,它检查basesubtask变量,不为0就去执行一个叫“久坐提醒、坐姿矫正”任务。坐姿矫正任务会根据basesubtask变量值,执行不同任务。像坐姿不端正,是播报“坐姿不端正,请调整姿势”。紧接着,此任务会把basesubtask变量置0,这样底盘那边就可下一轮检测。
(视频)上午10点,可能想做个这样的肩颈操,那可添加个定时触发,让在10点用语音提醒你做肩颈操。做操时,可再用Mediapipe,让台灯陪着做。对应刚才那视频,台灯识别出这姿势后,开始20秒计时。
或坐姿检测,或陪伴做操,得让底盘工作在不同场景,对应这里的“正坐(正面)”和“肩颈操”。台灯会提供方法进行场景切换,像有个物理按键。
{(视频)实现类似问询天气,可加个问询天气语音命令。这条语音触发设了优先级2,意味着它在运行时,上面但凡一条自动化符合条件了,都会抢掉它。}
3.3 家教
对台灯机器人,有个功能是充当家教。这条“问询书上题目”触发后,执行“做习题”任务,就和这目的有关。
“问询书上题目”触发方式是语音命令,它实现了类似这样的语音格式,“第3页第10题”,或“第60页第98题”。命令必须以“第”开始。这个变量是页数,也就是3或60。这个变量是页内题目序号,也就是10或98。
机器人解析出这条语音符合问询题目格式后,关联执行“做习题”。这任务有两个阶段。第一个阶段是根据页号和页内序号搜出问题是啥。实现方法是通过调用kHome小程序实现的kbook单任务。语音中的页号和页内序号会以着两个输入变量进入kbook单任务。
kbook单任务管理着一个问题表。在这示例,第3页第10题,题目文字部分是“写一首关于春天的诗”。第3页第15题则是“求出阴影部分面积”,同时会附带一张图像。
kbook根据页号和页内序号找到问题的文字和图像部分后,“做习题”进入第二阶段,即deekseek状态,这阶段目标要根据问题得到答案。实现方法是调用kHome小程序实现的deepseek单任务。第一阶段得到的问题文字部分赋值给输入变量ds_question,图像部分则赋给值ds_image。
在实现上,deepseek单任务就是把问题文字和图像一并发到一个云服务器,这里用的是百度智能云千帆AppBuilder,然后等着云服务器返回答案。
第3页第10题。问题是“写一首春天的诗”。(...)kbook把问题提交到云服务器,得到答案后,就显示出来。
第3页第15题。问题是“求出阴影部分面积”,附带张图像。(...)可以看到这等答案时间花了30多秒。在连接到的云平台,用的规划模型不是deepseek-v3或deepseek-r1,原因是要减少等待答案时间。
第60页第98题。问题是“轮到红方了,红方下步怎么下”。(...)这是一个关于下象棋的,或许可用在下象棋机器人。等待答案时间花了近一分钟。
商业化时,会用其它方式把答案呈现给用户,像投影仪。在问题表,或许可加上该问题的其它信息,像要点,相关知识点,营造针对这问题的一次虚拟课堂。
四、小程序
可以看到,要是没小程序,机器人都不会动,更别说实用功能。兰栖科技提供了数个小程序,这里说下三个,Basic、kHome和BLE Smart。
4.1 Basic
Basic提供的功能和系统相关,首先包含了6种驱动。要运行,有些驱动需要设置参数,像用哪型号产品、要连接哪串口。
导航页中功能目前不可用。存在这页初衷是要让前台小程序去执行“移动加任务”。可是目前有个规则,一旦运行前台小程序,如果有后台任务,Launcher会结束它,并且运行期间不让运行其它后台任务,基于这个,还是暂不可用。
语音识别和NLP聊天,都用科大讯飞sdk,在语音页设置登录科大讯飞三参数。
IoT驱动是以着涂鸭提供的云开发接口,向涂鸭云服务器查询发生在指定传感器的事件。Client ID、Client Secret是涂鸭云开发接口两密码。后面三个设备ID,是你要从它们接收事件的硬件ID。
Basic实现了一种充电单任务。它识别充电桩特征是直线,要能识别,充电桩宽度至少15cm,厚度至少5cm。
这图描述了一种触点碰触方案。在机器人尾部开两条槽,内粘两铜片,作为充电口母头。在充电桩,对应两槽的中心,放两个pogopin弹簧触点,作为充电口公头。当机器人对准充电桩后,弹簧触点会碰到槽内铜片,实现充电。对两条槽位置,用了上下,这样可以容许更大对准误差。
除驱动,Basic有提供数个任务。抓取、按壁上、按顶部都是机械臂类型的单任务。抓取是爪子做夹取动作,后两个是做按按钮动作,一个按的是壁上按钮,一个则在顶部。
修改环境变量是阻塞式单任务,可用它修改环境变量。这里把环境变量亮度改为10,依kLink设置后,亮度到10后会触发执行打开台灯。这时回看环境变量,env_light_已变成10。(过程大概)
说明变量是个cpp任务,它功能是说出它执行那一刻,含有哪些非环境变量的变量。一般用于调试。
4.2 kHome
kHome实现的功能一般和应用场景有关。
问询是通过和机器人语音交互,让机器人带您去问询商品的存放位置。想象下顾客到超市买手机数据线,但不知数据线在哪位置,就想让机器人带他过去。
餐厅用于餐厅场景,解决用户按下餐桌铃后,机器人向顾客报告上菜进度。
解析时间是个阻塞式单任务,它根据当前时间,得到点、分、秒、时段信息。报时cpp任务就用到它。解析后,会有三条分支。第一条是解析失败,这可能是传下一个无效的时间输入变量。第二条是分或秒不是0,即不是整点,播报类似“上午10点21分6秒”。第三条是整点,播报类似“上午10点”。
图像识别是个相机单任务,“基础功能”的“DNN”说过,收到图像后,送给Tensorflow提供的mobilenet_quant_v1_224.tflite模型,去做物体识别。
抓拍是个相机单任务。有4个输入变量。timestamp决定是否要在左上角加时间戳。png决定存储格式是jpg还是png,count决定要拍几张,not_send则是否不发送到C洼。一旦发送,那手机kDesktop可随即收到这抓拍到图像。它往往可做为巡检一部分。
4.3 BLE Smart
智能家居可分为两类,传感器类和控制类。传感器类,像门铃,烟雾报警器,它们向外发事件,Launcher是让IoT驱动去处理。控制类,像台灯、窗帘、空调、洗衣机,特点是接收外面发来的命令,依命令制去操作。控制类一般用蓝牙传输,计划是让BLE Smart处理这些控制类智能家居。
现有BLE Smart功能较简单,一是搜出旁边有的蓝牙外设。二是针对知道协议的去执行控制,目前就深圳爱尚智联的一种型号台灯。
五、开发者
在开发阶段,绝大多时间工作在Windows。开发工具推荐用微软的Visual Studio。
调试lua代码时,需要安装个lua调试插件。我用的是LuaDkmDebugger。安装它后,在“Externsions”会出现这么个叫“Lua Debugger”菜单。在想加断点的lua代码让调用cpp_breakpoint(),当运行到这里,就会触发断点,查看现场变量。
机器人最终要运行在Android,要用NDK编译出launcher代码。Android Studio则用于最后打包生成launcher.apk。
Launcher代码可都说是C++,小程序代码多了lua,它们都能做到很好跨平台能力。开发过程大致是这样的。假设一个月要发布app/小程序新版本,一般可做到20多天都在Windows开发,然后不用一天编译出Android版本,生成apk,剩下几天做发布前测试。
5.1 编译studio、launcher、kdesktop
除Visual studio,开发环境还需要能运行3个app:Launcher、kDesktop和Rose Studio。要得到这3个,方法是从C洼下载源码,这是解压后的源码目录,按这文章写的编译出它们。
3个app运行时都须要资源包,在Windows,那就须要让exe知道资源包在哪目录,这是通过“Command Arguments”去指定,指定在和源码同级目录,这正是下载时就出现的apps-src会和apps-src同目录放置。
小程序相关动态库生成后,会自动复制到资源包目录。以Basic为例,在设置的Post-Build Event有这么个复制、改名操作。目的是让生成的libleager_basic.dll要复制到这个windows目录,并改名为libroseaplt.dll。
5.2 rviz
调试导航时,极可能需要rviz这个可视化工具。要使用rviz,须让代码工作在Ros传统的一node一进程。修改方法是打开common.cpp,把nocopy_intra改为false。改完后,重编译launcher。
开一个ros cmd,运行roscore。
再开一个ros cmd,运行rosrun rviz rviz。加载设置文件,就可用rviz可视化导航了。
5.3 新建小程序
新建小程序要用到Rose Studio。在左侧顶结点按鼠标右键,弹出菜单中选新建小程序,输入想要bundle id,小程序就生成了。
等Visual studio reload结束后,编译,小程序能用了。接下是运行,不过先让在这两函数设置断点。
运行launcher,打开hello小程序。从断点可看到,aplt_load被调用。出来小程序主界面,显示字符串“Hello world”。退出时,aplt_unload被调用。lua是脚本语言,改了就会生效。把“Hello world”改为“Hello robot”,再运行hello,主界面变成修改后结果。
小程代码包括两部分,lua代码统一放在“applet”项目。初始会有三个文件。settings.cfg是配置文件,存储着版本号、以及能向外提供的任务修息。main.lua是小程序主表,home.lua则对着刚才看到home窗口代码。
aplt_leagor_hello是小程序资源包,可看到libs存储刚编译的libroseaplt.dll。
接下处理android。运行“cmd”,切换到源码包下的scripts目录,执行android_set_variable.bat,这部分内容参考这文章。接着执行ndk-build,成功后会在arm64-v8a下生成libleagor_hello.so。然后把这文件复制到资源包下的arm64-v8a,并改名为libroseaplt.so。
用studio,生成上传小程序需要的rsp包文件,包文件名是Bundle ID为前缀,后跟版本号。
在C洼个人中心,“创建小程序”,输入对应Bundle ID。选择只在Launcher运行这个app,横屏,上传一张960x540尺寸图像,上传文件选刚才生成的rsp。单击左上角“保存”,这小程序就能下载了。
商店上小程序分内测版和发行版。现在生成的是内测试,提交审核,并通过后,会变成发行版。内测版也能下载,不过下载内版时,只能通过商店的“下载内测版”按钮。
进入商店,点击“安装内测版小程序”,输入Bundle ID,下载后,就能运行该小程序。对内测版,桌面显示该名称时,会加上(development)字样。
5.4 编写小程序代码
写代码,可参考C洼上开发文档,还有是参考已有代码。
以底盘驱动为例,它要订阅“cmd_vel”话题,把这速度发向驱动板,让看轮趣底盘怎么实现。找到wheeltec.cpp,在构造twheeltec对象时会订阅“cmd_vel”话题,收到话题后,执行did_serial_geometry_msgs_Twist,后者调用send_Twist。send_Twist把Twist格式速度转换成轮趣底盘能识别的11字节包,然后调用send_data把这包发向底盘串口。这11字节是什么语义,见轮趣给的《STM32运动底盘开发手册.pdf》。
六、常见问题
Q:市面上Ros机器人一般运行在Ubuntu,然后让用户使用各种Ros包,控制上不少用命令行终端,Launcher也是这样吗?
A:Launcher修改了Ros,修改后的Ros商业化上支持Android、Windows,已不建议用Ubuntu。为适应在Android上运行,改出一种“进程内不复制(nocopy-intra)”模式。在这种模式下,所有node在一个进程内运行,Ros Master简单到几个变量,不再有延时、不稳定问题。在Windows,则同时支持nocopy-intra和Ros原有一node一进程,并可以灵活切换。关于“进程序内不复制”模式细节,参考“移植Ros(noetic)”。
对控制机器人方面,在Android不支持命令行终端,必须使用Launcher这个app。这app提供图形界面,和操作一个Android app没啥两样。在Windows,则是同时兼顾Launcher和命令行终端这两种方式。若要使用端终时,Launcher需编译成Ros原有一node一进程模式,这时就可使用Ros提供的像rviz,这样可图形化查看导航,便于开发和调试。
Q:想设置机器人Wifi IP、或忘了IP,怎么办?
A:有两种方法:用kDesktop或接HDMI,建议用第一种。kDesktop需是Android或iOS版。运行后,切换到“远程IP”页,这时kDesktop就会显示扫描到的机器人。如果机器人当前有IP,就会显示IP地址,否则IP地址部分是“0.0.0.0”。这时需要点击“修改IP”,去连接指定Wifi,获得IP了。kDesktop和机器人通信用的是蓝牙,为有好的质量,尽量让手机或Pad靠近机器人。
Q:想开发小程序,大概流程是怎样?
A:硬件上你需要一台Windows电脑,已完全可以不要Ubuntu。第一步:参考“开始机器人开发”,编译Launcher、kDesktop源码。第二步:参考“语音驱动(tspeech_slot)”,那里有一个视频,按视频讲述步骤开发小程序。
Q:如何使用深度学习模型进行本地推导?
A:内置的本地深度学习框架是TensorFlow Lite,需自已提供符合TFLite格式的模型。虽然有相关api,但考虑到模型功能太杂,目前api可能还不能直接用于你模型的话,可向“C洼”询要技术支持。当然,TensorFlow Lite是开源的,也可以写C++代码,直接调用它的api进行推导。