Projetando Algoritmos Críticos: Implementação

  1. Projeto
  2. Implementação
  3. Integração


Quando eu estava apenas começando minha carreira em desenvolvimento profissional, não entendia por que o código aberto era necessário. Também não entendi os projetos paralelos. Afinal, por que dar um trabalho valioso de graça? Ao longo dos anos, trabalhando em projetos de código aberto, bem como trabalhando com Apex.AI, ROS 2 e Autoware.Auto, cheguei a alguma compreensão do código aberto.



Os engenheiros adoram criar. As pessoas querem reconhecimento e gratidão.



Quando você combina esses fatores, você tem o caminho para o código aberto. Se estou construindo algo para atender às minhas necessidades criativas, por que não deixar que todos os outros apreciem meu trabalho e encontrem uso prático e valor nele? Afinal, não estou fazendo isso pelo dinheiro.



Quanto aos projetos paralelos, só percebi o charme deles depois que comecei a desenvolver profissionalmente e com mais cuidado abordar vários aspectos do meu trabalho. Para criar um produto confiável pelo qual as pessoas paguem, geralmente é necessário restringir artificialmente os fluxos de trabalho. Análise de projeto. Revisão de código. Padrões de codificação, guias de estilo, métricas de cobertura de teste e assim por diante. Não me interpretem mal - estas são todas as coisas boas que provavelmente são necessárias para desenvolver um produto de qualidade. Às vezes, um desenvolvedor quer um pouco de liberdade. Um desenvolvedor pode criar o que ele quer, como ele quer e quando ele quer. Não há reuniões, revisões ou casos de negócios.



Então, como você combina esses aspectos quando se trata de desenvolver algoritmos seguros ou de alta qualidade? Grande parte do fascínio do mundo do código aberto é a liberdade, e práticas que ajudam a garantir o desenvolvimento de códigos mais confiáveis ​​limitam essa liberdade.



A resposta que encontrei é seguir uma disciplina aberta e consistente e usar liberalmente muitas ferramentas interessantes que vieram do mundo do código aberto.



Planejando projetos de código aberto



Os engenheiros precisam de um conjunto de habilidades específicas para resolver esses problemas. Os engenheiros precisam estar focados, precisam de boas habilidades para resolver problemas. Os engenheiros também precisam ser capazes de separar as preocupações e ter as sólidas habilidades básicas necessárias para obter conhecimento de todas as opções acima.



Esse conjunto de habilidades em particular pode levar os engenheiros a ficar um pouco sobrecarregados.



Por todas as habilidades técnicas que os engenheiros possuem, eles são limitados em suas capacidades. Eu diria que a maioria dos desenvolvedores não consegue manter o projeto inteiro em mente enquanto escreve linhas de código individuais. Além disso, eu argumentaria que a maioria dos desenvolvedores não pode programar e manter um projeto mais amplo em mente sem esquecer os objetivos gerais de negócios.



É aqui que a magia negra do gerenciamento de projetos entra em cena.



Embora nós, desenvolvedores, possamos ter relações um tanto controversas com os gerentes de RH, técnicos ou de projetos, deve-se reconhecer que todas essas pessoas estão fazendo um trabalho importante. Os melhores representantes da profissão de gerente garantem que os desenvolvedores não percam de vista tarefas importantes, e irritantes irritantes não nos impedem de solucionar problemas com todas as armas.



E embora compreendamos a importância de diferentes gerentes, pessoas com essas habilidades geralmente não se envolvem em um projeto de código aberto típico cujo objetivo é se divertir.



Então, o que devemos fazer então?



Bem, nós desenvolvedores podemos sujar as mãos e gastar um pouco de tempo planejando com antecedência.



Não vou entrar nessas conversas, pois no post anterior entrei em detalhes sobre as etapas de planejamento de design e desenvolvimento. A conclusão é que, levando em consideração o design e a arquitetura, para os quais, em regra, consistem em muitos componentes e formam algumas dependências, em seu próprio projeto você mesmo cria o design e coleta seus componentes separadamente.



