BIG CHANGE: Re-organise structure. Changes to README

This commit is contained in:
GLEN TURNER (8GT6)
2015-05-29 16:21:09 -04:00
parent 8e5623bba9
commit d2313db98a
17 changed files with 2877 additions and 128 deletions

161
CMakeLists.txt Normal file
View File

@@ -0,0 +1,161 @@
cmake_minimum_required(VERSION 2.8.3)
project(rosbridge_GUI_example)
## 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
pcl_ros
)
## System dependencies are found with CMake's conventions
# find_package(Boost REQUIRED COMPONENTS system)
## Uncomment this if the package has a setup.py. This macro ensures
## modules and global scripts declared therein get installed
## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html
# catkin_python_setup()
################################################
## Declare ROS messages, services and actions ##
################################################
## To declare and build messages, services or actions from within this
## package, follow these steps:
## * Let MSG_DEP_SET be the set of packages whose message types you use in
## your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...).
## * In the file package.xml:
## * add a build_depend and a run_depend tag for each package in MSG_DEP_SET
## * If MSG_DEP_SET isn't empty the following dependencies might have been
## pulled in transitively but can be declared for certainty nonetheless:
## * add a build_depend tag for "message_generation"
## * add a run_depend tag for "message_runtime"
## * In this file (CMakeLists.txt):
## * add "message_generation" and every package in MSG_DEP_SET to
## find_package(catkin REQUIRED COMPONENTS ...)
## * add "message_runtime" and every package in MSG_DEP_SET to
## catkin_package(CATKIN_DEPENDS ...)
## * uncomment the add_*_files sections below as needed
## and list every .msg/.srv/.action file to be processed
## * uncomment the generate_messages entry below
## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...)
## Generate messages in the 'msg' folder
# add_message_files(
# FILES
# Message1.msg
# Message2.msg
# )
## Generate services in the 'srv' folder
# add_service_files(
# FILES
# Service1.srv
# Service2.srv
# )
## Generate actions in the 'action' folder
# add_action_files(
# FILES
# Action1.action
# Action2.action
# )
## Generate added messages and services with any dependencies listed here
# generate_messages(
# DEPENDENCIES
# std_msgs
# )
###################################
## 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 you 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 rosbridge_GUI_example
# CATKIN_DEPENDS roscpp rospy std_msgs
# DEPENDS system_lib
)
###########
## Build ##
###########
## Specify additional locations of header files
## Your package locations should be listed before other locations
# include_directories(include)
include_directories(
${catkin_INCLUDE_DIRS}
)
## Declare a cpp library
# add_library(rosbridge_GUI_example
# src/${PROJECT_NAME}/rosbridge_GUI_example.cpp
# )
## Declare a cpp executable
## Add cmake target dependencies of the executable/library
## as an example, message headers may need to be generated before nodes
# add_dependencies(rosbridge_GUI_example_node rosbridge_GUI_example_generate_messages_cpp)
## Specify libraries to link a library or executable target against
#############
## Install ##
#############
# all install targets should use catkin DESTINATION variables
# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html
## Mark executable scripts (Python etc.) for installation
## in contrast to setup.py, you can choose the destination
# install(PROGRAMS
# scripts/my_python_script
# DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
# )
## Mark executables and/or libraries for installation
# install(TARGETS rosbridge_GUI_example rosbridge_GUI_example_node
# ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
# LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
# RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
# )
## Mark cpp header files for installation
# install(DIRECTORY include/${PROJECT_NAME}/
# DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
# FILES_MATCHING PATTERN "*.h"
# PATTERN ".svn" EXCLUDE
# )
## Mark other files for installation (e.g. launch and bag files, etc.)
# install(FILES
# # myfile1
# # myfile2
# DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}
# )
#############
## Testing ##
#############
## Add gtest based cpp test target and link libraries
# catkin_add_gtest(${PROJECT_NAME}-test test/test_rosbridge_GUI_example.cpp)
# if(TARGET ${PROJECT_NAME}-test)
# target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME})
# endif()
## Add folders to be run by python nosetests
# catkin_add_nosetests(test)

View File

