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

机器人自主探索:基于边界点优化与多步路径规划的SLAM实践

1. 项目概述:让机器人自己“看”世界

在机器人领域,自主探索是一个极具魅力的核心挑战。想象一下,你有一台机器人,把它扔进一个完全未知的仓库、一栋废弃的建筑,甚至是一个陌生的星球表面,它能自己决定往哪里走、看哪里,最终绘制出整个环境的地图,而无需你手动遥控。这就是自主探索要解决的问题。它不仅是机器人SLAM(即时定位与地图构建)的终极应用之一,更是实现真正智能、自主移动机器人的基石。

我最近花了不少时间,深入实践了一个名为“基于边界点优化和多步路径规划的机器人自主探索”的项目。这个名字听起来有点学术,但拆解开来,核心思想非常直观:机器人需要找到地图的“边界”(即已探索区域和未知区域的交界处),然后高效、安全地规划一条路径过去,不断重复这个过程,直到探索完所有可到达的区域。这个项目不是纸上谈兵,而是基于ROS(机器人操作系统)和Gazebo仿真环境,从零搭建了一套完整的探索系统。整个过程充满了对算法细节的打磨和对现实物理约束的妥协,今天我就把这套方案的思路、实现细节以及踩过的坑,毫无保留地分享出来。

无论你是机器人方向的学生、刚入行的工程师,还是对自主导航感兴趣的爱好者,这篇文章都将带你走一遍完整的实现路径。你会明白为什么简单的“找最近边界点”策略会失效,如何通过优化让边界点选择更智能,以及多步路径规划如何显著提升探索效率和安全性的。我们直接进入正题。

2. 探索系统的整体架构与核心思路

一套完整的自主探索系统,可以看作一个感知-决策-执行的闭环。我们的架构也是围绕这个闭环搭建的。

2.1 核心模块拆解

整个系统主要包含以下几个核心模块,它们通过ROS的话题(Topic)和服务(Service)进行通信:

  1. 地图服务器:通常采用gmappingcartographer这类SLAM算法包。它订阅机器人的激光雷达(LaserScan)和里程计(Odometry)数据,实时构建并发布占据栅格地图(Occupancy Grid Map)。这张地图是探索算法决策的唯一依据。地图中每个栅格有三种状态:占用(障碍物)、空闲(可通行)、未知(未探索)。

  2. 边界点检测器:这是探索的“眼睛”。它持续订阅最新的地图,通过图像处理的方法,快速找出所有处于“边界”的栅格点。所谓边界点,就是其本身是空闲(可通行),但其八邻域内至少包含一个未知栅格的点。简单来说,它就是已探索区域的边缘,是机器人下一步可能要去探索的方向。

  3. 边界点优化器:这是决策的“大脑”,也是本项目的核心创新点之一。检测器给出的边界点可能成千上万,机器人该去哪一个?最简单的策略是选离机器人当前位置最近的一个。但这样往往效率低下,容易让机器人在局部区域打转。优化器的任务就是从海量边界点中,评估并筛选出最具“探索价值”的少量目标点。

  4. 全局路径规划器:负责计算从机器人当前位置到选定目标点的最优路径。我们通常使用A*或Dijkstra算法在全局代价地图(由静态地图+膨胀层构成)上进行搜索。这一步确保路径在已知地图范围内是最优的。

  5. 局部路径规划器与控制器:全局路径是一条粗略的指引。局部规划器(如ROS的dwa_local_plannerteb_local_planner)负责结合实时传感器数据(如激光雷达),在全局路径附近生成符合机器人动力学(速度、加速度约束)且能实时避障的局部轨迹。最后由底层控制器驱动轮子执行。

  6. 探索状态管理器:这是一个高层状态机,协调整个流程。例如,当机器人到达一个目标点,或规划路径失败时,它需要触发重新检测边界、重新选择目标等操作。

2.2 为什么需要“优化”和“多步规划”?

这是理解本项目价值的关键。传统的前沿探索(Frontier-Based Exploration)方法,其瓶颈往往在于:

  • 近视眼决策:只选择最近的边界点,可能导致机器人频繁往返于入口附近,而忽略了远处的大片未探索区域,整体探索时间很长。
  • 单步规划的脆弱性:一次只规划到下一个目标点的路径。如果这个目标点位于一个狭窄、复杂的走廊尽头,路径规划可能失败,或者机器人执行到一半发现是死胡同,需要整体回溯,非常低效。
  • 信息利用不足:没有综合考虑边界点的“质量”,比如它背后未知区域的大小(是一个小角落还是一整个大厅?)、到达它的路径成本、以及它对整体地图覆盖的贡献。