Voltando ao aspecto do planejamento do projeto, gosto de começar com os componentes com menos dependências (pense um minuto!) e continue trabalhando, adicionando stubs de implementação sempre que necessário para manter o desenvolvimento em andamento. Com essa ordem de trabalho, geralmente você pode criar muitos tickets (com algumas dependências correspondentes às dependências da arquitetura - se o rastreador de tarefas tiver essa funcionalidade). Esses tickets podem conter algumas notas gerais que são úteis para você ter em mente antes de mergulhar em qualquer tarefa com mais detalhes. Os ingressos devem ser tão pequenos e específicos quanto possível. Vamos ser sinceros - nosso foco e capacidade de manter o contexto são limitados. Quanto mais granularmente as tarefas de desenvolvimento são divididas, mais fácil - então por que não tentar tornar as tarefas difíceis o mais simples possível?



À medida que seu projeto evolui, seu trabalho será receber tickets em ordem de prioridade e concluir as tarefas atribuídas a eles.



Obviamente, esta é uma versão bastante simplificada do gerenciamento de projetos. Existem muitos outros aspectos no verdadeiro gerenciamento de projetos, como recursos, planejamento, casos de negócios concorrentes e assim por diante. O gerenciamento de projetos em código aberto pode ser mais simples e mais livre. Talvez, no mundo do desenvolvimento de código aberto, haja casos de gerenciamento de projeto completo.



Desenvolvimento aberto



Após digitar uma pilha de tickets, formar um plano de trabalho e entender todos os detalhes, podemos prosseguir para o desenvolvimento.



No entanto, muitos dos fatores de liberdade presentes no oeste selvagem do desenvolvimento aberto não devem estar no desenvolvimento de código seguro. Você pode evitar muitas armadilhas usando ferramentas de código aberto e com alguma disciplina (e tendo amigos).



Sou um grande defensor da disciplina como forma de melhorar a qualidade do trabalho (afinal, a disciplina está em 6º lugar na minha classificação no StrengthsFinder) Com disciplina suficiente para usar ferramentas de código aberto, ouvir outras pessoas, agir sobre os resultados e manter os fluxos de trabalho, podemos superar muitas das falhas que surgem nas abordagens de cowboys do mundo do código aberto.



Em resumo, o uso das seguintes ferramentas e práticas (que, com algumas ressalvas, podem ser facilmente aplicadas em qualquer projeto) ajuda a melhorar a qualidade do código:



  1. Testes (ou melhor ainda, desenvolvimento orientado a testes)
  2. Análise estática
  3. Integração Contínua (CI / CD)
  4. Revisão de código


Também darei vários princípios aos quais aderimos ao escrever diretamente o código:



  1. SECO
  2. Uso completo de linguagem e bibliotecas
  3. O código deve ser legível e cegamente óbvio.


Tentarei relacionar este texto à implementação real do algoritmo de localização NDT , que foi concluído em 10 solicitações de mesclagem pelo meu bom colega Yunus . Ele está muito ocupado com o trabalho direto, para que eu possa me apegar a algumas medalhas imaginárias escrevendo sobre seu trabalho.



Além disso, para ilustrar alguns dos processos e práticas, darei um exemplo de desenvolvimento de um algoritmo de código aberto para o controlador MPC . Ele foi desenvolvido em um estilo um pouco mais flexível (cowboy) em cerca de mais de 30 solicitações de mesclagem , sem contar edições adicionais e melhorias feitas após a conclusão do trabalho principal.



Teste



Vamos falar sobre testes.



