¿Qué es la plataforma de conducción autónoma Apollo?

Introducción al proyecto Apolo

Apollo es una plataforma de software lanzada por Baidu para socios de la industria automotriz y los campos de la conducción autónoma. Lanzado el 19 de abril de 2017, su objetivo es proporcionar una plataforma de software abierta, completa y segura a los socios de la industria automotriz y los campos de la conducción autónoma para ayudarlos a construir rápidamente un conjunto completo propio combinando vehículos y sistemas de hardware. sistema. El nombre de este plan como plan "Apolo" tomó prestado el significado del plan de alunizaje Apolo.

Puede experimentar la experiencia real de conducción de automóviles de Apollo aquí: Prueba de manejo de automóviles no tripulados CES 2018 Baidu Apollo 2.0 en Sunnyvale, EE. UU .

Nivel SAE

Para la conducción autónoma, la SAE (Sociedad de Ingenieros Automotrices, Sociedad Estadounidense de Ingenieros Automotrices) Internacional lanzó un sistema de clasificación de seis niveles diferentes, desde sistemas completamente manuales hasta sistemas completamente automáticos en 2014. Las descripciones de estos seis niveles son las siguientes:

Nivel SAE Nombre Capacidad del sistema Participación del conductor

La dirección del sitio web oficial del proyecto Apollo es la siguiente: http://apollo.auto

En el sitio web oficial del proyecto Apollo, el proyecto tiene las siguientes características:

  • Capacidades abiertas : Apollo es una plataforma abierta, completa y segura que ayudará a los socios de la industria automotriz y los campos de la conducción autónoma a construir rápidamente sus propios sistemas de conducción autónoma combinando vehículos y sistemas de hardware.
  • Comparta recursos y acelere la innovación : la plataforma abierta Apollo le proporciona servicios de mapas de alta precisión con tecnología líder, amplia cobertura y alta automatización; el único motor de simulación abierto del mundo con datos masivos; el mayor volumen de datos abiertos del mundo, conducción automática basada en profundidad Algoritmo de aprendizaje de extremo a extremo.
  • Beneficio mutuo continuo : con la plataforma abierta Apollo, puede desarrollar, probar e implementar vehículos autónomos más rápido. Cuantos más participantes, más datos de conducción se acumulan. En comparación con los sistemas cerrados, Apollo puede madurar a una velocidad más rápida, lo que permite que cada participante se beneficie más, ¡y la plataforma Apollo también mejorará con su participación!

Actualmente, hay casi 100 socios enumerados en su sitio web oficial.

El plano del proyecto Apolo es el siguiente:

  • 2017-07: Capacidades de conducción autónoma en lugares cerrados
  • 2017-12: Capacidades de conducción autónoma en condiciones simples de carreteras urbanas
  • 2020-12: Conducción totalmente automatizada en autopistas y vías urbanas habituales

El objetivo principal de la recién lanzada versión Apollo 2.5 es la conducción autónoma de nivel L2.

La información detallada sobre la evolución de la versión Apollo se muestra en la siguiente figura:

Código fuente

El código fuente del proyecto Apollo se puede obtener aquí: https://github.com/ApolloAuto . Esta ruta contiene 5 proyectos de código abierto:

  • apollo : El código fuente de la plataforma de conducción autónoma Apollo.
  • apollo-platform : El proyecto Apollo se basa en Robot Operating System (ROS) , aquí está el código relevante. El código fuente publicado actualmente se basa en ROS Indigo.
  • apollo-DuerOS : Apollo-DuerOS es un conjunto de productos telemáticos relacionados con Apollo, que incluye varios productos de código abierto. Acerca de DuerOS, consulte aquí: DuerOS .
  • apollo-kernel : Kernel de Linux para el proyecto Apollo.
  • http://ApolloAuto.github.io : Documentos relacionados con Apollo, a los que se puede acceder a través de https://apolloauto.github.io .

compilar y ejecutar

Consulte aquí para obtener información sobre cómo compilar y ejecutar el proyecto Apollo: https://apolloauto.github.io .

Se requieren entornos Ubuntu y Docker para realizar esta tarea.

Una vez completada la compilación, puede utilizar la función Dreamview proporcionada por el proyecto en su computadora para familiarizarse con el entorno. Se accede a Dreamview a través de un navegador y su interfaz se ve así:

Para obtener más instrucciones sobre Dreamview, consulte aquí: Tabla de uso de Dreamview

desarrollar

El desarrollo de la plataforma Ablo incluye los siguientes pasos:

  1. Comprender el motor de simulación fuera de línea Dreamviewer y los módulos de software principales ApolloAuto
  • Aprenda cómo funcionan los algoritmos en los automóviles
  • Comience a desarrollar inmediatamente sin utilizar un automóvil o hardware real

  1. Integración del módulo principal
  • Módulo de ubicación
  • Módulo de percepción: (admite soluciones de terceros, como cámaras basadas en chip Mobileye ES4 para el desarrollo L2) Procesa datos de nubes de puntos desde Lidar y devuelve información de objetos segmentados a pedido.
  • Módulo de planificación: calcula rutas de ajuste y proporciona información de control dinámico del vehículo para los segmentos de ruta atendidos por la ruta.
  • Módulo de rutina: implementación local de búsqueda de segmentos de ruta a través de la interfaz Navigator.

  1. Mapas en alta definición. La conducción autónoma de nivel L4 requiere mapas de alta definición. Dado que los vehículos autónomos necesitan reconstruir el mundo 3D en el sistema, las coordenadas de los objetos de referencia desempeñan un papel importante en la reubicación de mapas y la conducción autónoma en el mundo real.
  2. La simulación en línea basada en la nube impulsa motores de escenarios y centros de datos.
  • Como socio de Baidu, se le otorgará un certificado Docker para enviar nuevas imágenes y reproducir los algoritmos que desarrolle en la nube.
  • Cree y administre escenarios complejos para simular experiencias de conducción del mundo real.

Apolo y ROS

El nombre completo de ROS es Sistema Operativo de Robot. Contiene un conjunto de bibliotecas y herramientas de software de código abierto diseñadas específicamente para crear aplicaciones robóticas. La dirección de su sitio web oficial está aquí: http://www.ros.org .

Un sistema ROS contiene una serie de nodos independientes. La comunicación entre estos nodos se realiza a través de un modelo de mensajería de publicación/suscripción . Por ejemplo, el controlador de un determinado sensor se puede implementar como un nodo y luego los datos del sensor se pueden enviar en forma de mensajes publicados. Estos datos pueden ser recibidos por muchos otros nodos, como filtros, sistemas de registro, etc.

Los nodos en un sistema ROS pueden estar ubicados en diferentes hosts, por ejemplo: un dispositivo Arduino publica mensajes, una computadora portátil se suscribe a estos mensajes y un teléfono Android también monitorea estos mensajes.

El sistema ROS contiene un nodo maestro. El nodo maestro permite que otros nodos se consulten entre sí para comunicarse. Todos los nodos deben registrarse en el nodo maestro y luego pueden comunicarse con otros nodos. Como se muestra abajo:

Las personas que están familiarizadas con el sistema Android pueden encontrar fácilmente que tiene una función similar a la del ServiceManager en Binder.

Los nodos se comunican entre sí mediante la publicación y suscripción a temas (Temas). Por ejemplo, en un sistema robótico, hay un módulo de cámara ubicado en el robot que adquiere datos de imágenes. Además, hay un módulo de procesamiento de imágenes en el robot que necesita obtener datos de imágenes y, al mismo tiempo, hay otro módulo ubicado en la PC personal que también necesita estos datos de imágenes. Luego, el módulo de cámara puede publicar /image_dataeste tema para que los otros dos módulos se suscriban. Su estructura se muestra en la siguiente figura:

El proyecto Apollo se basa en ROS, pero ha sido modificado, incluyendo principalmente los siguientes tres aspectos:

  1. Optimización del rendimiento de la comunicación.
  2. Topología de red descentralizada
  3. Extensión de compatibilidad de datos

Optimización del rendimiento de la comunicación.

Los vehículos autónomos contienen una gran cantidad de sensores que pueden generar datos a velocidades de frecuencia muy altas, por lo que todo el sistema tiene altos requisitos de eficiencia de transmisión de datos. En el sistema ROS, los datos deben copiarse entre los nodos de publicación y suscripción de datos. En el caso de grandes cantidades de datos, es obvio que esto afectará la eficiencia de la transmisión de datos. Por lo tanto, la primera transformación de ROS del proyecto Apollo es reducir las copias de datos a través de memoria compartida para mejorar el rendimiento de la comunicación. Como se muestra abajo:

Topología de red descentralizada

Como mencionamos anteriormente, el sistema ROS contiene un nodo maestro de comunicación y todos los demás nodos deben confiar en este nodo para comunicarse. Por tanto, es obvio que si se produce un fallo de comunicación en este nodo, afectará a la comunicación de todo el sistema. Además, toda la estructura carece de un mecanismo de recuperación de anomalías.

Por lo tanto, la segunda transformación de ROS del proyecto Apollo es eliminar esta estructura de red centralizada. Apollo utiliza el protocolo de descubrimiento de servicios RTPS (publicación-suscripción en tiempo real) para implementar una topología de red P2P completa. Todo el proceso de comunicación incluye los siguientes cuatro pasos:

Para obtener detalles sobre RTPS, consulte aquí: Publicación-Suscripción en tiempo real

Extensión de compatibilidad de datos

La última gran mejora del proyecto Apollo a ROS es el ajuste del formato de datos.

En el sistema ROS, el archivo de descripción msg se utiliza para definir la interfaz de mensajes entre módulos. Desafortunadamente, después de la actualización de la interfaz, es difícil que las diferentes versiones de los módulos sean compatibles.

Por lo tanto, Apollo eligió los datos en formato Protocol Buffers de Google para resolver este problema.

Protocol Buffers es un lenguaje de descripción de datos desarrollado por Google. Es similar a XML y puede serializar datos estructurados. Puede usarse para almacenamiento de datos, protocolos de comunicación, etc. Es independiente del idioma y de la plataforma y extremadamente escalable. En esta etapa, admite oficialmente tres lenguajes de programación: C++, JAVA y Python, pero puede encontrar una gran cantidad de paquetes de expansión de terceros que cubren casi todos los lenguajes.

Nota: Si ve el código fuente del proyecto Apollo, puede ver muchas carpetas llamadas "proto", que contienen estructuras de datos en el formato de Protocol Buffers (protobuf para abreviar).

Arquitectura de hardware

El hardware necesario en Apollo 2.5 se muestra en la siguiente tabla:

Los periféricos incluyen lo siguiente:

La arquitectura del hardware se muestra en la siguiente figura:

Arquitectura de software

La arquitectura de software de la plataforma Apollo se muestra en la siguiente figura:

En Apollo, los módulos de software principales que se ejecutan incluyen:

  • Percepción: el módulo de percepción identifica el mundo que rodea a los vehículos autónomos. Hay dos submódulos importantes en el módulo Percepción: detección de obstáculos y detección de semáforos.
  • Predicción: el módulo de predicción predice la trayectoria de movimiento de los obstáculos percibidos en el futuro.
  • Rutas: el módulo Rutas indica a los vehículos autónomos cómo llegar a su destino a través de una serie de carriles o carreteras.
  • Planificación: El módulo de Planificación planifica la trayectoria espaciotemporal de los vehículos autónomos.
  • Control: el módulo de control ejecuta la trayectoria espaciotemporal planificada generando comandos de control como acelerador, freno y dirección.
  • CanBus: CanBus pasa comandos de control a la interfaz del hardware del vehículo. También pasa información del rack al sistema de software.
  • HD-Map: proporciona información estructurada específica sobre carreteras.
  • Localización: este módulo utiliza diversas fuentes de información como GPS, LiDAR e IMU para estimar la ubicación del vehículo autónomo.

La estructura interactiva de estos módulos se muestra en la siguiente figura:

Cada módulo se ejecuta como un nodo ROS independiente basado en CarOS. Cada nodo del módulo publica y se suscribe a ciertos temas. Los temas suscritos se utilizan como entrada de datos, mientras que los temas publicados se utilizan como salida de datos.

Para obtener información sobre la arquitectura del sistema de la plataforma Apollo, puede leer este documento: CÓMO ENTENDER LA ARQUITECTURA Y EL FLUJO DE TRABAJO .

De este documento vemos:

  • Los vehículos de conducción autónoma son controlados por el motor de planificación a través del bus CAN (bus Controller Area Network).
  • Para lograr eficiencia computacional, el módulo de Ubicación, el módulo de Percepción y el módulo de Planificación trabajan juntos como fuentes de entrada y salida independientes a través de P2P.
  • Al leer ${MODULE_NAME}/conflos archivos de configuración en el directorio fuente, podemos obtener información básica sobre los temas suscritos y publicados por el módulo.
  • Cada módulo comienza activando  Init una interfaz y registrando devoluciones de llamada.
  • Todos los módulos están registrados en este punto: AdapterManager::Init . Algunos fragmentos de código de esta función son los siguientes:
void AdapterManager::Init(const AdapterManagerConfig &configs) {
  if (Initialized()) {
    return;
  }

  instance()->initialized_ = true;
  if (configs.is_ros()) {
    instance()->node_handle_.reset(new ros::NodeHandle());
  }

  for (const auto &config : configs.config()) {
    switch (config.type()) {
      case AdapterConfig::POINT_CLOUD:
        EnablePointCloud(FLAGS_pointcloud_topic, config);
        break;
      case AdapterConfig::GPS:
        EnableGps(FLAGS_gps_topic, config);
        break;
      case AdapterConfig::IMU:
        EnableImu(FLAGS_imu_topic, config);
        break;
      case AdapterConfig::RAW_IMU:
        EnableRawImu(FLAGS_raw_imu_topic, config);
        break;
      case AdapterConfig::CHASSIS:
        EnableChassis(FLAGS_chassis_topic, config);
        break;
      case AdapterConfig::LOCALIZATION:
        EnableLocalization(FLAGS_localization_topic, config);
        break;
      case AdapterConfig::PERCEPTION_OBSTACLES:
        EnablePerceptionObstacles(FLAGS_perception_obstacle_topic, config);
        break;
      case AdapterConfig::TRAFFIC_LIGHT_DETECTION:
        EnableTrafficLightDetection(FLAGS_traffic_light_detection_topic,
                                    config);
     ...

El siguiente es un análisis de los principales módulos centrales del sistema.

módulo principal

apollo/modules/ contiene el código fuente de cada módulo del sistema.

Al leer estos códigos fuente, encontrará que todas las clases de estos módulos principales heredan de una clase base común ApolloApp. La estructura relevante se muestra en la siguiente figura:

La estructura de la clase ApolloApp se muestra a continuación:

Las funciones principales de esta clase se describen a continuación:

Nombre de la función ilustrar

En apollo_app.heste archivo de cabecera también se incluye una macro para facilitar la declaración de la función principal de cada módulo, el código correspondiente es el siguiente:

#define APOLLO_MAIN(APP)                                       \
  int main(int argc, char **argv) {                            \
    google::InitGoogleLogging(argv[0]);                        \
    google::ParseCommandLineFlags(&argc, &argv, true);         \
    signal(SIGINT, apollo::common::apollo_app_sigint_handler); \
    APP apollo_app_;                                           \
    ros::init(argc, argv, apollo_app_.Name());                 \
    apollo_app_.Spin();                                        \
    return 0;                                                  \
  }

El directorio raíz de cada módulo contiene un README.mdarchivo que describe el módulo. Podemos usar esto como punto de entrada para comprender la implementación del módulo.

Percepción

Introducción al módulo

Los vehículos autónomos utilizan cámaras frontales y radar para mantener la distancia con el vehículo más cercano en el camino (CIPV). El submódulo también predice el movimiento del obstáculo y la información de posición (por ejemplo, rumbo y velocidad). Apollo 2.5 admite la conducción autónoma a alta velocidad en autopistas sin mapas. Los algoritmos de redes profundas han aprendido a procesar datos de imágenes. El rendimiento de las redes profundas mejorará con el tiempo a medida que se recopilen más datos.

Entrada del módulo:

  • datos de radar
  • datos de imagen
  • Parámetros externos para la calibración del sensor de radar (del archivo YAML)
  • Parámetros externos e internos para la calibración de la cámara frontal (del archivo YAML)
  • Velocidad del vehículo y velocidad angular.

Salida del módulo:

  • Seguimiento de obstáculos en 3D, información de rumbo, velocidad y clasificación.
  • Información de señalización de carriles, información espacial e información semántica con parámetros de curvas de ajuste

Análisis de módulos

El módulo de Percepción necesita analizar rápidamente dos tipos de información en función de la información de entrada, a saber: carreteras y objetos. La red profunda se basa en el algoritmo YOLO [1] [2] .

Apollo 2.5 no admite carreteras con gran curvatura y sin marcas de carril, incluidas carreteras locales e intersecciones. El módulo de percepción se basa en la detección visual utilizando redes profundas con datos limitados. Por lo tanto, hasta que se lancen mejores redes, los conductores deben tener cuidado al conducir y estar siempre preparados para desactivar la conducción autónoma girando las ruedas en la dirección correcta.

  • Carreteras recomendadas
    • Líneas de carril blancas claras en ambos lados

  • Camino no recomendado
    • camino de alta curvatura
    • Camino sin marcas de carril
    • intersección
    • Punto de atraque o línea discontinua del carril
    • carretera publica

En el caso de los objetos, se dividen en objetos estáticos y objetos dinámicos. Los objetos estáticos incluyen carreteras y semáforos, etc. Los objetos dinámicos incluyen vehículos de motor, bicicletas, peatones, animales, etc.

Para mantener el vehículo en el carril se requiere la cooperación de una serie de módulos, el diagrama de flujo correspondiente es el siguiente:

El módulo Perception Initregistrará una serie de clases en la función para completar el trabajo normal después de que se inicie el módulo. El código relevante es el siguiente:

void Perception::RegistAllOnboardClass() {
  /// regist sharedata
  RegisterFactoryLidarObjectData();
  RegisterFactoryRadarObjectData();
  RegisterFactoryCameraObjectData();
  RegisterFactoryCameraSharedData();
  RegisterFactoryCIPVObjectData();
  RegisterFactoryLaneSharedData();
  RegisterFactoryFusionSharedData();
  traffic_light::RegisterFactoryTLPreprocessingData();

  /// regist subnode
  RegisterFactoryLidarProcessSubnode();
  RegisterFactoryRadarProcessSubnode();
  RegisterFactoryCameraProcessSubnode();
  RegisterFactoryCIPVSubnode();
  RegisterFactoryLanePostProcessingSubnode();
  RegisterFactoryAsyncFusionSubnode();
  RegisterFactoryFusionSubnode();
  RegisterFactoryMotionService();
  lowcostvisualizer::RegisterFactoryVisualizationSubnode();
  traffic_light::RegisterFactoryTLPreprocessorSubnode();
  traffic_light::RegisterFactoryTLProcSubnode();
}

Podemos usar esto como punto de entrada para comprender la lógica de cada submódulo.

Tomemos RegisterFactoryLidarProcessSubnodepor ejemplo.

Esta función en realidad no existe en el código RegisterFactoryLidarProcessSubnode. La definición de la función en realidad se completa mediante una macro. El código relevante es el siguiente:

El nombre completo de Lidar (también llamado LIDAR, LiDAR o LADAR) es LightDetection And Ranging, que significa detección y medición por láser.
// /modules/perception/onboard/subnode.h
#define REGISTER_SUBNODE(name) REGISTER_CLASS(Subnode, name)


// /modules/perception/lib/base/registerer.h
#define REGISTER_CLASS(clazz, name)                                           \
  class ObjectFactory##name : public apollo::perception::ObjectFactory {      \
   public:                                                                    \
    virtual ~ObjectFactory##name() {}                                         \
    virtual perception::Any NewInstance() {                                   \
      return perception::Any(new name());                                     \
    }                                                                         \
  };                                                                          \
  inline void RegisterFactory##name() {                                       \
    perception::FactoryMap &map = perception::GlobalFactoryMap()[#clazz];     \
    if (map.find(#name) == map.end()) map[#name] = new ObjectFactory##name(); \
  }

lidar_process_subnode.hLa macro anterior se utiliza en .

REGISTER_SUBNODE(LidarProcessSubnode);

Luego ObjectFactoryLidarProcessSubnodese genera una clase denominada, que hereda apollo::perception::ObjectFactoryy contiene RegisterFactoryLidarProcessSubnodeuna función denominada.

Predicción

Introducción al módulo

El módulo de Predicción recibe información de obstáculos del módulo de Percepción. Este módulo requiere información que incluye posición, rumbo, velocidad, aceleración y produce una trayectoria prevista con probabilidad de obstáculos.

Entrada del módulo:

  • Información de obstáculos del módulo de Predicción
  • Información de ubicación del módulo de localización

Salida del módulo:

  • Trayectoria prevista de los obstáculos.

Análisis de módulos

Se agregan tres devoluciones de llamada a la función de Predicción Initpara obtener actualizaciones de información de otros módulos:

AdapterManager::AddLocalizationCallback(&Prediction::OnLocalization, this);
AdapterManager::AddPlanningCallback(&Prediction::OnPlanning, this);
AdapterManager::AddPerceptionObstaclesCallback(&Prediction::RunOnce, this);

Lo más importante aquí es Prediction::RunOnceesta función. Esta función contiene la lógica principal del módulo de Predicción, que se activa cuando se recibe un nuevo mensaje de obstáculo.

Hay tres tipos importantes de submódulos en el módulo de Predicción.

El primer tipo es el Contenedor, que se utiliza para almacenar datos obtenidos de los canales de suscripción. incluir:

  • Información de obstáculos percibidos
  • Información de ubicación del vehículo
  • Información de planificación del vehículo

El segundo tipo es el Evaluador, que se utiliza para predecir la ruta y la velocidad de obstáculos específicos. Actualmente existen tres tipos de Evaluadores, entre ellos:

  • Evaluador de costos: calcula la probabilidad a través de un conjunto de funciones de costos
  • Evaluador MLP: Calcula la posibilidad a través del modelo MLP
  • Evaluador RNN: Calcula la posibilidad a través del modelo RNN

El evaluador EvaluatorManagerse administra a través de clases. La estructura de clases del evaluador es como se muestra a continuación:

El tercer submódulo importante del módulo Predicción es Predictor. Se utiliza para predecir la trayectoria de los obstáculos.

Las trayectorias de diferentes obstáculos serán diferentes, por lo que la implementación contiene muchos tipos de Predictores y sus estructuras se muestran en la siguiente figura.

De igual forma, habrá uno PredictorManagerpara gestionar el Predictor.

Enrutamiento

Introducción al módulo

El módulo de enrutamiento genera información de navegación basada en solicitudes.

Entrada del módulo:

  • datos del mapa
  • Solicitud, que incluye: posición inicial y final

Salida del módulo:

  • Información de navegación de ruta

Análisis de módulos

La estructura interna del módulo de enrutamiento se muestra en la siguiente figura:

La entrada del módulo de Enrutamiento son datos de mapas y solicitudes de navegación, por lo que su Initfunción gira en torno a esta lógica:

apollo::common::Status Routing::Init() {
  const auto routing_map_file = apollo::hdmap::RoutingMapFile();
  AINFO << "Use routing topology graph path: " << routing_map_file;
  navigator_ptr_.reset(new Navigator(routing_map_file));
  CHECK(common::util::GetProtoFromFile(FLAGS_routing_conf_file, &routing_conf_))
      << "Unable to load routing conf file: " + FLAGS_routing_conf_file;

  AINFO << "Conf file: " << FLAGS_routing_conf_file << " is loaded.";

  hdmap_ = apollo::hdmap::HDMapUtil::BaseMapPtr();
  CHECK(hdmap_) << "Failed to load map file:" << apollo::hdmap::BaseMapFile();

  AdapterManager::Init(FLAGS_routing_adapter_config_filename);
  AdapterManager::AddRoutingRequestCallback(&Routing::OnRoutingRequest, this);
  return apollo::common::Status::OK();
}

El enfoque de este código son los siguientes tres lugares:

  • apollo::hdmap::RoutingMapFile()Contiene datos de mapas HD.
  • NavigatorResponsable de la navegación, podemos pensar fácilmente que esta clase debería ser el núcleo del módulo.
  • Routing::OnRoutingRequestEs la función de devolución de llamada que recibe solicitudes de navegación.

En Routing::OnRoutingRequest, lo más importante es Navigator::SearchRoutebuscar rutas de navegación.

void Routing::OnRoutingRequest(const RoutingRequest& routing_request) {
  AINFO << "Get new routing request:" << routing_request.DebugString();
  RoutingResponse routing_response;
  apollo::common::monitor::MonitorLogBuffer buffer(&monitor_logger_);
  const auto& fixed_request = FillLaneInfoIfMissing(routing_request);
  if (!navigator_ptr_->SearchRoute(fixed_request, &routing_response)) {
    AERROR << "Failed to search route with navigator.";

    buffer.WARN("Routing failed! " + routing_response.status().msg());
    return;
  }
  buffer.INFO("Routing success!");
  AdapterManager::PublishRoutingResponse(routing_response);
  return;
}

Actualmente, la navegación en Apollo 2.5 se basa en el algoritmo A* . Este es un algoritmo que encuentra el costo de paso más bajo para una ruta con múltiples nodos en el plano de gráficos. Este algoritmo combina las ventajas de Best-First Search y el algoritmo de Dijkstra: mientras realiza una búsqueda heurística para mejorar la eficiencia del algoritmo, puede garantizar que se encuentre una ruta óptima (basada en la función de evaluación).

Durante el proceso de cálculo del algoritmo A*, se probarán múltiples rutas. Una vez que se encuentra un obstáculo, los puntos del camino se marcan como que no requieren mayor exploración (puntos sólidos en la figura). Continúe explorando los puntos huecos restantes. Finalmente encuentre el camino óptimo.

La siguiente figura describe dinámicamente el proceso del algoritmo A * para encontrar la ruta de destino.

portada animada

Planificación

Introducción al módulo

El módulo de planificación calcula una ruta segura y cómoda para que la ejecute el controlador en función de la información de posicionamiento, el estado del vehículo (posición, velocidad, aceleración, chasis), mapa, ruta, percepción y predicción.

La implementación actual del sistema contiene cuatro planificadores:

  • RTKReplayPlanner (desde Apollo 1.0): el planificador de reproducción RTK primero carga las trayectorias registradas en la inicialización y envía segmentos de trayectoria apropiados según la hora actual del sistema y la posición del vehículo.
  • EMPlanner (desde Apollo1.5. EM es la abreviatura de Expectation Maximization): planificador EM, que calcula decisiones de conducción y rutas basadas en mapas, rutas y obstáculos. El método basado en programación dinámica (DP) se utiliza primero para determinar la trayectoria original y la curva de velocidad, y luego el método basado en programación cuadrática (QP) se utiliza para optimizar aún más la trayectoria y la curva de velocidad para obtener una trayectoria suave.
  • LatticePlanner: planificador de cuadrículas
  • NaviPlanner: Se trata de un planificador basado en mapas relativos en tiempo real. Utiliza el sistema de coordenadas FLU (Frontal-Izquierda-Arriba) del vehículo para completar tareas de crucero, seguimiento, adelantamiento, aproximación, cambio de carril y estacionamiento.

Entrada del módulo:

  • Planificador de reproducción RTK:
    • Localización
    • Pistas RTK grabadas

  • Planificador EM:
    • Localización
    • Percepción
    • Predicción
    • Mapa HD
    • Enrutamiento

Salida del módulo:

  • Las trayectorias cómodas y sin colisiones permiten la ejecución del módulo de control

Análisis de módulos

En la Initfunción de inicialización del módulo de planificación, se registrarán todos los planificadores y luego se determinará el planificador utilizado actualmente en función de la configuración en el archivo de configuración. Actualmente, el planificador EM está configurado en el archivo de configuración.

El módulo de Planificación Startconfigura un Temporizador en la función para completar las tareas programadas:

Status Planning::Start() {
  timer_ = AdapterManager::CreateTimer(
      ros::Duration(1.0 / FLAGS_planning_loop_rate), &Planning::OnTimer, this);
...

Planning::OnTimerLo más importante es la llamada RunOnce(), y esta última contiene la lógica central del módulo de Planificación. Actualmente FLAGS_planning_loop_rateel valor es 10. En otras palabras, el módulo de Planificación se ejecuta 10 veces por segundo.

En la función Planificación::Plan, la ruta se calcula a través del planificador configurado y luego los resultados se publican al mundo exterior. El código clave es el siguiente:

Status Planning::Plan(const double current_time_stamp,
                      const std::vector<TrajectoryPoint>& stitching_trajectory,
                      ADCTrajectory* trajectory_pb) {
  auto* ptr_debug = trajectory_pb->mutable_debug();
  if (FLAGS_enable_record_debug) {
    ptr_debug->mutable_planning_data()->mutable_init_point()->CopyFrom(
        stitching_trajectory.back());
  }

  auto status = planner_->Plan(stitching_trajectory.back(), frame_.get());

  ExportReferenceLineDebug(ptr_debug);

  const auto* best_ref_info = frame_->FindDriveReferenceLineInfo();
  if (!best_ref_info) {
    std::string msg("planner failed to make a driving plan");
    AERROR << msg;
    if (last_publishable_trajectory_) {
      last_publishable_trajectory_->Clear();
    }
    return Status(ErrorCode::PLANNING_ERROR, msg);
  }
  ptr_debug->MergeFrom(best_ref_info->debug());
  trajectory_pb->mutable_latency_stats()->MergeFrom(
      best_ref_info->latency_stats());
  // set right of way status
  trajectory_pb->set_right_of_way_status(best_ref_info->GetRightOfWayStatus());
  for (const auto& id : best_ref_info->TargetLaneId()) {
    trajectory_pb->add_lane_id()->CopyFrom(id);
  }

  best_ref_info->ExportDecision(trajectory_pb->mutable_decision());

  ...
  
  last_publishable_trajectory_->PrependTrajectoryPoints(
      stitching_trajectory.begin(), stitching_trajectory.end() - 1);

  for (size_t i = 0; i < last_publishable_trajectory_->NumOfPoints(); ++i) {
    if (last_publishable_trajectory_->TrajectoryPointAt(i).relative_time() >
        FLAGS_trajectory_time_high_density_period) {
      break;
    }
    ADEBUG << last_publishable_trajectory_->TrajectoryPointAt(i)
                  .ShortDebugString();
  }

  last_publishable_trajectory_->PopulateTrajectoryProtobuf(trajectory_pb);

  best_ref_info->ExportEngageAdvice(trajectory_pb->mutable_engage_advice());

  return status;
}

Control

Introducción al módulo

El módulo de control utiliza diferentes algoritmos de control para generar una experiencia de conducción cómoda según el plan y el estado actual del vehículo. El módulo de control puede funcionar en modo normal y en modo de navegación.

Entrada del módulo:

  • ruta planificada
  • estado del vehículo
  • Información de posicionamiento
  • Solicitud de cambio de modo AUTO de Dreamview

Salida del módulo:

  • Comandos de control (dirección, acelerador, freno) al chasis

Análisis de módulos

La lógica principal del módulo de Control también se ejecuta periódicamente a través del Temporizador. En una función activada periódicamente Control::OnTimer, se generan y envían comandos:

void Control::OnTimer(const ros::TimerEvent &) {
  double start_timestamp = Clock::NowInSeconds();

  if (FLAGS_is_control_test_mode && FLAGS_control_test_duration > 0 &&
      (start_timestamp - init_time_) > FLAGS_control_test_duration) {
    AERROR << "Control finished testing. exit";
    ros::shutdown();
  }

  ControlCommand control_command;

  Status status = ProduceControlCommand(&control_command);
  AERROR_IF(!status.ok()) << "Failed to produce control command:"
                          << status.error_message();

  double end_timestamp = Clock::NowInSeconds();

  if (pad_received_) {
    control_command.mutable_pad_msg()->CopyFrom(pad_msg_);
    pad_received_ = false;
  }

  const double time_diff_ms = (end_timestamp - start_timestamp) * 1000;
  control_command.mutable_latency_stats()->set_total_time_ms(time_diff_ms);
  control_command.mutable_latency_stats()->set_total_time_exceeded(
      time_diff_ms < control_conf_.control_period());
  ADEBUG << "control cycle time is: " << time_diff_ms << " ms.";
  status.Save(control_command.mutable_header()->mutable_status());

  SendCmd(&control_command);
}

El módulo de Control dispone de tres controladores incorporados, su estructura y descripción es la siguiente:

  • LatController: controlador lateral basado en LQR que calcula objetivos de dirección. Consulte: Dinámica y control del vehículo para obtener más detalles .
  • LonController: Controlador longitudinal, calcula los valores de freno/aceleración.
  • MPCController: controlador MPC, que combina controladores horizontales y verticales.

Conclusión

Este artículo realiza principalmente una investigación y un análisis basados ​​en la versión 2.5 del proyecto Apollo.

También mencionamos anteriormente que la versión actual 2.5 es solo para conducción autónoma L2, mientras que Baidu planea lograr conducción autónoma L3 en 2019 y conducción autónoma L4 en 2021. Se puede ver que este proyecto se desarrollará muy rápidamente en los próximos años.

Además, tuve la oportunidad de asistir a la feria CES en Shanghai este año . En la exposición, también vimos dos modelos autónomos exhibidos por Baidu:

Uno es un minibús.

También hay un pequeño vehículo logístico.

Continuaré prestando atención a este proyecto en el futuro y continuaré compartiéndolo con ustedes si hay más información.

Supongo que te gusta

Origin blog.csdn.net/weixin_53678904/article/details/133181169
Recomendado
Clasificación