任务:在实验室原有的基于can总线控制的移动机器人平台上应用ROS
步骤:1.ROS推荐系统为ubuntu,首先需要重装机器人的操作系统。
           2.下载并安装ROS。
           3.原can卡不支持linux系统,须更换机器人的usbcan设备。
           4.利用所购产品附带的测试代码(c语言)测试硬件连接以及驱动和共享库的安装是否正常(即usbcan设备能否正常使用)。
           5.使用c++方式重新编译测试代码,解决出现的问题。
           6.原机器人平台采用的c#编程语言,但ROS暂不支持c#,必须把底层的控制代码移植为c++或python。
           7.应用ROS的目的是为了将底层的运动控制作为无需人为操作独立运行的一个节点,不需要操作界面,所以改写为控制台程序即可。

 

系统安装及硬件更换过程(略)

 

为新更换的can卡安装驱动与接口库

Linux下的usbcan驱动基于libusb实现,请先通过以下命令安装依赖库:

sudo apt-get install libusb-1.0-0

然后将can卡厂商提供的驱动共享库libusbcan.so, libusbcan.so.1拷到/lib目录下,在测试代码test目录下打开终端运行make命令即可编译。编译完成后运行./test,查看参数调用示例作为参考进行测试。

问题及注意事项

1、未安装驱动和动态链接库时,can卡指示灯会显示为红色。

只需,将libusbcan.so,libusbcan.so.1拷入/lib目录下即可(驱动和动态接口库同时解决)。成功后can卡指示灯变为绿色。

2、运行测试程序时出现错误:ret=-3。

ret=-3是指程序运行过程中出现权限问题,即需要使用root权限运行本程序。

sudo ./test

运行程序时可以根据前面提到的调用示例添加参数,eg:sudo ./test 4 0 1 0x1400 2 3 10 1000

3、在自己编写的c++代码中调用can卡接口库函数总是提示:未定义的引用。

1)、厂商提供的接口库函数是用c语言写的,所以如果要在c++文件中调用接口库函数(即在c++中调用c动态链接库),需要在头文件中的函数声明语句开头添加 extern "C" 。

在C++出现以前,很多代码都是C语言写的,而且很底层的库也是C语言写的,为了更好的支持原来的C代码和已经写好的C语言库,C++中提供了extern "C"这个宏。extern "C"的主要作用就是为了能够正确实现C++代码调用C语言代码。加上extern "C"后,会指示编译器这部分代码按C语言的方式进行编译以及连接,而不是C++的。(由于C++支持函数重载,因此编译器编译函数的过程中会将函数的返回类型也加到编译后的代码中,而不仅仅是函数名;而C语言并不支持函数重载,因此编译C语言代码的函数时不会带上函数的返回类型,一般只包括函数名。因此,同样的头文件,使用c和c++方式编译后的函数名是不同的,也就无法进行互相调用)

2)、由于extern "C"语法在C编译环境下是不允许的,因此如果想要使头文件中声明的库函数同时可以被c文件和c++文件调用编译(厂商提供的测试程序是c文件,而我们要写的是c++文件),要将extern "C"置于

#ifdef __cplusplus    

#endif

条件编译之中。即:

#ifdef __cplusplus
extern "C" {
#endif
//函数声明语句
#ifdef __cplusplus
}
#endif

这段代码的含义是如果是在C++文件中,才使用extern "C",这样使用是为了保证当这个头文件被用做C文件编译时,可以去掉C++结构,也就是建立起C和C++公共的头文件。

4、在自己编写的ros功能包中使用c++编写usbcan连接程序时,不仅要添加头文件,还要把动态链接库和头文件放置于同一文件夹(include)中,然后安装下面的步骤更改CMakeLists文件。否则也会报错:未定义的引用。

首先要添加动态链接库的绝对路径:

    include_directories(
      include ${catkin_INCLUDE_DIRS}
    # include
      ${catkin_INCLUDE_DIRS}    /home/ldz/TEST/src/test1/include/test1 #####就这样直接添加到后面即可
    )

然后要添加链接库的名称:

    target_link_libraries(testcan
      ${catkin_LIBRARIES}   usbcan  #####同样直接添加
    )

即可成功编译。

 

5、c程序移植为c++程序运行时出现malloc非法格式转换的问题:

C下,建议 int p = malloc(len sizeof(int))
C++下,建议 int p = (int )malloc(len * sizeof(int))    #####要使用强制类型转换
因为C++下有更严格的类型检查 ,c允许void*指针与普通指针互相赋值,但c++不允许void*指针赋予普通指针,必须经过强制转换才可以。

 

6、can卡设备不能够重复打开,否则报错:

device opened: Type=4, Card=0
段错误

7、调用usbcan共享库函数VCI_Transmit测试发送单条数据时可能出现的错误:

1)、硬件连接时高低电势接反,报错:request=1,transferred=0;

2)、发送数据的传入参数格式为整数时,注意08要写为8,因为c++中08代表八进制数且超过了表示范围,编译报错:invalid digit "8" in octal constant

3)、参数的数值大小一定要根据进制来转换,如十进制的144,16进制下应为90,如果数字不对会报错:request=1,transferred=0

8、不能使用【sudo+节点名称】的方式启动ROS节点,只能先利用sudo su进入root用户权限,再进入节点目录下启动或者使用rosrun的方式启动否则报错:

[FATAL] [1531025487.718466473]: ROS_MASTER_URI is not defined in the environment. Either t
ype the following or (preferrably) add this to your ~/.bashrc file in order set up your lo
cal machine as a ROS master:
 
export ROS_MASTER_URI=http://localhost:11311
 
then, type 'roscore' in another shell to actually launch the master program.
段错误

同时还要注意,一定记得修改root用户的~/.bashrc文件,将ROS环境变量添加到~/.bashrc文件中,即:
source /opt/ros/kinetic/setup.bash,否则一样会报错

除此之外,如果想要以rosrun的方式启动,还需要将功能包的环境变量配置脚本添加到~/.bashrc文件中,即:
source /home/ldz/New1/devel/setup.bash(普通用户下为:source ~/New1/devel/setup.bash,其中“~”代表当前用户目录,如果root用户下不修改“~”为绝对路径也会找不到功能包),否则会报错:package "new1" not found

9、编译和启动需要root权限的节点如何免root

1)、进入root用户下,gcc或catkin_make对源文件重新进行编译得到可执行文件(如果普通用户下编译过,必须删掉原可执行文件,重新编译生成可执行文件,否则无法利用第二步的操作更改运行权限)

2)、继续在root用户下输入命令“chmod u+s 可执行文件”即可成功免root运行程序,或者回到普通用户下输入命令“sudo chmod u+s 可执行文件” 

【番外】小技巧,使当前用户免密使用sudo权限:

sudo cp /etc/sudoers .      # 备份 /etc/sudoers
sudo visudo                 # 打开 /etc/sudoers
ldz ALL=NOPASSWD:ALL        # 在文件末尾加入当前用户权限