Eu tive um relacionamento longo e difícil (pelos meus padrões) com os testes. Quando cheguei à posição de desenvolvedor e assumi o primeiro projeto, eu absolutamente não acreditava que meu código funcionasse e, portanto, fui o primeiro da equipe que começou a escrever pelo menos alguns testes de unidade significativos. No entanto, eu estava absolutamente certo de que meu código não funcionava.



Desde então, minha relação tumultuada com testes passou por muitas reviravoltas dignas de filmes noturnos. Às vezes eu gostei. Às vezes eu odiava tudo. Eu escrevi muitos testes. Excesso de copiar e colar, muitos testes redundantes. Então o teste se tornou um trabalho de rotina, outra parte do desenvolvimento. Primeiro escrevi o código e depois escrevi testes para ele, essa era a ordem das coisas.



Agora eu tenho um relacionamento normal com os testes. É parte integrante do meu fluxo de trabalho, independentemente do aplicativo em que trabalho.



O que mudou para mim são as técnicas de desenvolvimento orientadas a testes que comecei a usar no meu projeto mpc.



Falei brevemente sobre desenvolvimento orientado a teste no texto anterior, mas aqui está outra descrição do processo:



  1. Desenvolva uma especificação (casos de uso, requisitos, etc.).
  2. Implementar a API / arquitetura
  3. Escreva testes com base na API e na especificação do projeto; eles devem falhar.
  4. Implementar lógica; testes devem passar


Há alguma iteração nesse processo (os testes não falham nos stubs, a implementação falha nos testes, a API pode ser estranha etc.), mas, no geral, acho que pode ser extremamente útil.



Eu falei muito sobre planejamento antes da implementação, e o desenvolvimento orientado a testes oferece essa oportunidade. O primeiro ponto foi observado. Então você pensa sobre arquitetura e APIs e mapeia-os para casos de uso. Isso oferece uma ótima oportunidade para você se aproximar do código, mas ainda pense sobre o problema de maneira mais ampla. O segundo ponto foi observado.



Em seguida, passamos a escrever testes. Existem várias razões para os benefícios de escrever testes antes da implementação, e acho que são todos importantes:



  1. Os testes devem ser escritos como objetos de primeira prioridade, não como complementos.
  2. , – .
  3. API , .
  4. , , , , .


No geral, acho que os benefícios do desenvolvimento orientado a testes são enormes e, mais uma vez, recomendo a todos que ao menos tentem.



Vamos voltar ao Autoware.Auto. Yunus, apesar de não seguir os métodos de desenvolvimento orientado a testes, escreveu testes para cada solicitação de mesclagem durante o desenvolvimento do NDT. Ao mesmo tempo, o volume do código de teste era igual (e às vezes até excedido) ao volume do código de implementação, e isso é bom. Em comparação, o SQLite , que provavelmente é a referência para testes (não apenas pelos padrões de projetos de código aberto), possui 662 vezes mais código de teste que código de implementação. No Autoware.Auto ainda não estamos nesse estágio, mas se você observar o histórico de solicitações de mesclagem relacionadas ao NDT, poderá ver que o volume do código de teste subiu lentamente até atingir 90% de cobertura (embora tenha caído desde então devido a outros designs e código externo).



E isso é legal.



Da mesma forma, meu projeto mpc tem testes para tudo, incluindo os próprios testes . Além disso, sempre conduzo cuidadosamente testes de regressão para garantir que o bug seja corrigido e não apareça novamente.



Eu sou bom companheiro.



Análise estática



Muitos conceitos são curiosos, pois as definições incluídas neles podem ser significativamente ampliadas. Por exemplo, o teste vai muito além dos testes funcionais escritos à mão. De fato, a verificação de estilo ou a busca de bugs também podem ser consideradas uma forma de teste (é essencialmente uma inspeção, mas se você esticar a definição, pode ser chamada de teste).



Tais "testes" são um tanto dolorosos e trabalhosos de se trabalhar. Afinal, validação, validação para guias / espaços alinhados? Não, obrigado.