因此,我们的“优化”旨在让选择更聪明;“多步规划”旨在让行动更鲁棒、更高效。接下来,我们深入这两个核心部分。

3. 边界点优化:从“最近”到“最佳”

边界点优化器的输入是当前地图和所有边界点集合,输出是一个(或少数几个)最优目标点。我们设计了一个多目标代价函数来评估每个边界点F_i的得分。

3.1 代价函数设计

我们为每个边界点计算一个综合代价C_i,通常设计为越小越好(或越大越好,这里以越小越好为例)。C_i由以下几部分加权求和:

C_i = w_dist * D_i + w_info * I_i + w_cluster * S_i

  • 路径距离代价D_i:从机器人当前位置到该边界点的预估路径长度。注意,这里不是直线距离,而是通过一个快速的、低分辨率的路径规划(如简化的A*)估算出的实际行走距离。这比欧氏距离更准确。

    • 为什么用预估路径而非直线距离?直线距离可能穿过墙壁,给出错误引导。快速路径估算能提前发现不可达的点,并将其代价设得极高。
  • 信息增益代价I_i:这个边界点所代表的潜在未知区域的信息量。一个简单的计算方法是:以该边界点为中心,划定一个扇形或圆形区域,统计该区域内未知栅格的数量。数量越多,I_i值越小(因为收益高,代价应低)。

    • 实操技巧:计算信息增益是计算密集型操作。可以对所有边界点进行聚类后,只计算聚类中心的信息增益,然后赋予聚类内所有点,能极大提升实时性。
  • 聚类惩罚代价S_i:为了鼓励机器人探索不同的区域,避免在已探索区域附近反复选择相似的点。我们对所有边界点进行基于距离的聚类(如DBSCAN)。对于属于大型聚类的点,给予一定的惩罚S_i(增大其代价);对于孤立或小聚类的点,惩罚减小。这能有效促进探索的多样性。

3.2 权重的调节与自适应

w_dist,w_info,w_cluster这三个权重决定了算法的“性格”。

  • w_dist大:机器人变得“懒惰”,倾向于去近处。
  • w_info大:机器人变得“贪婪”,倾向于去未知区域大的地方,哪怕很远。
  • w_cluster大:机器人变得“好奇”,喜欢去新的、没去过的方向。

一个重要的心得是:权重不应是固定的。我们可以实现一个简单的自适应策略:

  • 探索初期:地图空白很多,应增大w_info,鼓励机器人勇往直前,快速开图。
  • 探索中后期:地图大部分已探索,剩下一些零散未知区域,应增大w_distw_cluster,让机器人高效地“查漏补缺”,并探索孤立区域。

在我们的实现中,我们根据当前已探索面积占总面积(一个预估最大值)的比例,来动态平滑地调整这些权重,效果比固定权重好很多。

3.3 优化器的实现流程

  1. 输入:当前占据栅格地图,机器人位姿。
  2. 边界点聚类:使用DBSCAN对原始边界点进行聚类。这能减少后续计算量,并将点区分为“前沿区域”(大聚类)和“噪声点”(小聚类或孤立点)。
  3. 代表点选取:对每个聚类,计算其质心或选择离聚类中心最近的一个空闲点作为该聚类的“代表点”。这些代表点加上重要的孤立点,构成候选点集合。
  4. 代价计算:对每个候选点,并行计算其路径距离代价D_i和信息增益代价I_iS_i根据其所属聚类的大小确定。
  5. 加权排序:根据自适应权重计算综合代价C_i,并排序。
  6. 输出:选择综合代价最小的点作为当前最优目标点。有时也会输出前K个点,供多步规划使用。

注意:计算D_i时的快速路径规划,一定要在加入了障碍物膨胀层的代价地图上进行,以确保选出的目标点在机器人本体看来是可安全抵达的,避免选择了一个虽然空闲但被紧贴墙壁的“绝境”。

4. 多步路径规划:从“走一步看一步”到“谋定而后动”

