做一个网页控制ROS2机器人导航并且查看相机图像
rosbridge_server
是 ROS (Robot Operating System) 的一个组件,它提供了一个基于 WebSocket 的接口,使得各种非 ROS 客户端(例如浏览器、移动设备、远程服务器等)可以方便地与 ROS 进行通信。它的核心功能是桥接 ROS 和其他应用程序之间的通信,使得开发者可以使用不同的编程语言和平台与 ROS 进行交互。
主要功能
-
WebSocket 接口:
rosbridge_server
提供了一个 WebSocket 接口,通过该接口,客户端可以发送和接收 ROS 消息。WebSocket 是一种双向通信协议,适合实时应用。 -
跨语言支持: 通过
rosbridge_server
,可以使用 JavaScript、Python、Java 等多种编程语言与 ROS 通信。常见的用法是通过网页(使用 JavaScript 和 HTML)与 ROS 进行交互。 -
服务调用: 客户端可以通过
rosbridge_server
调用 ROS 服务,并接收服务的响应。 -
参数服务器:
rosbridge_server
允许客户端获取和设置 ROS 参数服务器中的参数。
安装
sudo apt install ros-$ROS_DISTRO-rosbridge-suite
创建Web
在工作空间下的src下面创建 index.html,并添加下面内容
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<style>
body {
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-start;
height: 100vh;
font-family: Arial, sans-serif;
background: url('1.jpg') no-repeat center center fixed;
background-size: cover;
overflow-y: auto;
}
h1 {
color: #fff;
text-shadow: 2px 2px 4px #000;
margin-bottom: 70px;
font-size: 2.8em;
}
.tab-container {
display: flex;
justify-content: center;
margin-bottom: 30px;
}
.tab-button {
padding: 20px 40px;
margin: 0 15px;
cursor: pointer;
background-color: #3498db;
color: white;
border: none;
border-radius: 5px;
font-size: 1.5em;
}
.tab-button.active {
background-color: #2980b9;
}
.tab-content {
display: none;
width: 100%;
max-width: 1200px;
}
.tab-content.active {
display: flex;
flex-direction: column;
align-items: center;
}
.joystick-container {
position: relative;
width: 300px;
height: 300px;
border: 2px solid #3498db;
border-radius: 50%;
background-color: rgba(255, 255, 255, 0.8);
margin-top: 20px;
}
.joystick {
position: absolute;
width: 75px;
height: 75px;
background-color: #3498db;
border-radius: 50%;
top: 112.5px;
left: 112.5px;
touch-action: none;
}
.status {
margin-top: 20px;
padding: 15px;
background-color: rgba(255, 255, 255, 0.8);
border-radius: 5px;
font-size: 1.2em;
}
.topic-selector {
margin-top: 20px;
padding: 15px;
background-color: rgba(255, 255, 255, 0.8);
border-radius: 5px;
font-size: 1.2em;
}
select {
padding: 15px;
font-size: 1.2em;
}
.speed-slider-container {
display: flex;
justify-content: center;
align-items: center;
margin-top: 20px;
gap: 20px;
}
.speed-slider {
height: 200px;
-webkit-appearance: slider-vertical;
}
.speed-label {
font-size: 1.2em;
color: #fff;
text-shadow: 2px 2px 4px #000;
text-align: center;
margin-top: 10px;
}
canvas {
margin-top: 20px;
border: 2px solid #3498db;
border-radius: 10px;
width: 800px;
height: 600px;
}
.container {
display: flex;
justify-content: center;
align-items: center;
margin-top: 20px;
}
.goal-inputs {
display: flex;
flex-direction: column;
align-items: center;
margin-top: 20px;
}
.goal-inputs input {
padding: 15px;
margin: 10px;
font-size: 1.5em;
}
.data-display-container {
display: flex;
justify-content: center;
margin-top: 20px;
width: 100%;
}
.data-display {
padding: 20px;
background-color: rgba(255, 255, 255, 0.9);
border-radius: 8px;
width: 100%;
max-width: 1200px;
height: 400px;
font-size: 1.5em;
line-height: 1.6;
overflow-y: auto;
color: #333;
margin: 0 auto;
}
.chart-container {
margin-top: 20px;
padding: 20px;
background-color: rgba(255, 255, 255, 0.9);
border-radius: 8px;
width: 100%;
max-width: 1200px;
height: 400px;
font-size: 1.5em;
line-height: 1.6;
overflow-y: auto;
color: #333;
margin: 0 auto;
display: none;
}
.chart-container.active {
display: block;
}
</style>
<script src="https://cdn.jsdelivr.net/npm/roslib@1.3.0/build/roslib.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
</head>
<body>
<h1>“田野间的守望者”—基于ROS的农业监测机器人</h1>
<div class="tab-container">
<button class="tab-button active" onclick="openTab('controlTab')">控制面板</button>
<button class="tab-button" onclick="openTab('cameraTab')">相机</button>
<button class="tab-button" onclick="openTab('mapTab')">地图</button>
<button class="tab-button" onclick="openTab('dataTab')">话题数据</button>
<button class="tab-button" onclick="openTab('armTab')">机械臂</button>
</div>
<div id="controlTab" class="tab-content active">
<div class="container">
<canvas id="controlCanvas" width="800" height="600"></canvas>
</div>
<div class="container">
<div class="joystick-container" id="joystick-container">
<div class="joystick" id="joystick"></div>
</div>
</div>
<div class="speed-slider-container">
<div>
<input type="range" min="0.1" max="1.0" value="0.5" step="0.1" class="speed-slider" id="linearSpeedSlider">
<div class="speed-label">线速度: <span id="linearSpeedValue">0.5</span></div>
</div>
<div>
<input type="range" min="0.1" max="1.0" value="0.5" step="0.1" class="speed-slider" id="angularSpeedSlider">
<div class="speed-label">角速度: <span id="angularSpeedValue">0.5</span></div>
</div>
</div>
<div class="status" id="status">
Status: Disconnected
</div>
</div>
<div id="cameraTab" class="tab-content">
<div class="topic-selector">