Mas uma das coisas mais agradáveis ​​e valiosas sobre programação é a capacidade de automatizar processos dolorosos e demorados. Ao mesmo tempo, o código pode obter resultados com mais rapidez e precisão do que qualquer pessoa. E se pudermos fazer o mesmo com bugs e construções problemáticas ou propensas a erros em nosso código?



Bem, nós podemos - com ferramentas de análise estática.



Eu escrevi sobre análise estática por tempo suficiente em um post anterior , para não aprofundar seus benefícios e as ferramentas que você pode usar.



No Autoware.Auto, usamos uma versão um pouco menor do conjunto ament_lintde nossos amigos íntimos do ROS 2. Essas ferramentas nos ajudam bastante, mas talvez o mais importante seja que a formatação automática de nosso código para eliminar disputas de estilo - ferramentas imparciais nos dizem o que é certo e o que é errado. Se você estiver interessado, observarei que o formato de clang é mais rigoroso do que não- confiável .



No projeto mpc, fui um pouco mais longe. Nele, usei a bandeira Weverything do compilador Clang, além de todos os avisos do clang-tidy e do analisador estático Clang. Surpreendentemente, o desenvolvimento comercial exigiu que várias opções fossem desabilitadas (devido a avisos redundantes e confusão conceitual) Ao interagir com código externo, tive que desativar muitas verificações - elas causaram ruído desnecessário.



Por fim, percebi que o uso de análise estática extensiva não interfere muito no desenvolvimento normal (no caso de escrever um novo código e depois de passar um certo ponto na curva de aprendizado)



É difícil quantificar o valor da análise estática, especialmente se você a usar desde o início. A questão é que é difícil adivinhar se o erro existia antes da introdução da análise estática ou não.



No entanto, acredito que o uso de avisos e análise estática é uma daquelas coisas em que, mesmo quando usado corretamente, não se pode ter certeza de que eles fizeram alguma coisa.. Em outras palavras, você não pode ter certeza sobre o valor de um analisador estático quando está ligado, mas, heck, você notará que ele não está lá imediatamente.



CI / CD



Por mais que eu goste de testes rigorosos e análise de código estático / dinâmico, todos os testes e verificações são inúteis se não executados. A CI pode enfrentar esses desafios com uma sobrecarga mínima.



Acho que todos concordam que ter uma infraestrutura de CI / CD é uma parte essencial do desenvolvimento moderno, além de usar um sistema de controle de versão e ter padrões de desenvolvimento (pelo menos guias de estilo). No entanto, o valor de um bom pipeline de CI / CD é que suas operações devem ser reproduzíveis.



O pipeline de CI / CD deve, no mínimo, criar código e executar testes antes de enviar o código ao seu repositório. Afinal, ninguém quer ser aquele cara (ou garota, ou persona) que interrompeu uma montagem ou algum tipo de teste e precisa consertar tudo de forma rápida e vergonhosa. Os ICs (e, portanto, seus queridos engenheiros de DevOps) protegem você dessa vergonha.



Mas a CI pode fazer muito mais por você.



Com um pipeline de CI robusto, você pode testar qualquer número de combinações de sistemas operacionais, compiladores e arquiteturas (com algumas limitações, considerando o teste de combinação ). Você também pode executar compilações, executar testes e outras operações que podem consumir muitos recursos ou dificultar o desempenho de um desenvolvedor manualmente. Você não pode pular sobre sua cabeça.



Voltando à declaração original, ter um pipeline de CI / CD (que usamos na Autoware.Auto ) em seu projeto de código aberto ajudará a desenvolver o desenvolvimento incontrolável. O código não poderá entrar no projeto se não criar ou passar nos testes. Se você aderir à rigorosa disciplina de teste, sempre poderá ter certeza de que o código funciona.



No Autoware.Auto, CI:



  1. Coleta código
  2. Executa testes (estilo, verificações de linter, testes funcionais).
  3. Mede a cobertura do teste
  4. Verifica se o código está documentado




