move_base中的多线程

move_base.cpp中用到的多线程:

1
2
3
4
5
boost::condition_variable_any  planner_cond_;

boost::thread* planner_thread_;

boost::recursive_mutex planner_mutex_;

代价地图里有个锁mutex_t,其实就是boost::recursive_mutex,膨胀层里还用到了读写锁boost::shared_mutex* access_

递归锁

move_base里用的锁主要是boost::recursive_mutex planner_mutex_,而且是和boost::unique_lock, boost::recursive_mutex::scoped_lock 搭配使用。

使用到planner_mutex_的函数有planThread, executeCb, executeCycle(6次), resetState。其他3个函数,每个都只使用了一次planner_mutex_

只有一次是在生成路径后,交互变量。其他全是和planThread有关的,基本是对runPlanner赋值,比如

1
2
3
4
5
boost::unique_lock<boost::recursive_mutex> lock(planner_mutex_);
planner_goal_ = goal;
runPlanner_ = true;
planner_cond_.notify_one();
lock.unlock();


经过我大量修改,move_base在有导航任务时,如果ctrl+C退出,终端必定会出现下面的错误,虽然毫无影响,但是毕竟不优雅
move_base 退出时报错死锁
这个错误是在有锁的情况下,仍然加锁。 也就是多调用了lock()函数。

搜索move_base,发现只有7个lock()。逐个查看,由于是退出时的报错,所以不可能是makePlan的那个,很容易发现是planThread函数最后的那个。加上判断即可解决

1
2
if( !lock.owns_lock() )
lock.lock();

对于其他使用lock()的地方,最好也加上这个判断。