当前位置: 首页 > article >正文

从OSM到CARLA:开源地图与仿真引擎的无缝对接指南

1. 为什么你需要把真实世界的地图“搬”进仿真器如果你正在捣鼓自动驾驶算法或者想搭建一个逼真的交通仿真环境那你肯定绕不开一个核心问题场景从哪来闭门造车画地图效率太低也不真实。用仿真引擎自带的几个示例小镇玩几次就腻了而且和你想测试的中国路况可能相差甚远。这时候一个绝佳的解决方案就浮出水面了直接把真实世界的地图数据拿过来用。这听起来很酷但具体怎么做呢我刚开始接触时也是一头雾水直到我发现了OpenStreetMapOSM和CARLA这对黄金组合。简单来说OSM 是一个由全球用户共同绘制的开源地图数据库你可以把它想象成地图界的“维基百科”里面的道路、建筑、交通标志等数据非常丰富而且是免费的。而 CARLA 则是目前最火的开源自动驾驶仿真引擎之一它提供了一个高度可编程的虚拟世界来测试你的算法。那么把 OSM 的真实地图“搬”进 CARLA 的虚拟世界这个想法是不是很诱人我实测下来这条路是通的而且效果相当不错。整个过程就像是为 CARLA 这个强大的游戏引擎导入了一张自定义的、基于现实世界的高清“游戏地图”。无论是想复现你公司楼下复杂的十字路口还是想模拟某个特定城市的环线高速OSM 都能提供基础数据。这篇文章我就来手把手带你走一遍这个流程分享我踩过的坑和总结出来的最佳实践让你也能轻松实现从 OSM 到 CARLA 的无缝对接。2. 第一步从 OSM 获取你想要的“地图切片”万事开头难但获取 OSM 数据这一步其实非常简单甚至不需要写一行代码。我们首先打开 OpenStreetMap 的官方网站。它的界面和普通在线地图很像你可以自由缩放和拖拽。2.1 精准定位与区域选择假设我想为上海张江高科技园区搭建一个仿真环境。我首先会在地图上找到张江的大致位置然后通过缩放来框选我需要的精确范围。这里有个关键技巧不要贪大。一开始我总想导出一个超大区域结果发现转换后的文件在 CARLA 里加载慢而且一些细节处理可能出问题。我的经验是优先选择一个边长在 2-3 公里左右的方形区域这个范围对于单个仿真场景来说已经足够丰富包含了主干道、支路、交叉口等典型元素。在 OSM 网站上你可以看到顶部工具栏有一个“导出”按钮。点击它地图上会出现一个可调整的矩形框。你可以通过拖拽边框的四个角来精确控制要导出的区域。确认范围后系统会默认让你导出为.osm格式的文件这就是我们需要的原始数据文件。它本质上是一个结构化的 XML 文件里面用标签tags详细描述了道路、建筑物、水系等各种地理要素。2.2 数据导出与初步检查点击“导出”后浏览器会下载一个类似map.osm的文件。我建议你用一个文本编辑器比如 VS Code打开它看一眼。虽然内容很多但你可以快速浏览一下文件头尾确认它确实包含了node,way,relation这些 OSM 的核心元素。这一步能帮你避免下载到一个空的或损坏的文件。拿到这个.osm文件我们就完成了原材料采购接下来要进入“加工”环节了。3. 核心转换将 .osm 文件“翻译”成 CARLA 能懂的 .xodr这是整个流程中最关键的一步。CARLA 仿真引擎内部用于定义道路网络的标准格式是OpenDRIVE后缀为.xodr。你可以把 OpenDRIVE 理解为描述道路的“编程语言”它用精确的数学公式定义了车道的几何形状、连接关系、交通标志位置等。而我们的.osm文件虽然包含了道路信息但它的描述方式和侧重点与 OpenDRIVE 完全不同。幸运的是CARLA 的开发团队早就想到了这一点他们在 Python API 中内置了一个非常强大的转换工具Osm2Odr。这个模块就是我们的“翻译官”。下面我给出一个我一直在用的、经过优化的转换脚本并详细解释每个参数的意义。import glob import os import sys # 1. 导入 CARLA Python API 模块 # 这部分代码是标准操作目的是找到并载入你安装的 CARLA 的 Python 接口 try: sys.path.append(glob.glob(../carla/dist/carla-*%d.%d-%s.egg % ( sys.version_info.major, sys.version_info.minor, win-amd64 if os.name nt else linux-x86_64))[0]) except IndexError: pass import carla # 2. 设置转换参数这是提升效果的关键 def convert_osm_to_xodr(osm_file_path, output_xodr_path): # 读取 OSM 文件 with open(osm_file_path, r, encodingutf-8) as f: osm_data f.read() # 创建转换设置对象 settings carla.Osm2OdrSettings() # 调整关键参数根据我的经验优化 # 顶点距离值越小道路曲线拟合越精细但文件也会变大。1.0-2.0 是个不错的起点。 settings.vertex_distance 2.0 # 最大道路长度如果一条路太长转换器会把它切成几段。设置太大会导致单个路段过于复杂。 settings.max_road_length 100.0 # 生成道路两侧的“墙”即路缘石的高度。设为0则不生成对于鸟瞰视角仿真可以设为0。 settings.wall_height 0.2 # 道路的额外宽度在原始道路宽度上增加一点让车道感觉更宽敞。 settings.extra_width 0.5 # 3. 执行转换 xodr_data carla.Osm2Odr.convert(osm_data, settings) # 4. 保存生成的 .xodr 文件 with open(output_xodr_path, w, encodingutf-8) as f: f.write(xodr_data) print(f转换成功文件已保存至{output_xodr_path}) if __name__ __main__: # 指定你的输入和输出文件路径 input_osm ./my_scene.osm output_xodr ./my_scene.xodr convert_osm_to_xodr(input_osm, output_xodr)3.1 参数调优告别“效果不佳”你提供的原始文章最后提到“效果不佳”这十有八九是默认参数不适合你的地图。我最初也遇到过转换出来的路要么断断续续要么弯道像折线一样生硬。经过多次尝试我发现了这几个参数的调节诀窍vertex_distance(顶点距离)这是最重要的参数。它控制着用多少个小线段来近似一条曲线。想象一下用乐高积木拼一个圆积木越小vertex_distance值越小拼出来的圆就越光滑。对于城市道路设置为1.5到2.5米之间效果很好。太小的值如0.5会导致.xodr文件巨大CARLA 加载时卡顿太大的值如5.0则会让道路看起来棱角分明。max_road_length(最大道路长度)OSM 里一条很长的路比如一条高速在转换时会被自动分割成多个 OpenDRIVE 路段。这个参数决定了每个路段的最大长度。我一般设置为80.0 - 150.0。这有助于保持道路数据的模块化。extra_width(额外宽度)OSM 中的道路宽度数据有时比较保守或者有些小路没有宽度信息。加上这个额外的宽度单位米可以让生成的车道感觉更符合驾驶仿真中的直观感受。0.3 到 0.8是我常用的范围。3.2 运行与验证确保你的 CARLA 服务已经运行在终端执行./CarlaUE4.sh或运行 Windows 下的可执行文件。然后在另一个终端运行上面的 Python 脚本。如果一切顺利你会在指定目录得到.xodr文件。我强烈建议你用一个简单的文本编辑器打开生成的.xodr文件搜索一下road标签看看里面是否有内容。这是一个快速验证转换是否成功产出了有效 OpenDRIVE 数据的好方法。4. 在 CARLA 中加载你的专属地图并丰富场景拿到.xodr文件我们离成功就只有一步之遥了。现在我们要把这张“道路设计图”变成 CARLA 世界里可驾驶的、有沉浸感的场景。4.1 加载 OpenDRIVE 地图CARLA 提供了两种主要模式来使用自定义地图。对于我们从 OSM 转换来的地图我推荐使用“OpenDRIVE 独立模式”。这个模式允许我们在一个基础的空旷世界如默认的TownXX上动态加载我们自己的道路网络。下面是一个加载脚本示例import carla import time # 连接到 CARLA 服务器 client carla.Client(localhost, 2000) client.set_timeout(10.0) world client.get_world() # 读取我们转换好的 .xodr 文件 xodr_file_path ./my_scene.xodr with open(xodr_file_path, r, encodingutf-8) as f: xodr_content f.read() # 获取当前世界的“车流管理器”它负责处理地图加载 traffic_manager client.get_trafficmanager() # 关键步骤将 OpenDRIVE 数据应用到当前世界 # 这里的 carla.OpendriveGenerationParameters 可以留空用默认值也可以调整道路材质等 vertex_distance 2.0 max_road_length 500.0 wall_height 0.0 additional_width 0.6 world.generate_opendrive_world( xodr_content, carla.OpendriveGenerationParameters( vertex_distancevertex_distance, max_road_lengthmax_road_length, wall_heightwall_height, additional_widthadditional_width, smooth_junctionsTrue, # 平滑连接处非常重要 enable_mesh_visibilityTrue # 生成可见的道路网格 ) ) print(自定义地图加载完成) time.sleep(2) # 等待一下让世界稳定 # 现在你可以像往常一样放置车辆、传感器了 spawn_points world.get_map().get_spawn_points() if spawn_points: blueprint_lib world.get_blueprint_library() vehicle_bp blueprint_lib.filter(model3)[0] vehicle world.spawn_actor(vehicle_bp, spawn_points[0]) print(f车辆已生成在自定义地图上。)运行这段代码后切换到 CARLA 的仿真窗口你会惊喜地发现原本的城镇消失了取而代之的是根据你的 OSM 数据生成的道路网络。道路的走向、交叉口都和你选择的真实区域一模一样。4.2 超越道路添加建筑、植被和交通只有光秃秃的道路网络是远远不够的那看起来就像一个未完工的工地。OSM 数据其实也包含了建筑物轮廓、公园、水域等信息但 CARLA 的Osm2Odr转换器目前主要只处理道路。为了让场景更逼真我们需要手动或半自动地添加环境资产。批量放置建筑我们可以从 OSM 数据中解析出建筑物的多边形轮廓building*标签。然后在 CARLA 中我们可以根据这些轮廓的位置和大致形状从蓝图库中选择不同样式的建筑模型如BlueprintLib.find(static.prop.building)下的各种模型进行批量放置。这需要一些额外的脚本工作但网上已经有社区开发者分享了一些基础的工具脚本可以参考。程序化生成植被对于绿地landusegrass、森林naturalwood区域我们可以使用 CARLA 的命令行工具DynamicMeshGenerator或在脚本中调用相关 API在这些区域内随机撒播树木和灌木的模型。注入交通流这是让场景“活”起来的关键。CARLA 强大的交通管理器Traffic Manager可以基于加载的道路网络自动生成车辆和行人。你只需要设置车辆数量、行人数目、行为模式如激进型、保守型它们就会自动在路上跑起来遵守基本的交通规则如红绿灯、避让。5. 实战技巧与避坑指南纸上得来终觉浅绝知此事要躬行。根据我多次项目的经验这里总结几个能让你事半功倍、避免抓狂的实战技巧。5.1 数据源质量决定上限OSM 的数据质量在全球分布不均。在欧美日等地区数据非常精细甚至包含了车道数、限速、详细的交通标志。但在一些地区数据可能只有主干道缺少小路或者道路几何形状不够精确。在导出 OSM 数据前最好先用网站的“编辑”视图粗略看一下你关注区域的绘制细节。如果道路线歪歪扭扭或信息缺失严重你可能需要考虑手动在 OSM 上做一些修正这也是为开源社区做贡献或者接受仿真场景会有些粗糙的事实。5.2 处理复杂的交叉口和立交桥OSM 对于复杂交叉口如大型环岛、多层立交的表述方式有时会让Osm2Odr转换器感到困惑导致生成的道路连接出现错乱比如车道莫名其妙断开或者连接关系错误。遇到这种情况我的解决办法是“分而治之”单独导出在 OSM 上只导出这个复杂路口及其周边一小片区域。单独转换和调试针对这一小块.osm文件进行转换并在 CARLA 中加载仔细观察问题所在。调整 OSM 数据有时需要回到 OSM 的编辑模式确保交叉口处的各条道路在数据上是正确连接的共享节点并且标签清晰。参数微调重点调整vertex_distance和smooth_junctions参数让转换器能更好地处理复杂几何。5.3 坐标系与比例尺这是一个隐藏的深坑。OSM 使用的是 WGS-84 经纬度坐标系而 CARLA 使用的是以米为单位的局部笛卡尔坐标系。Osm2Odr转换器内部会进行坐标转换。绝大多数情况下这没问题但如果你发现生成的地图在 CARLA 里严重扭曲或缩放不对可能需要检查转换过程。一个简单的验证方法是在 OSM 上测量一段你知道实际长度的道路比如一段标准的400米跑道然后在 CARLA 里用调试工具测量生成对应道路的长度看比例是否接近 1:1。5.4 性能优化当你导出的区域很大或者道路网络非常复杂时生成的.xodr文件可能达到几十兆。这会导致 CARLA 加载地图的时间变长运行时帧率下降。优化方法包括精简导出区域只导出必要的部分。增大vertex_distance在可接受的视觉质量下适当增加这个值能显著减少道路的几何复杂度。在 CARLA 中启用层级细节LOD对于你自己添加的大量建筑和植被模型确保它们有合理的 LOD 设置远离摄像机时自动切换为低面数模型。走通从 OSM 到 CARLA 的整个流程后你真的会有一种“创造世界”的成就感。它极大地解放了场景构建的生产力让你能快速基于任意真实地点进行算法测试。我记得第一次成功把我家附近的路口复现到 CARLA 里并看着自动驾驶车辆在上面运行时那种兴奋感难以言表。当然这条路不会一帆风顺转换参数需要反复调试复杂场景需要额外加工但一旦掌握了这套方法它就成为了你工具箱里一件非常强大的武器。希望这篇指南能帮你少走弯路更快地搭建出属于你的、逼真的自动驾驶仿真世界。如果在实际操作中遇到具体问题多看看 CARLA 的官方文档和社区论坛那里的讨论常常能给你带来启发。

