From 8f14b59275d190826ef1f0907cb326f128338f64 Mon Sep 17 00:00:00 2001 From: Paul Beuchat <beuchatp@control.ee.ethz.ch> Date: Tue, 28 Apr 2020 16:25:41 +0200 Subject: [PATCH] Web interface now working for launching both the master and agent. VERY IMPORTANT is the command added to the web interface install script that the www-data user must be added to the plugdev group so that nodes launched by the web interface have permission to access the CrazyRadio USB dongle --- dfall_ws/src/dfall_pkg/launch/pi_agent.launch | 144 ++++++++++++++++ .../src/dfall_pkg/launch/pi_master.launch | 40 +++++ web_interface/html/agent_tab_launch.html | 14 +- .../html/bashscripts/killRosAgent.sh | 22 +-- .../html/bashscripts/killRosMaster.sh | 27 +++ .../html/bashscripts/launchRosAgent.sh | 33 +++- .../html/bashscripts/launchRosMaster.sh | 38 +++++ .../rosCrazyRadioCommand_forAgent.sh | 35 ++-- .../bashscripts/rosSetNewSetpoint_forAgent.sh | 47 +++++- web_interface/html/callBashScript.php | 17 +- .../html/callBashScript_roslaunch.php | 60 +++++++ .../html/callBashScript_setNewSetpoint.php | 25 ++- web_interface/html/js/callbashscript.js | 14 +- web_interface/html/js/roslaunch.js | 110 ++++++++++++ web_interface/html/js/temp.js | 156 ------------------ web_interface/html/page_header.html | 1 + web_interface/install_dfall_server_WIP.sh | 11 ++ 17 files changed, 574 insertions(+), 220 deletions(-) create mode 100755 dfall_ws/src/dfall_pkg/launch/pi_agent.launch create mode 100755 dfall_ws/src/dfall_pkg/launch/pi_master.launch create mode 100755 web_interface/html/bashscripts/killRosMaster.sh create mode 100755 web_interface/html/bashscripts/launchRosMaster.sh create mode 100644 web_interface/html/callBashScript_roslaunch.php create mode 100644 web_interface/html/js/roslaunch.js delete mode 100644 web_interface/html/js/temp.js diff --git a/dfall_ws/src/dfall_pkg/launch/pi_agent.launch b/dfall_ws/src/dfall_pkg/launch/pi_agent.launch new file mode 100755 index 00000000..a4e6f97e --- /dev/null +++ b/dfall_ws/src/dfall_pkg/launch/pi_agent.launch @@ -0,0 +1,144 @@ +<launch> + + <!-- INPUT ARGUMENT OF THE AGENT's ID --> + <arg name="agentID" default="$(optenv DFALL_DEFAULT_AGENT_ID)" /> + + <!-- INPUT ARGUMENT OF THE COORDINATOR's ID --> + <arg name="coordID" default="$(optenv DFALL_DEFAULT_COORD_ID)" /> + + <!-- INPUT ARGUMENT FOR EMULATING THE CRAZY RADIO --> + <arg name="emulateRadio" default="false" /> + + <!-- Example of how to use the value in agentID --> + <!-- <param name="param" value="$(arg agentID)"/> --> + + <!-- Example of how to specify the agentID from command line --> + <!-- roslaunch dfall_pkg agentID:=1 --> + + <!-- Example of how to specify the withGUI from command line --> + <!-- roslaunch dfall_pkg withGUI:=false --> + + <group ns="$(eval 'agent' + str(agentID).zfill(3))"> + + <!-- CRAZY RADIO --> + <group unless="$(arg emulateRadio)"> + <node + pkg = "dfall_pkg" + name = "CrazyRadio" + output = "screen" + type = "CrazyRadio.py" + > + <rosparam + command = "load" + file = "$(find dfall_pkg)/param/BatteryMonitor.yaml" + ns = "CrazyRadioCopyOfBatteryMonitor" + /> + <rosparam + command = "load" + file = "$(find dfall_pkg)/param/CrazyRadioConfig.yaml" + ns = "CrazyRadioConfig" + /> + </node> + </group> + <group if="$(arg emulateRadio)"> + <node + pkg = "dfall_pkg" + name = "CrazyRadio" + output = "screen" + type = "CrazyRadioEmulator" + > + <rosparam + command = "load" + file = "$(find dfall_pkg)/param/CrazyRadioConfig.yaml" + ns = "CrazyRadioConfig" + /> + </node> + </group> + + + <!-- FLYING AGENT CLIENT --> + <node + pkg = "dfall_pkg" + name = "FlyingAgentClient" + output = "screen" + type = "FlyingAgentClient" + > + <param name="agentID" value="$(arg agentID)" /> + <param name="coordID" value="$(arg coordID)" /> + </node> + + <!-- BATTERY MONITOR --> + <node + pkg = "dfall_pkg" + name = "BatteryMonitor" + output = "screen" + type = "BatteryMonitor" + > + </node> + + <!-- DEFAULT CONTROLLER --> + <node + pkg = "dfall_pkg" + name = "DefaultControllerService" + output = "screen" + type = "DefaultControllerService" + > + </node> + + <!-- STUDENT CONTROLLER --> + <node + pkg = "dfall_pkg" + name = "StudentControllerService" + output = "screen" + type = "StudentControllerService" + > + </node> + + <!-- TEST MOTORS CONTROLLER --> + <node + pkg = "dfall_pkg" + name = "TestMotorsControllerService" + output = "screen" + type = "TestMotorsControllerService" + > + </node> + + <!-- PARAMETER SERVICE --> + <node + pkg = "dfall_pkg" + name = "ParameterService" + output = "screen" + type = "ParameterService" + > + <param name="type" type="str" value="agent" /> + <param name="agentID" value="$(arg agentID)" /> + <rosparam + command = "load" + file = "$(find dfall_pkg)/param/YamlFileNames.yaml" + ns = "YamlFileNames" + /> + <rosparam + command = "load" + file = "$(find dfall_pkg)/param/FlyingAgentClientConfig.yaml" + ns = "FlyingAgentClientConfig" + /> + <rosparam + command = "load" + file = "$(find dfall_pkg)/param/BatteryMonitor.yaml" + ns = "BatteryMonitor" + /> + <rosparam + command = "load" + file = "$(find dfall_pkg)/param/DefaultController.yaml" + ns = "DefaultController" + /> + <rosparam + command = "load" + file = "$(find dfall_pkg)/param/StudentController.yaml" + ns = "StudentController" + /> + </node> + + </group> + +</launch> diff --git a/dfall_ws/src/dfall_pkg/launch/pi_master.launch b/dfall_ws/src/dfall_pkg/launch/pi_master.launch new file mode 100755 index 00000000..3165b14b --- /dev/null +++ b/dfall_ws/src/dfall_pkg/launch/pi_master.launch @@ -0,0 +1,40 @@ +<launch> + + <!-- INPUT ARGUMENT FOR EMULATING THE MOTION CAPTURE --> + <arg name="emulateMocap" default="false" /> + + <!-- Example of how to specify the emulateMocap from command line --> + <!-- roslaunch dfall_pkg emulateMocap:=true --> + + <!-- CENTRAL MANAGER --> + <node + pkg="dfall_pkg" + name="CentralManagerService" + output="screen" + type="CentralManagerService" + > + </node> + + <!-- VICON DATA PUBLISHER --> + <group unless="$(arg emulateMocap)"> + <node + pkg="dfall_pkg" + name="ViconDataPublisher" + output="screen" + type="ViconDataPublisher" + > + <rosparam command="load" file="$(find dfall_pkg)/param/ViconConfig.yaml" /> + </node> + </group> + <group if="$(arg emulateMocap)"> + <node + pkg="dfall_pkg" + name="ViconDataPublisher" + output="screen" + type="MocapEmulator" + > + <rosparam command="load" file="$(find dfall_pkg)/param/MocapEmulatorConfig.yaml" /> + </node> + </group> + +</launch> diff --git a/web_interface/html/agent_tab_launch.html b/web_interface/html/agent_tab_launch.html index c8850726..06c04845 100644 --- a/web_interface/html/agent_tab_launch.html +++ b/web_interface/html/agent_tab_launch.html @@ -11,7 +11,7 @@ <button class="button-push navy fullwidth" id="buttonRosMasterStatus" - onclick="callBashScript_outputLabelID_clearOtherLabels_clickOtherButtons('checkForRosMaster', 'rosMasterStatus', null, null)" + onclick="callBashScript_outputLabelID_clearOtherLabels_clickOtherButtons('checkForRosMaster', 'rosMasterStatus', ['rosLaunchMasterStatus','killMasterStatus'], null)" > Check for ROS Master <div class="div-for-button-highlight-on-touchscreen navy"></div> @@ -27,7 +27,7 @@ <button class="button-push navy fullwidth" id="buttonLaunchRosMaster" - onclick="callBashScript_outputLabelID_clearOtherLabels_clickOtherButtons('launchRosMaster', 'rosLaunchMasterStatus', 'killMasterStatus', ['buttonRosMasterStatus','buttonRosAgentStatus','buttonRosNodeList'])" + onclick="roslaunch_outputLabelID_clearOtherLabels_clickOtherButtons('master', 'rosLaunchMasterStatus', ['rosMasterStatus','killMasterStatus'], ['buttonRosAgentStatus','buttonRosNodeList'])" > Launch ROS Master <div class="div-for-button-highlight-on-touchscreen navy"></div> @@ -59,7 +59,7 @@ <button class="button-push red fullwidth" id="buttonKillRosMaster" - onclick="callBashScript_outputLabelID_clearOtherLabels_clickOtherButtons('killRosMaster', 'killMasterStatus', 'rosLaunchMasterStatus', ['buttonRosMasterStatus','buttonRosAgentStatus','buttonRosNodeList'])" + onclick="callBashScript_outputLabelID_clearOtherLabels_clickOtherButtons('killRosMaster', 'killMasterStatus', ['rosMasterStatus','rosLaunchMasterStatus'], ['buttonRosAgentStatus','buttonRosNodeList'])" > Kill ROS Master <div class="div-for-button-highlight-on-touchscreen red"></div> @@ -83,7 +83,7 @@ <button class="button-push navy fullwidth" id="buttonRosAgentStatus" - onclick="callBashScript_outputLabelID_clearOtherLabels_clickOtherButtons('checkForRosAgent', 'rosAgentStatus', null, ['buttonRosMasterStatus','buttonRosNodeList'])" + onclick="callBashScript_outputLabelID_clearOtherLabels_clickOtherButtons('checkForRosAgent', 'rosAgentStatus', ['rosLaunchAgentStatus','killAgentStatus'], 'buttonRosNodeList')" > Check for ROS Agent <div class="div-for-button-highlight-on-touchscreen navy"></div> @@ -99,7 +99,7 @@ <button class="button-push navy fullwidth" id="buttonLaunchRosAgent" - onclick="callBashScript_outputLabelID_clearOtherLabels_clickOtherButtons('launchRosAgent', 'rosLaunchAgentStatus', 'killAgentStatus', ['buttonRosMasterStatus','buttonRosAgentStatus','buttonRosNodeList'])" + onclick="roslaunch_outputLabelID_clearOtherLabels_clickOtherButtons('agent', 'rosLaunchAgentStatus', ['rosAgentStatus','killAgentStatus'], 'buttonRosNodeList')" > Launch ROS Agent <div class="div-for-button-highlight-on-touchscreen navy"></div> @@ -131,7 +131,7 @@ <button class="button-push red fullwidth" id="buttonKillRosAgent" - onclick="callBashScript_outputLabelID_clearOtherLabels_clickOtherButtons('killRosAgent', 'killAgentStatus', 'rosLaunchAgentStatus', ['buttonRosMasterStatus','buttonRosAgentStatus','buttonRosNodeList'])" + onclick="callBashScript_outputLabelID_clearOtherLabels_clickOtherButtons('killRosAgent', 'killAgentStatus', ['rosAgentStatus','rosLaunchAgentStatus'], 'buttonRosNodeList')" > Kill ROS Agent <div class="div-for-button-highlight-on-touchscreen red"></div> @@ -168,7 +168,7 @@ <table class="ros-table"> <tr> - <td class="ros-info-cell"> + <td class="ros-info-cell" style="height:100px;vertical-align:text-top;"> <div id="rosnodeList"></div> </td> </tr> diff --git a/web_interface/html/bashscripts/killRosAgent.sh b/web_interface/html/bashscripts/killRosAgent.sh index 27fa7de6..1b687066 100755 --- a/web_interface/html/bashscripts/killRosAgent.sh +++ b/web_interface/html/bashscripts/killRosAgent.sh @@ -10,16 +10,16 @@ source /home/www-share/dfall/dfall-system/dfall_ws/src/dfall_pkg/launch/Config.s # > Note: the -q options converts the # grep output to a true/false if rosnode list | grep -q /rosout; then - # Check that if the agent is already - # launched - if rosnode list | grep -q "$(printf "/dfall/agent%03d" $DFALL_DEFAULT_AGENT_ID)"; then - # Kill all nodes starting with - # /dfall/agentXXX/ - rosnode list | grep "$(printf "/dfall/agent%03d" $DFALL_DEFAULT_AGENT_ID)" | xargs rosnode kill > /dev/null - echo "Agent $DFALL_DEFAULT_AGENT_ID killed" - else - echo "Agent $DFALL_DEFAULT_AGENT_ID not found" - fi + # Check that if the agent is already + # launched + if rosnode list | grep -q "$(printf "/dfall/agent%03d" $DFALL_DEFAULT_AGENT_ID)"; then + # Kill all nodes starting with + # /dfall/agentXXX/ + rosnode list | grep "$(printf "/dfall/agent%03d" $DFALL_DEFAULT_AGENT_ID)" | xargs rosnode kill > /dev/null + echo "Agent $DFALL_DEFAULT_AGENT_ID killed" + else + echo "Agent $DFALL_DEFAULT_AGENT_ID not found" + fi else - echo "ROS Master not found" + echo "ROS Master not found" fi diff --git a/web_interface/html/bashscripts/killRosMaster.sh b/web_interface/html/bashscripts/killRosMaster.sh new file mode 100755 index 00000000..8945b1ca --- /dev/null +++ b/web_interface/html/bashscripts/killRosMaster.sh @@ -0,0 +1,27 @@ +#!/bin/bash +# +# Make the ROS commands available +# NOTE: these paths should NOT use ~ +source /opt/ros/melodic/setup.bash +#source /home/www-share/dfall/dfall-system/dfall_ws/devel/setup.bash +source /home/www-share/dfall/dfall-system/dfall_ws/src/dfall_pkg/launch/Config.sh +# +# Check that the ROS Master exists +# > Note: the -q options converts the +# grep output to a true/false +if rosnode list | grep -q /rosout; then + # Kill all nodes + rosnode kill --all > /dev/null 2>&1 & + # The /rosout will respawn, so all kill any + # "roslaunch" process owned by the + # "www-data" user + pkill -u www-data roslaunch + # For debugging it is usefull to running the + # following commands on the server machine + # >> ps -aux + # >> pgrep -u www-data + # Inform the user + echo "Killed all ros nodes" +else + echo "ROS Master not found" +fi diff --git a/web_interface/html/bashscripts/launchRosAgent.sh b/web_interface/html/bashscripts/launchRosAgent.sh index b8fec36a..a2ba643f 100755 --- a/web_interface/html/bashscripts/launchRosAgent.sh +++ b/web_interface/html/bashscripts/launchRosAgent.sh @@ -1,5 +1,20 @@ #!/bin/bash # +# Check that exactly one command is supplied +if [ "$#" -ne 1 ]; then + echo "exactly one argument must be supplied" + exit 1 +fi +# +# Check that the first command supplied is valid +if [ "$1" != "true" ] && [ "$1" != "false" ]; then + echo "emulate crazyradio = $1, is not a valid boolean." + exit 1 +fi +# +# Put the commands into variables for make things more readable +emulateradio=$1 +# # Make the ROS commands available # NOTE: these paths should NOT use ~ source /opt/ros/melodic/setup.bash @@ -16,14 +31,14 @@ export ROS_LOG_DIR=/var/www/html/.ros/log # > Note: the -q options converts the # grep output to a true/false if rosnode list | grep -q /rosout; then - # Check that if the agent is already - # launched - if rosnode list | grep -q "$(printf "/dfall/agent%03d" $DFALL_DEFAULT_AGENT_ID)"; then - echo "Agent $DFALL_DEFAULT_AGENT_ID is already running" - else - nohup roslaunch dfall_pkg agent.launch withGUI:=false emulateRadio:=true > /dev/null 2>&1 & - echo "Agent $DFALL_DEFAULT_AGENT_ID successfully launched" - fi + # Check that if the agent is already + # launched + if rosnode list | grep -q "$(printf "/dfall/agent%03d" $DFALL_DEFAULT_AGENT_ID)"; then + echo "Agent $DFALL_DEFAULT_AGENT_ID is already running" + else + nohup roslaunch dfall_pkg pi_agent.launch emulateRadio:=$emulateradio > /dev/null 2>&1 & + echo "Agent $DFALL_DEFAULT_AGENT_ID successfully launched" + fi else - echo "ROS Master not found" + echo "ROS Master not found" fi diff --git a/web_interface/html/bashscripts/launchRosMaster.sh b/web_interface/html/bashscripts/launchRosMaster.sh new file mode 100755 index 00000000..a6b95473 --- /dev/null +++ b/web_interface/html/bashscripts/launchRosMaster.sh @@ -0,0 +1,38 @@ +#!/bin/bash +# +# Check that exactly one command is supplied +if [ "$#" -ne 1 ]; then + echo "exactly one argument must be supplied" + exit 1 +fi +# +# Check that the first command supplied is valid +if [ "$1" != "true" ] && [ "$1" != "false" ]; then + echo "emulate mocap = $1, is not a valid boolean." + exit 1 +fi +# +# Put the commands into variables for make things more readable +emultemocap=$1 +# +# Make the ROS commands available +# NOTE: these paths should NOT use ~ +source /opt/ros/melodic/setup.bash +source /home/www-share/dfall/dfall-system/dfall_ws/devel/setup.bash +source /home/www-share/dfall/dfall-system/dfall_ws/src/dfall_pkg/launch/Config.sh +# +# Set the ROS log location +export ROS_LOG_DIR=/var/www/html/.ros/log +# +# Mount the dfall workspace folder +#sudo mount --bind /home/pbeuchat/gitrep/dfall/dfall-system/dfall_ws /var/www/html/dfall_ws +# +# Check that the ROS Master exists +# > Note: the -q options converts the +# grep output to a true/false +if rosnode list | grep -q /rosout; then + echo "ROS Master is already running" +else + nohup roslaunch dfall_pkg pi_master.launch emulateMocap:=$emultemocap > /dev/null 2>&1 & + echo "ROS Master successfully launched" +fi \ No newline at end of file diff --git a/web_interface/html/bashscripts/rosCrazyRadioCommand_forAgent.sh b/web_interface/html/bashscripts/rosCrazyRadioCommand_forAgent.sh index ed6c359c..1d826fd3 100755 --- a/web_interface/html/bashscripts/rosCrazyRadioCommand_forAgent.sh +++ b/web_interface/html/bashscripts/rosCrazyRadioCommand_forAgent.sh @@ -2,13 +2,13 @@ # # Check that exactly one command is supplied if [ "$#" -ne 1 ]; then - echo "failed" + echo "exactly one argument must be supplied" exit 1 fi # # Check that the command supplied is valid if [ "$1" != "0" ] && [ "$1" != "1" ]; then - echo "failed" + echo "command = $1, is not a valid option" exit 1 fi # @@ -25,18 +25,25 @@ source /home/www-share/dfall/dfall-system/dfall_ws/src/dfall_pkg/launch/Config.s # > Note: the -q options converts the # grep output to a true/false if rosnode list | grep -q /rosout; then - # Convert the agent ID to a zero padded string - agentnamespace=$(printf "agent%03d" $DFALL_DEFAULT_AGENT_ID) - # Send the message - if [ "$command" == "0" ]; then - temp="$(rostopic pub -1 /$ROS_NAMESPACE/$agentnamespace/FlyingAgentClient/crazyRadioCommand dfall_pkg/IntWithHeader '{data: 0, shouldCheckForAgentID: False}')" + # Convert the agent ID to a zero padded string + agentnamespace=$(printf "agent%03d" $DFALL_DEFAULT_AGENT_ID) + # Send the message + if [ "$command" == "0" ]; then + # Publish the request + temp="$(rostopic pub -1 /$ROS_NAMESPACE/$agentnamespace/FlyingAgentClient/CrazyRadioCommand dfall_pkg/IntWithHeader "{data: 0, shouldCheckForAgentID: False}")" + # Return that the message was sent + echo "sent" + # + elif [ "$command" == "1" ]; then + # Publish the request + temp="$(rostopic pub -1 /$ROS_NAMESPACE/$agentnamespace/FlyingAgentClient/CrazyRadioCommand dfall_pkg/IntWithHeader "{data: 1, shouldCheckForAgentID: False}")" + # Return that the message was sent + echo "sent" + else + # Return that the command is not recognised + echo "command = $command is not a valid option" fi - if [ "$command" == "1" ]; then - temp="$(rostopic pub -1 /$ROS_NAMESPACE/$agentnamespace/FlyingAgentClient/crazyRadioCommand dfall_pkg/IntWithHeader '{data: 1, shouldCheckForAgentID: False}')" - fi - # - # Return that the message was sent - echo "sent" + else - echo "ROS Master not found" + echo "ROS Master not found" fi diff --git a/web_interface/html/bashscripts/rosSetNewSetpoint_forAgent.sh b/web_interface/html/bashscripts/rosSetNewSetpoint_forAgent.sh index e81dffdf..26fd8756 100755 --- a/web_interface/html/bashscripts/rosSetNewSetpoint_forAgent.sh +++ b/web_interface/html/bashscripts/rosSetNewSetpoint_forAgent.sh @@ -2,13 +2,13 @@ # # Check that exactly five commands are supplied if [ "$#" -ne 5 ]; then - echo "failed" + echo "exaclty five arguments must be supplied" exit 1 fi # # Check that the first command supplied is valid if [ "$1" != "default" ] && [ "$1" != "student" ]; then - echo "failed" + echo "command = $1, is not a valid option." exit 1 fi # @@ -19,6 +19,28 @@ ynew=$3 znew=$4 yawnew=$5 # +# Check that the new setpoint values are purely numerical +# > For x: +if ! [[ $xnew =~ ^[+-]?[0-9]+\.?[0-9]*$ ]];then + echo "x = $xnew, is not a float." + exit 1 +fi +# > For y: +if ! [[ $ynew =~ ^[+-]?[0-9]+\.?[0-9]*$ ]];then + echo "y = $ynew, is not a float." + exit 1 +fi +# > For z: +if ! [[ $znew =~ ^[+-]?[0-9]+\.?[0-9]*$ ]];then + echo "z = $znew, is not a float." + exit 1 +fi +# > For yaw: +if ! [[ $yawnew =~ ^[+-]?[0-9]+\.?[0-9]*$ ]];then + echo "yaw = $yawnew, is not a float." + exit 1 +fi +# # Make the ROS commands available # NOTE: these paths should NOT use ~ source /opt/ros/melodic/setup.bash @@ -33,14 +55,21 @@ if rosnode list | grep -q /rosout; then agentnamespace=$(printf "agent%03d" $DFALL_DEFAULT_AGENT_ID) # Send the message if [ "$command" == "default" ]; then - "$(rostopic pub -1 /$ROS_NAMESPACE/$agentnamespace/DefaultControllerService/RequestSetpointChange dfall_pkg/SetpointWithHeader "{x: $xnew, y: $ynew, z: $znew, yaw: $yawnew, shouldCheckForAgentID: False}")" - fi - if [ "$command" == "student" ]; then - "$(rostopic pub -1 /$ROS_NAMESPACE/$agentnamespace/StudentControllerService/RequestSetpointChange dfall_pkg/SetpointWithHeader "{x: $xnew, y: $ynew, z: $znew, yaw: $yawnew, shouldCheckForAgentID: False}")" - fi + # Publish the request + temp="$(rostopic pub -1 /$ROS_NAMESPACE/$agentnamespace/DefaultControllerService/RequestSetpointChange dfall_pkg/SetpointWithHeader "{x: $xnew, y: $ynew, z: $znew, yaw: $yawnew, shouldCheckForAgentID: False}")" + # Return that the message was sent + echo "sent" + # + elif [ "$command" == "student" ]; then + # Publish the request + temp="$(rostopic pub -1 /$ROS_NAMESPACE/$agentnamespace/StudentControllerService/RequestSetpointChange dfall_pkg/SetpointWithHeader "{x: $xnew, y: $ynew, z: $znew, yaw: $yawnew, shouldCheckForAgentID: False}")" + # Return that the message was sent + echo "sent" # - # Return that the message was sent - echo "sent" + else + # Return that the command is not recognised + echo "controller = $command is not a valid option" + fi else echo "ROS Master not found" diff --git a/web_interface/html/callBashScript.php b/web_interface/html/callBashScript.php index a89f9031..0e2b4553 100644 --- a/web_interface/html/callBashScript.php +++ b/web_interface/html/callBashScript.php @@ -30,19 +30,25 @@ $temp = shell_exec("./bashscripts/catkin_make.sh"); $output = "<pre>$temp</pre>"; } + // // For the LAUNCH tab elseif ($scriptname == "checkForRosMaster") { $output = shell_exec("./bashscripts/checkForRosMaster.sh"); } - elseif ($scriptname == "checkForRosAgent") { - $output = shell_exec("./bashscripts/checkForRosAgent.sh"); + // + // "launch Ros Master" is handled separately + // because it requires an input argument + // + elseif ($scriptname == "killRosMaster") { + $output = shell_exec("./bashscripts/killRosMaster.sh"); } elseif ($scriptname == "checkForRosAgent") { $output = shell_exec("./bashscripts/checkForRosAgent.sh"); } - elseif ($scriptname == "launchRosAgent") { - $output = shell_exec("./bashscripts/launchRosAgent.sh"); - } + // + // "launch Ros Agent" is handled separately + // because it requires an input argument + // elseif ($scriptname == "killRosAgent") { $output = shell_exec("./bashscripts/killRosAgent.sh"); } @@ -50,6 +56,7 @@ $temp = shell_exec("./bashscripts/rosnodeList.sh"); $output = "<pre>$temp</pre>"; } + // // For the CONTROL tab: // { RADIO CONNECTION, TAKE-OFF, LAND, MOTORS-OFF, LOAD CONTROLLER } elseif ($scriptname == "rosConnect") { diff --git a/web_interface/html/callBashScript_roslaunch.php b/web_interface/html/callBashScript_roslaunch.php new file mode 100644 index 00000000..bca63740 --- /dev/null +++ b/web_interface/html/callBashScript_roslaunch.php @@ -0,0 +1,60 @@ +<?php + // GET THE BASH SCRIPT NAME + $scriptname = $_GET['scriptname']; + + // ONLY EXECUTE "SCRIPT NAMES" WITH AN EXACT MATCH + // + // > For the MASTER + if ($scriptname == "master") + { + // GET THE VALUES OF THE EMULATE MOCAP FLAG + // > This will be a string + $emulate_mocap = strtolower( $_GET['emulatemocap'] ); + // Check that the new setpoint values are numerical + if (in_array($emulate_mocap, array("true", "1", "yes"), true)) + { + $emulate_mocap = "true"; + } + elseif (in_array($emulate_mocap, array("false", "0", "no"), true)) + { + $emulate_mocap = "false"; + } + else + { + echo "emulate mocap flag = $emulate_mocap, is not a boolean value."; + exit(); + } + // Call the bash script for launching the master + $output = shell_exec("./bashscripts/launchRosMaster.sh $emulate_mocap"); + } + // + // > For the AGENT + elseif ($scriptname == "agent") + { + // GET THE VALUES OF THE EMULATE MOCAP FLAG + // > This will be a string + $emulate_crazyradio = strtolower( $_GET['emulatecrazyradio'] ); + // Check that the new setpoint values are numerical + if (in_array($emulate_crazyradio, array("true", "1", "yes"), true)) + { + $emulate_crazyradio = "true"; + } + elseif (in_array($emulate_crazyradio, array("false", "0", "no"), true)) + { + $emulate_crazyradio = "false"; + } + else + { + echo "emulate crazyradio flag = $emulate_crazyradio, is not a boolean value."; + exit(); + } + // Call the bash script for launching the agent + $output = shell_exec("./bashscripts/launchRosAgent.sh $emulate_crazyradio"); + } + else + { + $output = "launch name = $scriptname is not a valid option"; + } + + echo "$output"; +?> diff --git a/web_interface/html/callBashScript_setNewSetpoint.php b/web_interface/html/callBashScript_setNewSetpoint.php index 4d52c0c1..2e44ae0c 100644 --- a/web_interface/html/callBashScript_setNewSetpoint.php +++ b/web_interface/html/callBashScript_setNewSetpoint.php @@ -3,15 +3,36 @@ $scriptname = $_GET['scriptname']; // GET THE (x,y,z,yaw) VALUES OF THE NEW SETPOINT + // > These will be strings $x_new = $_GET['x']; $y_new = $_GET['y']; $z_new = $_GET['z']; $yaw_new = $_GET['yaw']; + // Check that the new setpoint values are numerical + if ( ! (is_numeric($x_new)) ) + { + echo "x = $x_new, is not a numeric value."; + exit(); + } + if ( ! (is_numeric($y_new)) ) + { + echo "y = $y_new, is not a numeric value."; + exit(); + } + if ( ! (is_numeric($z_new)) ) + { + echo "z = $z_new, is not a numeric value."; + exit(); + } + if ( ! (is_numeric($yaw_new)) ) + { + echo "yaw = $yaw_new, is not a numeric value."; + exit(); + } - // ONLY EXECUTE NAMES WITH AN EXACT MATHC - + // ONLY EXECUTE "SCRIPT NAMES" WITH AN EXACT MATCH // For the CONTROL tab: // GET SETPOINT if ($scriptname == "rosSetSetpointDefault") { diff --git a/web_interface/html/js/callbashscript.js b/web_interface/html/js/callbashscript.js index d4a563fd..e494f3c1 100644 --- a/web_interface/html/js/callbashscript.js +++ b/web_interface/html/js/callbashscript.js @@ -1,4 +1,4 @@ -function callBashScript_outputLabelID_clearOtherLabels_clickOtherButtons(bashscript, labelID, otherLabels, otherbuttons) +function callBashScript_outputLabelID_clearOtherLabels_clickOtherButtons(bashscript, labelID, otherLabels, otherButtons) { // Create a variable for sending an AJAX request var xmlhttp = new XMLHttpRequest(); @@ -11,15 +11,15 @@ function callBashScript_outputLabelID_clearOtherLabels_clickOtherButtons(bashscr var base_string = ""; document.getElementById(labelID).innerHTML = base_string + this.responseText; // Click the "other buttons" as requested - if (otherbuttons) + if (otherButtons) { - if ( typeof(otherbuttons) == "string" ) + if ( typeof(otherButtons) == "string" ) { - document.getElementById(otherbuttons).click(); + document.getElementById(otherButtons).click(); } - else if (otherbuttons.constructor === Array) + else if (otherButtons.constructor === Array) { - for (otherButtonID of otherbuttons) + for (otherButtonID of otherButtons) { if (otherButtonID) { @@ -51,7 +51,7 @@ function callBashScript_outputLabelID_clearOtherLabels_clickOtherButtons(bashscr } else if (otherLabels.constructor === Array) { - for (otherLabelID of otherbuttons) + for (otherLabelID of otherLabels) { if (otherLabelID) { diff --git a/web_interface/html/js/roslaunch.js b/web_interface/html/js/roslaunch.js new file mode 100644 index 00000000..0f537573 --- /dev/null +++ b/web_interface/html/js/roslaunch.js @@ -0,0 +1,110 @@ +function roslaunch_outputLabelID_clearOtherLabels_clickOtherButtons(launchName, labelID, otherLabels, otherButtons) +{ + // Convert the "controllerName" to a heading string + var scriptname_for_php = ""; + if (launchName == "master") + { + scriptname_for_php = "master"; + } + else if (launchName == "agent") + { + scriptname_for_php = "agent"; + } + else + { + return; + } + + // Get the booleans for emulation + emulated_mocap = document.getElementById("checkboxEmulateMocap").checked; + emulated_crazyradio = document.getElementById("checkboxEmulateCrazyRadio").checked; + + // Set the label to be sending + if(labelID){document.getElementById(labelID).innerHTML = "sending...";} + + // Create a variable for sending an AJAX request + var xmlhttp = new XMLHttpRequest(); + // Add the function to be run when the response is recieved + xmlhttp.onreadystatechange = function() + { + if (this.readyState == 4 && this.status == 200) + { + // Construct and display the appropriate information + var base_string = ""; + if(labelID){document.getElementById(labelID).innerHTML = base_string + this.responseText;} + // Click the "other buttons" as requested + if (otherButtons) + { + if ( typeof(otherButtons) == "string" ) + { + document.getElementById(otherButtons).click(); + } + else if (otherButtons.constructor === Array) + { + for (otherButtonID of otherButtons) + { + if (otherButtonID) + { + if ( typeof(otherButtonID) == "string" ) + { + document.getElementById(otherButtonID).click(); + } + } + } + } + } + + } + else + { + // Construct and display the appropriate information + var base_string = ""; + var display_message = getDisplayMessageForXMLHttpRequest(this); + if (this.readyState == 4) + { + if(labelID){document.getElementById(labelID).innerHTML = base_string + display_message;} + } + else + { + //if(labelID){document.getElementById(labelID).innerHTML = base_string + display_message;} + } + } + }; + if (launchName == "master") + { + xmlhttp.open("GET", "callBashScript_roslaunch.php?scriptname=" + scriptname_for_php + "&emulatemocap=" + emulated_mocap, true); + xmlhttp.send(); + } + else if (launchName == "agent") + { + xmlhttp.open("GET", "callBashScript_roslaunch.php?scriptname=" + scriptname_for_php + "&emulatecrazyradio=" + emulated_crazyradio, true); + xmlhttp.send(); + } + else + { + if(labelID){document.getElementById(labelID).innerHTML = "ERROR: launch name = " + launchName + " is not a valid option";} + } + + + // Clear the other labels as requested + if (otherLabels) + { + if ( typeof(otherLabels) == "string" ) + { + document.getElementById(otherLabels).innerHTML = ""; + } + else if (otherLabels.constructor === Array) + { + for (otherLabelID of otherLabels) + { + if (otherLabelID) + { + if ( typeof(otherLabelID) == "string" ) + { + document.getElementById(otherLabelID).innerHTML = ""; + } + } + } + } + } +} \ No newline at end of file diff --git a/web_interface/html/js/temp.js b/web_interface/html/js/temp.js deleted file mode 100644 index 3f1a6f4d..00000000 --- a/web_interface/html/js/temp.js +++ /dev/null @@ -1,156 +0,0 @@ -function checkForRosMaster() -{ - // Create a variable for sending an AJAX request - var xmlhttp = new XMLHttpRequest(); - // Add the function to be run when the response is recieved - xmlhttp.onreadystatechange = function() - { - if (this.readyState == 4 && this.status == 200) - { - //var base_string = "Connection success, "; - var base_string = ""; - document.getElementById("rosMasterStatus").innerHTML = base_string + "ROS Master " + this.responseText; - } - else - { - var base_string = "Connection error"; - var error_message = getErrorMessageForXMLHttpRequest(this); - document.getElementById("rosMasterStatus").innerHTML = base_string + ", " + error_message; - // - // Alternatively, just put "loading..." - //document.getElementById("rosMasterStatus").innerHTML = "loading..."; - } - }; - xmlhttp.open("GET", "checkForRosMaster.php", true); - xmlhttp.send(); -} - - - -function checkForRosAgent() -{ - // Create a variable for sending an AJAX request - var xmlhttp = new XMLHttpRequest(); - // Add the function to be run when the response is recieved - xmlhttp.onreadystatechange = function() - { - if (this.readyState == 4 && this.status == 200) - { - //var base_string = "Connection success, "; - var base_string = ""; - document.getElementById("rosAgentStatus").innerHTML = base_string + this.responseText; - } - else - { - //var base_string = "Connection error"; - //var error_message = getErrorMessageForXMLHttpRequest(this); - //document.getElementById("rosAgentStatus").innerHTML = base_string + ", " + error_message; - // - // Alternatively, just put "loading..." - document.getElementById("rosAgentStatus").innerHTML = "loading..."; - } - }; - xmlhttp.open("GET", "checkForRosAgent.php", true); - xmlhttp.send(); -} - - - - -function launchRosAgent() -{ - // Create a variable for sending an AJAX request - var xmlhttp = new XMLHttpRequest(); - // Add the function to be run when the response is recieved - xmlhttp.onreadystatechange = function() - { - if (this.readyState == 4 && this.status == 200) - { - //var base_string = "Connection success, "; - var base_string = ""; - document.getElementById("rosLaunchAgentStatus").innerHTML = base_string + this.responseText; - // Call the function to check for and - // update the "ROS Agent Status" field - checkForRosAgent(); - } - else - { - //var base_string = "Connection error"; - //var error_message = getErrorMessageForXMLHttpRequest(this); - //document.getElementById("rosLaunchAgentStatus").innerHTML = base_string + ", " + error_message; - // - // Alternatively, just put "loading..." - document.getElementById("rosLaunchAgentStatus").innerHTML = "loading..."; - } - }; - xmlhttp.open("GET", "launchRosAgent.php", true); - xmlhttp.send(); -} - - - - - - -function killRosAgent() -{ - // Create a variable for sending an AJAX request - var xmlhttp = new XMLHttpRequest(); - // Add the function to be run when the response is recieved - xmlhttp.onreadystatechange = function() - { - if (this.readyState == 4 && this.status == 200) - { - //var base_string = "Connection success, "; - var base_string = ""; - document.getElementById("killAgentStatus").innerHTML = base_string + this.responseText; - // Call the function to check for and - // update the "ROS Agent Status" field - checkForRosAgent(); - // Call the function to update the list - // of ROS nodes - rosnodeList() - } - else - { - //var base_string = "Connection error"; - //var error_message = getErrorMessageForXMLHttpRequest(this); - //document.getElementById("killAgentStatus").innerHTML = base_string + ", " + error_message; - // - // Alternatively, just put "loading..." - document.getElementById("killAgentStatus").innerHTML = "loading..."; - } - }; - xmlhttp.open("GET", "killRosAgent.php", true); - xmlhttp.send(); -} - - - - -function rosnodeList() -{ - // Create a variable for sending an AJAX request - var xmlhttp = new XMLHttpRequest(); - // Add the function to be run when the response is recieved - xmlhttp.onreadystatechange = function() - { - if (this.readyState == 4 && this.status == 200) - { - //var base_string = "Connection success, "; - var base_string = ""; - document.getElementById("rosnodeList").innerHTML = base_string + this.responseText; - } - else - { - //var base_string = "Connection error"; - //var error_message = getErrorMessageForXMLHttpRequest(this); - //document.getElementById("rosnodeList").innerHTML = base_string + ", " + error_message; - // - // Alternatively, just put "loading..." - document.getElementById("rosnodeList").innerHTML = "loading..."; - } - }; - xmlhttp.open("GET", "rosnodeList.php", true); - xmlhttp.send(); -} diff --git a/web_interface/html/page_header.html b/web_interface/html/page_header.html index 9caeb038..a2377b8c 100644 --- a/web_interface/html/page_header.html +++ b/web_interface/html/page_header.html @@ -33,6 +33,7 @@ <script src="js/general.js?ver=0.1"></script> <script src="js/callbashscript.js?ver=0.1"></script> <script src="js/callgit.js?ver=0.1"></script> + <script src="js/roslaunch.js?ver=0.1"></script> <script src="js/sendRosMessage.js?ver=0.1"></script> <script src="js/setSetpointViaRosMessage.js?ver=0.1"></script> <script src="js/getSetpointViaRosServiceCall.js?ver=0.1"></script> diff --git a/web_interface/install_dfall_server_WIP.sh b/web_interface/install_dfall_server_WIP.sh index 09e47cfb..6df43f81 100644 --- a/web_interface/install_dfall_server_WIP.sh +++ b/web_interface/install_dfall_server_WIP.sh @@ -14,6 +14,17 @@ sudo -u www-data git clone https://... # "git pull" commands www-data ALL=(www-data) /usr/bin/git pull +# Add the "www-data" user to the "plugdev" group +# NOTE: this is the group nominated in the udev +# rules for the CrazyRadio (see the "install" +# folder). This allows a CrazyRadio node +# that is launched by the web interface to +# access the USB dongle. +sudo usermod -a -G plugdev www-data + +# To confirm the group allocation, view the file: +less /etc/group + -- GitLab