传统的探索是“单步”的:选一个目标,规划一条路径,走过去,再重复。多步规划则尝试一次性规划一条访问多个有序目标点的路径。

4.1 多步规划的优势

  1. 全局效率:类似于旅行商问题(TSP),规划一条访问多个目标点的最优回路(或路径),能显著减少总的移动距离和转弯次数。
  2. 鲁棒性提升:单步规划中,如果去目标A的路径被临时障碍(可能是地图噪声或动态物体)挡住,规划会失败,状态管理器需要重新选择目标,过程可能卡顿。多步规划中,如果去第一个目标的路径受阻,可以尝试直接规划到第二个目标的路径,系统更流畅。
  3. 应对死胡同:当机器人进入一个死胡同时,单步规划需要完全退出后才能选择新目标。多步规划可以在进入死胡同前,就规划好“进入-探索-退出”的完整路径,或者当发现是死胡同时,因为已有后续目标点序列,可以快速切换到下一个目标,减少犹豫时间。

4.2 实现方案:基于聚类的序列规划

完全求解TSP对于实时系统来说开销太大。我们采用一种轻量级的分层方案:

  1. 生成候选点集:利用优化器,不仅输出最优目标点,还输出代价排名前N(例如N=5)的候选点。
  2. 区域聚类与排序:将这N个候选点按其在地图上的位置进行粗略分区。例如,将地图划分为四个象限。机器人会优先规划前往当前所在象限的候选点,然后再前往相邻象限的点。这相当于一个贪心策略,优先探索当前区域,再探索相邻区域,符合人类探索习惯,也能减少整体移动距离。
  3. 序列路径拼接
    • 首先,规划从当前位置到序列中第一个目标点G1的路径P1
    • 然后,以G1为起点,规划到第二个目标点G2的路径P2。这里的关键是,规划P2时,起点G1是一个未来的位姿,我们无法精确知道机器人到达G1时的朝向。一个实用的方法是:假设机器人到达G1时,其朝向是G1指向G2的方向。或者更简单地,在G1处规划时,允许机器人在一个小的范围内旋转,以找到可行的路径。
    • P1,P2, ... 在衔接处平滑处理后,拼接成一条完整的路径序列。
  4. 执行与重规划:机器人开始执行这条多步路径。同时,系统持续监控:
    • 地图更新:如果执行过程中发现了新的、信息增益极高的边界点,可以中断当前序列,重新进行优化和规划。
    • 路径失效:如果某一段路径因发现新障碍物而变得不可行,则从当前点开始,对剩余的目标点序列重新进行规划。

4.3 与单步规划的融合策略

在实际系统中,我们并非完全抛弃单步规划。我们采用一种混合策略:

  • 主循环为多步规划:正常情况下,机器人按照多步路径序列执行。
  • 局部避障仍依赖单步局部规划器:多步规划提供的是全局航点序列,机器人在两个航点之间移动时,其底层的局部规划器(如DWA)仍然在工作,负责实时避障和轨迹生成。这保证了安全性。
  • 触发重规划的条件
    1. 到达序列中最后一个目标点。
    2. 当前序列中所有剩余目标点都已被探索(即其周围的未知区域在移动过程中已被扫清)。
    3. 发现了信息增益远超当前序列中所有点的新边界点(“重大发现”)。
    4. 连续一段时间无法向序列中的下一个目标点前进(可能被锁死)。

这种混合策略既利用了多步规划的宏观效率,又保留了单步规划的实时灵活性。

5. 系统集成与ROS实战细节

理论说完,我们来看看在ROS中如何具体实现。我们的工作空间主要包含几个自定义的功能包。

5.1 功能包创建与依赖

# 创建功能包,依赖必要的ROS包 catkin_create_pkg autonomous_exploration roscpp rospy std_msgs geometry_msgs nav_msgs visualization_msgs tf costmap_2d

关键依赖说明:

  • nav_msgs: 用于发布路径(Path)和目标点(PoseStamped)。
  • costmap_2d: 用于管理全局和局部代价地图,这是路径规划的基础。我们的优化器计算D_i时也需要调用costmap_2d的接口来检查可达性。
  • visualization_msgs: 用于在Rviz中可视化边界点、候选点、路径序列等,调试时至关重要。

5.2 边界点检测的实现