相关文章:

从OSM到CARLA:开源地图与仿真引擎的无缝对接指南

1. 为什么你需要把真实世界的地图“搬”进仿真器? 如果你正在捣鼓自动驾驶算法,或者想搭建一个逼真的交通仿真环境,那你肯定绕不开一个核心问题:场景从哪来? 闭门造车画地图?效率太低,也不真实。…...

Vue项目中集成百度地图API的实战指南与优化技巧

1. 从零开始:在Vue项目中引入百度地图API 如果你正在开发一个需要展示地理位置、规划路线或者标记兴趣点的Vue应用,那么集成一个地图组件几乎是绕不开的。百度地图作为国内主流的地图服务,其JavaScript API功能强大、文档齐全,对于…...

WSL2 网络配置全攻略:解决 localhost 代理、Docker 和局域网访问问题

WSL2 网络配置深度解析:从原理到实战,打通开发环境任督二脉 如果你和我一样,从纯粹的 Linux 或 macOS 开发环境迁移到 Windows,并拥抱了 WSL2,那么网络配置这块“硬骨头”你大概率啃过。那种在浏览器里 localhost:3000…...

微前端架构实战:从原理到框架选型

1. 微前端到底是什么?从“大泥球”到“乐高积木”的进化 如果你做过几年前端开发,大概率遇到过这样的项目:一个庞大的单体应用,代码库动辄几十万行,技术栈可能是五年前甚至更早的。每次改一个小功能都心惊胆战&#xf…...

Spring Boot 3.5.x 实战:SpringDoc 2 与 Swagger3 的深度集成与配置优化

1. 为什么在Spring Boot 3.5.x时代,我坚定地选择了SpringDoc 2 如果你和我一样,是从Spring Boot 2.x时代一路升级上来的老开发者,那你肯定对Swagger 2.x和它的老朋友springfox-boot-starter不陌生。当年,它几乎是Spring Boot项目生…...

ESP8684-WROOM-04C射频特性深度解析与工程落地指南

ESP8684-WROOM-04C 射频特性深度解析与工程落地指南射频性能是无线模组的核心竞争力,直接决定通信距离、抗干扰能力、功耗表现与系统稳定性。ESP8684-WROOM-04C 作为乐鑫新一代高集成度 Wi-Fi 6 Bluetooth 5.3 双模模组,其射频设计在保持小尺寸封装&…...

立创开源Type-C超声波切割刀DIY全解析:从STC8H驱动到GU-18脉冲变压器设计

立创开源Type-C超声波切割刀DIY全解析:从STC8H驱动到GU-18脉冲变压器设计 最近在捣鼓一些桌面小工具,想做一个能轻松切割3D打印支撑和纸张的超声波切割刀。市面上的成品要么太贵,要么不够小巧,于是决定自己动手做一个。这个项目从…...