@@ -2,92 +2,30 @@
The purpose of this project is an example of how to write a web page that can be accessed by any device on the same network as the host computer by accessing the IP of that host computer.
Here are the following setup requirements:
1. A roscore running
2. The IP of the machine running ROS
3. Web Server up and running
### Quick Start Guide
This guide is for after you have completed the setup requirements
If you are connecting to a remote computer that is running the roscore, you need to run the following lines in the terminal:
sudo route add 192.168.2.1 gw <your IP>
sudo route add 192.168.2.1 gw <Host computer IP>
export ROS_MASTER_URI=http://<Host computer IP>:11311
export ROS_IP=<your IP>
Then run the bash file in the working directory by running the following in the terminal.
bash bashLaunchFile.bash
bash launch.bash
If you are having troubles, make sure the .bash file's permissions permit execution and make sure the working directory ("rosbridge\_GUI\_example") and all it's sub folder's permissions for "others" permit "Create and delete files" for enlcosed files and folders.
# Making Changes
#Setup Requirements
Feel free to clone this project and use it as a base for your own GUI.
## ROS Core
If you are either using a remote or local rosmaster, make sure on the computer that you are going to use to host the webpage can access and echo topics that you wish to display on the webpage.
There is a file called "RobotDisplyPanel.html" that is pasted into the "Robot Display Panel" on the web page. This is where you should put in all your HTML for what you want to display.
## The IP of the machine running ROS
This is required when connecting using the rosbridge
All ROS related Javascript should go in the "/include/js/ros_scripts.js" file.
All functions that are used to update the GUI should go in the "update_guis.js" file
## Web Server up and running
There are two options for launching a web server. Python and apache2. Python is a single line run in the work directory while apache2 runs in the background.
## Python Web Server
### apache2 up and running
apache2 is used to host the webpage on your computer.
Google can help you find the install instructions which are straight forward.
The only next trick is to change the host directory to the working directory.
1.check where is configuration. Generally, apache2 configuration file is located in /etc/apache2/ folder.
nano /etc/apache2/apache2.conf
in that file, you can find out the location of "DocumentRoot" config. An example might look like this:
Include sites-enabled/
that indicates your configration file is in "/etc/apache2/sites-enabled/".
2.Edit DocumentRoot config
nano /etc/apache2/sites-enabled/000-default
In that file, you can find the "DocumentRoot" like below
DocumentRoot /home/glenturner/catkin\_ws/src/asctec\_pelican\_gui
And, modify that as you want.
4.Change in apa.conf file to include:
<Directory /home/glenturner/catkin_ws/src/asctec_pelican_gui>
AllowOverride All
Require all granted
</Directory>
5. Folder Permissions
This was a big problem for me. If you ever get errors on the page that permissions where denied, navigate to the directory above the working directory, right click on the directory that you are working in, change the permissions for all folders and sub folders so that everyone can access it.
3.Restart apache.
service apache2 restart
## Web Server up and running
Here the rosbridge\_suite that is used to link the websocket and ROS: http://wiki.ros.org/rosbridge_suite.
Basic ROS functionality of rosbridge: http://wiki.ros.org/roslibjs/Tutorials/BasicRosFunctionality
the launch command: roslaunch rosbridge_server rosbridge_websocket.launch
# TODO
By using ROSBridge, this GUI will attempt to display relevant information over the web for any device.
@@ -96,4 +34,3 @@ TODO:
1. Display camera image
1. Move connection information to a new tab
1. Check why on iPad the default IP address doesn't load

25
RobotDisplayPanel.html Normal file
View File

@@ -0,0 +1,25 @@
<div id="content">
<div class="panel panel-default">
<div class="panel-heading">
Example Pannel Heading
</div>
<div class="panel-body">
<div class="row">
<label class="col-sm-2"> Bar Title </label>
<div class="progress">
<div id="progressBar1" class="progress-bar progress-bar-striped active" role="progressbar"
aria-valuenow="40" aria-valuemin="0" aria-valuemax="100" style="width:100%" >
No data recieved yet. </div>
</div>
</div>
</div>
<div class="row">
<label class="col-sm-2"> Up Time (s): </label>
<div class="col-sm-1" id="UpTime">
N/A
</div>
</div>
</div>
</div>

5
include/css/bootstrap.min.css vendored Normal file

File diff suppressed because one or more lines are too long

7
include/js/bootstrap.min.js vendored Normal file

File diff suppressed because one or more lines are too long

1
include/js/eventemitter2.min.js vendored Normal file

File diff suppressed because one or more lines are too long

4
include/js/jquery.min.js vendored Normal file

File diff suppressed because one or more lines are too long

83
include/js/ros_scripts.js Normal file
View File

