源文件
关于源代码makefile学习文件的编写。
netft: netft.o gcc netft.o -o netft netft.o: netft.c gcc -c netft.c -o netft.o clean: rm *.o netft
书写格式一般为: 首先写下最终生成的可执行文件。 2、gcc netft.o -o netft 的效果与 gcc -o netft netft.o一样。 3.冒号前面是需要生成的文件;冒号后面需要空间;冒号后面的文件是需要的文件。 4、-c是编译,-o链接成可执行文件。 5、clean可通过执行make clean实现。
在cppc文件被调用到文件中
因为源代码是用C语言编写的,ros中常用的是c 因此,首先试着单独写文件cppc文件被调用到文件中。 既然是要在cpp在文件中调用c文件,首先要在原始c文件中调用c文件main函数改为普通函数,然后添加返回值。在这里返回指针型。 然后在c和c 需要之间调用 在.h文件中
#include <stdio.h> #ifndef _NETFT_H_ #define _NETFT_H_ #ifdef __cplusplus extern "C" {
#endif int *a(int argc,char **argv); #ifdef __cplusplus } #endif #endif
在.c将头文件导入文件 在.cpp文件中
#include <stdio.h> #ifdef __cplusplus extern "C" {
#endif #include "netft.h" #ifdef __cplusplus } #endif int main(int argc, char **argv) {
while(1) printf("%d\n",a(argc,argv)[1]);
}
完成了程序设计,接下来需要进行编译和链接等。 首先需要生成c源文件的库文件
gcc -c netft.c -o netft.o
这里会报错netft.c:10:19: fatal error: netft.h: 没有那个文件或目录 这里一种可行的办法是,将**.h文件移动到/usr/include**然后再执行就可。 生成库文件以后,就要进行链接生成可执行文件
g++ diaoyong.cpp netft
完成!
ros中实现
首先需要选择合适的消息结构,以及正确的赋值方法:(ps:当然也需要加上上面的技巧)
/** * 该例程将发布chatter话题,消息类型String */
#include <sstream>
#include "ros/ros.h"
#include "geometry_msgs/WrenchStamped.h"
#include <stdio.h>
#ifdef __cplusplus
extern "C"
{
#endif
#include "netft.h"
#ifdef __cplusplus
}
#endif
int main(int argc, char **argv)
{
// ROS节点初始化
ros::init(argc, argv, "talker");
// 创建节点句柄
ros::NodeHandle n;
// 创建一个Publisher,发布名为chatter的topic,消息类型为std_msgs::String
ros::Publisher chatter_pub = n.advertise<geometry_msgs::WrenchStamped>("chatter", 1000);
// 设置循环的频率
ros::Rate loop_rate(100);
int nn = 0;
int count = 0;
while (ros::ok())
{
// 初始化std_msgs::String类型的消息
geometry_msgs::WrenchStamped msg;
msg.wrench.force.x = a(argc,argv)[0];
msg.wrench.force.y = a(argc,argv)[1];
msg.wrench.force.z = a(argc,argv)[2];
msg.wrench.torque.x = a(argc,argv)[3];
msg.wrench.torque.y = a(argc,argv)[4];
msg.wrench.torque.z = a(argc,argv)[5];
nn++;
printf("%d\n",nn);
// 发布消息
chatter_pub.publish(msg);
// 循环等待回调函数
ros::spinOnce();
// 按照循环频率延时
loop_rate.sleep();
++count;
}
return 0;
}
然后。最后就是文件。就比较神奇,在这里我们不需要进行链接操作,除了添加消息结构的库以外,只需要在这里加上这句就可以:
add_executable(talker src/talker.cpp src/netft.c)
存在的问题
比较狗的问题是:好像这个程序本身也只能读取一段数据,然后好象就断了连接。在单独测试效果就是这样,在ros中会报错:Couldn’t find an AF_INET address for [localhost] 试了网上的方法都不可。 希望以后可以填坑,也希望大佬多多指教!
还愿
emmmmmm忽然就那么解决了。 想想解决问题的步骤:首先测试了单独程序,想在源代码中实现while,所以就需要想这个while应该加在什么地方,最终想到了不能重复初始化这个问题,因此在源代码中加上初始化部分只进一次的标志,并将定义移到函数外,解决!!!
/* Simple demo showing how to communicate with Net F/T using C language. */
//#include <netft.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "netft.h"
#define PORT 49152 /* Port the Net F/T always uses */
#define COMMAND 2 /* Command code 2 starts streaming */
#define NUM_SAMPLES 1 /* Will send 1 sample before stopping */
/* Typedefs used so integer sizes are more explicit */
typedef unsigned int uint32;
typedef int int32;
typedef unsigned short uint16;
typedef short int16;
typedef unsigned char byte;
typedef struct response_struct {
uint32 rdt_sequence;
uint32 ft_sequence;
uint32 status;
int32 FTData[6];
} RESPONSE;
int pp[6];
int socketHandle; /* Handle to UDP socket used to communicate with Net F/T. */
struct sockaddr_in addr; /* Address of Net F/T. */
struct hostent *he; /* Host entry for Net F/T. */
byte request[8]; /* The request data sent to the Net F/T. */
RESPONSE resp; /* The structured response received from the Net F/T. */
byte response[36]; /* The raw response data received from the Net F/T. */
int i; /* Generic loop/array index. */
int err; /* Error status of operations. */
char * AXES[] = {
"Fx", "Fy", "Fz", "Tx", "Ty", "Tz" }; /* The names of the force and torque axes. */
int m = 0;
int *a( int argc, char ** argv ) {
if(m==0)!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!这里
{
if ( 2 > argc )
{
fprintf( stderr, "Usage: %s IPADDRESS\n", argv[0] );
return -1;
}
/* Calculate number of samples, command code, and open socket here. */
socketHandle = socket(AF_INET, SOCK_DGRAM, 0);
if (socketHandle == -1) {
exit(1);
}
}
m = 1;
*(uint16*)&request[0] = htons(0x1234); /* standard header. */
*(uint16*)&request[2] = htons(COMMAND); /* per table 9.1 in Net F/T user manual. */
*(uint32*)&request[4] = htonl(NUM_SAMPLES); /* see section 9.1 in Net F/T user manual. */
/* Sending the request. */
he = gethostbyname(argv[1]);
memcpy(&addr.sin_addr, he->h_addr_list[0], he->h_length);
addr.sin_family = AF_INET;
addr.sin_port = htons(PORT);
err = connect( socketHandle, (struct sockaddr *)&addr, sizeof(addr) );
send( socketHandle, request, 8, 0 );
/* Receiving the response. */
recv( socketHandle, response, 36, 0 );
resp.rdt_sequence = ntohl(*(uint32*)&response[0]);
resp.ft_sequence = ntohl(*(uint32*)&response[4]);
resp.status = ntohl(*(uint32*)&response[8]);
for( i = 0; i < 6; i++ ) {
resp.FTData[i] = ntohl(*(int32*)&response[12 + i * 4]);
}
/* Output the response data. */
for (i =0;i < 6;i++) {
pp[i] = resp.FTData[i];
}
return pp;
}
//int main(int argc, char ** argv )
//{
//int e =1;
//while(e--)
// for (int i =0;i < 6;i++) {
// printf("%d\n",a(argc,argv)[i]);
// }
//return 0;
//}