立创EDA开源项目:ALL IN ONE全统一超高速HUB硬件设计与实现全解析

立创EDA开源项目:ALL IN ONE全统一超高速HUB硬件设计与实现全解析 最近在立创开源硬件平台上看到一个挺有意思的项目,叫“ALL IN ONE全统一超高速HUB”。这名字听起来就挺唬人的,点进去一看,好家伙,这哪里是个普通的US…...

【国家级等保2.0强制要求】:MCP 2.0消息完整性校验必须满足的4项密码学硬指标(附国密SM4-GMAC审计清单)

第一章:MCP 2.0消息完整性校验的等保2.0合规性定位与密码学基线解读MCP 2.0(Message Control Protocol 2.0)作为关键业务系统间安全通信的核心协议,其消息完整性校验机制直接关联《网络安全等级保护基本要求》(GB/T 22…...

次元画室教程:锁定“风格密码”,批量产出AE可用素材(附案例)

次元画室教程:锁定“风格密码”,批量产出AE可用素材(附案例) 1. 引言:从“单张美图”到“批量素材库”的思维转变 如果你是After Effects的深度用户,下面这个场景你一定不陌生:项目需要一个风…...

Linux网络驱动开发:PHY状态机与链路检测机制详解(附实战代码分析)

Linux网络驱动开发:PHY状态机与链路检测机制详解(附实战代码分析) 在嵌入式Linux网络驱动开发中,PHY芯片的管理是连接物理层与数据链路层的核心桥梁。对于许多中高级工程师而言,理解内核如何感知并响应网线插拔、协商速…...

ollama部署本地大模型|embeddinggemma-300m在金融研报相似度分析应用

ollama部署本地大模型|embeddinggemma-300m在金融研报相似度分析应用 金融分析师每天需要阅读大量研报,如何快速找到相似内容、发现关联信息?本文将手把手教你用ollama部署embeddinggemma-300m模型,构建金融研报智能分析系统。 1.…...

ESP32-P4 VDMA多块传输与低功耗中断驱动详解

ESP32-P4 VDMA 控制器深度解析:多块传输机制、低功耗设计与中断驱动配置实践1. VDMA 多块传输终止判定机制详解VDMA(Video Direct Memory Access)控制器在 ESP32-P4 中承担着高吞吐、低延迟的数据搬运任务,其核心能力之一在于对多…...

线程池核心参数?如何设置?

这句先记住。线程池核心参数决定了:线程池最多开多少线程?任务怎么排队?线程空闲多久回收?线程怎么创建?满了之后怎么办?一、线程池 7 个核心参数Java 里最常见的是 ThreadPoolExecutor:ThreadP…...

YOLOv6 安装及使用详细教程

前言 YOLOv6 是美团研发的轻量级目标检测算法,兼顾检测精度与推理速度,适配工业落地与学术入门场景。该算法针对工程化部署深度优化,环境配置简单、运行流程清晰,是零基础用户入门目标检测的优选方案。本文将手把手带你完成 YOLO…...

Windows安装OpenClaw龙虾(新手入门必备)

目录 一、准备工作(必做) 二、方案A:原生PowerShell一键安装(新手首选) 1. 打开管理员PowerShell 2. 解锁脚本执行权限(必做) 3. 一键安装OpenClaw 4. 验证安装 5. 初始化配置&#xff0…...

基于终端 ANSI 转义序列的“等离子体流体动画”

目录 创意项目:终端等离子体场 (Terminal Plasma) 代码设计的“极限”考量 挑战扩展方向 如果您喜欢此文章,请收藏、点赞、评论,谢谢,祝您快乐每一天。 挑战开发极限,不仅是代码量的缩减,更是对算法、位…...

JVM面试题100道(含答案解析)

在Java后端开发面试中,JVM(Java Virtual Machine) 几乎是必问的核心知识点。 很多互联网公司(如大厂或中大型技术团队)在技术面试中都会重点考察 JVM内存模型、垃圾回收机制、类加载机制以及JVM调优能力。 本文整理了一…...

【杂谈】结构体的内存对齐与位段

目录 一、结构体内存对齐问题(节省时间) 1.什么是内存对齐 2.需要使用内存对齐的原因 3.内存对齐的规则 4.举例 5.小结 二、结构体实现位段操作(节省空间) 1.位域简介与使用原因 2.位域的定义与使用时的注意事项 3.举例 …...

前端开发 - this 指向问题(直接调用函数、对象方法、类方法)

一、直接调用函数 1、基本介绍非严格模式:this 为 window严格模式,this 为 undefined2、演示 function fn() {console.log(this); } fn();# 非严格模式下运行,输出结果Window {window: Window, self: Window, document: document, name: , lo…...

2026精选课题-基于springboot大学生社团管理系统的设计与实现

专注于大学生项目实战开发,讲解,毕业答疑辅导,欢迎高校老师/学生代理交流合作✌。 技术范围:SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容:…...

智能电网无线通信中仅存在式被动侦察的基准数据集

大家读完觉得有帮助记得关注和点赞!!!摘要在智能电网通信中对仅存在式被动侦察进行基准测试具有挑战性,因为攻击者只接收信号,但附近的观察者仍然可以通过额外的阴影和多径效应改变传播,从而重塑信道相干性…...

Web安全实战:绕过__wakeup漏洞攻防解析

1. 从一道CTF题说起:为什么我的反序列化总被“叫醒”? 大家好,我是老张,一个在Web安全领域摸爬滚打了十来年的老兵。今天想和大家聊聊一个在PHP安全里既经典又有点“狡猾”的漏洞——__wakeup魔术方法的绕过。这事儿说起来&#x…...

Vue3+WebRtcServer实现海康监控rtsp流视频的跨域播放解决方案

1. 为什么你的海康监控视频在Vue3里播不出来? 最近好几个做安防项目的朋友都跟我吐槽同一个问题:他们在Vue3项目里想直接播放海康威视摄像头的RTSP视频流,结果要么黑屏,要么疯狂报跨域错误。浏览器控制台里一片红,全是…...

深入解析tile_images与tile_images_offset:图像拼接的灵活应用

1. 从“拼图游戏”到工业视觉:为什么你需要了解图像拼接 如果你玩过拼图游戏,或者用手机App把几张照片拼成一张长图,那你对“图像拼接”这个概念一定不陌生。在工业视觉和图像处理领域,这种需求同样普遍,甚至更为关键。…...

Ubuntu22.04下BBR与CUBIC拥塞控制算法的性能对比测试

1. 为什么我们要关心拥塞控制算法? 如果你用过家里的宽带,或者在公司里传过大文件,肯定遇到过这种情况:明明网速标称很高,但下载东西就是时快时慢,看视频也总在缓冲。很多时候,这口“锅”可能不…...

手把手教你玩转Nunchaku FLUX.1:从安装到出图,新手完整指南

手把手教你玩转Nunchaku FLUX.1:从安装到出图,新手完整指南 想试试用AI生成图片,但看到复杂的界面和参数就头疼?别担心,今天我来带你从零开始,一步步玩转Nunchaku FLUX.1 CustomV3这个强大的文生图工具。你…...

R提供了一些函数用于判断逻辑表达式的结果

下面内容摘录自《用R探索医药数据科学》专栏文章的部分内容(原文5241字)。 3章4节:R的逻辑运算和矩阵运算_逻辑判断矩阵在r语言中的应用-CSDN博客 逻辑运算和矩阵运算是R语言中两个重要的功能模块,前者用于逻辑判断和条件筛选&am…...

Linux下hadoop2.9.2单节点伪分布搭建完全教程

配置静态 IP 在实际应用中,由于我们使用的是 DHCP(Dynamic Host Configuration Protocol: 动态主机配置协议)服务器来分配的地址,那么每次重启DHCP 服务器 ip 地址有 可能是会变动的。 而我们用Linux 来搭建集群学习Ha…...

OpenClaw 技能插件开发实战:适配职业教育的 AI 实训案例

一、前言随着人工智能技术在职业教育领域的深度渗透,传统AI实训模式逐渐暴露出诸多痛点:实训内容脱离企业真实应用场景、学生上手门槛高、实训平台功能固化难以拓展、缺乏可落地的实战化开发任务,难以满足职教领域“岗课赛证”融合的人才培养…...