Merge "Debounce the winch button"
diff --git a/aos/network/rawrtc.cc b/aos/network/rawrtc.cc
index a92b408..89141db 100644
--- a/aos/network/rawrtc.cc
+++ b/aos/network/rawrtc.cc
@@ -12,6 +12,11 @@
 #include "flatbuffers/flatbuffers.h"
 #include "glog/logging.h"
 
+DEFINE_int32(min_ice_port, -1,
+             "Minimum port number to use for ICE candidates.");
+DEFINE_int32(max_ice_port, -1,
+             "Maximum port number to use for ICE candidates.");
+
 namespace aos {
 namespace web_proxy {
 namespace {
@@ -186,6 +191,13 @@
   CHECK_RAWRTC(rawrtc_peer_connection_configuration_set_sctp_buffer_length(
       configuration, TRANSPORT_BUFFER_LENGTH, TRANSPORT_BUFFER_LENGTH));
 
+  if (FLAGS_min_ice_port >= 0 && FLAGS_max_ice_port >= 0) {
+    CHECK_LT(FLAGS_min_ice_port, FLAGS_max_ice_port);
+    // Set the port range to use for ICE candidates.
+    CHECK_RAWRTC(rawrtc_peer_connection_configuration_set_ice_udp_port_range(
+        configuration, FLAGS_min_ice_port, FLAGS_max_ice_port));
+  }
+
   // Create peer connection
   CHECK_RAWRTC(rawrtc_peer_connection_create(
       &connection_, configuration, StaticNegotiationNeededHandler,
diff --git a/aos/network/web_proxy.cc b/aos/network/web_proxy.cc
index a486b94..4d3f513 100644
--- a/aos/network/web_proxy.cc
+++ b/aos/network/web_proxy.cc
@@ -17,7 +17,7 @@
 struct list *tmrl_get(void);
 }
 
-DEFINE_int32(proxy_port, 8080, "Port to use for the web proxy server.");
+DEFINE_int32(proxy_port, 1180, "Port to use for the web proxy server.");
 
 namespace aos {
 namespace web_proxy {
diff --git a/aos/time/time.cc b/aos/time/time.cc
index 0a633ef..882f925 100644
--- a/aos/time/time.cc
+++ b/aos/time/time.cc
@@ -221,7 +221,7 @@
   using systick_duration =
       std::chrono::duration<uint32_t, std::ratio<1, F_CPU>>;
 
-  return time_point(aos::time::round<std::chrono::nanoseconds>(
+  return time_point(std::chrono::round<std::chrono::nanoseconds>(
       std::chrono::milliseconds(ms_count) + systick_duration(counter_up)));
 
 #endif  // __linux__
diff --git a/aos/time/time.h b/aos/time/time.h
index 37ff3a8..52d763f 100644
--- a/aos/time/time.h
+++ b/aos/time/time.h
@@ -109,67 +109,6 @@
 // Converts a timeval object to a monotonic_clock::time_point.
 ::aos::monotonic_clock::time_point from_timeval(struct timeval t);
 
-namespace time_internal {
-
-template <class T>
-struct is_duration : std::false_type {};
-template <class Rep, class Period>
-struct is_duration<std::chrono::duration<Rep, Period>> : std::true_type {};
-
-}  // namespace time_internal
-
-// Returns the greatest duration t representable in ToDuration that is less or
-// equal to d.
-// Implementation copied from
-// https://en.cppreference.com/w/cpp/chrono/duration/floor.
-// TODO(Brian): Remove once we have C++17 support.
-template <class To, class Rep, class Period,
-          class = std::enable_if_t<time_internal::is_duration<To>{}>>
-constexpr To floor(const std::chrono::duration<Rep, Period> &d) {
-  To t = std::chrono::duration_cast<To>(d);
-  if (t > d) return t - To{1};
-  return t;
-}
-
-// Returns the value t representable in ToDuration that is the closest to d. If
-// there are two such values, returns the even value (that is, the value t such
-// that t % 2 == 0).
-// Implementation copied from
-// https://en.cppreference.com/w/cpp/chrono/duration/round.
-// TODO(Brian): Remove once we have C++17 support.
-template <class To, class Rep, class Period,
-          class = std::enable_if_t<
-              time_internal::is_duration<To>{} &&
-              !std::chrono::treat_as_floating_point<typename To::rep>{}>>
-constexpr To round(const std::chrono::duration<Rep, Period> &d) {
-  To t0 = aos::time::floor<To>(d);
-  To t1 = t0 + To{1};
-  auto diff0 = d - t0;
-  auto diff1 = t1 - d;
-  if (diff0 == diff1) {
-    if (t0.count() & 1) return t1;
-    return t0;
-  } else if (diff0 < diff1) {
-    return t0;
-  }
-  return t1;
-}
-
-// Returns the nearest time point to tp representable in ToDuration, rounding to
-// even in halfway cases, like std::chrono::round in C++17.
-// Implementation copied from
-// https://en.cppreference.com/w/cpp/chrono/time_point/round.
-// TODO(Brian): Remove once we have C++17 support.
-template <class To, class Clock, class FromDuration,
-          class = std::enable_if_t<
-              time_internal::is_duration<To>{} &&
-              !std::chrono::treat_as_floating_point<typename To::rep>{}>>
-constexpr std::chrono::time_point<Clock, To> round(
-    const std::chrono::time_point<Clock, FromDuration> &tp) {
-  return std::chrono::time_point<Clock, To>{
-      aos::time::round<To>(tp.time_since_epoch())};
-}
-
 }  // namespace time
 }  // namespace aos
 
diff --git a/third_party/rawrtc/rawrtc/include/rawrtc/ice_gather_options.h b/third_party/rawrtc/rawrtc/include/rawrtc/ice_gather_options.h
index e676947..d30613b 100644
--- a/third_party/rawrtc/rawrtc/include/rawrtc/ice_gather_options.h
+++ b/third_party/rawrtc/rawrtc/include/rawrtc/ice_gather_options.h
@@ -34,6 +34,14 @@
     enum rawrtc_ice_gather_policy const gather_policy);
 
 /*
+ * Force ICE candidates to be generated within a specific range of UDP ports.
+ */
+enum rawrtc_code rawrtc_ice_gather_options_set_udp_port_range(
+    struct rawrtc_ice_gather_options* const options,
+    uint16_t min_udp_port,
+    uint16_t max_udp_port);
+
+/*
  * Add an ICE server to the gather options.
  */
 enum rawrtc_code rawrtc_ice_gather_options_add_server(
diff --git a/third_party/rawrtc/rawrtc/include/rawrtc/peer_connection_configuration.h b/third_party/rawrtc/rawrtc/include/rawrtc/peer_connection_configuration.h
index 6d92d20..c331211 100644
--- a/third_party/rawrtc/rawrtc/include/rawrtc/peer_connection_configuration.h
+++ b/third_party/rawrtc/rawrtc/include/rawrtc/peer_connection_configuration.h
@@ -94,3 +94,11 @@
  */
 enum rawrtc_code rawrtc_peer_connection_configuration_set_sctp_mtu_discovery(
     struct rawrtc_peer_connection_configuration* configuration, bool on);
+
+/*
+ * Force local ICE candidate generation to use the specified local UDP ports.
+ */
+enum rawrtc_code rawrtc_peer_connection_configuration_set_ice_udp_port_range(
+    struct rawrtc_peer_connection_configuration* configuration,
+    uint16_t min_port,
+    uint16_t max_port);
diff --git a/third_party/rawrtc/rawrtc/src/ice_gather_options/options.c b/third_party/rawrtc/rawrtc/src/ice_gather_options/options.c
index 92dbb06..24005ce 100644
--- a/third_party/rawrtc/rawrtc/src/ice_gather_options/options.c
+++ b/third_party/rawrtc/rawrtc/src/ice_gather_options/options.c
@@ -43,6 +43,25 @@
     return RAWRTC_CODE_SUCCESS;
 }
 
+enum rawrtc_code rawrtc_ice_gather_options_set_udp_port_range(
+    struct rawrtc_ice_gather_options* const options,
+    uint16_t min_udp_port,
+    uint16_t max_udp_port) {
+
+    if (!options) {
+        return RAWRTC_CODE_INVALID_ARGUMENT;
+    }
+
+    if (max_udp_port <= min_udp_port) {
+        return RAWRTC_CODE_INVALID_ARGUMENT;
+    }
+
+    options->udp_port_range.min = min_udp_port;
+    options->udp_port_range.max = max_udp_port;
+
+    return RAWRTC_CODE_SUCCESS;
+}
+
 /*
  * Add an ICE server instance to the gather options.
  */
diff --git a/third_party/rawrtc/rawrtc/src/ice_gather_options/options.h b/third_party/rawrtc/rawrtc/src/ice_gather_options/options.h
index c43b9c8..28a8474 100644
--- a/third_party/rawrtc/rawrtc/src/ice_gather_options/options.h
+++ b/third_party/rawrtc/rawrtc/src/ice_gather_options/options.h
@@ -7,6 +7,10 @@
 struct rawrtc_ice_gather_options {
     enum rawrtc_ice_gather_policy gather_policy;
     struct list ice_servers;
+    struct {
+        uint16_t min;
+        uint16_t max;
+    } udp_port_range;
 };
 
 enum rawrtc_code rawrtc_ice_gather_options_add_server_internal(
diff --git a/third_party/rawrtc/rawrtc/src/ice_gatherer/gatherer.c b/third_party/rawrtc/rawrtc/src/ice_gatherer/gatherer.c
index 51002fe..6a06338 100644
--- a/third_party/rawrtc/rawrtc/src/ice_gatherer/gatherer.c
+++ b/third_party/rawrtc/rawrtc/src/ice_gatherer/gatherer.c
@@ -106,6 +106,12 @@
         goto out;
     }
 
+    err = trice_set_port_range(gatherer->ice, options->udp_port_range.min, options->udp_port_range.max);
+    if (err) {
+        DEBUG_WARNING("Unable to set trickle ICE port range, reason: %m\n", err);
+        goto out;
+    }
+
     // Get local DNS servers
     err = dns_srv_get(NULL, 0, dns_servers, &n_dns_servers);
     if (err) {
diff --git a/third_party/rawrtc/rawrtc/src/peer_connection/connection.c b/third_party/rawrtc/rawrtc/src/peer_connection/connection.c
index ceb1a43..c3730b0 100644
--- a/third_party/rawrtc/rawrtc/src/peer_connection/connection.c
+++ b/third_party/rawrtc/rawrtc/src/peer_connection/connection.c
@@ -520,6 +520,13 @@
         return error;
     }
 
+    error = rawrtc_ice_gather_options_set_udp_port_range(
+        options, connection->configuration->ice_udp_port_range.min,
+        connection->configuration->ice_udp_port_range.max);
+    if (error) {
+        return error;
+    }
+
     // Add ICE servers to gather options
     for (le = list_head(&connection->configuration->ice_servers); le != NULL; le = le->next) {
         struct rawrtc_ice_server* const source_server = le->data;
diff --git a/third_party/rawrtc/rawrtc/src/peer_connection_configuration/configuration.c b/third_party/rawrtc/rawrtc/src/peer_connection_configuration/configuration.c
index ebf16f2..48fb719 100644
--- a/third_party/rawrtc/rawrtc/src/peer_connection_configuration/configuration.c
+++ b/third_party/rawrtc/rawrtc/src/peer_connection_configuration/configuration.c
@@ -258,3 +258,18 @@
     configuration->sctp.mtu_discovery = on;
     return RAWRTC_CODE_SUCCESS;
 }
+
+enum rawrtc_code rawrtc_peer_connection_configuration_set_ice_udp_port_range(
+    struct rawrtc_peer_connection_configuration* configuration,
+    uint16_t min_port,
+    uint16_t max_port) {
+    if (!configuration) {
+        return RAWRTC_CODE_INVALID_ARGUMENT;
+    }
+    if (max_port <= min_port) {
+        return RAWRTC_CODE_INVALID_ARGUMENT;
+    }
+    configuration->ice_udp_port_range.min = min_port;
+    configuration->ice_udp_port_range.max = max_port;
+    return RAWRTC_CODE_SUCCESS;
+}
diff --git a/third_party/rawrtc/rawrtc/src/peer_connection_configuration/configuration.h b/third_party/rawrtc/rawrtc/src/peer_connection_configuration/configuration.h
index 34fd7c1..f89e7b4 100644
--- a/third_party/rawrtc/rawrtc/src/peer_connection_configuration/configuration.h
+++ b/third_party/rawrtc/rawrtc/src/peer_connection_configuration/configuration.h
@@ -17,6 +17,10 @@
         uint32_t mtu;
         bool mtu_discovery;
     } sctp;
+    struct {
+        uint16_t min;
+        uint16_t max;
+    } ice_udp_port_range;
 };
 
 enum rawrtc_code rawrtc_peer_connection_configuration_add_ice_server_internal(
diff --git a/y2020/control_loops/superstructure/shooter/shooter.cc b/y2020/control_loops/superstructure/shooter/shooter.cc
index 9f4edb2..e6fa3cf 100644
--- a/y2020/control_loops/superstructure/shooter/shooter.cc
+++ b/y2020/control_loops/superstructure/shooter/shooter.cc
@@ -28,7 +28,8 @@
       (std::abs(goal->velocity_finisher() - finisher_.avg_angular_velocity()) <
            kVelocityToleranceFinisher &&
        std::abs(goal->velocity_finisher() - finisher_.velocity()) <
-           kVelocityToleranceFinisher);
+           kVelocityToleranceFinisher &&
+       goal->velocity_finisher() > kVelocityToleranceFinisher);
   accelerator_ready_ =
       (std::abs(goal->velocity_accelerator() -
                 accelerator_left_.avg_angular_velocity()) <
@@ -39,7 +40,8 @@
        std::abs(goal->velocity_accelerator() - accelerator_left_.velocity()) <
            kVelocityToleranceAccelerator &&
        std::abs(goal->velocity_accelerator() - accelerator_right_.velocity()) <
-           kVelocityToleranceAccelerator);
+           kVelocityToleranceAccelerator &&
+       goal->velocity_accelerator() > kVelocityToleranceAccelerator);
   return (finisher_ready_ && accelerator_ready_);
 }
 
@@ -74,15 +76,7 @@
   accelerator_right_.Update(output == nullptr);
 
   if (goal) {
-    if (UpToSpeed(goal) &&
-        goal->velocity_finisher() > kVelocityToleranceFinisher &&
-        goal->velocity_accelerator() > kVelocityToleranceAccelerator) {
-      ready_ = true;
-    } else {
-      ready_ = false;
-      finisher_ready_ = false;
-      accelerator_ready_ = false;
-    }
+    ready_ = UpToSpeed(goal);
   }
 
   flatbuffers::Offset<FlywheelControllerStatus> finisher_status_offset =
diff --git a/y2020/control_loops/superstructure/superstructure.h b/y2020/control_loops/superstructure/superstructure.h
index 3eb6cb2..07b7575 100644
--- a/y2020/control_loops/superstructure/superstructure.h
+++ b/y2020/control_loops/superstructure/superstructure.h
@@ -32,7 +32,7 @@
   static constexpr std::chrono::milliseconds kPreloadingTimeout =
       std::chrono::seconds(2);
   static constexpr std::chrono::milliseconds kPreloadingBackpowerDuration =
-      std::chrono::milliseconds(50);
+      std::chrono::milliseconds(55);
 
   using PotAndAbsoluteEncoderSubsystem =
       ::frc971::control_loops::StaticZeroingSingleDOFProfiledSubsystem<
diff --git a/y2020/joystick_reader.cc b/y2020/joystick_reader.cc
index bf6cd9f..ec4965d 100644
--- a/y2020/joystick_reader.cc
+++ b/y2020/joystick_reader.cc
@@ -42,6 +42,7 @@
 const ButtonLocation kAutoTrack(3, 3);
 const ButtonLocation kAutoNoHood(3, 5);
 const ButtonLocation kHood(3, 2);
+const ButtonLocation kShootSlow(4, 2);
 const ButtonLocation kFixedTurret(3, 1);
 const ButtonLocation kFeed(4, 1);
 const ButtonLocation kFeedDriver(1, 2);
@@ -151,7 +152,7 @@
     double intake_pos = -0.89;
     double turret_pos = 0.0;
     float roller_speed = 0.0f;
-    float roller_speed_compensation = 0.0f;
+    bool roller_speed_compensation = false;
     double accelerator_speed = 0.0;
     double finisher_speed = 0.0;
     double climber_speed = 0.0;
@@ -185,12 +186,15 @@
         accelerator_speed = setpoint_fetcher_->accelerator();
         finisher_speed = setpoint_fetcher_->finisher();
       }