Por sua vez, meu IC compilado às pressas no projeto mpc:



  1. Coleta código
  2. Executa uma varredura (análise estática de Clang)
  3. Executa testes (mas não para o IC se os testes falharem).


Um pipeline de CI montado por um engenheiro experiente do DevOps (como nosso J.P. Samper ou Hao Peng !) Pode fazer muito mais. Aprecie seus engenheiros de DevOps. Eles tornam nossa vida (como desenvolvedores) muito mais fácil.



Revisão de código



Benchmarks, analisadores e IC são ótimos. Você pode executar testes, analisar tudo e garantir que esses testes sejam feitos usando o IC, certo?



Infelizmente não.



Novamente, todos os testes no mundo são inúteis se forem ruins. Então, como você garante que seus testes sejam bons?



Infelizmente, não tenho respostas mágicas. De fato, voltarei à antiga técnica de engenharia, a revisão por pares. Em particular, para a revisão do código.



Geralmente, acredita-se que duas cabeças são melhores que uma. De fato, eu argumentaria que esse conceito é apoiado não apenas pela literatura, mas também pela teoria.



Conjunto de métodosno aprendizado de máquina ilustra essa teoria. Acredita-se que o uso de um conjunto de métodos seja uma maneira rápida e fácil de melhorar o desempenho de modelos estatísticos (o conhecido método de reforço é um exemplo ). Da mesma forma, do ponto de vista puramente estatístico, a variação é menor (com suposições) quanto mais amostras você tiver. Em outras palavras, é mais provável que você esteja mais próximo da verdade se conectar mais funcionários.



Você pode experimentar esta técnica com um exemplo ao vivo, fazendo um exercício de formação de equipe . Uma versão menos divertida pode envolver adivinhar estatísticas aleatórias individualmente e em grupo.



Teoria e formação de equipe à parte, a revisão de código é uma ferramenta importante e poderosa. Não é de surpreender que a revisão de código seja parte integrante de qualquer processo de desenvolvimento profissional e até recomendada pela norma ISO 26262.



Tudo isso sugere que sempre existe o risco de uma criança ter sete babás. Além disso, às vezes a revisão de código pode causar certas dificuldades.



No entanto, acho que as revisões de código podem ser agradáveis ​​e simples, se o revisor e a revisada por pares se lembrarem do seguinte:



  1. Você não é seu código.
  2. Você está conversando com outra pessoa.
  3. Seja educado
  4. Todo mundo está trabalhando para o mesmo objetivo; a revisão de código não representa nenhuma competição (embora às vezes ocorra na programação )


Muitas pessoas mais inteligentes e agradáveis ​​do que eu escrevemos sobre como fazer revisões de código corretamente, e convido você a dar uma olhada no trabalho delas . A última coisa que posso dizer é que você deve fazer análises de código se quiser que seu código seja mais confiável.



SECO



Entrei em detalhes sobre os processos e ferramentas que podem ser usados ​​para moldar o ambiente de desenvolvimento: verificações e ferramentas que conduzem verificações e garantem que o código seja bom o suficiente.



Em seguida, gostaria de passar a uma rápida conversa sobre proezas de programação e compartilhar algumas reflexões sobre os processos e a intenção por trás da escrita de linhas de código individuais.



Existem alguns conceitos que me ajudaram a melhorar muito meu código. Um desses conceitos era a capacidade de lembrar intenção, semântica e legibilidade, sobre as quais falarei um pouco mais adiante. Outra é a compreensão do POO e a separação de preocupações . A última idéia importante é SECA ( não se repita ) ou o princípio "Não se repita".



DRY é o que é ensinado na escola e, como em muitas outras coisas, colocamos esse pensamento na prateleira de trás e não atribuímos muita importância a ele fora dos exames (pelo menos para mim). Mas, como é o caso de muitas outras coisas na escola, não aprendemos nada assim. De fato, essa é uma boa prática.