@@ -0,0 +1,83 @@
var ros = new ROSLIB.Ros();
ros.connectioninfo = ['ws://', '192', '168', '0', '100', '9090'];
// ros.connectionName = 'ws://localhost:9090';
ros.connectionName = 'ws://192.168.0.100:9090';
// If there is an error on the backend, an 'error' emit will be emitted.
ros.on('error', function(error) {
document.getElementById("ConnectionIPForm").className = "form-group has-warning has-feedback";
document.getElementById("ConnectionIPInput").value = ros.connectionName;
document.getElementById("ConnectionIPLabel").innerHTML = 'No connection';
document.getElementById("ConnectionButton").className = "btn btn-warning"
document.getElementById("rosbridgeconnection_badge").innerHTML = 'No connection';
rosbridgeconnection_badge
console.log(error);192
});
// Find out exactly when we made a connection.
ros.on('connection', function() {
console.log('Connection made!');
document.getElementById("ConnectionIPForm").className = "form-group has-success has-feedback";
document.getElementById("ConnectionIPInput").value = ros.connectionName;
document.getElementById("ConnectionIPLabel").innerHTML = 'Connection made at:';
document.getElementById("rosbridgeconnection_badge").innerHTML = 'Connected';
document.getElementById("ConnectionButton").className = "btn btn-success"
});
ros.on('close', function() {
console.log('Connection closed.');
});
// Create a connection to the rosbridge WebSocket server.
ros.connect(ros.connectionName);
// attept to connect to the ros master from the IP given orgrab it from the form
ros.attemptConnection = function(ipAddress)
{
if( typeof ipAddress !== "undefined")
{
ros.connectionName = ipAddress;
}
else
{
ros.connectionName = document.getElementById("ConnectionIPInput").value
}
console.log('Connection = ' + ros.connectionName);
ros.connect(ros.connectionName);
}
function getTopics() {
var topicsClient = new ROSLIB.Service({
ros : ros,
name : '/rosapi/topics',
serviceType : '/rosapi/Topics'
});
var request = new ROSLIB.ServiceRequest();
topicsClient.callService(request, function(result) {
ros.topics = result.topics;
});
return ros.topics
};
function getTime() {
var topicsClient = new ROSLIB.Service({
ros : ros,
name : '/rosapi/get_time',
serviceType : '/rosapi/GetTime'
});
var request = new ROSLIB.ServiceRequest({});
topicsClient.callService(request, function(result) {
console.log("Getting Time...");
console.log(result.time.secs);
});
};

2302
include/js/roslib.js Normal file

File diff suppressed because it is too large Load Diff

1
include/js/roslib.min.js vendored Normal file

File diff suppressed because one or more lines are too long

96
include/js/update_guis.js Normal file
View File

@@ -0,0 +1,96 @@
function updateVoltage(voltage)
{
var voltage_min = 9.5;
var voltage_max = 12.5;
var voltage_range = voltage_max - voltage_min;
var voltage_percentage = (voltage - voltage_min) / voltage_range * 100;
var voltage_string = "";
voltage_string = voltage_string.concat(voltage_percentage);
voltage_string = voltage_string.substring(0,4);
voltage_string = voltage_string.concat('%');
document.getElementById("VoltageDisplay").style.width = voltage_string;
document.getElementById("VoltageDisplay").innerHTML = voltage_string;
if (voltage_percentage < 50 && voltage_percentage > 25 ) {
document.getElementById("VoltageDisplay").className = "progress-bar progress-bar-warning"
}
else if ( voltage_percentage <= 25)
{
document.getElementById("VoltageDisplay").className = "progress-bar progress-bar-danger"
var sound = document.getElementById("audio");
sound.play()
console.log("Pay Sound")
}
else
{
document.getElementById("VoltageDisplay").className = "progress-bar progress-bar-success"
}
};
function updateTopicsGUI()
{
topics = getTopics()
if(topics != null){
var innerHTML = "";
for (var i = 0; i < topics.length; i++ )
{
innerHTML = innerHTML.concat(topics[i]);
innerHTML = innerHTML.concat("<br>");
}
document.getElementById("ROSTopics").innerHTML = innerHTML;
}
};
window.setInterval(function(){
updateTopicsGUI()
}, 500);
function validateForm()
{
ros.attemptConnection();
return false;
};
function addInputsForConnection()
{
var innerHTML = "";
for (var i = 0; i < ros.connectioninfo.length; i ++)
{
console.log(ros.connectioninfo[i])
el = document.getElementById("ConnectionInformation")
innerHTML = innerHTML.concat("<span class=\"col-sm-1\">");
innerHTML = innerHTML.concat("<input type=\"text\" class=\"form-control\" value=\"");
innerHTML = innerHTML.concat(ros.connectioninfo[i])
innerHTML = innerHTML.concat("\"/>")
innerHTML = innerHTML.concat("</span>")
if(i >0 && i < 4)
{
innerHTML = innerHTML.concat("<span class=\"col-sxm-1\">.</span>")
}
}
el.innerHTML = innerHTML;
console.log(innerHTML)
}