+    } else if (data.IsPressed(kShootSlow)) {
+      accelerator_speed = 150.0;
+      finisher_speed = 200.0;
     }
 
     if (data.IsPressed(kIntakeExtend) || data.IsPressed(kIntakeExtendDriver)) {
       intake_pos = 1.2;
       roller_speed = 7.0f;
-      roller_speed_compensation = 2.0f;
+      roller_speed_compensation = true;
       preload_intake = true;
     }
 
@@ -198,12 +202,12 @@
         superstructure_status_fetcher_->intake()->zeroed() &&
         superstructure_status_fetcher_->intake()->position() > -0.5) {
       roller_speed = std::max(roller_speed, 6.0f);
-      roller_speed_compensation = 2.0f;
+      roller_speed_compensation = true;
     }
 
     if (data.IsPressed(kIntakeIn)) {
-      roller_speed = 6.0f;
-      roller_speed_compensation = 2.0f;
+      roller_speed = 5.0f;
+      roller_speed_compensation = true;
       preload_intake = true;
     } else if (data.IsPressed(kSpit)) {
       roller_speed = -6.0f;
@@ -288,7 +292,7 @@
       superstructure_goal_builder.add_turret(turret_offset);
       superstructure_goal_builder.add_roller_voltage(roller_speed);
       superstructure_goal_builder.add_roller_speed_compensation(
-          roller_speed_compensation);
+          roller_speed_compensation ? 1.5f : 0.0f);
       superstructure_goal_builder.add_shooter(shooter_offset);
       superstructure_goal_builder.add_shooting(data.IsPressed(kFeed) ||
                                                data.IsPressed(kFeedDriver));
diff --git a/y2020/y2020_roborio.json b/y2020/y2020_roborio.json
index 89dded8..3176d41 100644
--- a/y2020/y2020_roborio.json
+++ b/y2020/y2020_roborio.json
@@ -369,6 +369,7 @@
     {
       "name": "web_proxy",
       "executable_name": "web_proxy_main",
+      "args": ["--min_ice_port=5800", "--max_ice_port=5810"],
       "nodes": [
         "roborio"
       ]