diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000000000000000000000000000000000000..57cdbadebf970588cf1432063ae971bfce7b51a3 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "html/js-yaml"] + path = html/js-yaml + url = https://github.com/nodeca/js-yaml.git diff --git a/config/goals.yaml b/config/goals.yaml new file mode 100644 index 0000000000000000000000000000000000000000..30b1c15a06f52f64ffea4c8da2cf9bdd404a991d --- /dev/null +++ b/config/goals.yaml @@ -0,0 +1,18 @@ +goals: + - id: goal1 + x: 8.2 + y: 6.0 + yaw: 1.5709 + type: 0 + + - id: goal2 + x: -1.3 + y: 6.0 + yaw: -1.5709 + type: 1 + + - id: goal3 + x: -0.2 + y: -0.2 + yaw: 0.0 + type: 2 diff --git a/html/data/goals0.yaml b/html/data/goals0.yaml new file mode 100644 index 0000000000000000000000000000000000000000..d4a1753aa2e417e59bdbd4ccbbedff62f71cff53 --- /dev/null +++ b/html/data/goals0.yaml @@ -0,0 +1,18 @@ +goals: + - id: goal1 + x: 1.0 + y: 0.22 + yaw: 0.0 + type: 0 + + - id: goal2 + x: 2.0 + y: 0.22 + yaw: 0.0 + type: 1 + + - id: goal3 + x: 3.0 + y: -0.22 + yaw: 3.14159 + type: 2 diff --git a/html/data/goals1.yaml b/html/data/goals1.yaml new file mode 100644 index 0000000000000000000000000000000000000000..d4a1753aa2e417e59bdbd4ccbbedff62f71cff53 --- /dev/null +++ b/html/data/goals1.yaml @@ -0,0 +1,18 @@ +goals: + - id: goal1 + x: 1.0 + y: 0.22 + yaw: 0.0 + type: 0 + + - id: goal2 + x: 2.0 + y: 0.22 + yaw: 0.0 + type: 1 + + - id: goal3 + x: 3.0 + y: -0.22 + yaw: 3.14159 + type: 2 diff --git a/html/data/goals2.yaml b/html/data/goals2.yaml new file mode 100644 index 0000000000000000000000000000000000000000..d4a1753aa2e417e59bdbd4ccbbedff62f71cff53 --- /dev/null +++ b/html/data/goals2.yaml @@ -0,0 +1,18 @@ +goals: + - id: goal1 + x: 1.0 + y: 0.22 + yaw: 0.0 + type: 0 + + - id: goal2 + x: 2.0 + y: 0.22 + yaw: 0.0 + type: 1 + + - id: goal3 + x: 3.0 + y: -0.22 + yaw: 3.14159 + type: 2 diff --git a/html/images/carnet.png b/html/images/carnet.png new file mode 100644 index 0000000000000000000000000000000000000000..9c7b37270a99b2fafd5b3193e87502d16d580e8f Binary files /dev/null and b/html/images/carnet.png differ diff --git a/html/index.html b/html/index.html index c300af0986ce073bde3e2ca704423036c45e6356..ad61240316a1356c9ba6a48a3da1e036960ae2bb 100644 --- a/html/index.html +++ b/html/index.html @@ -16,30 +16,59 @@ <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.1/dist/js/bootstrap.bundle.min.js" integrity="sha384-/bQdsTh/da6pkI1MST/rWKFNjaCP5gBSY4sEBT38Q/9RBh9AH40zEOg7Hlq2THRZ" crossorigin="anonymous"></script> <script src="timer.js"></script> + <script src="./js-yaml/dist/js-yaml.min.js"></script> <link rel="stylesheet" href="style.css"> <script> - document.title="index"; + document.title="ADC GUI"; var ip; ip = document.domain; //ip = window.location.hostname //ip = prompt("Enter server ip address", "192.168.100.219"); + ////////////////////////////////////// + ///ROS var ros = new ROSLIB.Ros(); ros.connect('ws://'+ip+':9090'); + + var goals_param = new ROSLIB.Param({ + ros : ros, + name : '/goals' + }); + + var adc_jury_service_client = new ROSLIB.Service({ + ros : ros, + name : '/jury_mode', + serviceType : 'iri_adc_msgs/jury_mode' + }); + + var srv_request = new ROSLIB.ServiceRequest({ + enable : false + }); + + var adc_jury_client = new ROSLIB.ActionClient({ + ros : ros, + serverName : '/adc_jury', + actionName : 'iri_adc_msgs/adc_juryAction' + }); + + var goal_array_msg = new ROSLIB.Message( + { + }); var team; var challenge; var feedback_text=""; + var last_feedback_line=""; var i=0; - - - //console.log("team=",team); - //localStorage.setItem('team', team); - - //console.log("set team var"); - //console.log("get team: "+localStorage.getItem('team')); + var service_answered=false; + var service_ok=false; + var received_feedback=false; + var feedback_timer; + var jury_mode_running=false; + var action_running=false; + var goals_loaded=false; function update_team() { @@ -53,18 +82,240 @@ localStorage.setItem('challenge', challenge); } - function add_feedback() + function send_goal() { - feedback_new_line='This is a feedback text example '+i; - feedback_text = feedback_new_line + '\ ' + feedback_text ; - i=i+1; + //load_goals_from_yaml(); //TODO: sync load. Now is async and done on input.onchange and at the beginning + + init_goal_msg(); + + action_goal.send(); + + document.getElementById("action_info").innerHTML = "Goal sent. Expecting feedback..."; + document.getElementById("action_info").style.backgroundColor = 'white' ; + + feedback_watchdog_timer(); + //action_running=true; //true when received feedback? + } + + function init_goal_msg() + { + action_goal = new ROSLIB.Goal( + { + actionClient : adc_jury_client, + goalMessage : goal_array_msg + } + ); + + action_goal.on('feedback', function(msg) + { + received_feedback=true; + action_running=true; + document.getElementById("action_info").innerHTML = "Feedback received!"; + document.getElementById("action_info").style.backgroundColor = 'green' ; + var feedback_new_line= msg.status; + add_feedback_line(feedback_new_line); + }); + + action_goal.on('result', function(result) + { + if(action_running) + { + finish_action(); + } + }); + + } + + function finish_action() + { + if(timer_running) + startStop(); + document.getElementById("action_info").innerHTML = "Action finished"; + document.getElementById("action_info").style.backgroundColor = 'white' ; + action_running=false; + clearTimeout(feedback_timer); + add_feedback_line("Finished"); + } + + function cancel_goal() + { + action_goal.cancel(); + document.getElementById("action_info").innerHTML = "Goal cancelled"; + document.getElementById("action_info").style.backgroundColor = 'white' ; + } + + function jury_mode() + { + if(!jury_mode_running) + jury_mode_enable(); + else + jury_mode_disable(); + } + + function jury_mode_enable() + { + document.getElementById("service_info").innerHTML = "Called service, waiting response..."; + document.getElementById("service_info").style.backgroundColor = 'yellow' ; + document.getElementById('jury_mode_button').disabled=true; + srv_request.enable=true; + adc_jury_service_client.callService(srv_request, + function(result) + { + service_answered=true; + service_ok=true; + jury_mode_answered(); + }, + function(result) + { + service_answered=true; + service_ok=false; + jury_mode_answered(); + }); + } + + function jury_mode_disable() + { + document.getElementById("service_info").innerHTML = "Called service server, waiting response..."; + document.getElementById("service_info").style.backgroundColor = 'yellow' ; + document.getElementById('jury_mode_button').disabled=true; + srv_request.enable=false; + adc_jury_service_client.callService(srv_request, + function(result) + { + service_answered=true; + service_ok=true; + jury_mode_answered(); + }, + function(result) + { + service_answered=true; + service_ok=false; + jury_mode_answered(); + }); + } + + function jury_mode_answered() + { + document.getElementById('jury_mode_button').disabled=false; + if(service_ok) + { + service_ok=false; + document.getElementById("service_info").innerHTML = "Service responded"; + document.getElementById("service_info").style.backgroundColor = 'green' ; + if(!jury_mode_running) + { + add_feedback_line("Jury mode enabled"); + jury_mode_running = true; + document.getElementById("jury_mode_button").innerHTML = "DISABLE"; + document.getElementById('jury_mode_button').style.backgroundColor="Red"; + if(document.getElementById("startStop").innerHTML=="START") + document.getElementById('startStop').disabled=true; + } + else + { + add_feedback_line("Jury mode disabled"); + jury_mode_running = false; + document.getElementById("jury_mode_button").innerHTML = "ENABLE"; + document.getElementById('jury_mode_button').style.backgroundColor="RoyalBlue"; + if(document.getElementById("startStop").innerHTML=="START") + document.getElementById('startStop').disabled=false; + } + } + else + { + document.getElementById("service_info").innerHTML = "ERROR: couldn't contact service server!!!"; + document.getElementById("service_info").style.backgroundColor = 'red' ; + console.log("ERROR: couldn't contact service server!!!"); + } + } + + // function add_fake_feedback() + // { + // feedback_new_line=document.getElementById("fake_feedback_text").value+" "+i; + // i=i+1; + // add_feedback_line(feedback_new_line); + // } + + function add_feedback_line(text) + { + if(text!=last_feedback_line) + { +// var currentTime = new Date(); +// var secs = Math.floor(currentTime.getTime()/1000); +// var nsecs = Math.round(1000000000*(currentTime.getTime()/1000-secs)); +// var time = "["+secs+","+nsecs+"]: "; + var time = "[" + time_string + "]: "; + + feedback_text = time + text + '
' + feedback_text ; + document.getElementById("feedback_text").innerHTML = feedback_text; + } + last_feedback_line=text; + } + + function clear_feedback() + { + feedback_text=""; + last_feedback_line=""; + i=0; document.getElementById("feedback_text").innerHTML = feedback_text; } + + function feedback_watchdog_timer() + { + feedback_timer = setTimeout( + function() + { + if(action_running) + { + if(received_feedback) + { + received_feedback=false; + document.getElementById("action_info").innerHTML = "Feedback received!"; + document.getElementById("action_info").style.backgroundColor = 'green' ; + feedback_watchdog_timer(); + } + else + { + //clearTimeout(feedback_timer); + console.log("ERROR: feedback not received!"); + document.getElementById("action_info").innerHTML = "ERROR: feedback NOT received!"; + document.getElementById("action_info").style.backgroundColor = 'red' ; + //TODO: what to do then? + feedback_watchdog_timer(); + } + } + },2000); + } + + function load_goals_from_yaml() + { + goals_file = document.getElementById("goals_file").value; + var goals_from_yaml; + + $.get(goals_file).done(function (data) + //$.get( goals_file, function( data ) + { + goals_from_yaml = jsyaml.load( data ); + + //TODO: check if loaded succesfully or not + //console.log("Loaded goals"); + + goal_array_msg = new ROSLIB.Message( + { + goals: goals_from_yaml + }); + + goals_loaded=true; + + }); + } $(document).ready ( function () { + load_goals_from_yaml(); + if ("team" in localStorage) { team = localStorage.getItem('team'); @@ -73,6 +324,7 @@ else { team=1; + localStorage.setItem('team', team); } if ("challenge" in localStorage) @@ -83,22 +335,22 @@ else { challenge=1; + localStorage.setItem('challenge', challenge); } - - } ); </script> </head> + <body> <style>body { padding-top: 60px;}</style> <nav class="navbar navbar-expand-md navbar-dark bg-dark fixed-top"> - <a class="navbar-brand" href="https://www.iri.upc.edu"> - <img src="images/iri.png" width="30" height="30" class="d-inline-block align-top" alt=""> - IRI + <a class="navbar-brand" href="https://autonomous-driving-challenge.com/"> + <img src="images/carnet.png" width="30" height="30" class="d-inline-block align-top" alt=""> + ADC </a> <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarsExampleDefault" aria-controls="navbarsExampleDefault" aria-expanded="false" aria-label="Toggle navigation"> <span class="navbar-toggler-icon"></span> @@ -109,37 +361,65 @@ <li class="nav-item active"> <a class="nav-link" href="index.html"><b>Home</b></a> </li> + <!-- <li class="nav-item"> <a class="nav-link" href="map.html">Map<a/> </li> - </li> + --> </ul> </div> </nav> <main role="main" class="container"> + Team:          <input type="number" id="team_input" min="1" max="6" step="1" style="width: 2em" value="1" onchange="update_team()"> <br> - Challenge: <input type="number" id="challenge_input" min="1" max="5" step="1" style="width: 2em" value="1" onchange="update_challenge()"> + Challenge: <input type="number" id="challenge_input" min="0" max="5" step="1" style="width: 2em" value="1" onchange="update_challenge()"> + + <hr> + <b>Goals file:</b> (will be automatic for each chosen challenge # (goals#.yaml)) <br> - Timer: + + <input type="text" id="goals_file" value="./data/goals0.yaml" onchange="load_goals_from_yaml()"/> <br> - <p id = "output" class = "text-left">00:00:00</p> + <!--<button class="btn btn-primary" id = "load_goals_button" onclick = "load_goals_from_yaml()">Load goals</button>--> + + <hr> + + <b>Attempt</b> + <br> + <div id = "controls" class = "text-left"> - <button class="btn btn-primary" id = "startPause" onclick = "startPause()">START</button> - <button class="btn btn-danger" onclick = "reset()">RESET</button> + <button class="btn btn-success" id = "startStop" style="width:49.25%; height: 50px" onclick = "this.blur();startStop()">START</button> + <br> + <span id="action_info" > </span> + <!--<button class="btn btn-danger" id = "resetButton" style="width:49.25%; height: 50px; background-color: red" onclick = "this.blur();reset()">RESET</button>--> </div> - Feedback: - <div style="overflow-y: auto; height:75px; border-style:solid"> - <!-- Feedback text example1<br> - Feedback text example2<br> - Feedback text example3<br> - Feedback text example4<br> - Feedback text example5<br> - Feedback text example6<br>--> - <span id="feedback_text">Received feedback messages will be shown here</span> + <br> + <p id = "output" class = "text-left">00:00:00</p> + + + <hr> + + <b>Jury Mode</b> + <div id = "controls2" class = "text-left"> + <button class="btn btn-primary" id = "jury_mode_button" style="width:49.25%; height: 50px" onclick = "this.blur();jury_mode()">ENABLE</button> </div> - <button class="btn btn-primary" id = "add_feedback" onclick = "add_feedback()">Add fake feedback</button> + <span id="service_info" > </span> + + <hr> + <b>Feedback</b> + <br> + <textarea readonly id="feedback_text" style="resize: vertical; width:100%; border-style:solid;" wrap='off' rows="3" cols="auto">Received feedback messages will be shown here. Each message starting a new line</textarea> + <br> + <button class="btn btn-danger" id = "clear_feedback" onclick = "this.blur();clear_feedback()">Clear feedback</button> + <br> + <!-- + Debug: + <br><button class="btn btn-primary" id = "add_feedback" onclick = "add_fake_feedback()">Add fake feedback</button> + <input type="text" id="fake_feedback_text" size="50" value="This is a fake feedback text example"/> + <hr> + --> </main> diff --git a/html/js-yaml b/html/js-yaml new file mode 160000 index 0000000000000000000000000000000000000000..49baadd52af887d2991e2c39a6639baa56d6c71b --- /dev/null +++ b/html/js-yaml @@ -0,0 +1 @@ +Subproject commit 49baadd52af887d2991e2c39a6639baa56d6c71b diff --git a/html/map.html b/html/map.html index 79bc7a3c44fd997479a75bda1ce4b4505efdb6bb..5d3789963543f8f4127310945913ccefe2e7cc9b 100644 --- a/html/map.html +++ b/html/map.html @@ -77,8 +77,8 @@ <nav class="navbar navbar-expand-md navbar-dark bg-dark fixed-top"> <a class="navbar-brand" href="https://www.iri.upc.edu"> - <img src="images/iri.png" width="30" height="30" class="d-inline-block align-top" alt=""> - IRI + <img src="images/carnet.png" width="30" height="30" class="d-inline-block align-top" alt=""> + ADC </a> <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarsExampleDefault" aria-controls="navbarsExampleDefault" aria-expanded="false" aria-label="Toggle navigation"> <span class="navbar-toggler-icon"></span> diff --git a/html/style.css b/html/style.css index e47b2bf4bd3f519219e45efc34440890c8a1eeff..e3c7fd0bc0e88fe59b9b2271802799dd58ef2d23 100644 --- a/html/style.css +++ b/html/style.css @@ -6,7 +6,7 @@ } #output { - font-size: 2.0em; + font-size: 3.0em; width: auto; height: auto; background-color: white; diff --git a/html/timer.js b/html/timer.js index 4939fbaa26688cee01a03cc24dfaf9d4711b7b96..30b78e2ac93ffd2fbd80119faef9283459145f70 100644 --- a/html/timer.js +++ b/html/timer.js @@ -1,27 +1,37 @@ var time = 0; -var running = 0; +var timer_running = false; +var timer_timeout; +var time_string=""; -function startPause() { - if (running == 0) { - running = 1; - increment(); - document.getElementById("startPause").innerHTML = "PAUSE"; - } else { - running = 0; - document.getElementById("startPause").innerHTML = "RESUME"; - } +function startStop() +{ + if (!timer_running) + { + time=0; + timer_running = true; + increment(); + document.getElementById("startStop").innerHTML = "STOP"; + document.getElementById('startStop').style.backgroundColor="red"; + send_goal(); + } + else + { + timer_running = false; + document.getElementById("startStop").innerHTML = "START"; + document.getElementById('startStop').style.backgroundColor="green"; + cancel_goal(); + } } -function reset(){ - running = 0; - time = 0; - document.getElementById("startPause").innerHTML = "START"; - document.getElementById("output").innerHTML = "00:00:00"; -} - -function increment() { - if (running == 1) { - setTimeout(function() { +function increment() +{ + if (timer_running) + { + timer_timeout = setTimeout( + function() + { + if(timer_running) + { time++; var mins = Math.floor(time/10/60); var secs = Math.floor(time/10 % 60); @@ -32,8 +42,10 @@ function increment() { if (secs < 10) { secs = "0" + secs; } - document.getElementById("output").innerHTML = mins + ":" + secs + ":" + "0" + tenths; + time_string = mins + ":" + secs + ":" + "0" + tenths; + document.getElementById("output").innerHTML = time_string ; increment(); - },100); - } + } + },100); + } }