我正在开发一个实现机器人控制器的自定义OpenRAVE ControllerBase
C ++类。
我会尝试尽可能减少代码:
typedef actionlib::SimpleActionClient<control_msgs::FollowJointTrajectoryAction> TrajClient;
class ArmController : public ControllerBase {
.
.
.
virtual bool SetPath(TrajectoryBaseConstPtr ptraj) {
if (ptraj != NULL) {
TrajectoryBasePtr traj = SimplifyTrajectory(ptraj);
PlannerStatus status = planningutils::RetimeTrajectory(traj, false, 1.0, 1.0, "LinearTrajectoryRetimer");
if (status != PS_HasSolution) {
ROS_ERROR("Not executing trajectory because retimer failed.");
return false;
}
trajectory_msgs::JointTrajectory trajectory = FromOpenRaveToRosTrajectory(traj);
control_msgs::FollowJointTrajectoryGoal goal;
goal.trajectory = trajectory;
_ac->sendGoal(goal);
}
return true;
}
virtual bool IsDone() {
_ac->waitForResult(ros::Duration(5.0));
if (_ac->getState() == actionlib::SimpleClientGoalState::SUCCEEDED) {
return true;
}
}
}
这是机器人手臂的单个控制器,我已经为末端执行器实现了另一个,在这种情况下当前没有使用(末端执行器断开连接),但是它做了一些基本的操作(比如打开) ,关闭抓手,听听它的联合状态。)
然后我有一个Python脚本试图在机器人上执行轨迹:
robot.multicontroller = RaveCreateMultiController(env, "")
robot.SetController(robot.multicontroller)
robot_controller = RaveCreateController(env, 'arm_controller')
robot.multicontroller.AttachController(robot_controller, [2, 1, 0, 4, 5, 6], 0)
hand_controller = RaveCreateController(env, 'gripper_controller')
robot.multicontroller.AttachController(hand_controller, [3], 0)
trajectory_object = some_trajectory_object
robot.GetController().SetPath(trajectory_object)
robot.WaitForController(0)
轨迹正在真实机器人上执行但成功但代码阻塞在robot.WaitForController(0)
并且实际上处于控制器的IsDone()
方法中的无限循环中。
有什么想法吗?
答案 0 :(得分:0)
我假设你的末端效应器控制器也实现了一个类似的IsDone()
方法,它具有类似的逻辑(即等待末端效应器达到其目标以返回true,否则返回false)。
由于您使用的是MultiController
,因此Python脚本中的WaitForController(0)
不仅仅是关于arm控制器,而是关注连接到MultiController
的所有控制器。
来自bool OpenRAVE::MultiController::IsDone() virtual
仅当所有控制器都返回true时,才返回true。
由于您说其中一个控制器(末端效应器控制器)未使用,因此该控制器的IsDone
返回false
,因此MultiController的WaitForController(0)
为阻止不在您怀疑的手臂控制器上,而是等待这个未使用的末端执行器控制器IsDone
评估为true
,这将永远不会,因为您已将它与系统;因此阻塞。
我认为有三种选择:
IsDone
方法的逻辑,如果未连接,则返回true。这是一个快速解决方案:
def _is_rostopic_name_exists(self, topic_name):
if topic_name[0] != "/":
topic_name = "/" + topic_name
topics = rospy.get_published_topics()
for topic in topics:
if topic[0] == topic_name:
return True
return False
if _is_rostopic_name_exists("CModelRobotInput") and _is_rostopic_name_exists("CModelRobotOutput"):
hand_controller = RaveCreateController(env, 'robotiqcontroller')
robot.multicontroller.AttachController(hand_controller, [3], 0)
else:
RaveLogWarn("End-effector controller not attached, topics ('CModelRobotInput' or/and 'CModelRobotOutput') are not available.")
这样我们就可以将第二个控制器连接到多控制器,如果存在正常执行该控制器所需的某些必需的ROS主题。