我们创建一个节点frontier_detector.cpp。这里不贴完整代码,讲核心逻辑:

  1. 订阅地图:订阅/map话题(类型为nav_msgs::OccupancyGrid)。
  2. 遍历栅格:使用OpenCV的Mat结构存储地图数据,效率更高。遍历所有栅格。
  3. 判断边界点:对于每个状态为FREE(0) 的栅格,检查其八邻域。如果任何一个邻域的状态是UNKNOWN(-1),则该点为边界点。
    • 优化技巧:使用OpenCV的滤波操作(如dilateerode)可以快速找到处于自由区域边缘的点,再进行精细判断,速度更快。
  4. 发布可视化:将检测到的所有边界点封装成visualization_msgs::MarkerArray发布到/frontiers话题,在Rviz中用绿色点云显示。

5.3 优化器与多步规划器的核心节点

这是最复杂的部分,我们将其放在一个节点exploration_planner.cpp中。

关键数据结构:

struct FrontierCluster { int id; std::vector<geometry_msgs::Point> points; geometry_msgs::Point centroid; // 代表点 double info_gain; // 信息增益 int size; // 聚类大小 };

主循环逻辑:

  1. 接收来自frontier_detector的边界点。
  2. 调用clusterFrontiers函数进行DBSCAN聚类。
  3. 对每个聚类,计算代表点和信息增益。
  4. 为每个代表点,通过costmap_2d::Costmap2DROS提供的getRobotFootprint()getCostmap(),调用A*规划器的一个轻量级版本,估算路径代价D_i
  5. 根据自适应权重公式计算综合代价,排序。
  6. 多步序列生成:取前N个点,按4.2节的策略排序,生成目标点序列std::vector<geometry_msgs::PoseStamped>
  7. 将序列中的第一个点作为当前目标,通过move_baseSimpleActionClient发送给导航栈。同时,将整个序列发布到/exploration_path话题用于可视化。

5.4 与导航栈的协作

我们并不取代ROS标准的导航栈(move_base),而是作为它的上层指挥。

  • 我们的exploration_planner节点将单个目标点(序列中的当前点)发送给move_base
  • move_base负责调用全局规划器(如global_planner)和局部规划器(如dwa_local_planner)来完成具体的路径规划和跟踪。
  • move_base报告目标到达(SUCCEEDED)或失败(ABORTED,REJECTED)时,我们的状态管理器被触发。
    • 如果成功,则从序列中取出下一个点作为新目标。
    • 如果失败,则根据失败原因(如规划失败、长时间卡住),决定是重试当前点、跳过当前点,还是触发全局重规划(重新检测边界并生成新序列)。

6. 仿真测试与参数调优实录

算法实现后,需要在仿真中反复测试和调优。我们使用Gazebo搭建了一个包含多个房间、走廊和障碍物的办公室环境。

6.1 测试环境搭建

  1. 机器人模型:使用TurtleBot3 Waffle Pi模型,它自带激光雷达和差速驱动,非常适合算法验证。
  2. Gazebo世界:设计一个约20m x 20m的封闭环境,包含多个连通性不同的房间,并放置一些桌子和箱子作为内部障碍。
  3. 启动文件:编写launch文件,一次性启动Gazebo世界、机器人模型、SLAM(gmapping)、move_base、我们的frontier_detectorexploration_planner节点。

6.2 关键参数调优经验

参数调优是个细致活,以下是一些关键参数和我们的调优经验:

参数模块参数名含义调优经验与影响
边界检测frontier_search_radius判断边界点的邻域半径通常为1(八邻域)。增大它会让边界点更“粗”,减少数量,但可能漏掉狭窄缝隙。
DBSCAN聚类eps邻域距离阈值非常关键。太小会导致每个点都是独立聚类,失去聚类意义;太大会把所有边界点归为一类。建议设为机器人半径的3-5倍(例如0.3-0.5米)。需要根据地图分辨率调整。
DBSCAN聚类min_samples形成核心点的最小样本数设为3-5。小于此值的点集被视为噪声(孤立点),噪声点也可能很有探索价值,不应丢弃。
代价函数w_dist,w_info,w_cluster各项权重初始可设为1.0, 0.5, 0.3动态调整策略的增益系数需要仔细测试。观察机器人行为:如果总在门口徘徊,增大w_info;如果总是舍近求远,增大w_dist
多步规划candidate_points_num(N)候选点数量通常5-10个。太多会增加规划开销,太少则多步规划优势不明显。
路径规划inflation_radius(costmap)代价地图膨胀半径安全相关!必须大于机器人轮廓半径。设置过小会导致规划路径贴障碍物太近,执行时易碰撞;设置过大会让机器人无法通过狭窄通道。
局部规划max_vel_x,acc_lim_x(DWA)最大速度/加速度探索时建议设置为机器人最大能力的70%-80%。更保守的速度能让SLAM建图更稳定,避障更从容。

6.3 典型问题与排查技巧

在测试中,我们遇到了各种各样的问题,以下是部分实录:

问题1:机器人卡在门口,反复进出同一个房间。

