Exemplo n.º 1
0
        /// <summary>
        /// Static all-in-one method to fit the splines and evaluate at X coordinates.
        /// </summary>
        /// <param name="x">Input. X coordinates to fit.</param>
        /// <param name="y">Input. Y coordinates to fit.</param>
        /// <param name="xs">Input. X coordinates to evaluate the fitted curve at.</param>
        /// <param name="startSlope">Optional slope constraint for the first point. Single.NaN means no constraint.</param>
        /// <param name="endSlope">Optional slope constraint for the final point. Single.NaN means no constraint.</param>
        /// <param name="debug">Turn on console output. Default is false.</param>
        /// <returns>The computed y values for each xs.</returns>
        public static double[] Compute(double[] x, double[] y, double[] xs, double startSlope = double.NaN, double endSlope = double.NaN, bool debug = false)
        {
            CubicSpline spline = new CubicSpline();

            return(spline.FitAndEval(x, y, xs, startSlope, endSlope, debug));
        }
Exemplo n.º 2
0
        private static void OnMessage(string message)
        {
            message = HasData(message);

            if (message == null)
            {
                _socket.Send("42[\"manual\",{}]");
                return;
            }

            Message msg = JsonConvert.DeserializeObject <Message>(message);

            double brake_speed  = 0;
            bool   car_in_front = false;

            for (int i = 0; i < msg.sensor_fusion.Length; i++)
            {
                double[] car_data = msg.sensor_fusion[i];
                double   vx       = car_data[3];
                double   vy       = car_data[4];
                double   s        = car_data[5];
                double   d        = car_data[6];

                if (d > lane * LANE_WIDTH && d < (lane + 1) * LANE_WIDTH)
                {
                    double distance           = s - msg.s;
                    double distance_threshold = msg.speed / 1.2;

                    if (s > msg.s && distance < distance_threshold)
                    {
                        double distance_violation = distance_threshold - distance;
                        double car_vel_mph        = Math.Sqrt(vx * vx + vy * vy) * MS_TO_MPH;
                        double speed_diff         = desired_velocity_mph - car_vel_mph;
                        brake_speed  = speed_diff * BRAKE_SPEED_FACTOR + distance_violation * BRAKE_DIST_FACTOR;
                        car_in_front = true;

                        break;
                    }
                }
            }

            if (car_in_front)
            {
                brake_speed           = brake_speed > MAX_SPEED_DIFF ? MAX_SPEED_DIFF : brake_speed;
                desired_velocity_mph -= brake_speed;
            }
            // Don't use msg.speed, it lags behind and will cause desired velocity to get too high
            else if (desired_velocity_mph < TARGET_VELOCITY_MPH)
            {
                desired_velocity_mph += MAX_SPEED_DIFF;
            }

            if (current_action == null)
            {
                LaneChangeInfo info_left  = CheckCarsOnAdjacentLane(-1, msg.s, msg.sensor_fusion);
                LaneChangeInfo info_right = CheckCarsOnAdjacentLane(1, msg.s, msg.sensor_fusion);

                List <PathPlannerAction> actions = new List <PathPlannerAction>();
                double straight_cost             = Math.Abs(TARGET_VELOCITY_MPH - desired_velocity_mph) * SPEED_COST + Math.Abs(lane - DESIRED_LANE) * LANE_COST;
                actions.Add(new PathPlannerAction(0, straight_cost));

                // TODO: Use timer
                int time_since_last_last_change = Environment.TickCount - last_lane_change;

                if (time_since_last_last_change > TIME_UNTIL_NEXT_LANE_CHANGE_MS && (lane != DESIRED_LANE || car_in_front))
                {
                    if (info_left != null)
                    {
                        double lane_change_left_cost = Math.Abs((lane - 1) - DESIRED_LANE) * LANE_COST + info_left.AdjacentCarDeltaSpeed * SPEED_COST;
                        actions.Add(new PathPlannerAction(-1, lane_change_left_cost));
                    }
                    if (info_right != null)
                    {
                        double lane_change_right_cost = Math.Abs((lane + 1) - DESIRED_LANE) * LANE_COST + info_right.AdjacentCarDeltaSpeed * SPEED_COST;
                        actions.Add(new PathPlannerAction(1, lane_change_right_cost));
                    }
                }

                // Round the costs to filter out jitters. If values are the same, straight will be preferred
                // as this action is the first one in the list
                PathPlannerAction desired_action = actions.OrderBy(a => Math.Round(a.Cost)).First();
                lane += desired_action.LaneShift;
                if (desired_action.LaneShift != 0)
                {
                    current_action = desired_action;
                }
            }
            else
            {
                if (msg.d > lane * LANE_WIDTH && msg.d < (lane + 1) * LANE_WIDTH)
                {
                    current_action   = null;
                    last_lane_change = Environment.TickCount;
                }
            }

            double desired_velocity_ms = desired_velocity_mph * MPH_TO_MS;

            double smooth_step = desired_velocity_ms * TIME_TO_REACH_POINT;

            double[] rough_x   = new double[NUMBER_OF_ROUGH_POINTS];
            double[] rough_y   = new double[NUMBER_OF_ROUGH_POINTS];
            int      prev_size = msg.previous_path_x.Length;

            double ref_x   = msg.x;
            double ref_y   = msg.y;
            double ref_yaw = deg2rad(msg.yaw);

            if (prev_size < 2)
            {
                double prev_car_x = msg.x - Math.Cos(msg.yaw);
                double prev_car_y = msg.y - Math.Sin(msg.yaw);
                rough_x[0] = prev_car_x;
                rough_x[1] = msg.x;
                rough_y[0] = prev_car_y;
                rough_y[1] = msg.y;
            }
            else
            {
                ref_x = msg.previous_path_x[prev_size - 1];
                ref_y = msg.previous_path_y[prev_size - 1];
                double ref_x_prev = msg.previous_path_x[prev_size - 2];
                double ref_y_prev = msg.previous_path_y[prev_size - 2];
                ref_yaw = Math.Atan2(ref_y - ref_y_prev, ref_x - ref_x_prev);

                rough_x[0] = ref_x_prev;
                rough_x[1] = ref_x;
                rough_y[0] = ref_y_prev;
                rough_y[1] = ref_y;
            }

            for (int i = 2; i < NUMBER_OF_ROUGH_POINTS; i++)
            {
                double   next_s = msg.s + (i - 1) * ROUGH_STEP_SIZE * (current_action == null ? 1.0 : LANE_CHANGE_ROUGH_STEP_SIZE_FACTOR);
                double   next_d = GetCenterOfLane(lane);
                double[] xy     = getXY(next_s, next_d);
                rough_x[i] = xy[0];
                rough_y[i] = xy[1];
            }

            double yaw_sin = Math.Sin(-ref_yaw);
            double yaw_cos = Math.Cos(-ref_yaw);

            for (int i = 0; i < NUMBER_OF_ROUGH_POINTS; i++)
            {
                double shift_x = rough_x[i] - ref_x;
                double shift_y = rough_y[i] - ref_y;
                rough_x[i] = shift_x * yaw_cos - shift_y * yaw_sin;
                rough_y[i] = shift_x * yaw_sin + shift_y * yaw_cos;
            }

            CubicSpline spline = new CubicSpline(rough_x, rough_y);

            double[] next_x_vals = new double[NUMBER_OF_PATH_POINTS];
            double[] next_y_vals = new double[NUMBER_OF_PATH_POINTS];

            for (int i = 0; i < prev_size; i++)
            {
                next_x_vals[i] = msg.previous_path_x[i];
                next_y_vals[i] = msg.previous_path_y[i];
            }

            yaw_sin = Math.Sin(ref_yaw);
            yaw_cos = Math.Cos(ref_yaw);

            for (int i = 0; i < next_x_vals.Length - prev_size; i++)
            {
                double x_point = (i + 1) * smooth_step;
                double y_point = spline.Eval(new double[] { x_point })[0];

                double x_ref = x_point;

                x_point  = x_ref * yaw_cos - y_point * yaw_sin;
                y_point  = x_ref * yaw_sin + y_point * yaw_cos;
                x_point += ref_x;
                y_point += ref_y;

                next_x_vals[prev_size + i] = x_point;
                next_y_vals[prev_size + i] = y_point;
            }

            JObject answer = new JObject();

            answer.Add("next_x", JToken.FromObject(next_x_vals));
            answer.Add("next_y", JToken.FromObject(next_y_vals));
            string answer_str = "42[\"control\"," + answer.ToString() + "]";

            _socket.Send(answer_str);
        }