Simplificando, se você se encontra frequentemente copiando e colando códigos ou escrevendo códigos muito semelhantes com frequência, essa é uma indicação muito boa de que códigos repetíveis devem se tornar uma função ou parte de alguma abstração.



Mas o DRY vai além da verificação de que algum código deve ser movido para uma função. Esse conceito também pode servir de base para algumas decisões de arquitetura.



Embora essa abordagem se cruze com alguns conceitos de arquitetura (como alias, conectividade e separação de interesses), um exemplo de como o DRY é aplicado à arquitetura pode ser visto no meu projeto mpc. Durante o desenvolvimento do controlador mpc, notei que precisaria duplicar algum código se escrever outro controlador. Trata-se de código padrão para rastrear estado, postagens, assinaturas, conversões e similares. Em outras palavras, parecia que era uma tarefa separada do controlador mpc.



Essa foi uma boa indicação de que eu deveria separar os designs e funcionalidades gerais em uma classe separada . O retorno foi duplo: o controlador mpc é 100% focado no código relacionado ao mpc e como módulo associado a ele é apenas um modelo de configuração. Em outras palavras, devido a abstrações arquitetônicas, não preciso reescrever tudo ao trabalhar com um controlador diferente.



O mundo é composto de tons de cinza, portanto, essas decisões de design devem ser aprofundadas com cuidado e com a mentalidade certa. Caso contrário, você pode ir longe demais e começar a criar abstrações onde elas não são necessárias. No entanto, se o desenvolvedor estiver atento aos conceitos que essas abstrações modelam, o DRY é uma ferramenta poderosa para moldar as decisões de arquitetura. Na minha opinião, DRY é o principal conceito para manter seu código limpo e denso.



Afinal, um dos principais benefícios do código é sua capacidade de executar tarefas repetitivas; então, por que não mudar a repetição para funções e classes bem projetadas?



Uso completo da linguagem e da biblioteca



DRY, na minha opinião, é um conceito tão importante e difundido que esse ponto é realmente apenas uma continuação da conversa sobre DRY.



Se o seu idioma suportar algo, geralmente você deve usar a implementação em linha, a menos que tenha boas razões para optar por não participar. E o C ++ possui muitas coisas incorporadas .



A programação é uma habilidade e há uma grande diferença nos níveis de habilidade. Eu só tive um vislumbre de quão alta é a montanha dessa habilidade e, em geral, acho que as pessoas que criam padrões são melhores na implementação de padrões comuns do que eu.



Um argumento semelhante pode ser feito para a funcionalidade das bibliotecas (embora talvez não seja tão categoricamente). Outra pessoa já fez o mesmo, e provavelmente em um bom nível, então não há razão para reinventar a roda.



No entanto, este, como muitos outros, este parágrafo é uma recomendação, e não uma regra rígida e urgente a ser aplicada. Embora não valha a pena reinventar a roda e, embora as implementações padrão sejam geralmente muito boas, não há sentido em tentar espremer uma peça quadrada em um buraco redondo. Pense com sua cabeça.



Código legível



O último conceito que me ajudou a melhorar minhas habilidades de programação foi que a programação não se resume tanto à escrita de código, mas também à comunicação. Se não for a comunicação com outros desenvolvedores, comunique-se com você no futuro. Obviamente, você precisa pensar em memória, matemática e na complexidade do Big O, mas depois de concluir isso, precisará começar a pensar em intenção, semântica e clareza.



Há um livro muito famoso e amplamente recomendado sobre esse tópico, o Código Limpo , portanto não há muito que eu possa acrescentar sobre esse tópico. Aqui estão algumas informações gerais às quais me refiro ao escrever e fazer revisões de código:



  1. Tente manter suas aulas claras e focadas:

    • Minimizar snagging
    • ()



      • const, noexcept? ? (, )




    • , (, , ).
    • (, )
    • .
  2. -



    • «», , .
    • (, ).
    • ( ) ().
  3. ? ()



    • , ().
    • , , , (, ).