View File

@@ -1,86 +1,122 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<head>
<meta charset="utf-8" />
<!--
Link to included files. These are typically done by fetching from the web.
Because this needs to run without an internet conection, the files were saved
locally
-->
<script type="text/javascript" src="include/eventemitter2.min.js"></script>
<script type="text/javascript" src="include/roslib.min.js"></script>
-->
<script type="text/javascript" src="include/js/eventemitter2.min.js"></script>
<!-- Bootstrap is a beatuful and usefull library of GUIs. Docs can be found here: http://getbootstrap.com/
Tutorials can be found here: http://www.w3schools.com/bootstrap/default.asp
-->
<link rel="stylesheet" href="include/bootstrap.min.css">
<script src="include/jquery.min.js"></script>
<script src="include/bootstrap.min.js"></script>
<script src="include/roslib.js"></script>
-->
<link rel="stylesheet" href="include/css/bootstrap.min.css">
<script src="include/js/jquery.min.js"></script>
<script src="include/js/bootstrap.min.js"></script>
<script>
$(function(){
$("#RobotInfo").load("RobotDisplayPanel.html");
});
</script>
<audio id="audio" src="audio/beep-04.mp3" autostart="false" ></audio>
<script src="include/js/roslib.js"></script>
<script type="text/javascript" src="include/js/roslib.min.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script type="text/javascript" src="include/js/ros_scripts.js"></script>
<script type="text/javascript" src="include/js/update_guis.js"></script>
<script type="text/javascript" src="src/ros_scripts.js"></script>
<script type="text/javascript" src="src/update_guis.js"></script>
</head>
<body>
<div class="container">
<div class="jumbotron">
<h1>Asctec Pelican</h1>
</div>
<audio id="audio" src="audio/beep-04.mp3" autostart="false" ></audio>
<!-- <button onclick="testAlert('<strong>Danger!</strong> ')">test</button> -->
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="import" href="RobotDisplayPanel.html">
</head>
<body>
<div class="container">
<div class="jumbotron">
<h1>Example GUI</h1>
</div>
<ul id="tabs" class="nav nav-pills" data-tabs="tabs">
<li class="active">
<a href="#RobotInfo" data-toggle="tab">
Robot Display
</a>
</li>
<li> <a href="#rosbridgeconnection" data-toggle="tab">
ROS Bridge Connection
<span id="rosbridgeconnection_badge" class="badge">
Not Connected
</span></a></li>
</ul>
<div id="my-tab-content" class="tab-content">
<div class="tab-pane active" id="RobotInfo">
<!-- !!!!!!!!!!!!!!!!!!!!!VERY IMPORTANT !!!!!!!!!!!!!!!!! -->
<!-- The contents of RobotDisplayPannel are goint to be pasted here -->
<div class="panel panel-default">
<div class="panel-body">
<form class="form-inline" role="form" onsubmit="return validateForm()">
<div id="ConnectionIPForm" class="form-group has-warning" align="center">
<label id="ConnectionIPLabel" class="col-sm-3 control-label" for="inputWarning">Connection warning</label>
<div class="col-sm-6">
<input type="text" class="form-control" id="ConnectionIPInput" value="No IP Address yet"/>
<script type="text/javascript">
document.getElementById("ConnectionIPInput").value = ros.connectionName;
</script>
</div>
<div class="col-sm-1">
<button id="ConnectionButton" type="button" class="btn btn-warning" onclick="ros.attemptConnection()">Connect</button>
</div>
</div>
</form>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
Pelican Status
</div>
<div class="panel-body">
<div class="tab-pane" id="rosbridgeconnection">
<div class="row">
<label class="col-sm-2"> Battery Voltage: </label>
<div class="progress">
<div id="VoltageDisplay" class="progress-bar progress-bar-striped active" role="progressbar"
aria-valuenow="40" aria-valuemin="0" aria-valuemax="100" style="width:100%" >
No data recieved yet.
</div>
<div class="panel panel-default">
<div class="panel-body">
<form class="form-inline" role="form" onsubmit="return validateForm()">
<div id="ConnectionIPForm" class="form-group has-warning" align="center">
<label id="ConnectionIPLabel" class="col-sm-3 control-label" for="inputWarning">
Connection Warning
</label>
<div class="col-sm-6">
<input type="text" class="form-control" id="ConnectionIPInput" value="No IP Address yet"/>
<script type="text/javascript">
document.getElementById("ConnectionIPInput").value = ros.connectionName;
</script>
</div>
<div class="col-sm-2">
<button id="ConnectionButton" type="button" onclick="ros.attemptConnection()">
Connect
</button>
</div>
</div>
</form>
</div>
</div>
<div class="row">
<label class="col-sm-2"> Up Time (s): </label>
<div class="col-sm-1" id="UpTime">
N/A
<br>
<div class="panel panel-default">
<div class="panel-heading">
ROS Topics
</div>
<div class="panel-body">
<div class="col-sm-1" id="ROSTopics">
N/A
</div>
</div>
</div>
</div>
</div>
</div>
</body>
</div>
</body>
</html>