  • 现象:机器人探索完一个房间后,出门,在门口检测到两个房间的边界点,代价相近,它可能又掉头回到刚出来的房间。
  • 排查:检查边界点聚类。可能是eps设置过大,将门内外的边界点聚成了一类,代表点落在了门内。
  • 解决:适当减小eps,确保门内外的边界点被分为不同的聚类。同时,增加w_cluster的权重,或引入“历史惩罚”——对近期访问过的聚类区域内的点,临时增加其代价。

问题2:机器人选择了一个无法到达的目标点,导致规划失败,系统停滞。

  • 现象move_base频繁返回ABORTEDREJECTED
  • 排查:检查优化器中路径代价D_i的计算。是否使用了直线距离?是否在计算前没有检查目标点本身是否在障碍物上(尽管它是边界点,但可能地图有误差)?
  • 解决:确保D_i是基于膨胀后的代价地图进行的快速路径规划长度。在将点加入候选集前,先用costmap->getCost(x, y)检查该点的代价值,如果大于costmap_2d::INSCRIBED_INFLATED_OBSTACLE,则直接剔除。

问题3:多步路径序列在Rviz中显示为断开的线段,机器人执行完第一段就停了。

  • 现象:路径可视化不连贯,机器人行为不符合预期。
  • 排查:检查序列路径拼接逻辑。规划P2时,起点是否正确地设置为G1的位姿?G1的朝向(yaw)是如何设定的?
  • 解决:为每个目标点赋予一个合理的朝向。一个简单有效的启发式是:将朝向设置为从上一个点指向该点的方向角。在路径拼接时,确保相邻路径的末端和首端在位置和朝向上是连续的,可以通过插入一个原地旋转的路径段进行平滑。

问题4:探索效率后期急剧下降,机器人在已知区域“兜圈子”。

  • 现象:地图覆盖率到80%-90%后,进度条几乎不动。
  • 排查:检查是否还有边界点。很可能剩下一些零散的、孤立的未知栅格(如墙角、家具背后)。这些点信息增益I_i很小,距离代价D_i相对较大,在代价函数中永远排不到前面。
  • 解决:调整自适应权重策略。在探索后期,显著降低w_info的权重,甚至可以将I_i项改为一个常数,让决策主要由距离和聚类多样性驱动。或者,专门实现一个“查漏补缺”模式,当检测到的边界点总面积小于阈值时,切换到该模式,算法会优先前往最近的边界点,无论其信息增益大小。

7. 性能评估与未来优化方向

经过大量仿真测试,这套“边界点优化+多步规划”的方案相比传统最近邻前沿探索,在复杂室内环境下的全图探索时间平均减少了约25%-40%,并且机器人的移动轨迹更加平滑、有序,减少了无谓的往返和徘徊。

评估指标

  1. 总探索时间:从开始到地图覆盖率(如98%)达到目标的时间。
  2. 总路径长度:机器人轮式里程计累积的行走总距离。
  3. 重复探索率:机器人重复经过同一区域(如关键路口)的次数。
  4. 计算耗时:每个规划周期内,边界检测、优化、路径规划所花费的时间,需确保实时性(通常要求<1秒)。

未来可能的优化方向

