旭日X3派连接蓝牙与控制小海龟
非常感谢古月居平台推出的高校合作计划,我有幸能够使用旭日X3派进行学习和制作毕业设计。本周使用旭日X3派作为主控芯片,与手柄进行连接,通信,并控制小海龟进行运动。
硬件准备
XBOX one 手柄一个,旭日X3派 (ubuntu20.04 ros2 foxy)
旭日X3派蓝牙开启
开发板蓝牙功能默认没有开启,需要执行 /usr/bin/startbt6212.sh
脚本进行初始化,脚本执行成功后的log如下:
此时,通过ps
可看到蓝牙进程已经运行:
root@ubuntu:~# ps ax | grep "/usr/bin/dbus-daemon\|brcm_patchram_plus\|/usr/lib/bluetooth/bluetoothd"
2695 ? Ss 0:06 /usr/bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation --syslog-only
2963 ? Ss 0:00 /usr/bin/dbus-daemon --session --address=systemd: --nofork --nopidfile --systemd-activation --syslog-only
3241 ? Ss 0:00 /usr/lib/bluetooth/bluetoothd
5717 pts/0 S+ 0:00 grep --color=auto /usr/bin/dbus-daemon\|brcm_patchram_plus\|/usr/lib/bluetooth/bluetoothd
XBOX one 手柄驱动安装
首先需要安装手安装joy package包。 joy package为通用的Linux操纵杆提供了ROS驱动,它包括了一个joy_node节点,可以让Linux操纵杆和ROS交互.这个节点发布一个”Joy”消息,包含了操纵杆每一个按钮和轴的当前状态.
sudo apt install ros-foxy-joy
注意我的ubuntu为20.04版本,下载的ros 版本为 ros2 foxy版本。
此时需要下载XBOX 无线驱动
-
安装dkms
sudo apt-get install dkms
-
安装xboxdrv
sudo apt install xboxdrv
此时手柄驱动已安装完成。
蓝牙连接手柄
1、命令行连接步骤
- 执行
sudo bluetoothctl
进入交互模式下的蓝牙配置界面
sunrise@ubuntu:/dev/input$ sudo bluetoothctl
Agent registered
[bluetooth]#
- 使用show命令查看蓝牙信息
[bluetooth]# show
Controller 70:F7:54:CD:CB:90 (public)
Name: ubuntu
Alias: ubuntu
Class: 0x00000000
Powered: no
Discoverable: no
DiscoverableTimeout: 0x000000b4
Pairable: yes
UUID: A/V Remote Control (0000110e-0000-1000-8000-00805f9b34fb)
UUID: PnP Information (00001200-0000-1000-8000-00805f9b34fb)
UUID: Message Access Server (00001132-0000-1000-8000-00805f9b34fb)
UUID: Message Notification Se.. (00001133-0000-1000-8000-00805f9b34fb)
UUID: Phonebook Access Server (0000112f-0000-1000-8000-00805f9b34fb)
UUID: Generic Access Profile (00001800-0000-1000-8000-00805f9b34fb)
UUID: OBEX Object Push (00001105-0000-1000-8000-00805f9b34fb)
UUID: Generic Attribute Profile (00001801-0000-1000-8000-00805f9b34fb)
UUID: OBEX File Transfer (00001106-0000-1000-8000-00805f9b34fb)
UUID: Vendor specific (00005005-0000-1000-8000-0002ee000001)
UUID: A/V Remote Control Target (0000110c-0000-1000-8000-00805f9b34fb)
UUID: IrMC Sync (00001104-0000-1000-8000-00805f9b34fb)
Modalias: usb:v1D6Bp0246d0535
Discovering: no
Advertising Features:
ActiveInstances: 0x00
SupportedInstances: 0x05
SupportedIncludes: tx-power
SupportedIncludes: appearance
SupportedIncludes: local-name
[bluetooth]#
-
使用power on 开启蓝牙,
[bluetooth]# power on Changing power on succeeded
-
执行
discoverable on
使得蓝牙可被发现属性[bluetooth]# discoverable on Changing discoverable on succeeded
蓝牙名称为ubuntu
-
输入
scan on
打开自动扫描再次使用关闭扫描
-
蓝牙设备配对
- 配对命令:
pair [targetMAC]
,输入该命令后,根据提示输入yes
,并在对端蓝牙设备选择配对
选项完成配对 - 配对成功后,可以使用
trust [targetMAC]
将设备加入配对列表,下次使用时自动链接
- 配对命令:
-
手柄中间X圆键长亮,即为连接成功。
2、桌面连接
使用VNC进行远程控制X3派,找到Bluetooth Devices,打开,找到Xbox wireless Controller右键点击连接即可。
测试和校准手柄
jstest-gtk是一个可以测试手柄的工具,可以显示哪个按钮和轴被按下,可以校准和重新为手柄设置每个按钮的索引
-
安装jstest-gtk
sudo apt install jsest-gtk
-
在终端输入以下命令,打开jstest-gtk的GUI:
找到Xbox wireless Controller,点击Properties,如果没有,点击刷新,进入的界面如下:
使用手柄控制小海龟
首先创建功能包
代码如下
#include "p9n_node/teleop_twist_joy_node.hpp"
namespace p9n_node
{
TeleopTwistJoyNode::TeleopTwistJoyNode(const rclcpp::NodeOptions & options)
: rclcpp::Node("teleop_twist_joy_node", options)
{
const std::string hw_name = this->declare_parameter<std::string>(
"hw_type", p9n_interface::HW_NAME::DUALSENSE);
this->linear_max_speed_ =
this->declare_parameter<double>("linear_speed", 0.2);
this->angular_max_speed_ =
this->declare_parameter<double>("angular_speed", 0.6);
try {
this->hw_type_ = p9n_interface::getHwType(hw_name);
} catch (std::runtime_error & e) {
RCLCPP_ERROR(this->get_logger(), e.what());
RCLCPP_ERROR(
this->get_logger(), "Please select hardware from %s",
p9n_interface::getAllHwName().c_str());
exit(EXIT_FAILURE);
return;
}
this->p9n_if_ =
std::make_unique<p9n_interface::PlayStationInterface>(this->hw_type_);
using namespace std::placeholders; // NOLINT
this->joy_sub_ = this->create_subscription<Joy>(
"joy", rclcpp::SensorDataQoS().keep_last(1),
std::bind(&TeleopTwistJoyNode::onJoy, this, _1));
this->twist_pub_ = this->create_publisher<Twist>(
"cmd_vel", rclcpp::QoS(10).reliable().durability_volatile());
using namespace std::chrono_literals; // NOLINT
this->timer_watchdog_ = this->create_wall_timer(
1s, std::bind(&TeleopTwistJoyNode::onWatchdog, this));
if (this->joy_sub_->get_publisher_count() == 0) {
RCLCPP_WARN(this->get_logger(), "Joy node not launched");
}
}
void TeleopTwistJoyNode::onJoy(Joy::ConstSharedPtr joy_msg)
{
this->timer_watchdog_->reset();
this->p9n_if_->setJoyMsg(joy_msg);
static bool stopped = true;
if (this->p9n_if_->isTiltedStickL()) {
auto twist_msg = std::make_unique<Twist>();
twist_msg->linear.set__x(this->linear_max_speed_ * this->p9n_if_->tiltedStickLY());
twist_msg->angular.set__z(this->angular_max_speed_ * this->p9n_if_->tiltedStickLX());
this->twist_pub_->publish(std::move(twist_msg));
stopped = false;
} else if (!stopped) {
// Stop cart
auto twist_msg = std::make_unique<Twist>(rosidl_runtime_cpp::MessageInitialization::ZERO);
this->twist_pub_->publish(std::move(twist_msg));
stopped = true;
}
}
void TeleopTwistJoyNode::onWatchdog()
{
RCLCPP_WARN(this->get_logger(), "Couldn't subscribe joy topic before timeout");
// Publish zero velocity to stop vehicle
auto twist_msg = std::make_unique<Twist>(rosidl_runtime_cpp::MessageInitialization::ZERO);
this->twist_pub_->publish(std::move(twist_msg));
this->timer_watchdog_->cancel();
}
} // namespace p9n_node
配置cmakelists.txt
cmake_minimum_required(VERSION 3.8)
project(p9n_node)
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
add_compile_options(-Wall -Wextra -Wpedantic)
endif()
find_package(ament_cmake_auto REQUIRED)
ament_auto_find_build_dependencies()
# Display Node ======================================================
set(TARGET teleop_twist_joy_node)
set(MY_LIB_NAME ${PROJECT_NAME}_${TARGET})
ament_auto_add_library(${MY_LIB_NAME} SHARED src/${TARGET}.cpp)
rclcpp_components_register_node(
${MY_LIB_NAME}
PLUGIN "${PROJECT_NAME}::TeleopTwistJoyNode"
EXECUTABLE ${TARGET}_exec)
# Testing ===========================================================
if(BUILD_TESTING)
find_package(ament_lint_auto REQUIRED)
set(ament_cmake_copyright_FOUND TRUE)
set(ament_cmake_cpplint_FOUND TRUE)
ament_lint_auto_find_test_dependencies()
endif()
ament_auto_package()
创建launch组合功能包
from launch import LaunchDescription
from launch.actions import DeclareLaunchArgument
from launch.substitutions import LaunchConfiguration
from launch.substitutions import TextSubstitution
from launch_ros.actions import ComposableNodeContainer, Node
from launch_ros.descriptions import ComposableNode
def generate_launch_description():
"""Generate launch description."""
hw_type_arg = DeclareLaunchArgument(
'hw_type', default_value=TextSubstitution(text='DualSense'))
topic_name_arg = DeclareLaunchArgument(
'topic_name', default_value=TextSubstitution(text='/turtle1/cmd_vel'))
joy_container = ComposableNodeContainer(
name='joy_container',
package='rclcpp_components',
executable='component_container',
namespace='',
composable_node_descriptions=[
ComposableNode(
package='joy',
plugin='joy::Joy',
name='joy',
namespace='',
),
ComposableNode(
package='p9n_node',
plugin='p9n_node::TeleopTwistJoyNode',
name='teleop_twist_joy_node',
namespace='',
parameters=[{
'hw_type': LaunchConfiguration('hw_type')
}],
remappings=[
('cmd_vel', LaunchConfiguration('topic_name'))
],
)
],
)
turtlesim = Node(
name='turtlesim',
package='turtlesim',
executable='turtlesim_node'
)
ld = LaunchDescription()
ld.add_action(hw_type_arg)
ld.add_action(topic_name_arg)
ld.add_action(joy_container)
ld.add_action(turtlesim)
return ld
配置setup.py
"""Setup."""
from glob import glob
from setuptools import setup
package_name = 'p9n_bringup'
setup(
name=package_name,
version='1.1.0',
packages=[package_name],
data_files=[
('share/ament_index/resource_index/packages',
['resource/' + package_name]),
('share/' + package_name, ['package.xml']),
('share/{}/launch'.format(package_name), glob('launch/*.launch.py')),
],
install_requires=['setuptools'],
zip_safe=True,
maintainer='m12watanabe1a',
maintainer_email='40206149+m12watanabe1a@users.noreply.github.com',
description='PlayStation Interface Node Launch Files.',
license='Apache License 2.0',
tests_require=['pytest'],
entry_points={
'console_scripts': [
],
},
)
运行如下命令:
-
创建工作空间
mkdir joy_test cd joy_test
-
复制程序
git clone https://gitee.com/xiaogujiayou/ros2_joy.git
-
编译
colcon build
-
添加环境变量
source install/setup.sh
-
运行程序
ros2 launch p9n_bringup teleop_turtlesim.launch.py
即可看到现象,如下:
评论(0)
您还未登录,请登录后发表或查看评论