linux下读取ATI公司力传感器数据&&c++中调用c源文件&&移植到ros+问题解决

本文档详细记录了在Linux环境下,使用C语言读取ATI公司力传感器数据,然后在C++中调用C源码,最终将程序移植到ROS系统中的过程。遇到的主要问题包括makefile的编写、C++调用C文件的头文件引用、ROS中消息结构的选择和赋值,以及程序运行时的连接中断问题。通过修改源代码,解决了连接中断问题,实现了ROS中力传感器数据的发布。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

linux下读取ATI公司力传感器数据&&c++中调用c源文件&&移植到ros+问题解决

源文件

关于源代码中makefile文件的编写,进行学习。

netft: netft.o
	gcc netft.o -o netft 
netft.o: netft.c
	gcc -c netft.c -o netft.o
clean:
	rm *.o netft

书写格式一般为:
1、最终生成的可执行文件首先写。
2、gcc netft.o -o netft 的效果与 gcc -o netft netft.o一样。
3、冒号前面是需要生成的文件;冒号后面需要有空格;冒号后面的文件是需要的文件。
4、-c是编译,-o是链接成可执行文件。
5、clean可以通过执行make clean实现。

在cpp文件中调用c文件

因为源代码是用c语言编写,而ros中常用的是c++文件,因此首先尝试在单独的cpp文件中调用c文件。
既然是要在cpp文件中调用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;
}

然后将c源文件、头文件与cpp文件放在统一功能包的src文件夹下。最后就是cmakelist文件。就比较神奇,在这里我们不需要进行链接操作,除了添加消息结构的库以外,只需要在这里加上这句就可以:

add_executable(talker src/talker.cpp src/netft.c)

存在的问题

比较狗的问题是:好像这个程序本身也只能读取一段数据,然后好象就断了连接。在单独测试效果就是这样,在ros中会报错:Couldn’t find an AF_INET address for [localhost]
试了网上的方法都不可。
希望以后可以填坑,也希望大佬多多指教!

May the force be with you!


还愿

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;
//}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值