5
launch.bash Normal file
View File

@@ -0,0 +1,5 @@
#!/bin/bash
killall -9 rosmaster
roslaunch rosbridge_GUI_example all.launch &
python -m SimpleHTTPServer 8000

View File

@@ -1,4 +1,4 @@
<launch>
<include file="$(find rosbridge_server)/launch/rosbridge_websocket.launch" />
<include file="$(find axis_mapping_web_app)/launch/bagger.launch" />
<!-- <include file="$(find rosbridge_GUI_example)/launch/bagger.launch" /> -->
</launch>

3
launch/bagger.launch Normal file
View File

@@ -0,0 +1,3 @@
<launch>
# <node name="bagger" pkg="rosbridge_GUI_example" type="bagger.py" />
</launch>

50
package.xml Normal file
View File

@@ -0,0 +1,50 @@
<?xml version="1.0"?>
<package>
<name>rosbridge_GUI_example</name>
<version>0.0.0</version>
<description>The rosbridge_GUI_example package</description>
<!-- One maintainer tag required, multiple allowed, one person per tag -->
<!-- Example: -->
<!-- <maintainer email="jane.doe@example.com">Jane Doe</maintainer> -->
<maintainer email="turner.glen@gmail.com">glen</maintainer>
<!-- One license tag required, multiple allowed, one license per tag -->
<!-- Commonly used license strings: -->
<!-- BSD, MIT, Boost Software License, GPLv2, GPLv3, LGPLv2.1, LGPLv3 -->
<license>TODO</license>
<!-- Author tags are optional, mutiple are allowed, one per tag -->
<!-- Authors do not have to be maintianers, but could be -->
<!-- Example: -->
<!-- <author email="jane.doe@example.com">Jane Doe</author> -->
<!-- The *_depend tags are used to specify dependencies -->
<!-- Dependencies can be catkin packages or system dependencies -->
<!-- Examples: -->
<!-- Use build_depend for packages you need at compile time: -->
<!-- <build_depend>message_generation</build_depend> -->
<!-- Use buildtool_depend for build tool packages: -->
<!-- <buildtool_depend>catkin</buildtool_depend> -->
<!-- Use run_depend for packages you need at runtime: -->
<!-- <run_depend>message_runtime</run_depend> -->
<!-- Use test_depend for packages you need only for testing: -->
<!-- <test_depend>gtest</test_depend> -->
<buildtool_depend>catkin</buildtool_depend>
<build_depend>roscpp</build_depend>
<build_depend>rospy</build_depend>
<build_depend>std_msgs</build_depend>
<run_depend>roscpp</run_depend>
<run_depend>rospy</run_depend>
<run_depend>std_msgs</run_depend>
<!-- The export tag contains other, unspecified, tags -->
<export>
<!-- Other tools can request additional information be placed here -->
</export>
</package>

33
src/bagger.py Normal file
View File

@@ -0,0 +1,33 @@
#!/usr/bin/env python
import rospy
from std_msgs.msg import String
import rospkg
import subprocess
import os
import signal
class Bagger(object):
def __init__(self):
rospy.init_node("bagger", anonymous=True)
rospy.Subscriber("bag_publisher", String, self.callback)
self.pub = rospy.Publisher("bag_notifier", String, queue_size=10)
self.proc = None
rospack = rospkg.RosPack()
self.data_path = os.path.join(rospack.get_path("rosbridge_GUI_example"), "data")
def callback(self, msg):
if msg.data == "STOP" and self.proc is not None:
os.killpg(self.proc.pid, signal.SIGINT)
self.pub.publish("STOPPED")
else:
bag_file = os.path.join(self.data_path, msg.data)
self.proc = subprocess.Popen(["rosbag", "record",
"kinect2/depth_lowres/points", "kinect2/rgb_lowres/image",
"tf", "imu/data", "-o", bag_file], preexec_fn=os.setsid)
self.pub.publish("STARTED")
if __name__ == '__main__':
Bagger()
rospy.spin()