  1. 更智能的信息增益预测:当前的信息增益计算是基于几何面积的。可以引入语义信息,例如,通过一个轻量级的图像识别网络(运行在机器人上),判断边界另一侧是“开阔空间”还是“狭窄走廊”,从而更准确地预测探索价值。
  2. 多机器人协同探索:将本系统扩展到多机器人场景。核心挑战在于任务分配和防冲突。优化器需要为每个机器人分配不同的目标点集(如通过市场拍卖算法),并在多步规划中考虑其他机器人的预计轨迹。
  3. 集成深度学习前端:使用神经网络直接从传感器数据(如激光雷达点云)中预测“潜在探索方向”,而不是依赖基于栅格地图的几何边界检测。这可能对非结构化环境(如废墟、森林)更有鲁棒性。
  4. 能耗与风险感知:在代价函数中加入电池消耗预估和地形风险(如坡度、光滑度)的考量,让探索行为更加安全和持久。

这个项目让我深刻体会到,机器人自主探索是一个系统工程,算法、工程实现和参数调优环环相扣。任何一个环节的粗糙处理,都可能导致整个系统在实际中表现不佳。从“能跑通”到“跑得好”,中间需要大量的实验、观察和迭代。希望这篇详尽的分享,能为你实现自己的探索机器人提供扎实的参考。记住,仿真中的成功只是第一步,最终还是要到真实的机器人上去面对传感器噪声、里程计漂移和不确定的动态环境,那又是另一个充满挑战的故事了。

http://www.cnnetsun.cn/news/2480852.html

相关文章:

  • 2026实测10款AI智能降重工具红黑榜!优缺点全透明,达标率直接对标行业天花板
  • 2023年CNCF五大新锐项目深度解析:Kwasm、KubeArmor、OpenCost、Headlamp与Dragonfly
  • Chromium内核全面拥抱HEVC:从Chrome硬解支持看浏览器视频生态变革
  • 保姆级教程:手把手教你将YOLOv8n模型导出为TensorRT/RKNN/Horizon可用的ONNX格式(附避坑点)
  • 用AT89C51和DS18B20复刻一个智能电饭煲:从原理图到Proteus仿真的保姆级教程
  • 如何用Obsidian Zettelkasten模板终结知识碎片化:完整指南
  • 使用 curl 命令直接测试 Taotoken 聊天补全接口的快速方法
  • 深入浅出DPCM与DAPM:图解高通音频架构如何实现动态功耗管理与低延迟播放
  • Office 365 官方部署工具保姆级教程:只装Word/Excel/PPT,彻底告别OneDrive和Outlook
  • 嵌入式开发回调注册机制:从函数指针到STM32实战应用
  • 告别盲调!用CCS调试器实时观察TMS320F28377D的SPI寄存器状态
  • 告别单线程!在STM32F4上基于FreeRTOS和LWIP搭建多客户端TCP服务器的完整流程
  • Simulink模型服务接口测试:从策略到实践的完整指南
  • 别再手动算CRC了!用UartAssist的校验计算器5分钟搞定Modbus调试
  • Figma界面汉化终极指南:3分钟实现全中文设计环境
  • VSCode里npm命令报错?别慌,这3种常见原因和解决方法(附环境变量配置)
  • 从“玄学”到科学:实测对比Buck电路环路补偿前后,动态响应到底差多少?(附示波器实测图)
  • 如何快速上手TransNet V2:智能视频镜头检测的完整指南
  • GD32做示波器,模拟前端电路怎么设计?聊聊信号调理与衰减的那些‘坑’
  • 从零连接电脑串口到成功通信:艾德克斯IT6831A电源SCPI控制避坑全记录
  • 高校实验室内部流出:Perplexity物理查询黄金参数配置(含3个未公开API调用指令)
  • 给嵌入式新手的MIPI-DSI协议扫盲:从手机屏幕到Linux驱动的那些事儿
  • ARM核心板存储选型实战:从DDR到eMMC的避坑指南
  • RTOS如何通过确定性调度与内存管理增强嵌入式系统安全可靠性
  • NXP FRDM-MCXN236评估板:边缘智能开发的硬件利器与原型验证平台
  • 如何在Windows电脑上轻松安装APK文件:APK安装器终极指南
  • VMware Unlocker 4.2.7终极指南:在非苹果硬件上高效运行macOS虚拟机
  • Mohist 1.20.1:终极Minecraft服务器解决方案,模组与插件的完美融合
  • 海豚调度dolphinscheduler实战:手把手配置企业级Email告警通道
  • 空间约束化学气相沉积:精准调控硬碳微观结构,赋能高性能碱金属离子电池负极