Outro grande recurso que aborda esse tipo de problema são as Diretrizes Principais da ISO C ++ .



Reiterarei que nenhum desses princípios é revolucionário, novo ou único, mas se a redação dos princípios tiver valor (ou alguém disser "aha" ao ler ), não desperdicei bits e tráfego para escrever esta postagem. ...



Olhando para trás



Essas foram algumas das ferramentas, princípios e processos que usamos no desenvolvimento e implementação do algoritmo de localização NDT, bem como ao trabalhar no controlador MPC. Muito trabalho foi feito, foi divertido, não é tão interessante falar sobre isso.



No geral, fizemos um ótimo uso das ferramentas e práticas que mencionei, mas não éramos perfeitos.



Assim, por exemplo, ao trabalhar no NDT, não seguimos os idiomas do desenvolvimento orientado a testes (embora tenhamos tudo perfeitamente testado!). Por sua vez, segui técnicas de desenvolvimento orientadas a teste no MPC, mas esse projeto não se beneficiou do IC mais poderoso incorporado ao Autoware.Auto. Além disso, o projeto MPC não era público e, portanto, não recebeu os benefícios de uma revisão de código.



Ambos os projetos podem se beneficiar da introdução de análises estáticas, testes mais detalhados e mais feedback. No entanto, estamos falando de projetos criados por uma pessoa, então acho que os testes realizados e o feedback recebido são suficientes. Quando se trata de análise estática, formas melhores e mais próximas geralmente caem no campo dos interesses de desenvolvimento de produtos e se afastam da comunidade de desenvolvedores de código aberto (embora idéias interessantes possam aparecer no horizonte ).



Não tenho nada a dizer sobre o desenvolvimento simultâneo de dois algoritmos - trabalhamos da melhor maneira possível, aderindo aos princípios que descrevi acima.



Eu acho que fizemos um excelente trabalho de decompor grandes problemas em pedaços menores (embora o componente MR no algoritmo NDT pudesse ser menor) e fizemos testes extensivos. Eu acho que os resultados preliminares falam por si.



Movimento para frente



Após a implementação, é hora de integração. É necessário conectar-se a um sistema maior com seus próprios componentes complexos. Este sistema irá receber sua entrada, digeri-la e produzir os resultados do seu algoritmo. A integração é talvez a parte mais difícil do desenvolvimento de um algoritmo, pois você precisa acompanhar o plano geral do sistema e corrigir problemas de baixo nível. Qualquer erro em qualquer uma das suas muitas linhas de código pode impedir a integração do seu algoritmo.



Vou abordar isso no terceiro e último post desta série.



Como uma prévia, direi que durante o processo de desenvolvimento, nenhum grande erro foi encontrado durante o uso e a integração do controlador mpc. É verdade que houve alguns problemas ao escrever scripts , montar,testes , a validação dos dados de entrada foi ignorada e também houve problemas com a incompatibilidade das configurações de QoS , mas não havia nada de terrível no código.



Na verdade, ele foi capaz de executar (ignorando incompatibilidades de QoS e definindo opções) quase que imediatamente .



O mesmo se aplica ao algoritmo NDT, que encontrou vários problemas menores, como instabilidade de covariância , erro na pesquisa de strings no código existente e mapas alinhados incorretamente. Independentemente disso, ele também foi capaz de trabalhar fora da caixa .



Nada mal para produtos projetados para todo mundo ver.



Inscreva-se nos canais:

@TeslaHackers — Tesla-, Tesla

@AutomotiveRu — ,







imagem



- automotive . 2500 , 650 .



, , . ( 30, ), -, -, - (DSP-) .



, . , , , . , automotive. , , .


:






All Articles