总线伺服舵机SDK使用手册(ROS)¶
1.概述¶
本SDK内容有
- ROS-Melodic安装
- 基于总线伺服舵机通信协议的API函数,适用于所有总线伺服舵机型号。
- ROS功能包,包括Message以及Python和C++的节点实例。
1.1.上位机软件¶
上位机软件可以调试总线伺服舵机,测试总线伺服舵机的功能。
-
使用说明:总线伺服舵机上位机软件使用说明
1.2.SDK¶
本文例程、API下载。
- ROS_SDK下载链接:SDK for ROS
1.4.图例¶
HP8-U45-M总线伺服舵机
总线伺服舵机转接板UC-01
2.接线说明¶
- 安装USB转TTL模块的驱动程序。
- 将TTL/USB调试转换板UC-01与控制器、总线伺服舵机以及电源连接。
3.ROS-Melodic安装手册¶
本文讲解了如何在Ubuntu18.04下安装ROS发行版Melodic。
使用以下命令来查询您的Ubuntu版本,如与本文不一致,可参考网上其他教程安装对应ROS版本。
当您能够成功打开小海龟窗口时,即代表ROS安装完成。
3.1.系统信息¶
3.2.官方wiki¶
3.3.安装melodic¶
sources.list初始化
sudo sh -c 'echo "deb http://packages.ros.org/ros/ubuntu $(lsb_release -sc) main" > /etc/apt/sources.list.d/ros-latest.list'
添加keys
sudo apt-key adv --keyserver 'hkp://keyserver.ubuntu.com:80' --recv-key C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654
更新系统软件源
安装ROS
修改.bashrc
3.4.安装依赖包¶
sudo apt install python-rosdep python-rosinstall python-rosinstall-generator python-wstool build-essential
3.5.安装rosdep¶
rosdep
初始化
修改IP地址映射
在初始化rosdep
之前,需要重定向网址raw.githubusercontent.com
的IP地址, 原因是被墙了,
使用网站 https://www.ipaddress.com/ 查询 raw.githubusercontent.com
最新的IP地址,
追加一行(注:IP地址可以用你查到的地址) URL对应的IP解析地址有很多个,选取一个可用的。
编辑完成之后保存并退出,
注释原有的nameserver
, 追加两行,
修改rosdep的源码
rosdep update
的时候,一直提示timeout错误的原因是rosdep
包里面的超时判断条件太短了,国内访问raw.githubusercontent.com
的速度很慢,所以需要修改rosdep
包的源码里面的超时判断条件。
设置全局变量DOWNLOAD_TIMEOUT =45
,
需要修改如下三个Python脚本里面的DOWNLOAD_TIMEOUT
sudo gedit /usr/lib/python2.7/dist-packages/rosdep2/sources_list.py
sudo gedit /usr/lib/python2.7/dist-packages/rosdep2/gbpdistro_support.py
sudo gedit /usr/lib/python2.7/dist-packages/rosdep2/rep3.py
修改之后,可能还是会遇到timeout
的情况,多试几次。
rosdep初始化与更新
输出日志
$ rosdep update
reading in sources list data from /etc/ros/rosdep/sources.list.d
Hit https://raw.githubusercontent.com/ros/rosdistro/master/rosdep/osx-homebrew.yaml
Hit https://raw.githubusercontent.com/ros/rosdistro/master/rosdep/base.yaml
Hit https://raw.githubusercontent.com/ros/rosdistro/master/rosdep/python.yaml
Hit https://raw.githubusercontent.com/ros/rosdistro/master/rosdep/ruby.yaml
Hit https://raw.githubusercontent.com/ros/rosdistro/master/releases/fuerte.yaml
Query rosdistro index https://raw.githubusercontent.com/ros/rosdistro/master/index-v4.yaml
Skip end-of-life distro "ardent"
Skip end-of-life distro "bouncy"
Skip end-of-life distro "crystal"
Skip end-of-life distro "dashing"
Skip end-of-life distro "eloquent"
Add distro "foxy"
Add distro "galactic"
Skip end-of-life distro "groovy"
Skip end-of-life distro "hydro"
Skip end-of-life distro "indigo"
Skip end-of-life distro "jade"
Skip end-of-life distro "kinetic"
Skip end-of-life distro "lunar"
Add distro "melodic"
Add distro "noetic"
Add distro "rolling"
updated cache in /home/kyle/.ros/rosdep/sources.cache
4.创建Workspace¶
创建Workspace文件夹,这一步可以自定义文件夹名称,但是后续操作需要对应修改。
输出日志
kyle@turing:~/catkin_ws$ catkin_make
Base path: /home/kyle/catkin_ws
Source space: /home/kyle/catkin_ws/src
Build space: /home/kyle/catkin_ws/build
Devel space: /home/kyle/catkin_ws/devel
Install space: /home/kyle/catkin_ws/install
Creating symlink "/home/kyle/catkin_ws/src/CMakeLists.txt" pointing to "/opt/ros/melodic/share/catkin/cmake/toplevel.cmake"
####
#### Running command: "cmake /home/kyle/catkin_ws/src -DCATKIN_DEVEL_PREFIX=/home/kyle/catkin_ws/devel -DCMAKE_INSTALL_PREFIX=/home/kyle/catkin_ws/install -G Unix Makefiles" in "/home/kyle/catkin_ws/build"
####
-- The C compiler identification is GNU 7.5.0
-- The CXX compiler identification is GNU 7.5.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Using CATKIN_DEVEL_PREFIX: /home/kyle/catkin_ws/devel
-- Using CMAKE_PREFIX_PATH: /opt/ros/melodic
-- This workspace overlays: /opt/ros/melodic
-- Found PythonInterp: /usr/bin/python2 (found suitable version "2.7.17", minimum required is "2")
-- Using PYTHON_EXECUTABLE: /usr/bin/python2
-- Using Debian Python package layout
-- Using empy: /usr/bin/empy
-- Using CATKIN_ENABLE_TESTING: ON
-- Call enable_testing()
-- Using CATKIN_TEST_RESULTS_DIR: /home/kyle/catkin_ws/build/test_results
-- Found gtest sources under '/usr/src/googletest': gtests will be built
-- Found gmock sources under '/usr/src/googletest': gmock will be built
-- Found PythonInterp: /usr/bin/python2 (found version "2.7.17")
-- Looking for pthread.h
-- Looking for pthread.h - found
-- Looking for pthread_create
-- Looking for pthread_create - not found
-- Looking for pthread_create in pthreads
-- Looking for pthread_create in pthreads - not found
-- Looking for pthread_create in pthread
-- Looking for pthread_create in pthread - found
-- Found Threads: TRUE
-- Using Python nosetests: /usr/bin/nosetests-2.7
-- catkin 0.7.29
-- BUILD_SHARED_LIBS is on
-- BUILD_SHARED_LIBS is on
-- Configuring done
-- Generating done
-- Build files have been written to: /home/kyle/catkin_ws/build
####
#### Running command: "make -j4 -l4" in "/home/kyle/catkin_ws/build"
####
将工作区的devel/setup.bash
添加到.bashrc
,
追加一行
注: 这里的kyle
改成你自己的用户名。
5.C++功能包¶
5.1.安装依赖¶
需要在Ubuntu上安装总线伺服舵机 C++ SDK,参见教程:总线伺服舵机SDK使用手册(C++)
- cserialport # 轻量级串口通信库
- fsuartservo # FashionStar总线伺服舵机SDK (C++)
5.2.创建包¶
官方文档参考:ROS Wiki - Creating a ROS Package
进入文件夹
创建包
5.3.创建Message¶
官方文档参考:ROS wiki - msg
创建文件夹
在fashionstar_uart_servo_ros1
工程内新建msg
文件夹,放置Message
创建Message文件
标准信息格式支持如下
- int8,int16,int32,int64
- float32,float64
- string
- 其他自定义msg:package/MessageName
- 不定长array[ ]以及定长array[N]
此处以setRawAngle API
为例,需要舵机id和目标角度两个参数,因此设置msg为:
SetServoAngle.msg
配置pakcage.xml
添加如下两行:
构建的时候生成message的依赖
运行的时候message依赖
配置CMakeLists.txt
配置find_package
## Find catkin macros and libraries
## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
## is used, also find other catkin packages
find_package(catkin REQUIRED COMPONENTS
roscpp
rospy
std_msgs
message_generation # Message生成依赖
)
注册.msg
文件
## Generate messages in the 'msg' folder
## 这里添加msg文件夹下的msg文件名称
add_message_files(
FILES
SetServoAngle.msg
)
添加生成message的时候需要的依赖
## Generate added messages and services with any dependencies listed here
generate_messages(
DEPENDENCIES
std_msgs
)
配置catkin, CATKIN_DEPENDS
里面添加message_runtime
###################################
## catkin specific configuration ##
###################################
## The catkin_package macro generates cmake config files for your package
## Declare things to be passed to dependent projects
## INCLUDE_DIRS: uncomment this if your 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 fashionstar_uart_servo_ros1
CATKIN_DEPENDS message_runtime roscpp rospy std_msgs
DEPENDS system_lib
)
构建Message
使用rosmsg查看创建的msg
指令格式
示例:
kyle@turing:~/catkin_ws$ rosmsg show SetServoAngle
[fashionstar_uart_servo_ros1/SetServoAngle]:
uint8 id
float32 angle
5.4.创建Service文件¶
创建文件夹
在fashionstar_uart_servo_ros1
工程内新建文件夹srv
创建Service文件
在srv
文件夹下创建query_servo_angle.srv
query_servo_angle.srv
Service
与Message
很相似,---
符号上方是传入参数,下方是回传的参数。
配置package.xml
与Message
配置方式一致。
配置CMakeLists.txt
注册service文件,
其他部分跟Message
的配置方式一致。
构建Service
5.5.C++节点-实际控制节点¶
在src
下创建uservo_demo_node.cpp
/*
* 舵机控制节点(Demo)
*/
// 导入ROS依赖
#include "ros/ros.h"
#include "fashionstar_uart_servo_ros1/SetServoAngle.h"
#include "fashionstar_uart_servo_ros1/SetServoDamping.h"
#include "fashionstar_uart_servo_ros1/QueryServoAngle.h"
#include "CSerialPort/SerialPort.h"
#include "FashionStar/UServo/FashionStar_UartServoProtocol.h"
#include "FashionStar/UServo/FashionStar_UartServo.h"
using namespace fsuservo;
using namespace fashionstar_uart_servo_ros1;
// 参数定义
#define SERVO_PORT_NAME "/dev/ttyUSB0" // Linux下端口号名称 /dev/ttyUSB{}
#define SERVO_ID 0 // 舵机ID号
// 创建协议对象
FSUS_Protocol protocol(SERVO_PORT_NAME, FSUS_DEFAULT_BAUDRATE);
// 创建一个舵机对象
FSUS_Servo servo0(SERVO_ID, &protocol);
/* 舵机角度设置回调函数 */
void set_servo_angle_callback(const SetServoAngle& data){
ROS_INFO("[RECV] Servo ID = %d Set Angle = %.1f", data.id, data.angle);
// 设置舵机角度
servo0.setRawAngle(data.angle, 0);
}
/* 舵机阻尼模式回调函数 */
void set_servo_damping_callback(const SetServoDamping& data){
ROS_INFO("[RECV] Servo ID = %d, Set Damping Power = %d", data.id, data.power);
servo0.setDamping(data.power);
}
/* 舵机角度查询 */
bool query_servo_angle_callback(QueryServoAngle::Request& req, QueryServoAngle::Response& res){
float angle;
// 通过SDK查询舵机角度
angle = servo0.queryRawAngle();
// 填写返回数据包
res.angle = angle;
// 打印日志
ROS_INFO("[RECV] Servo ID = %d , Query Servo Angle = %.1f", req.id, angle);
// 注: C++版本的 服务回调函数,最后一定要返回一个bool值
return true;
}
int main(int argc, char **argv)
{
// 创建节点名称
ros::init(argc, argv, "uservo_demo_node");
// 创建NodeHandle
ros::NodeHandle node_handle;
// 创建接收者
ros::Subscriber set_servo_angle_sub = node_handle.subscribe("set_servo_angle", 2, set_servo_angle_callback);
ros::Subscriber set_servo_damping_sub = node_handle.subscribe("set_servo_damping", 2, set_servo_damping_callback);
// 创建服务
ros::ServiceServer query_servo_angle_srv = node_handle.advertiseService("query_servo_angle", query_servo_angle_callback);
// 进入循环等待
ros::spin();
}
5.6.C++节点-Message发送者¶
以使用简易角度控制API,控制舵机在-90°~90°之间来回运动为例。
在src
下创建test_set_angle_node.cpp
/*
* 测试舵机角度控制节点
*/
#include "ros/ros.h"
// 自定义消息
#include "fashionstar_uart_servo_ros1/SetServoAngle.h"
using namespace fashionstar_uart_servo_ros1;
#define SERVO_ID 0 // 舵机ID号
int main(int argc, char **argv)
{
// 创建节点名称
ros::init(argc, argv, "test_set_angle_node");
// 创建NodeHandle
ros::NodeHandle node_handle;
// 创建发布者
ros::Publisher set_servo_angle_pub = node_handle.advertise<SetServoAngle>("set_servo_angle", 2);
// 循环频率0.2HZ
ros::Rate loop_rate(0.2);
// 创建Message
SetServoAngle msg;
float angle = 90.0;
while(ros::ok()){
// 修改目标角度
angle *= -1.0;
// 构建Message
msg.id = SERVO_ID;
msg.angle = angle;
// 发布消息
set_servo_angle_pub.publish(msg);
// 输出日志
ROS_INFO("Set Servo %d Angle = %.1f", msg.id, msg.angle);
// 延时等待
loop_rate.sleep();
}
}
5.7.C++节点-Service客户端¶
以使用当前角度查询API,查询角度为例。
src/test_query_angle_node.cpp
/*
* 测试舵机角度查询节点
*/
#include "ros/ros.h"
// 自定义消息
#include "fashionstar_uart_servo_ros1/SetServoDamping.h"
// 自定义服务
#include "fashionstar_uart_servo_ros1/QueryServoAngle.h"
using namespace fashionstar_uart_servo_ros1;
#define SERVO_ID 0 // 舵机ID号
int main(int argc, char **argv)
{
// 创建节点名称
ros::init(argc, argv, "test_query_angle_node");
// 创建NodeHandle
ros::NodeHandle node_handle;
// 创建发布者
ros::Publisher set_servo_damping_pub = node_handle.advertise<SetServoDamping>("set_servo_damping", 2);
// 创建阻尼模式Message
SetServoDamping damping_msg;
// 角度查询服务客户端
ros::ServiceClient query_angle_client = node_handle.serviceClient<QueryServoAngle>("query_servo_angle");
// 创建服务对象
QueryServoAngle query_angle_srv;
// 等待角度查询服务开启
query_angle_client.waitForExistence();
// 设置舵机为阻尼模式
damping_msg.id = SERVO_ID;
damping_msg.power = 400;
set_servo_damping_pub.publish(damping_msg);
// 循环频率1HZ
ros::Rate loop_rate(1);
float angle = 90.0;
while(ros::ok()){
// 构造服务请求头
query_angle_srv.request.id = SERVO_ID;
// 发送服务请求
if(query_angle_client.call(query_angle_srv)){
// 服务成功
ROS_INFO("[Send]Query Servo %d Angle %.1f", SERVO_ID, query_angle_srv.response.angle);
}else{
// 发送失败
ROS_INFO("[Send]Query Servo %d Angle Failed", SERVO_ID);
}
// 延时等待
loop_rate.sleep();
}
}
5.8.配置CMakeLists.txt
¶
配置CMakeLists.txt
添加include
路径,这样才可以找到依赖库的.h
文件所在的路径
set(CMAKE_INSTALL_PREFIX /usr/local)
include_directories(
# include
${catkin_INCLUDE_DIRS}
${CMAKE_INSTALL_PREFIX}/include
)
设置link
文件夹, 动态链接库所在的位置
添加可执行程序
## Declare a C++ executable
## With catkin_make all packages are built within a single CMake context
## The recommended prefix ensures that target names across packages don't collide
## 定义C++可执行文件
# - 总线伺服舵机服务示例节点
add_executable(uservo_demo_node src/uservo_demo_node.cpp)
add_executable(test_set_angle_node src/test_set_angle_node.cpp)
add_executable(test_query_angle_node src/test_query_angle_node.cpp)
动态链接
## Specify libraries to link a library or executable target against
target_link_libraries(uservo_demo_node
${catkin_LIBRARIES}
cserialport # 轻量级串口通信库
fsuartservo # FashionStar总线伺服舵机SDK (C++)
)
target_link_libraries(test_set_angle_node
${catkin_LIBRARIES}
)
修改完成的CMakeLists.txt
cmake_minimum_required(VERSION 3.0.2)
project(fashionstar_uart_servo_ros1)
## Compile as C++11, supported in ROS Kinetic and newer
# add_compile_options(-std=c++11)
## Find catkin macros and libraries
## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
## is used, also find other catkin packages
find_package(catkin REQUIRED COMPONENTS
roscpp
rospy
std_msgs
message_generation # Message生成依赖
)
################################################
## Declare ROS messages, services and actions ##
################################################
## Generate messages in the 'msg' folder
## 这里添加msg文件夹下的msg文件名称
add_message_files(
FILES
SetServoAngle.msg # 设置舵机角度
SetServoDamping.msg # 设置舵机为阻尼模式
)
## Generate services in the 'srv' folder
add_service_files(
FILES
QueryServoAngle.srv # 舵机角度查询服务
)
## Generate added messages and services with any dependencies listed here
generate_messages(
DEPENDENCIES
std_msgs
)
###################################
## catkin specific configuration ##
###################################
catkin_package(
INCLUDE_DIRS include
LIBRARIES fashionstar_uart_servo_ros1
CATKIN_DEPENDS message_runtime roscpp rospy std_msgs
DEPENDS system_lib
)
###########
## Build ##
###########
## Specify additional locations of header files
## Your package locations should be listed before other locations
set(CMAKE_INSTALL_PREFIX /usr/local)
include_directories(
# include
${catkin_INCLUDE_DIRS}
${CMAKE_INSTALL_PREFIX}/include
)
# 设置总线伺服舵机链接库的位置
link_directories(
${CMAKE_INSTALL_PREFIX}/lib
)
## Declare a C++ executable
## With catkin_make all packages are built within a single CMake context
## The recommended prefix ensures that target names across packages don't collide
## 定义C++可执行文件
# - 总线伺服舵机服务示例节点
add_executable(uservo_demo_node src/uservo_demo_node.cpp)
add_executable(test_set_angle_node src/test_set_angle_node.cpp)
add_executable(test_query_angle_node src/test_query_angle_node.cpp)
## Specify libraries to link a library or executable target against
target_link_libraries(uservo_demo_node
${catkin_LIBRARIES}
cserialport # 轻量级串口通信库
fsuartservo # FashionStar总线伺服舵机SDK (C++)
)
target_link_libraries(test_set_angle_node
${catkin_LIBRARIES}
)
target_link_libraries(test_query_angle_node
${catkin_LIBRARIES}
)
5.9.运行例程¶
运行Master节点
运行实际控制节点
运行舵机角度控制节点(Message发送者)
运行当前角度查询节点(运行Service客户端节点)
6.Python功能包¶
6.1.创建包¶
官方文档参考:ROS Wiki - Creating a ROS Package
进入文件夹
创建包
6.2.创建Message¶
官方文档参考: ROS wiki - msg
创建文件夹
在fashionstar_uart_servo_ros1
工程内新建msg
文件夹,放置Message
创建Message文件
标准信息格式支持如下
- int8,int16,int32,int64
- float32,float64
- string
- 其他自定义msg:package/MessageName
- 不定长array[ ]以及定长array[N]
此处以set_servo_angle API
为例,需要舵机id和目标角度两个参数,因此设置msg为:
SetServoAngle.msg
配置pakcage.xml
添加如下两行:
构建的时候生成message的依赖,
运行的时候message依赖,
配置CMakeLists.txt
配置find_package
## Find catkin macros and libraries
## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
## is used, also find other catkin packages
find_package(catkin REQUIRED COMPONENTS
roscpp
rospy
std_msgs
message_generation # Message生成依赖
)
注册.msg
文件
## Generate messages in the 'msg' folder
## 这里添加msg文件夹下的msg文件名称
add_message_files(
FILES
SetServoAngle.msg
)
添加生成message的时候需要的依赖
## Generate added messages and services with any dependencies listed here
generate_messages(
DEPENDENCIES
std_msgs
)
配置catkin,CATKIN_DEPENDS
里面添加message_runtime
###################################
## catkin specific configuration ##
###################################
## The catkin_package macro generates cmake config files for your package
## Declare things to be passed to dependent projects
## INCLUDE_DIRS: uncomment this if your 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 fashionstar_uart_servo_ros1
CATKIN_DEPENDS message_runtime roscpp rospy std_msgs
DEPENDS system_lib
)
构建Message
使用rosmsg查看创建的msg
指令格式
示例:
kyle@turing:~/catkin_ws$ rosmsg show SetServoAngle
[fashionstar_uart_servo_ros1/SetServoAngle]:
uint8 id
float32 angle
6.3.创建Service文件¶
创建文件夹
在fashionstar_uart_servo_ros1
工程内创建文件夹srv
创建Service文件
在srv
文件夹下创建QueryServoAngle.srv
QueryServoAngle.srv
Service
与Message
很相似,---
符号上方是传入参数,下方是回传的参数
配置package.xml
添加如下两行:
配置CMakeLists.txt
注册service文件,
其他部分跟Message
的配置方式一致。
构建Service
Python节点-服务提供者
新添加一个设置舵机为阻尼模式的Message,具体设置参考**创建message**
SetServoDamping.msg
服务提供者的完整源码如下,
uservo_demo_node.py
#!/usr/bin/env python
#coding:utf-8
'''
舵机控制节点(Demo)
'''
import rospy
import serial
from uservo import UartServoManager
from fashionstar_uart_servo_ros1.msg import SetServoAngle, SetServoDamping
from fashionstar_uart_servo_ros1.srv import QueryServoAngle, QueryServoAngleResponse
# 参数配置
# 角度定义
SERVO_PORT_NAME = u'/dev/ttyUSB0' # 舵机串口号 <<< 修改为实际串口号
SERVO_BAUDRATE = 115200 # 舵机的波特率
SERVO_ID = 0 # 舵机的ID号
SERVO_HAS_MTURN_FUNC = False # 舵机是否拥有多圈模式
# 初始化串口
uart = serial.Serial(port=SERVO_PORT_NAME, baudrate=SERVO_BAUDRATE,\
parity=serial.PARITY_NONE, stopbits=1,\
bytesize=8,timeout=0)
# 初始化舵机管理器
uservo = UartServoManager(uart)
def set_servo_angle_callback(data):
'''回调函数-设置舵机角度'''
rospy.loginfo("[Recv] Servo ID ={} Set Angle={}".format(data.id, data.angle))
# 调用舵机SDK - 设置舵机的角度
uservo.set_servo_angle(data.id, data.angle, interval=0)
def set_servo_damping_callback(data):
'''回调函数-设置舵机为阻尼模式'''
rospy.loginfo("[Recv] Servo ID ={} Set Damping Power={}".format(data.id, data.power))
# 调用舵机SDK - 设置舵机为阻尼模式
uservo.set_damping(data.id, data.power)
def query_servo_angle_callback(req):
'''回调函数-查询舵机角度'''
# 创建回传对象
response = QueryServoAngleResponse()
# 查询舵机的角度
angle = uservo.query_servo_angle(req.id)
# 填充回传对象的内容
response.angle = angle
rospy.loginfo("[Recv] Servo ID ={} Query Angle={}".format(req.id, angle))
return response
def uart_manager():
# 初始化节点
rospy.init_node('uservo_node', anonymous=True)
# 舵机角度设置订阅者
rospy.Subscriber("set_servo_angle", SetServoAngle, set_servo_angle_callback)
# 舵机阻尼模式订阅者
rospy.Subscriber("set_servo_damping", SetServoDamping, set_servo_damping_callback)
# 舵机角度查询服务
rospy.Service('query_servo_angle', QueryServoAngle, query_servo_angle_callback)
# 持续等待, 直到节点结束
rospy.spin()
if __name__ == '__main__':
uart_manager()
6.4.Python节点-实际控制节点¶
fashionstar_uart_servo_ros1
工程文件里面,创建Python脚本的文件夹scripts
将Python2版本的uservo.py
拷贝到scripts
文件夹里面
并创建一个串口总线舵机的Python节点 uservo_demo_node.py
赋予其执行权限
uservo_demo_node.py
#!/usr/bin/env python
#coding:utf-8
'''
舵机控制节点(Demo)
'''
import rospy
import serial
from uservo import UartServoManager
from fashionstar_uart_servo_ros1.msg import SetServoAngle, SetServoDamping
from fashionstar_uart_servo_ros1.srv import QueryServoAngle, QueryServoAngleResponse
# 参数配置
# 角度定义
SERVO_PORT_NAME = u'/dev/ttyUSB0' # 舵机串口号 <<< 修改为实际串口号
SERVO_BAUDRATE = 115200 # 舵机的波特率
SERVO_ID = 0 # 舵机的ID号
SERVO_HAS_MTURN_FUNC = False # 舵机是否拥有多圈模式
# 初始化串口
uart = serial.Serial(port=SERVO_PORT_NAME, baudrate=SERVO_BAUDRATE,\
parity=serial.PARITY_NONE, stopbits=1,\
bytesize=8,timeout=0)
# 初始化舵机管理器
uservo = UartServoManager(uart)
def set_servo_angle_callback(data):
'''回调函数-设置舵机角度'''
rospy.loginfo("[Recv] Servo ID ={} Set Angle={}".format(data.id, data.angle))
# 调用舵机SDK - 设置舵机的角度
uservo.set_servo_angle(data.id, data.angle, interval=0)
def set_servo_damping_callback(data):
'''回调函数-设置舵机为阻尼模式'''
rospy.loginfo("[Recv] Servo ID ={} Set Damping Power={}".format(data.id, data.power))
# 调用舵机SDK - 设置舵机为阻尼模式
uservo.set_damping(data.id, data.power)
def query_servo_angle_callback(req):
'''回调函数-查询舵机角度'''
# 创建回传对象
response = QueryServoAngleResponse()
# 查询舵机的角度
angle = uservo.query_servo_angle(req.id)
# 填充回传对象的内容
response.angle = angle
rospy.loginfo("[Recv] Servo ID ={} Query Angle={}".format(req.id, angle))
return response
def uart_manager():
# 初始化节点
rospy.init_node('uservo_node', anonymous=True)
# 舵机角度设置订阅者
rospy.Subscriber("set_servo_angle", SetServoAngle, set_servo_angle_callback)
# 舵机阻尼模式订阅者
rospy.Subscriber("set_servo_damping", SetServoDamping, set_servo_damping_callback)
# 舵机角度查询服务
rospy.Service('query_servo_angle', QueryServoAngle, query_servo_angle_callback)
# 持续等待, 直到节点结束
rospy.spin()
if __name__ == '__main__':
uart_manager()
注意: 文件头必须有如下声明
否则运行的时候会遇到报错
kyle@turing:~/catkin_ws$ rosrun fashionstar_uart_servo_ros1 uservo_demo_node.py
import-im6.q16: not authorized `rospy' @ error/constitute.c/WriteImage/1037.
from: can't read /var/mail/fashionstar_uart_servo_ros1.msg
/home/kyle/catkin_ws/src/fashionstar_uart_servo_ros1/scripts/uservo_node.py: line 6: syntax error near unexpected token `('
/home/kyle/catkin_ws/src/fashionstar_uart_servo_ros1/scripts/uservo_node.py: line 6: `def set_servo_angle_callback(data):'
6.5.Python节点-Message发送者¶
创建另外一个文件test_set_angle_node.py
并赋予其可执行权限
test_set_angle_node.py
#!/usr/bin/env python
#coding:utf-8
'''
电机角度控制测试节点
'''
import rospy
from fashionstar_uart_servo_ros1.msg import SetServoAngle
SERVO_ID = 0 # 测试的电机ID
def test_set_servo_angle():
'''回调函数'''
# 创建节点
rospy.init_node('test_set_angle_node', anonymous=True)
# 创建发布者
# - Topic名称为: 'set_servo_angle'
# - Message格式类型: set_servo_angle
# - queue_size 消息队列尺寸,自定义
pub = rospy.Publisher('set_servo_angle', SetServoAngle, queue_size=2)
# 设置发送节拍 0.2HZ
rate = rospy.Rate(0.2)
# 电机角度
angle = 90.0
# 创建信息对象
msg = SetServoAngle()
while not rospy.is_shutdown():
# 修改电机角度
angle *= -1.0
# 填充Message
msg.id = SERVO_ID
msg.angle = angle
rospy.loginfo('Set Servo {} = {}'.format(msg.id, msg.angle))
pub.publish(msg)
rate.sleep()
if __name__ == '__main__':
test_set_servo_angle()
6.6.Python节点-Service客户端¶
test_query_angle_node.py
#!/usr/bin/env python
#coding:utf-8
'''
电机角度查询节点
'''
import rospy
from fashionstar_uart_servo_ros1.msg import SetServoDamping
from fashionstar_uart_servo_ros1.srv import QueryServoAngle
SERVO_ID = 0 # 测试的电机ID
def test_query_servo_angle():
'''回调函数'''
# 创建节点
rospy.init_node('test_query_angle_node', anonymous=True)
# 等待角度查询服务开启
srv_query_servo_angle = rospy.ServiceProxy('query_servo_angle', QueryServoAngle)
# 创建发布者 - 舵机阻尼模式发布器
set_servo_damping_pub = rospy.Publisher('set_servo_damping', SetServoDamping, queue_size=1)
# 构造Damping控制指令
damping_msg = SetServoDamping()
damping_msg.id = SERVO_ID # 舵机ID
damping_msg.power = 400 # 功率
rospy.sleep(2)
set_servo_damping_pub.publish(damping_msg) # 设置为Damping模式
rospy.loginfo("Servo #{} Set Damping Mode, Power={} mW".format(SERVO_ID, damping_msg.power))
# 设置发送节拍 0.2HZ
rate = rospy.Rate(1)
while not rospy.is_shutdown():
# 设置舵机为阻尼模式
# 理论上来讲,发一次就可以了, 但是实际上因为message通信模式
# 不能保证发出的一定被接受到,所以保险还是多发几次
# set_servo_damping_pub.publish(damping_msg)
# 请求query_servo_angle的服务
try:
response = srv_query_servo_angle(SERVO_ID)
# 提取查询的角度
angle = response.angle
# 输出角度查询日志
rospy.loginfo("Servo #{} Angle={}".format(SERVO_ID, angle))
except rospy.ServiceException as e:
# 服务并不总是可以被处理,会存在一定概率的服务请求失败的问题
print("Service Call Failed : {}".format(e))
# 等待
rate.sleep()
if __name__ == '__main__':
test_query_servo_angle()
6.7.运行例程¶
运行Master节点
运行实际控制节点
运行舵机角度控制节点(Message发送者)
运行当前角度查询节点(运行Service客户端节点)
注:若提示/dev/ttyUSB0 permission denied,请运行以下指令:
6.8.控制舵机¶
修改uservo_demo_node.py
文件,导入FashionStar 舵机Python3的SDK,驱动舵机转动起来。
可以根据自己的需求定制角度控制的具体的参数,例如指定时间/功率/转速等等。
具体的API请参阅总线伺服舵机SDK使用手册(Python )。
#!/usr/bin/env python
#coding:utf-8
'''
舵机控制节点
'''
import rospy
import serial
from uservo import UartServoManager
from fashionstar_uart_servo_ros1.msg import SetServoAngle
# 参数配置
# 角度定义
SERVO_PORT_NAME = u'/dev/ttyUSB0' # 舵机串口号 <<< 修改为实际串口号
SERVO_BAUDRATE = 115200 # 舵机的波特率
SERVO_ID = 0 # 舵机的ID号
SERVO_HAS_MTURN_FUNC = False # 舵机是否拥有多圈模式
# 初始化串口
uart = serial.Serial(port=SERVO_PORT_NAME, baudrate=SERVO_BAUDRATE,\
parity=serial.PARITY_NONE, stopbits=1,\
bytesize=8,timeout=0)
# 初始化舵机管理器
uservo = UartServoManager(uart)
def set_servo_angle_callback(data):
'''回调函数-设置舵机角度'''
rospy.loginfo("[Recv] Servo ID ={} Set Angle={}".format(data.id, data.angle))
uservo.set_servo_angle(data.id, data.angle, interval=0)
def uart_manager():
# 初始化节点
rospy.init_node('uservo_node', anonymous=True)
# 舵机角度订阅者
rospy.Subscriber("set_servo_angle", SetServoAngle, set_servo_angle_callback)
# 持续等待, 直到节点结束
rospy.spin()
if __name__ == '__main__':
uart_manager()
7.API使用¶
7.1.描述¶
ROS功能包源码依语言分为两类,可以在Fashion Star Wiki页面获取到对应的SDK使用手册。
-
C++
-
Python
另外,根据通信协议中指令在默认情况下是否带舵机响应包,建议在设置命令节点时根据原始指令是否带响应包,使用不同的通信机制。
Message
:指令不带响应包,发送后无需等待响应数据,例如set_servo_angle
等控制指令。Service
:指令带响应包,发送后需要得到响应数据,例如Ping
、query_servo_angle
等指令。
判断API是否带响应包
查看总线伺服舵机通信协议中原始指令是否带响应包,其对应的API也即有无响应包。
7.2.例程结构¶
节点 | 描述 |
---|---|
实际控制节点 | 控制硬件串口收发的节点,根据其他节点的Message或者Service请求进行动作 |
Message发送者节点 | 用户根据使用条件,编写的Message发送者节点,使用Message间接控制舵机 |
Service客户端节点 | 用户根据使用条件,编写的Service客户端节点,使用Service间接控制舵机 |
7.3.举例¶
因ROS环境下使用舵机基于 C++_SDK
或 Python_SDK
,本SDK使用手册仅举例说明API的使用,关于API的更多信息,可以参考对应SDK使用手册。
setRawAngle
1.根据总线伺服舵机通信协议,在原始指令中,设置舵机角度的响应包默认不开启,因此舵机不会在收到请求包后反馈响应包,使用Message即可。
2.根据C++_SDK
中函数原型如下,编程时使用该接口。
3.在实际控制节点中,设置回调函数,其他部分,只需对照例程配置即可。