在这里首先要说明的是,youbot的机械臂不需要底座也可以用电脑来控制。也就是说机械臂的驱动和控制都在那个机械臂内,另外一点,它的eth0和eth1的口是不能同时插在两个电脑上的,即使说是同时插上,但是只有一个电脑进行控制,这样的话,也是控制不了的,在实验和小伙伴一起试过。
还有一点要注意,修改config文件,因为在有底座和手臂的情况下,我们的Joint编号是从底座开始的,也就是Joint1,Joint2,Joint3,Joint4对应于四个万向轮,Joint5-Joint9对应于5自由度的机械臂。如果单独使用机械臂,这里的youbot-manipulator.cfg文件的joint号要由Joint5-Joint9改为Joint1-Joint5才可以识别。
文件在/opt/ros/hydro/share/youbot_driver/config目录下,修改youbot-manipulator.cfg
在文件夹/opt/ros/hydro/share/youbot_driver_ros_interface/launch
将youbot_driver.launch这句的value值由true改为false,我们没有base,单独控制机械臂。
修改完以后就可以用命令加载youbot的驱动了
roslaunch youbot_driver_ros_interface youbot_driver.launch
合并action相关的topic后的节点图如下所示:
由上面的节点关系图,我们可以看出youbot_driver已经为我们加载了一些topic,尤其要注意的是它订阅的topic,也就是上图中左边的前四个。另外,这里的driver也只有位置控制和速度控制,并没有力矩控制。前两个topic我们可以看出是arm和gripper(夹子)的位置控制,第三个是arm的速度控制,最后一个是action控制。本篇文章想要介绍的是前两个topic的控制。
下面是控制代码,官方给出的是fuerte的版本,因为太久没更新,有些地方要做修改,下面是已经修改完毕的代码。包括cpp,CMakeList和xml文件。
xml文件
youbot_ros_simple_trajectory
0.0.0
The youbot_ros_simple_trajectory package
yake
TODO
catkin
actionlib
control_msgs
roscpp
rospy
trajectory_msgs
brics_actuator
actionlib
control_msgs
roscpp
rospy
trajectory_msgs
brics_actuator
cmake_minimum_required(VERSION 2.8.3)
project(youbot_ros_simple_trajectory)
find_package(catkin REQUIRED COMPONENTS
actionlib
control_msgs
roscpp
rospy
trajectory_msgs
brics_actuator
)
## INCLUDE_DIRS: uncomment this if you package contains header files
## LIBRARIES: libraries you create in this project that dependent projects also need
## CATKIN_DEPENDS: catkin_packages dependent projects also need
## DEPENDS: system dependencies of this project that dependent projects also need
catkin_package(
# INCLUDE_DIRS include
LIBRARIES youbot_ros_simple_trajectory
CATKIN_DEPENDS actionlib control_msgs roscpp rospy trajectory_msgs brics_actuator
DEPENDS system_lib
)
include_directories(
${catkin_INCLUDE_DIRS}
)
add_executable(youbot_ros_p2p src/youbot_ros_simple_trajectory.cpp)
add_executable(youbot_ctl src/youbot_trajectory_controller.cpp)
target_link_libraries(youbot_ros_p2p
${catkin_LIBRARIES}
)
target_link_libraries(youbot_ctl
${catkin_LIBRARIES}
)
Cpp文件
#include
#include
#include
#include
#include
#include
#include
#include "ros/ros.h"
#include "trajectory_msgs/JointTrajectory.h"
#include "brics_actuator/CartesianWrench.h"
#include "brics_actuator/JointPositions.h"
#include
using namespace std;
//static const double INIT_POS[] = {2.94961, 1.352, -2.591, 0.1, 0.12}; // Twist fold
//static const double INIT_POS[] = {2.56, 1.05, -2.43, 1.73, 0.12}; // Upstraight
static const double INIT_POS[] = {0.11, 0.11, -0.11, 0.11, 0.12}; // Home
static const double Gripper_Init_Pos[] = {0.008, 0.008};
static const string JOINTNAME_PRE = "arm_joint_";
static const string GRIPPER_JOINTNAME_PRE = "gripper_finger_joint_";
static const uint NUM_ARM_JOINTS = 5;
static const uint NUM_GRIPPER_JOINTS = 2;
ros::Publisher armPositionsPublisher;
ros::Publisher gripperPositionPublisher;
vector trajectories;
void trajectoryCallback(const control_msgs::FollowJointTrajectoryActionGoal::ConstPtr& msg)
{
ROS_INFO("callback: Trajectory received");
//cout << "Msg-Header" << endl << msg->header << endl;
trajectories.push_back(msg);
}
void moveToInitPos(brics_actuator::JointPositions &command)
{
std::stringstream jointName;
for (int i = 0; i < NUM_ARM_JOINTS; ++i)
{
jointName.str("");
jointName << JOINTNAME_PRE << (i + 1);
command.positions[i].joint_uri = jointName.str();
command.positions[i].value = INIT_POS[i];
command.positions[i].unit = boost::units::to_string(boost::units::si::radians);
cout << "Joint " << command.positions[i].joint_uri << " = " << command.positions[i].value << " " << command.positions[i].unit << endl;
}
cout << command << endl;
armPositionsPublisher.publish(command); // trully send
cout << "sending command for arm joint init position... and wait" << endl;
ROS_INFO("End of arm_joint_init-pos");
// ros::Duration(5).sleep();
}
void moveToGripperInitPos(brics_actuator::JointPositions &command)
{
std::stringstream gripperJointName;
for( int k = 0; k < NUM_GRIPPER_JOINTS; ++k)
{
gripperJointName.str("");
(k == 0) ? gripperJointName<< GRIPPER_JOINTNAME_PRE << "l": (gripperJointName<< GRIPPER_JOINTNAME_PRE << "r");
command.positions[k].joint_uri = gripperJointName.str();
command.positions[k].value = Gripper_Init_Pos[k];
command.positions[k].unit = boost::units::to_string(boost::units::si::meter);
cout << "Joint " << command.positions[k].joint_uri << " = " << command.positions[k].value << " " << command.positions[k].unit << endl;
}
cout << command << endl;
gripperPositionPublisher.publish(command); // trully send
cout << "command for gripper joint init position... and wait" << endl;
ROS_INFO("End of gripper_joint_init-pos");
}
int main(int argc, char **argv) {
ros::init(argc, argv, "youbot_trajectory_controller");
ros::NodeHandle n;
uint loop_counter = 0;
brics_actuator::JointPositions arm_command;
brics_actuator::JointPositions gripper_command;
vector armJointPositions;
vector gripperJointPositions;
armJointPositions.resize(NUM_ARM_JOINTS);
gripperJointPositions.resize(NUM_GRIPPER_JOINTS);
arm_command.positions = armJointPositions;
gripper_command.positions = gripperJointPositions;
armPositionsPublisher = n.advertise ("arm_1/arm_controller/position_command", 1);
gripperPositionPublisher = n.advertise ("arm_1/gripper_controller/position_command", 1);
ros::spinOnce();
ros::Duration(1).sleep();
ros::spinOnce();
moveToInitPos(arm_command);
moveToGripperInitPos(gripper_command);
//ros::Duration(10).sleep();
ROS_INFO("Init Pos should be reached");
return 0;
}
#include
#include "brics_actuator/JointPositions.h"
#include "brics_actuator/JointValue.h"
#include "brics_actuator/Poison.h"
#include
#include
#include
using std::cout;
using std::endl;
int main(int argc, char** argv)
{
ros::init(argc, argv, "gripper_move_test_node");
ros::NodeHandle nh("~");
ros::Publisher gPublisher = nh.advertise("/arm_1/gripper_controller/position_command", 1);
double floatVal;
if(argc !=2)
{
cout << "set to max open value: 0.011m." << endl;
floatVal = 0.011;
}
else
{
floatVal = atof(argv[1]);
}
ros::Rate loop_rate(20);
brics_actuator::JointPositions jp;
brics_actuator::JointValue jvl;
brics_actuator::JointValue jvr;
brics_actuator::Poison myPoison;
/**************************
*
*topic: /arm_1/gripper_controller/position_command
*topic type: -----> brics_actuator/JointPositions
brics_actuator/Poison poisonStamp
string originator
string description
float32 qos
brics_actuator/JointValue[] positions
time timeStamp
string joint_uri
string unit
float64 value
*
**************************/
while(nh.ok())
{
myPoison.originator = "gripper_demo";
myPoison.description = "demo";
myPoison.qos = 0.0;
jp.poisonStamp = myPoison;
jvl.timeStamp = ros::Time::now();
jvl.joint_uri = "gripper_finger_joint_l";
jvl.unit = boost::units::to_string(boost::units::si::meter);
jvl.value = floatVal;
// jp.positions[0]=jvl;
jp.positions.push_back (jvl);
jvr.timeStamp = ros::Time::now();
jvr.joint_uri = "gripper_finger_joint_r";
jvr.unit = boost::units::to_string(boost::units::si::meter);
jvr.value = floatVal;
// jp.positions[1]=jvr;
jp.positions.push_back (jvr);
gPublisher.publish(jp);
ros::spinOnce();
loop_rate.sleep();
}
return 0;
}
#include
#include
#include
#include
#include
#include "sensor_msgs/JointState.h"
using namespace std;
/******
*topic: /joint_states
*topic type:-----> sensor_msgs/JointState
std_msgs/Header header
uint32 seq
time stamp
string frame_id
string[] name
float64[] position
float64[] velocity
float64[] effort
*******/
char date[20];
void printCallback(const sensor_msgs::JointState::ConstPtr& msg)
{
time_t t = msg->header.stamp.toSec();
struct tm *tm = localtime(&t);
strftime(date, sizeof(date), "%F %T", tm);
cout<name.size(); i++)
{
cout<name[i]<<"; ";
}
cout<position.size(); i++)
{
cout<position[i]<<"; ";
}
cout<velocity.size(); i++)
{
cout<velocity[i]<<"; ";
}
cout<header.stamp << endl;
output_file << date << endl;
for(int i=0; i < msg->name.size(); i++)
{
output_file<name[i]<<"; ";
}
output_file<position.size(); i++)
{
output_file<position[i]<<"; ";
}
output_file<velocity.size(); i++)
{
output_file<velocity[i]<<"; ";
}
output_file<
输出文件的内容,注意这里的joint的名字不是按规律排出来的。千万注意。
这里我要说一下我在写这个cpp文件中遇到的一些问题,第一个遇到的就是gripper的名称问题,这里要注意的是在我们KUKA那个user Manual中40页那里,
我们的gipper必须是gripper_finger_joint_l或gripper_finger_joint_r哦,前缀那里不要瞎加
3.2
最开始我加入gripper的时候会发生core dump,因为以前学习GDB调试的时候遇到过这个,所以又花了些时间在GDB上。我们可以利用core-dump文件查看到出错的具体信息
当发生这个core dump的时候,内存访问错误,于是我开启GDB去调试一下,看看能否有具体原因:
gdb -c 后面的两个参数是core文件和可执行文件
仔细查看源文件,是访问了越界的数组而导致的core dump
修改完毕后执行rosrun youbot_ros_simple_trajectory youbot_ctl
输出结果
可以看到图中最后就是arm和gripper接收到的初始化信息,至此,我们和youbot_driver 的通信与控制就完成了。
参考资料: