<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://mohankarthik.dev/feed.xml" rel="self" type="application/atom+xml" /><link href="https://mohankarthik.dev/" rel="alternate" type="text/html" /><updated>2025-08-02T14:21:29+00:00</updated><id>https://mohankarthik.dev/feed.xml</id><title type="html">Mohan Karthik</title><subtitle>Talks about Dev, Tech, Product and Leadership</subtitle><author><name>Mohan Karthik</name></author><entry><title type="html">The Embedded Engineer’s Place in an AI-Driven World</title><link href="https://mohankarthik.dev/engineering/2025/08/02/the-embedded-engineers-place-in-an-ai-driven-world.html" rel="alternate" type="text/html" title="The Embedded Engineer’s Place in an AI-Driven World" /><published>2025-08-02T04:30:00+00:00</published><updated>2025-08-02T04:30:00+00:00</updated><id>https://mohankarthik.dev/engineering/2025/08/02/the-embedded-engineers-place-in-an-ai-driven-world</id><content type="html" xml:base="https://mohankarthik.dev/engineering/2025/08/02/the-embedded-engineers-place-in-an-ai-driven-world.html"><![CDATA[<h1 id="the-embedded-engineers-place-in-an-ai-driven-world">The Embedded Engineer’s Place in an AI-Driven World</h1>

<p>It’s impossible to <a href="https://www.google.com/search?q=https://www.bloomberg.com/opinion/articles/2023-03-20/the-world-is-short-of-computer-coders-ai-is-coming-to-the-rescue">ignore</a>, <a href="https://www.google.com/search?q=https://www.businessinsider.com/ai-beats-top-human-coder-in-programming-competition-2022-2">the</a>, <a href="https://www.google.com/search?q=https://www.tomshardware.com/tech-industry/artificial-intelligence/nvidia-ceo-says-the-era-of-coding-is-over-kids-shouldnt-learn-to-code-but-focus-on-more-valuable-expertise">headlines</a>. Every week, a new AI model seems to be released that can write code, fix bugs, and even build entire applications from a single prompt. We see impressive demos from Google, OpenAI and others, and it’s natural to ask the question on every developer’s mind: “Will an AI take my job?”</p>

<h2 id="programming-vs-engineering">Programming vs. Engineering</h2>

<p>Let’s be clear: the anxiety around AI is not unfounded. The act of <strong>programming</strong>—translating a well-defined requirement into code—is becoming increasingly automated. We see this with tools like GitHub Copilot becoming a standard part of the developer workflow, and companies like <a href="https://www.cognition-labs.com/introducing-devin">Cognition Labs with their AI agent Devin</a> are pushing the boundaries of what’s possible. For tasks with clear inputs and outputs, like building a standard CRUD API or a simple web form, AI is incredibly effective because it excels at pattern matching on a massive scale.</p>

<p>This is a good thing. It frees us from rote work. But it’s crucial to distinguish this from the broader discipline of <strong>engineering</strong>. Engineering isn’t just writing code. It’s the messy, human process of architecting systems, making trade-offs, diagnosing emergent behavior, and maintaining critical systems over time. It’s about asking the right questions—a process that can take months—before a single line of code is written. What are the concurrency trade-offs for this database design? How do we scale this backend for a 100x increase in traffic? Should we scale now, or are we overprovisioning? An AI can’t answer these questions because the answers depend on business context, future goals, and deep systems knowledge.</p>

<p>This is where the future lies: not in being a better coder than an AI, but in being a better engineer who uses AI to offload tedious work. This distinction is vastly more apparent in the world of embedded systems.</p>

<h2 id="war-stories">War Stories</h2>

<p>An AI can write a Python script to parse a file because it has seen a million examples. But can it debug a system where a single flipped bit in memory leads to catastrophic failure? This is where an embedded engineer’s real value lies. Here are a few examples from the real world.</p>

<h3 id="toyotas-unintended-acceleration">Toyota’s Unintended Acceleration</h3>

<p><img src="/assets/images/2025-08-02/Toyota.webp" alt="Toyota" class="align-center" />
<a href="https://www.csmonitor.com/USA/2010/0226/Report-Rogue-car-acceleration-is-not-just-a-Toyota-problem" class="text-center">Source</a></p>

<p>For years, Toyota faced reports of its cars accelerating without driver input. The initial blame was placed on floor mats. The real culprit, however, was a ghost in the machine. <a href="https://www.google.com/search?q=https://www.safetyresearch.net/blog/articles/toyota-unintended-acceleration-and-big-bowl-%25E2%2580%259Cspaghetti%25E2%2580%259D-code">Expert testimony in court cases</a> revealed critical flaws in the engine control unit’s firmware. The issues weren’t simple bugs; they were complex system failures like <strong>stack overflow</strong>, where memory management fails and causes unpredictable behavior. Critical tasks could be disabled by other tasks, and the code was riddled with thousands of global variables, creating a “spaghetti code” nightmare. An AI could not have debugged this. It required engineers with a deep understanding of real-time operating systems, memory management, and safety-critical coding standards (like MISRA C) to painstakingly trace the complex interactions that could lead to the throttle control system failing in an unsafe state.</p>

<h3 id="bricking-nest">Bricking Nest</h3>

<p><img src="/assets/images/2025-08-02/nest.webp" alt="Nest" class="align-center" />
<a href="https://www.amazon.in/Nest-Learning-Thermostat-Generation-Office/dp/B01M65EKLG" class="text-center">Source</a></p>

<p>In 2016, a faulty firmware update rendered thousands of <a href="https://www.google.com/search?q=https://www.nytimes.com/2016/01/14/fashion/nest-thermostat-glitch-leaves-users-in-the-cold.html">Nest smart thermostats unresponsive</a>, effectively “bricking” them in the middle of winter. The problem wasn’t a server outage; it was a deep-seated embedded bug. The issue was reportedly a flaw in the device’s sleep/wake algorithm. When the device woke for routine tasks, the bug sometimes prevented it from returning to a proper low-power state, causing the battery to drain completely. Once drained, the device couldn’t function or even recharge itself. This is a classic embedded problem. An AI might write a sleep algorithm, but debugging it requires measuring micro-amps of current with an oscilloscope, understanding the power state transitions of every component on the board, and correlating that physical data with the software’s execution. It’s a perfect blend of hardware and software detective work.</p>

<h3 id="ariane-5">Ariane 5</h3>

<p><img src="/assets/images/2025-08-02/ariane5.webp" alt="Ariane 5" class="align-center" />
<a href="https://hackaday.com/2016/06/30/fail-of-the-week-in-1996-the-7-billion-dollar-overflow/" class="text-center">Source</a></p>

<p>One of the most famous software failures in history was the explosion of the Ariane 5 rocket just 40 seconds into its maiden flight in 1996. The cause was a single, catastrophic software error detailed in the <a href="https://www.esa.int/Newsroom/Press_Releases/Ariane_501_-_Presentation_of_Inquiry_Board_report">official inquiry board report</a>. Engineers had reused code from the slower Ariane 4 rocket that converted a 64-bit floating-point number representing the rocket’s horizontal velocity into a 16-bit signed integer. On the faster Ariane 5, the velocity value was much larger than the Ariane 4’s, and the number became too big for the 16-bit integer to hold. This caused an <strong>integer overflow</strong>, which the system interpreted as a flight path error. The rocket’s software did exactly what it was told to do with the bad data: it swiveled the nozzles to “correct” the non-existent problem, causing the rocket to veer off course and self-destruct. An AI, without the full system context, might see the data conversion code as correct in isolation. It took human engineers to understand the <em>new physical constraints</em> of the Ariane 5 and realize that the reused code was no longer valid.</p>

<h2 id="systems-endingeering">Systems Endingeering</h2>

<p>The war stories above highlight the true nature of embedded work: it is fundamentally systems engineering. An embedded engineer’s “IDE” isn’t just a text editor; it’s a collection of tools and documents that bridge the digital and physical worlds. To solve a problem, you must look far beyond the code itself.</p>

<ul>
  <li><strong>The Schematic:</strong> You have to read hardware blueprints to understand which processor pin connects to which LED, sensor, or motor driver. Is a pull-up resistor missing? Is the I2C bus shared? The answer isn’t in the code; it’s on the schematic.</li>
  <li><strong>The Datasheet:</strong> A 1,000-page microcontroller datasheet is your bible. It contains the “API documentation” for the hardware. You need to understand the precise sequence of register writes to configure a peripheral, the timing constraints for a memory interface, or the exact current draw in different low-power modes.</li>
  <li><strong>The Oscilloscope &amp; Logic Analyzer:</strong> Your debugger isn’t just GDB. It’s a physical probe that lets you see electrical signals in real-time. Is a signal noisy? Is there a voltage drop when a motor turns on? Is the timing of an SPI signal meeting the spec? These are questions code cannot answer.</li>
  <li><strong>The Laws of Physics:</strong> You can’t escape physics. Code that works perfectly on a dev board might fail in a hot engine bay due to thermal issues. A long wire might act as an antenna, picking up noise that corrupts your sensor data. Power consumption, heat dissipation, and signal integrity are your constant companions.</li>
</ul>

<p>An AI can’t hold an oscilloscope probe, read a thermal camera, or understand the nuance of a datasheet that contradicts a schematic. The job of an embedded engineer is to synthesize information from all these disparate, messy, real-world sources. That is not programming; that is true systems engineering.</p>

<p>The future isn’t about competing with AI; it’s about leveraging it. We should welcome AI as a powerful assistant, and incredible tools already exist to handle the tedious parts of our job:</p>

<ul>
  <li><strong>Large Language Models:</strong> General-purpose LLMs like <a href="https://gemini.google.com/">Gemini</a>, <a href="https://chat.openai.com/">ChatGPT</a>, and <a href="https://claude.ai/">Claude</a> are fantastic for deep research and getting a second opinion on architectural decisions. With their vision capabilities, they can even analyze a screenshot from your oscilloscope or logic analyzer and help decode a complex timing diagram.</li>
  <li><strong>Document-Grounded AI:</strong> Tools like <a href="https://notebooklm.google.com/">NotebookLM</a> or <a href="https://www.chatpdf.com/">ChatPDF</a> are game-changers for our line of work. You can upload a 1,000-page datasheet and start asking specific questions, like “What is the exact sequence to enable the ADC?” or “Summarize all low-power modes.” It turns a day of document searching into a 5-minute conversation.</li>
  <li><strong>Hardware-Aware AI:</strong> Emerging tools like <a href="https://docs.flux.ai/tutorials/ai-for-hardware-design">Flux Copilot</a> are being built specifically for hardware design. They can help analyze schematics, suggest components, and even help debug PCB layouts, augmenting the physical side of our engineering work.</li>
  <li><strong>RTOS-Aware Analysis:</strong> Specialized tools like <a href="https://percepio.com/tracealyzer/">Percepio Tracealyzer</a> use sophisticated visualization and algorithmic analysis to find complex bugs in RTOS-based systems. They can automatically spot issues like priority inversion and task deadlocks that are nearly impossible to find with traditional debuggers.</li>
</ul>

<p>This frees us up to focus on the work that truly matters: the complex, multi-disciplinary engineering that AI can’t touch. It allows us to spend more time with an oscilloscope, more time architecting a fault-tolerant system, and more time understanding the deep physics of the problem we’re trying to solve. In an age where routine programming can be automated, the systems-level detective work of an embedded engineer is not only secure, it’s more valuable than ever.</p>]]></content><author><name>Mohan Karthik</name></author><category term="engineering" /><category term="embedded" /><category term="ai" /><summary type="html"><![CDATA[The Embedded Engineer’s Place in an AI-Driven World]]></summary></entry><entry><title type="html">‘Just a quick question’: How to Protect Your Focus and Set Boundaries</title><link href="https://mohankarthik.dev/work-life/2025/07/25/just-a-quick-question-how-to-protect-your-focus-and-set-boundaries.html" rel="alternate" type="text/html" title="‘Just a quick question’: How to Protect Your Focus and Set Boundaries" /><published>2025-07-25T04:30:00+00:00</published><updated>2025-07-25T04:30:00+00:00</updated><id>https://mohankarthik.dev/work-life/2025/07/25/just-a-quick-question-how-to-protect-your-focus-and-set-boundaries</id><content type="html" xml:base="https://mohankarthik.dev/work-life/2025/07/25/just-a-quick-question-how-to-protect-your-focus-and-set-boundaries.html"><![CDATA[<h1 id="just-a-quick-question-how-to-protect-your-focus-and-set-boundaries">“Just a quick question”: How to Protect Your Focus and Set Boundaries</h1>

<p>The workday begins. Laptop on, a glass of hot water for the perpetually sore throat (thanks, Bangalore weather), and a round of good mornings to the other early birds. I settle in to check my work.</p>

<p>And there it is: the overnight test failed with some interesting logs. I’ve spent a week chasing this exact bug, and this could be the break I need. The water is getting cold, forgotten as I dive in, making notes, checking hypotheses. I’m getting close. A new idea starts to form, and I have a good feeling about this one.</p>

<p>I’m deep in the zone when a tap on the shoulder breaks the spell. “Coffee?” I politely decline, eager to get back. But before I can, another voice calls from across the desk about a different bug, sparking a discussion. I try to pull my focus back, but just like that, it’s gone. The thread of thought is lost, the promising idea evaporated.</p>

<h2 id="the-true-cost-of-yes-why-i-believe-boundaries-are-non-negotiable">The True Cost of ‘Yes’: Why I Believe Boundaries Are Non-Negotiable</h2>
<p>At every company I’ve worked for, no matter what my role, I knew that if I left, my position would be backfilled. The machine is designed to keep running. But at home, to my wife, my son, my parents, and my friends, I am irreplaceable. There is no backfill for that role, and I wouldn’t want there to be. The memories I have of eating messy mangoes on the balcony with my wife, or telling my son terrible dad jokes—those are the things that stick. I can’t remember the details of the few weekends I worked in my entire career, but I can remember the taste of the mangoes. That’s the real currency.</p>

<p>Many a time, we think of multitasking as a superpower, but I’ve learned it’s not. Every time I’m pulled from a complex problem, I pay a tax. It’s not just the five minutes of the interruption. It’s the hour I lose reloading that complex problem, and the creative reflections lost forever in the switch. When that happens frequently enough, I end up paying more in taxes than I earn in actual progress. This isn’t just about lost productivity on a feature; it’s about what that lost time truly represents, and ultimately, one of those dimensions pays the price.</p>

<p>This isn’t a manifesto against hard, passionate work, though. I’ve had those nights: it’s 10 PM, the team chatroom is silent, and I’m fueled by coffee and the thrill of the chase. Those nights are memorable, but the key difference is that I chose to be there, driven by my own passion, not by poor planning.</p>

<h2 id="the-fear-of-no-the-real-reasons-we-struggle-to-set-boundaries">The Fear of ‘No’: The Real Reasons We Struggle to Set Boundaries</h2>
<p>So if the cost is so high, why do we so willingly give up our focus? Let’s be honest, saying “no” feels confrontational. We’re often wired to be agreeable, and the fear of social friction or being seen as unhelpful can easily outweigh the need to protect our time. This is compounded by the very real pressures of career and job security. It’s easy to worry, “If I say no, will it affect my performance review? Will I be passed over for a promotion?” So we say yes to everything, hoping that sheer volume of work will keep us safe.</p>

<p>We often treat our energy like a credit card with no limit, telling ourselves, “I’ll just push through this crunch period, and then I’ll rest.” But “later” is a moving target. Another project always comes up, and we rack up a “burnout debt” that can’t be paid off with a single long weekend. Sometimes this debt also comes from within: we make a mistake, misjudge a timeline, and our first instinct is guilt. Instead of being transparent, we try to overcompensate, throwing our evenings and weekends at the problem because we’re afraid to own our mistake and ask for help.</p>

<p>Breaking this cycle requires a different kind of inspiration. When I look for it, I think of Satya Nadella. He has often said that his perspective on life and leadership was fundamentally reshaped by his experience raising his son, who had cerebral palsy. He learned a deep sense of empathy at home that became the foundation for transforming Microsoft’s culture. In his own words:</p>

<blockquote>
  <p>“It has shaped my personal passion for and philosophy of connecting new ideas to empathy for others. And it is why I am deeply committed to pushing the bounds on what love and compassion combined with human ingenuity and passion to have impact can accomplish with my colleagues at Microsoft.”</p>
</blockquote>

<p>This shows that he didn’t succeed in spite of his family commitments; he succeeded because of the efforts he spent with his family. He is living proof that bringing your whole self to your job is what creates great leadership.</p>

<h2 id="how-i-built-the-confidence-to-set-boundaries">How I Built the Confidence to Set Boundaries</h2>
<p>For me, the confidence to set boundaries didn’t come from a place of arrogance (hopefully), but from a place of security.</p>

<h3 id="adopting-the-two-hats-philosophy">Adopting the “Two Hats” Philosophy</h3>
<p>I have a “Work Hat” and a “Home Hat,” and I try to treat both as equally important. By investing in my life outside of work—nurturing my relationships, pursuing hobbies—I’ve built an identity that is separate from my job title. I read voraciously, I’m a pianist, I’m an avid gamer. These have become my “re-create-ional” anchor. It reminds me that a bad day at work is just that—a bad day at work. It’s not a reflection of my entire worth. I’ve found that a strong family and a strong sense of self don’t distract from a strong career; they are its foundation.</p>

<h3 id="building-my-career-confidence">Building My Career Confidence</h3>
<p>A huge part of being confident at work is knowing that people have my back. Knowing my wife, family, and friends (my emotional anchor) will support me emotionally if I ever need to leave a toxic environment is incredibly empowering. It’s my psychological safety net, and it allows me to say, “This isn’t right,” without the paralyzing fear of being alone. It gives me the courage to stand up for myself, a gift for which I’m incredibly grateful.</p>

<h3 id="building-my-financial-confidence">Building My Financial Confidence</h3>
<p>This is the most practical pillar of confidence. I realized the fear of losing a job is often, at its core, a fear of not being able to pay my bills. Hence, financial literacy was one of the most powerful tools that we (my Wife and I) learned. Our goal wasn’t to become wealthy (but hey, who’s complaining if we get there), but to create options for ourselves. Having an emergency fund, living below our means, and understanding our finances means that we are not operating from a place of desperation. I can make career decisions based on our well-being and long-term goals, not on short-term financial panic. This financial cushion is what turns the terrifying prospect of saying “no” into a calculated, and often wise, business decision.</p>

<h2 id="practical-steps-that-have-worked-for-me">Practical Steps That Have Worked For Me</h2>
<p>OK, that’s a lot of philosophy! So, what do I do tactically on a day-to-day basis?</p>

<h3 id="reclaiming-my-calendar">Reclaiming My Calendar</h3>
<ul>
  <li><strong>Block and defend my focus time</strong>. I block “Focus Time” on my public calendar and I treat it like any other important meeting.</li>
  <li><strong>“Do Not Schedule” blocks</strong>. I block out time for lunch, personal appointments and time outside work with “DNS” blocks. This helps prevent my entire day from being consumed by meetings and respects my time outside of work.</li>
</ul>

<h3 id="reclaiming-my-meetings">Reclaiming My Meetings</h3>
<ul>
  <li><strong>Push back on ad-hoc meetings</strong>. I try to use polite replies like, “Could we handle this over chat so I can give it my full attention after my current task?” or “Happy to connect. Could you share a quick agenda so I can prepare?” You’ll be surprised at how many issues can be resolved over a couple of chats rather than spending 30 minutes in a meeting.</li>
  <li><strong>Go asynchronous</strong>. For many recurring meetings, A shared document or a chat thread is more efficient for everyone. A lot of credit to my team for pushing me on this equally.</li>
  <li><strong>Effective 1-on-1s</strong>. 1-1s are important to get a sense of the person. But they can easily digress into chit-chat. I try to create a shared agenda doc, ask the other person to add to it beforehand, discuss what’s needed, and end the meeting promptly.</li>
</ul>

<h3 id="reclaiming-my-time">Reclaiming My Time</h3>
<ul>
  <li><strong>Dedicating time with family</strong>. Everyone (including your family) has a busy life. Aligning everyone takes effort, but it’s effort that’s well worth to do every day to keep nurturing that connection.</li>
  <li><strong>Being conscious of social breaks at work</strong>. Socializing at work is important, but many times a quick chat is turning into a major time sink that will derail my whole day.</li>
  <li><strong>Commit to a strict end-of-day time</strong>. This has been a game-changer. It forces me to be more efficient. The goal is to fit my work into the container I’ve set, not to let it expand indefinitely.</li>
</ul>

<h3 id="reclaiming-my-reputation">Reclaiming My Reputation</h3>
<ul>
  <li><strong>Remind myself that a “no” is a “yes” to my existing commitments</strong>. I’ve come to see saying “no” as an act of responsibility. It allows me to protect the quality of my current work. I’ve also learned that my reputation is built on reliability. Delivering consistently on my promises, even if I take on less, has been far better for my career than over-promising and under-delivering.</li>
</ul>

<hr />
<p>Setting boundaries isn’t about building walls or avoiding work, but rather about building a sustainable career. It’s about recognizing that my best work comes from a place of focus, not from a state of constant distraction. It’s about having the confidence to protect my time and energy so I can bring my best self to my team, and just as importantly, to my family.</p>

<p>This isn’t an overnight change. It’s a practice. If any of this resonates with you, I hope you’ll try one small thing tomorrow. Block consistent time with family every day. Say a polite “I can’t step away right now” to one request. It’s a small step, but neither Rome nor our lives are built in a day.</p>]]></content><author><name>Mohan Karthik</name></author><category term="work-life" /><category term="philosophy" /><summary type="html"><![CDATA[“Just a quick question”: How to Protect Your Focus and Set Boundaries]]></summary></entry><entry><title type="html">Introduction to Automotive Networks</title><link href="https://mohankarthik.dev/engineering/2022/06/23/introduction-to-automotive-networks.html" rel="alternate" type="text/html" title="Introduction to Automotive Networks" /><published>2022-06-23T04:30:00+00:00</published><updated>2022-06-23T04:30:00+00:00</updated><id>https://mohankarthik.dev/engineering/2022/06/23/introduction-to-automotive-networks</id><content type="html" xml:base="https://mohankarthik.dev/engineering/2022/06/23/introduction-to-automotive-networks.html"><![CDATA[<h1 id="why-do-we-need-automotive-networks">Why do we need automotive networks</h1>
<p>The internet has forever changed the way we interact with the world, and has deeply embedded itself into our lives. More and more devices are now connected and getting “smarter”! While the term “smarter” is debatable: I would like my TV to simply play what I command via the remote rather than tell me a million times “I can’t understand what you said” (thank you Alexa!).</p>

<p>As this revolution happens, a silent, albiet very powerful upgrade has been happening within our cars. And I don’t just mean that automobiles are getting connected and you can control them via your mobile, but how the various devices within a car talk to each other.</p>

<h2 id="evolution-of-the-electronic-control-unit-ecu">Evolution of the Electronic Control Unit (ECU)</h2>
<p>An ECU is a small computer in your car that is responsible for controlling a specific feature (say brakes, traction control, steering, etc…). Over the years, the number of ECUs in the car have exploded from a few 10s of ECUs to more than 100s of ECUs in each car. No longer are these crucial components mechanically controlled. The original car used to have a brake pedal connected to the brake piston via brake fluid and transmits the pressure on the brake pedal to the brake pads to bring the car to a stop.</p>

<p class="text-center"><img src="/assets/images/2022-06-23/2022-06-23-mechanical-braking.webp" alt="Mechanical brakes" class="align-center" />
Mechanical braking - <a href="https://projectsgeek.com/2020/03/mechanical-braking-system-project.html">Image credit</a></p>

<p>Now, no more; when you press the brake pedal, a sensor ECU now collects the pressure on the pedal, encodes it into a message and sends it to another ECU that controls the brakes. The recieving ECU processes the incoming message, and then actuates not just the brakes, but the powertrain too to bring the car to a stop!</p>

<p class="text-center"><img src="/assets/images/2022-06-23/2022-06-23-electric-brake.webp" alt="Electric brakes" class="align-center" />
Audi e-tron’s electronic braking - <a href="https://www.autoevolution.com/news/what-is-brake-by-wire-and-how-it-works-150856.html">Image credit</a></p>

<h2 id="explosion-of-ecus">Explosion of ECUs</h2>
<p>Thanks to the speed at which features are being added into automobiles, pretty much every function is turning into an electronic component.</p>

<p>The following image shows the different major electronic systems in the car. And this is still a very bird’s eye view and misses showing many of the sub-systems that exists.</p>

<p class="text-center"><img src="/assets/images/2022-06-23/2022-06-23-electonic-components-in-car.webp" alt="ECUs in a car " class="align-center" />
ECUs in a car - <a href="https://autotechdrive.com/electronic-control-unit/">Image credit</a></p>

<p>Thanks to this, the average number of ECUs in the car has been growing exponentially. A lot more due to the disruption by non traditional OEMs such as Telsa, Rivian, etc…</p>

<p class="text-center"><img src="/assets/images/2022-06-23/2022-06-23-average-ecus-in-car.webp" alt="Average ECUs in a car" class="align-center" />
Average ECUs in a car - <a href="https://www.greencarcongress.com/2015/07/20150729-berger.html">Image credit</a></p>

<p>And with this, the market has also been expanding rapidly.</p>

<p class="text-center"><img src="/assets/images/2022-06-23/2022-06-23-average-ecu-market.webp" alt="ECU market" class="align-center" />
ECU market - <a href="https://www.marketsandmarkets.com/Market-Reports/automotive-ecu-market-34863602.html">Image credit</a></p>

<h1 id="evolution-of-automotive-networks">Evolution of automotive networks</h1>
<p>Given how the automotive ECU’s have exploded, the need for good and robust networking solutions have also increased! When it comes to automotive networks, there are two major segments:</p>
<ul>
  <li>Control plane (powertrain, chassis, errors, etc…)</li>
  <li>Media plane (entertainment, infortainment, etc…)</li>
</ul>

<p>This division is historical and has started merging into a single entity lately. But for the sake of a good story (who doesn’t like a good story, that too about networks /s), let’s understand the evolution here.</p>

<h2 id="control-plane">Control plane</h2>
<p>The control plane is primarily focused on getting sensor data to actuators.</p>

<p class="text-center"><img src="/assets/images/2022-06-23/2022-06-23-sensor-controller-actuator.webp" alt="Sensor-Controller-Actuator" class="align-center" />
Sensor - Controller - Actuator - <a href="https://www.geeksforgeeks.org/actuators-in-iot/">Image credit</a></p>

<p>Sensors are ECUs / components that sense different information, say the pressure on the brake / acceleration pedals; the fuel level of the car; a radar signal to measure the distance of the car in front; a crash sensor to inform if an accident is occuring, etc…</p>

<p>Actuators on the other hand are components that perform actions. A brake actuator that actually brings the car to a stop, an airbag actuator that deploys the airbag on certain condtions, a speed actuator that controls the speed of the car depending on the cruise-control or the driver’s acceleration input.</p>

<p>Between these two components is the controller ECU. This is the one that would recieve inputs from different sensors, understand the inputs and take decisions. For instance, an airbag controller would look at inputs from the crash sensor, but also from occupancy sensors (sensors that tell if a passenger is present or not). It would then check to see from other sensors to confirm a crash (say from a radar or from an inertial measurement unit) and then send an actuation message to airbag actuators where passengers are present to deploy the airbag. This of course is gross simplification since it would take many articles to talk just about the <a href="https://www.hella.com/techworld/uk/Technical/Car-electronics-and-electrics/Car-airbag-system-3083/">airbag flow</a>.</p>

<p>For obvious reasons, this plane needs to be secure and safe. Secure meaning that it should not allow unauthorized access and safe meaning that an error (either in the ecu, or the network) should be immediately highlighted, there should be redundancies and the car should reach a safe state that minimizes the loss of life. This is covered in detail under <a href="https://en.wikipedia.org/wiki/ISO_26262">ISO26262</a> and <a href="https://www.nhtsa.gov/technology-innovation/vehicle-cybersecurity">Automotive Cybersecurity</a>. Topics for another day.</p>

<h2 id="media-plane">Media plane</h2>
<p>The media plane is primarily focused on getting entertainment information to the passengers. Essentially getting netflix, youtube to our spoiled asses as we drive, allowing us to make calls in and out, etc… As more and more of the car gets autonomous, the main differentiating factor is the in cabin experience and getting the media plane right goes a long way in securing good customer experience.</p>

<p>As opposed to the control plane, the networks in the media plane is focused on bandwidth and latency. Safety and security are still important, but not to the same level as the control plane.</p>

<h2 id="automotive-networks">Automotive Networks</h2>
<p>Now that we’ve detailed out the two planes, let’s look at the various different automotive network protocols that exist in cars today.</p>

<p class="text-center"><img src="/assets/images/2022-06-23/2022-06-23-automotive-networks.webp" alt="Automotive Networks" class="align-center" />
Automotive Networks - <a href="https://standards.ieee.org/wp-content/uploads/import/documents/other/d1-03_matheus_evolution_of_ethernet_based_automotive_networks.pdf">Image credit</a></p>

<p class="text-center"><img src="/assets/images/2022-06-23/2022-06-23-automotive-networks-in-car.webp" alt="Automotive Networks in cars" class="align-center" />
Automotive Networks in car - <a href="https://silvaco.com/blog/design-ip-for-automotive-socs-trends-and-solutions/">Image credit</a></p>

<p><em>Now an obvious question would be, why the hell do we’ve so many networks and not just one! If only the world of engineering always agreed. Each of these networks evolved for a specialized use-case and they continue to be used either because they are already in production, and it’s difficult to change; or they solve a use-case so specific that a generic network cannot solve</em></p>

<p>The most popular networks are</p>
<ul>
  <li>Controller Area Network (CAN): Developed by Bosch in 1983, it is still the most commonly used automotive network in the car for all things related to the control plane.</li>
  <li>Local Interconnect Network (LIN): Developed by a group of OEMs (BMW, Volkswagen Group, Audi, Volvo Cars, Mercedes-Benz) in 2002, LIN became the low cost, simpler alternative to CAN focusing on last mile connectivity again for control plane.</li>
  <li>Media Oriented System Transport (MOST): Developed by SMSC (today owned by Microchip) with the primary aim to address the media plane with bandwidth going from 25mpbs to 150mbps today. This is currently the defacto network in every car for entertainment data.</li>
  <li>Ethernet: Surprisingly Ethernet is yet to enter mainstream automotive networks in a big way. While most cars on road today have a small sprinkling of Ethernet and it’s growing exponentially, there is a big historical reason why it took so long for Ethernet to penetrate the Automotive market.</li>
</ul>

<p>In the next edition of this series, we’ll talk about how the automotive network architecture has evolved and the networks themselves in more detail.</p>]]></content><author><name>Mohan Karthik</name></author><category term="engineering" /><category term="embedded" /><category term="automotive" /><category term="networks" /><category term="ethernet" /><summary type="html"><![CDATA[Why do we need automotive networks The internet has forever changed the way we interact with the world, and has deeply embedded itself into our lives. More and more devices are now connected and getting “smarter”! While the term “smarter” is debatable: I would like my TV to simply play what I command via the remote rather than tell me a million times “I can’t understand what you said” (thank you Alexa!).]]></summary></entry><entry><title type="html">Setting up GitHub Actions to Deploy JAVA code on Elastic Beanstalk</title><link href="https://mohankarthik.dev/engineering/2022/03/23/setting-up-github-actions-to-deploy-java.html" rel="alternate" type="text/html" title="Setting up GitHub Actions to Deploy JAVA code on Elastic Beanstalk" /><published>2022-03-23T04:30:00+00:00</published><updated>2022-03-23T04:30:00+00:00</updated><id>https://mohankarthik.dev/engineering/2022/03/23/setting-up-github-actions-to-deploy-java</id><content type="html" xml:base="https://mohankarthik.dev/engineering/2022/03/23/setting-up-github-actions-to-deploy-java.html"><![CDATA[<p>See the <a href="https://mohankarthik.dev/engineering/2022/03/21/setting-up-github-actions-to-deploy-angular.html">previous post</a> for details on how to understand the basics of GitHub actions and to set it up</p>

<p>The below is the workflow yml that will build and deploy a maven war file to Elastic Beanstalk. If you’ve questions on how to use this, and why certain things are being used, fire away in the comments.</p>

<h1 id="github-action-for-java-using-maven">GitHub action for Java (using maven)</h1>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>name: &lt;name&gt;
on:
  push:
    branches:
      - &lt;branch&gt;
  workflow_dispatch:
concurrency: &lt;name&gt;
jobs:
  &lt;name&gt;:
    name: &lt;name&gt;
    timeout-minutes: &lt;time to wait before timeout&gt;
    runs-on: ubuntu-latest
    env:
      CORRETTO_URL: https://corretto.aws/downloads/latest/amazon-corretto-8-x64-linux-jdk.tar.gz
    steps:
      - name: Checkout the code
        uses: actions/checkout@v2
        with:
          fetch-depth: 0
      - name: Cache jdk binary
        uses: actions/cache@v2
        with:
          path: ${{ runner.temp }}/jdk
          key: ${{ runner.os }}-jdk-8
          restore-keys: ${{ runner.os }}-jdk
      - name: retrieve latest corretto 8 jdk
        run: |
          test -d ${{ runner.temp }}/jdk || mkdir ${{ runner.temp }}/jdk
          test -f ${{ runner.temp }}/jdk/corretto.tar.gz || ( wget -qP ${{ runner.temp }}/jdk $ {{ env.CORRETTO_URL }} )
      - name: Set up JDK 8 from file
        uses: actions/setup-java@v2
        with:
          distribution: 'jdkfile'
          jdkFile: ${{ runner.temp }}/jdk/corretto.tar.gz
          java-version: '8'
          architecture: x64
          cache: "maven"
      - name: Enable caching
        uses: actions/cache@v2
        with:
          path: ~/.m2/repository
          key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
          restore-keys: |
            ${{ runner.os }}-m2
      - name: Create the installer after running the tests
        run: mvn clean install
      - name: Get the current time
        id: time
        uses: nanzm/get-time-action@v1.1
        with:
          timeZone: 8
          format: 'YYYY-MM-DD-HH-mm-ss'
      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v1
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: us-east-1
      - name: Upload the war file to AWS
        env:
          TIME: "${{ steps.time.outputs.time }}"
        run: |
          cp ./&lt;project&gt;/target/&lt;filename&gt;.war ./&lt;project&gt;/target/$TIME.war
          aws s3 cp ./&lt;project&gt;/target/$TIME.war s3://&lt;s3 bucket name&gt;/
          aws elasticbeanstalk create-application-version --application-name &lt;app name&gt; --version-label $TIME --source-bundle S3Bucket="&lt;s3 bucket name&gt;",S3Key="$TIME.war" --auto-create-application
          aws elasticbeanstalk update-environment --environment-name &lt;env name&gt; --version-label $TIME
</code></pre></div></div>]]></content><author><name>Mohan Karthik</name></author><category term="engineering" /><category term="devops" /><category term="github-actions" /><category term="aws" /><category term="maven" /><category term="java" /><category term="corretto" /><summary type="html"><![CDATA[See the previous post for details on how to understand the basics of GitHub actions and to set it up]]></summary></entry><entry><title type="html">Setting up GitHub Actions to Deploy Front-End Code on AWS S3 and Cloudfront</title><link href="https://mohankarthik.dev/engineering/2022/03/21/setting-up-github-actions-to-deploy-angular.html" rel="alternate" type="text/html" title="Setting up GitHub Actions to Deploy Front-End Code on AWS S3 and Cloudfront" /><published>2022-03-21T04:30:00+00:00</published><updated>2022-03-21T04:30:00+00:00</updated><id>https://mohankarthik.dev/engineering/2022/03/21/setting-up-github-actions-to-deploy-angular</id><content type="html" xml:base="https://mohankarthik.dev/engineering/2022/03/21/setting-up-github-actions-to-deploy-angular.html"><![CDATA[<h1 id="assumption">Assumption</h1>
<p>AWS S3 and Cloudfront are fantastic infrastructure to deploy your production website (either static, say a simple HTML/CSS, or generated via a static site generator via Gatsby, Hugo, Jekyll, etc…); or a dynamic front-end (say using React, Angular, etc…). This post will cover on how to deploy an angular / react / vue code to S3 and Cloudfront.</p>

<p>This post assumes that you already have a working JS project (either Angular / React / Vue / etc…), and that you’ve <a href="https://docs.aws.amazon.com/AmazonS3/latest/userguide/WebsiteHosting.html">setup AWS S3 bucket with a website endpoint</a></p>

<p>The post also assumes that you’ve your code hosted on Github.</p>

<h1 id="cicd-alternatives">CI/CD alternatives</h1>
<p>There are many CI/CD platforms today, including Jenkins, GitHub Actions, Circle CI, Atlassian Bamboo, etc… Given that most of us end up using Github to host the code, and that GitHub provides free minutes to run the pipelines, it’s just a very convinient option without any significant downsides.</p>

<h1 id="how-does-github-actions-work">How does Github Actions work</h1>
<p>Github actions can be triggered by many actions</p>
<ul>
  <li>Manually</li>
  <li>On a periodic interval via a cronjob</li>
  <li>On pushing a new commit to a branch</li>
  <li>On creating / updating / deleting a pull request</li>
</ul>

<p>Depending on the configuration, GitHub would simply create a new container (using very similar concepts to Docker) and do the job that you specify. The job could be anything. You could create a GitHub action to print “Hello World!”. Which is a nice way to test out things and get yourself comfortable with the idea.</p>

<h1 id="structure-of-the-github-workflow-file">Structure of the GitHub workflow file</h1>
<p>A GitHub workflow file is basically a YAML file and follows the <a href="https://docs.ansible.com/ansible/latest/reference_appendices/YAMLSyntax.html">YAML syntax</a>. This <a href="https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions">page</a> provides an excellent reference for how the GitHub syntax is structured. If you are interested to learn the basics, please go through this before proceeding.</p>

<h1 id="github-action-to-deploy-javascript-code">GitHub action to deploy Javascript code</h1>
<p>To create a new GitHub workflow, you create a <code class="language-plaintext highlighter-rouge">.github</code> folder in the root of your project and then a <code class="language-plaintext highlighter-rouge">workflows</code> folder. Within this folder, you can add a <code class="language-plaintext highlighter-rouge">&lt;name&gt;.yml</code> to define your workflow / pipeline. Below is the code that you can directly use, and then we’ll break it down.</p>

<p>Note the below config uses <code class="language-plaintext highlighter-rouge">yarn</code> but you can replace it with <code class="language-plaintext highlighter-rouge">npm</code> if that’s your package manager.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>name: &lt;name&gt;
on:
  push:
    branches: 
      - master
concurrency: &lt;name&gt;
jobs:
  &lt;name&gt;:
    name: &lt;name&gt;
    timeout-minutes: &lt;time in minutes after which the job should timeout&gt;
    runs-on: ubuntu-latest
    env:
      NODE_VERSION: '&lt;Node version number&gt;'
      S3_BUCKET: &lt;s3 bucket ID&gt;
      CDN_DISTRIBUTION_ID: &lt;cloudfront ID&gt;
      AWS_REGION: &lt;aws region&gt;
    steps:
      - name: Checkout the code
        uses: actions/checkout@v2
        with:
          fetch-depth: 0
      - name: Install node
        uses: actions/setup-node@v2
        with:
          node-version: ${{ env.NODE_VERSION }}
      - name: Get yarn cache directory path
        id: yarn-cache-dir-path
        run: echo "::set-output name=dir::$(yarn cache dir)"
      - name: Cache the dependencies
        uses: actions/cache@v2
        id: yarn-cache
        with:
          path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
          key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
          restore-keys: |
            ${{ runner.os }}-yarn-
      - name: yarn install
        run: yarn --prefer-offline
      - name: build
        run: &lt;your yarn command to build your site&gt;
      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v1
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: {{ env.AWS_REGION }}
      - name: deploy
        run: |
          aws s3 rm s3://${{ env.S3_BUCKET }}/ --recursive
          aws s3 cp ./target/www s3://${{ env.S3_BUCKET }} --cache-control 'public, max-age=31104000' --recursive
          aws configure set preview.cloudfront true
          aws cloudfront create-invalidation --distribution-id ${{ env.CDN_DISTRIBUTION_ID }} --paths "/*"
</code></pre></div></div>

<p>Let’s break the above down</p>

<h2 id="triggers">Triggers</h2>
<p>This <a href="https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows">page</a> contains detailed information. In summary,  the most conventional triggers used are as follows:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>on:
  push:
    branches: 
      - master # Matches any push on the master branch
      - *asd* # Matches any branch that has asd in the name like basd, basdf, etc...
  pull_request:
    types:
      - opened # When a new PR is opened
      - reopened # When a PR is re-opened
      - synchronize # When a PR is updated
</code></pre></div></div>

<p>The above are your conventional triggers. So if you want to build and deploy anytime you push / merge to a branch (say the main / master). This is what we do in our original example. If you want to build each time a pull request is updated, so you get to test the bleeding edge work, then you can trigger it on pull_request -&gt; types -&gt; opened, synchronized.</p>

<h2 id="choosing-the-runner">Choosing the Runner</h2>
<p>In the above example, we use <code class="language-plaintext highlighter-rouge">ubuntu-latest</code>. This could be the default choice for most people, but look at <a href="https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners">other options</a>.</p>

<h2 id="naming-the-job">Naming the Job</h2>
<p>A job has a name</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>jobs:
  &lt;name&gt;:
    name: &lt;name&gt;
</code></pre></div></div>

<p>Pretty straightforward. Everyone has a name (except if you are <a href="https://www.youtube.com/watch?v=TgXlQlOrSx8">Arya Stark</a>)! It’s just cruel to be nameless!</p>

<h2 id="defining-environment-variables">Defining environment variables</h2>
<p>It’s a good idea to always defining common variables in once place, so you can easily use them in multiple places. Same as <a href="https://en.wikipedia.org/wiki/Don%27t_repeat_yourself">DRY</a></p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    env:
      NODE_VERSION: '&lt;Node version number&gt;'
      S3_BUCKET: &lt;s3 bucket ID&gt;
      CDN_DISTRIBUTION_ID: &lt;cloudfront ID&gt;
      AWS_REGION: &lt;aws region&gt;
</code></pre></div></div>

<p>In this case, let’s also define what these variables are.</p>
<ul>
  <li>NODE_VERSION: This is straight forward. Simply put the node version that you’ve locally used to build the project. Also ensure to keep this aligned with your local version, so you don’t get surprises when you deploy</li>
  <li>S3_BUCKET: This is the name of the S3 bucket. Typically you want a name that is unique. In my case it would be <code class="language-plaintext highlighter-rouge">dev.mohankarthik.xxx</code> and since I own <code class="language-plaintext highlighter-rouge">mohankarthik.dev</code>, the naming convention becomes unique for me.</li>
  <li>CDN_DISTRIBUTION_ID: This is the ID of the cloudfront entry. You can skip cloudfront, but it’s pretty spectacular and I’d suggest enabling it even for hobby projects.</li>
  <li>AWS_REGION: The Region where your AWS account is hosted. us-east-1, etc…</li>
</ul>

<h2 id="steps">Steps</h2>
<p>This is where the money is. Now let’s dive in.</p>

<p>Each step has an <code class="language-plaintext highlighter-rouge">name</code> and either <code class="language-plaintext highlighter-rouge">uses</code> or <code class="language-plaintext highlighter-rouge">run</code>. <code class="language-plaintext highlighter-rouge">uses</code> essentially uses an existing module directly with no work from us. How cool is that. We get small open-source tasks to run and get us what we want. You can see the list of all existing actions <a href="https://github.com/marketplace?type=actions">here</a>.</p>

<h3 id="checkout-the-code">Checkout the code</h3>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>      - name: Checkout the code
        uses: actions/checkout@v2
        with:
          fetch-depth: 0
</code></pre></div></div>

<p>This piece of code basically checks your code out into the machine that’s building the code. <code class="language-plaintext highlighter-rouge">fetch-depth</code> being set to 0 basically means that it will do a shallow pull, only the current commit and not the entire history.</p>

<h3 id="installing-node">Installing node</h3>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>      - name: Install node
        uses: actions/setup-node@v2
        with:
          node-version: ${{ env.NODE_VERSION }}
</code></pre></div></div>

<p>This installs the node version that you’ve specified in the env. For other frameworks / languages, change to the approrpriate setup. There are many <a href="https://github.com/marketplace?type=actions&amp;query=setup+">existing actions</a> to help setup other languages.</p>

<h3 id="caching">Caching</h3>
<p>This is a really cool feature of GitHub (and many other CI/CD tools too). GitHub Actions will save all the dependencies (the infamous <code class="language-plaintext highlighter-rouge">node_modules</code> folder) into memory, and then the next time you run your workflow, it’ll restore the local version before trying to get it from the internet. Which will speed up the whole build significantly.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>      - name: Get yarn cache directory path
        id: yarn-cache-dir-path
        run: echo "::set-output name=dir::$(yarn cache dir)"
</code></pre></div></div>

<p>The above part gets the directory where the cache will get stored and sets it as the yarn cache directory</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>      - name: Cache the dependencies
        uses: actions/cache@v2
        id: yarn-cache
        with:
          path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
          key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
          restore-keys: |
            ${{ runner.os }}-yarn-
</code></pre></div></div>

<p>This is the part that actually caches all the dependencies after the first install. You can update this to your language of choice by changing the cache directory to where your framework / language will store the dependencies. <code class="language-plaintext highlighter-rouge">.pub-cache</code> for flutter, <code class="language-plaintext highlighter-rouge">.m2</code> for maven, etc…</p>

<h3 id="install-dependencies">Install dependencies</h3>
<p>This part is simple</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>      - name: yarn install
        run: yarn --prefer-offline
</code></pre></div></div>

<p>Call a console command to install all dependencies by calling <code class="language-plaintext highlighter-rouge">yarn</code> or <code class="language-plaintext highlighter-rouge">npm install</code>. You can do similar for other languages like <code class="language-plaintext highlighter-rouge">pip install -r requirements.txt</code>, etc…</p>

<p>This part will also automatically fetch from the cache specified ahead instead of fetching from internet if the cache already has data.</p>

<h3 id="build">Build</h3>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>      - name: build
        run: &lt;your yarn command to build your site&gt;
</code></pre></div></div>

<p>Simple as it is. Call the command line that you want to build the project. And can be customized for the language / framework of choice</p>

<h3 id="deploying-to-aws">Deploying to AWS</h3>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v1
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: {{ env.AWS_REGION }}
</code></pre></div></div>

<p>Before we get to this section, we’ll need to setup an IAM account on AWS dedicated for this GitHub workflow. It’s generally a good idea to not use the same IAM account for multiple purposes, so create one just for this. Copy the Key ID and Access Key to GitHub Settings -&gt; Secrets (the url would be something like <code class="language-plaintext highlighter-rouge">https://github.com/&lt;organization&gt;/&lt;repository&gt;/settings/secrets/actions</code>). This will then be accessible to the workflow in run time using the above script.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>      - name: deploy
        run: |
          aws s3 rm s3://${{ env.S3_BUCKET }}/ --recursive
          aws s3 cp ./target/www s3://${{ env.S3_BUCKET }} --cache-control 'public, max-age=31104000' --recursive
          aws configure set preview.cloudfront true
          aws cloudfront create-invalidation --distribution-id ${{ env.CDN_DISTRIBUTION_ID }} --paths "/*"
</code></pre></div></div>

<p>This is the code that actually pushes the built distributable onto AWS.</p>
<ul>
  <li>In this case the first line deletes the existing content on S3 so it’s a clean slate.</li>
  <li>Then the second line copies the entire website content to the S3 bucket. While doing so, it adds headers onto each object so that the browser fetching these information will cache it efficiently.</li>
  <li>The 3rd &amp; 4th line invalidates the cloudfront cache, so the next time a browser requests for the data, it’ll get the latest objects that we just push.</li>
</ul>

<h1 id="wrapping-up">Wrapping up</h1>
<p>That’s pretty much it. Now all you need is to add this file into your repository and commit it in and watch the magic happen!</p>]]></content><author><name>Mohan Karthik</name></author><category term="engineering" /><category term="devops" /><category term="github-actions" /><category term="aws" /><category term="angular" /><category term="react" /><category term="vue" /><summary type="html"><![CDATA[Assumption AWS S3 and Cloudfront are fantastic infrastructure to deploy your production website (either static, say a simple HTML/CSS, or generated via a static site generator via Gatsby, Hugo, Jekyll, etc…); or a dynamic front-end (say using React, Angular, etc…). This post will cover on how to deploy an angular / react / vue code to S3 and Cloudfront.]]></summary></entry><entry><title type="html">The Battle Unseen</title><link href="https://mohankarthik.dev/leadership/2021/11/30/the-battle-unseen.html" rel="alternate" type="text/html" title="The Battle Unseen" /><published>2021-11-30T04:30:00+00:00</published><updated>2021-11-30T04:30:00+00:00</updated><id>https://mohankarthik.dev/leadership/2021/11/30/the-battle-unseen</id><content type="html" xml:base="https://mohankarthik.dev/leadership/2021/11/30/the-battle-unseen.html"><![CDATA[<p>For eons, a battle has raged between two mighty forces. The likes of which has never been penned in any fiction nor reminisced in any myth. The likes of which dwarfs the epic battles of our cinemas and novels and make them look like fairy tales. And yet, this battle has all but been oblivious to us “five sensed” earthlings, us who see, yet are blind; who hear and yet are deaf.</p>

<p>Since our planet first matured, the mountains have grown tall and proud. Even today the mountains continuously evolve with some growing a few centimeters each year due to the continued tectonic pressure. Too high did the mountains climb, so high that their peaks were covered with snow, and crowned white. And while they looked at each other and marveled at their splendid crowns, little did they know that they had just birthed their arch enemies.</p>

<p>As the sun shone it’s light and warmth on these tall mastiffs, the snow melted down and from there came the water streams. The mountains cared little for the tiny rivulets, as they did nothing more than to add to their proud beauty. As these streams, Brookes and rivulets met, they slowly gave rise to formidable rivers that thundered down these mountains. Even then the mountains cared little for they were confident in their tenacity and their strength. Who among this earth could ever change those majestic mountains, those that were made of earth and stone, those that could host entire forests on their slopes and those that could tower over even the clouds and look down upon the rest of the earth.</p>

<p><img src="/assets/images/2021-11-30/01.webp" alt="The Sleeping Buddha" class="align-center" /></p>

<p>And yet the mountains failed to account that their off-springs would be just as tenacious and persevering as they themselves. The rivers were the great equalizers, and they wanted to chart a course through these tall peaks and level the field. And yet they knew that their objective wasn’t easy. They knew that the gallant and daunting mountains were not easy subjects who would bend to their wills. And so they persevered. At each turn, the rivers would try chipping away at the smallest bit of the mountain. They would fail a million times before they succeeded. And yet they knew that they only had to keep trying until they succeeded.</p>

<p>And thus began the longest battle that our planet has known. Mountains, who grew ever so slowly and aimed to persevere, and rivers that slowly tried to chip away at the mountains and level them. Who will win this battle is no longer relevant, as we unfortunately wouldn’t be here to witness the end. But there is much to learn from these two titans.</p>

<p><img src="/assets/images/2021-11-30/02.webp" alt="Stream" class="align-center" /></p>

<p>The mountains achieve their purpose through being gentle, patient and unmoving. They see the rivers chipping at them, and it would be easy for them to look at their losses and assume that eventually the rivers would beat them down, and yet they don’t lose hope. They stand tall, proud and steady. They persevere.</p>

<p>The rivers are aggressive, dynamic and yet they too are patient. They see their failures a million times each day as they try and try and fail at chipping away even the tiniest block off a mountain. It would be so easy for them to look at these failures and think that they would never achieve their goals, and yet they don’t give up. They dart this way and that, trying different things each time. They persevere.</p>

<p>In life too, at every step, in every venture that we take, we face uncertainties, we face hardships and we face losses. It is terribly natural for us to look at these losses and assume that we’ll never succeed. And yet, we see instances all around us, both among nature and people, of success that comes through perseverance. I’m of the belief that along with empathy and rationality, perseverance forms the holy trinity of mental traits that leads to a healthy life. It gives us the strength to fight through hardships and it evens us out during our successes. It keeps us going when there is nothing left to go on. And it’s the stuff that stories are made of.</p>

<p>This then is our quest. To find things that help us persevere. For me, it’s looking at stars as they chart a billion year life cycle across the cosmos, rivers sculpting their way through mountains, predators prowling all night to hunt their prey, mammals migrating thousands of kilometers to evade harsh weather, humans going to extraordinary lengths to protect each other and nature. Find things that inspire you to persevere and hold onto it. For it shall be the light in the darkest of the days and will make this journey of life a breeze to live on.</p>]]></content><author><name>Mohan Karthik</name></author><category term="leadership" /><category term="philosophy" /><summary type="html"><![CDATA[For eons, a battle has raged between two mighty forces. The likes of which has never been penned in any fiction nor reminisced in any myth. The likes of which dwarfs the epic battles of our cinemas and novels and make them look like fairy tales. And yet, this battle has all but been oblivious to us “five sensed” earthlings, us who see, yet are blind; who hear and yet are deaf.]]></summary></entry><entry><title type="html">Unit Testing for Machine Learning</title><link href="https://mohankarthik.dev/engineering/2017/10/21/unit-testing-for-machine-learning.html" rel="alternate" type="text/html" title="Unit Testing for Machine Learning" /><published>2017-10-21T04:30:00+00:00</published><updated>2017-10-21T04:30:00+00:00</updated><id>https://mohankarthik.dev/engineering/2017/10/21/unit-testing-for-machine-learning</id><content type="html" xml:base="https://mohankarthik.dev/engineering/2017/10/21/unit-testing-for-machine-learning.html"><![CDATA[<p>Would love to share a <a href="https://medium.com/@keeper6928/how-to-unit-test-machine-learning-code-57cf6fd81765">great article</a> that I read today.</p>

<p>Some key points to take away from here.</p>

<ol>
  <li>You can have a common set of tests (such as trainable parameters, shape validation, etc…) written that can be re-used across all your ML code. Think of it as your common regression suite.</li>
  <li>Look at Udacity’s <a href="https://github.com/udacity/deep-learning">Deep Learning code</a>, most of the projects already have unit test stubs written so that the student can test against it, while developing their code. This is a great idea to continue during your own development as well.</li>
  <li>And since most of ML is written in python anyway, it’s an even greater idea to pair
<a href="https://medium.com/u/9e396dff421b">Chase Roberts’s</a> idea with python unit testing frameworks. Here are <a href="https://jeffknupp.com/blog/2013/12/09/improve-your-python-understanding-unit-testing/">some</a> <a href="http://docs.python-guide.org/en/latest/writing/tests/">fantastic</a> <a href="https://cgoldberg.github.io/python-unittest-tutorial/">articles</a> to get you started.</li>
</ol>]]></content><author><name>Mohan Karthik</name></author><category term="engineering" /><category term="machine-learning" /><summary type="html"><![CDATA[Would love to share a great article that I read today.]]></summary></entry><entry><title type="html">Path Planning in Highways for an Autonomous Vehicle</title><link href="https://mohankarthik.dev/engineering/2017/07/31/path-planning-in-highways-for-an-autonomous-vehicle.html" rel="alternate" type="text/html" title="Path Planning in Highways for an Autonomous Vehicle" /><published>2017-07-31T04:30:00+00:00</published><updated>2017-07-31T04:30:00+00:00</updated><id>https://mohankarthik.dev/engineering/2017/07/31/path-planning-in-highways-for-an-autonomous-vehicle</id><content type="html" xml:base="https://mohankarthik.dev/engineering/2017/07/31/path-planning-in-highways-for-an-autonomous-vehicle.html"><![CDATA[<p>This article is the write up for my Path Planning project for Term 3, of the Udacity’s Self Driving Car NanoDegreee. The entire article assumes knowledge of how the <a href="https://github.com/udacity/self-driving-car-sim/releases/tag/T3_v1.2">Udacity Term 3 simulator</a> works.</p>

<h2 id="introduction">Introduction</h2>

<p>Path planning is an interesting problem. In essence, it’s the process of finding a safe, comfortable and efficient (in that order) path through a set of dynamic maneuverable objects to reach our goal. Now let’s break it down.</p>

<p>Traditionally, say if we wanted to find a route between a source and a destination, and we wanted to find the fastest / shortest path, there are tons of algorithms to do this: <a href="https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm">Dijkstra’s</a>, <a href="https://en.wikipedia.org/wiki/Breadth-first_search">Breadth First Search</a>, [A<em>](https://en.wikipedia.org/wiki/A</em>_search_algorithm), etc…. But in a road scene, whether it be a highway or urban roads, one of the most important difference is that the scene is not static. So our plan needs to be a dynamic one too.</p>

<p>What complicates the scenario even further is, while we can track the other objects with Sensor Fusion(dynamic such as other cars, pedestrians, bikes, etc…., and static such as trees, curbs, lamp posts), the dynamic object’s behaviour can dynamically change; i.e: they can be maneuvered. So a simple extrapolation based on the current tracked information, say from a <a href="https://en.wikipedia.org/wiki/Kalman_filter">Kalman Filter</a>, would be insufficient for the task, as the car could suddenly change lane, or the pedestrian could suddenly stop midway during a road cross to message someone (those idiots!! :P).</p>

<h2 id="behaviour-prediction-of-maneuverable-objects">Behaviour prediction of Maneuverable Objects</h2>
<p>So the first step is to predict the behaviour of all dynamic objects on the scene, and then based on this, predict a trajectory for each of the them. This is a pretty difficult task, since each of the object on the scene have a lot of choices in them. The method to solve them is to use something that is known as <a href="http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.61.9763&amp;rep=rep1&amp;type=pdf">multiple-model algorithms for maneuvering target tracking</a>. These methods allow us to evaluate multiple different models (such as: continue straight, turn left, turn right, slow down, speed up, and combinations of these) simultaneously for each of the object, and then based on the current observation (do we see him speed up, or turn, etc…) the algorithm would assign a probability to each of the model for each of the object. Once the probability reaches a certain threshold, we could assume that behaviour for that object and generate a predicted trajectory for that object based on that behaviour.</p>

<p>In my current implementation of the path planner (shown at the end of this article), this step is not implemented, as an extensive behaviour prediction was not necessary for the case of a simple highway driving. But for urban driving scenes, this almost becomes mandatory. Think of a intersection ;).</p>

<h2 id="behaviour-planning">Behaviour Planning</h2>
<p>Now that we’ve the predicted trajectories of each of the objects around us, the next step is to plan our behaviour. Do we in turn, speed up, slow down, change lanes, etc… This comes down to two things (and I’m going to be specific to highway scenario).</p>

<ol>
  <li>Estimating a score for each lane, to determine the best lane for us to be in (efficiency)</li>
  <li>Evaluating the feasibility of moving to that lane in the immediate future (safety &amp; comfort)</li>
</ol>

<p>So the three factors that we mentioned in the problem statement are covered here in the two points.</p>

<h2 id="ranking-lanes">Ranking Lanes</h2>
<p>The method I took to rank lanes are using the following 3 factors</p>
<ol>
  <li>The lesser the number of lanes we need to change, the better. Because the lesser we change lanes, the more comfortable the drive is for the passengers (takes care of comfort)</li>
</ol>

<p><img src="/assets/images/2017-07-31/01.webp" alt="Lane Change Score" class="align-center" /></p>

<ol>
  <li>The distance of the car ahead of us in that lane. The more the distance, the better the score</li>
</ol>

<p><img src="/assets/images/2017-07-31/02.webp" alt="Distance Score" class="align-center" /></p>

<ol>
  <li>The velocity of the car ahead of us in that lane. The greater the velocity, the faster we can travel in that lane, before being forced to change lane again.</li>
</ol>

<p><img src="/assets/images/2017-07-31/03.webp" alt="Velocity Score" class="align-center" /></p>

<p>Note:</p>
<ol>
  <li>If a particular lane does not have any car ahead of us, then it would get the full score of the corresponding weights for velocity &amp; distance scores.</li>
  <li>We could augment this with other factors such as number of cars ahead of us in that lane, slowest car ahead of us in the lane (not just the closest car), include the behaviour prediction we talked about in section 1, etc…</li>
</ol>

<h2 id="feasibility-checks">Feasibility Checks</h2>
<p>Now that we’ve ranked the lanes, we now need to check if transition to that lane is feasible or not! This is done with the following flow.</p>

<p><img src="/assets/images/2017-07-31/04.webp" alt="Feasibility Flow" class="align-center" /></p>
<ol>
  <li>Loop across the lanes in the order from best to worst lane.</li>
  <li>If the currently looped lane is our current lane, then nothing to do, everything is great, keep moving, break the loop.</li>
  <li>If not, then check if the new lane would be jerk &amp; collision feasible. The sections below explain how this is done.</li>
  <li>If they are feasible, then increment a vote count, just so that we don’t take instantaneous decisions. We want to take decisions after pondering them over several timesteps. So once this vote count reaches a threshold, we can take up the decision.</li>
  <li>Once the votes are there, then we output the desired <code class="language-plaintext highlighter-rouge">d: the destination lane</code> and the desired <code class="language-plaintext highlighter-rouge">s/time: the velocity</code>.</li>
  <li>The s/time parameter is essentially based on the car ahead of us and if there is no car, then it aims for the maximum velocity without breaking the speed limit.</li>
</ol>

<h2 id="jerk--collision-feasible-checks">Jerk &amp; Collision Feasible checks</h2>
<p>There are many different ways this can be done. The way I chose to do here is the following</p>

<p>Experimentally, I identified that at the speed limit of 50mph, a single lane change is always jerk feasible. This is automatically taken care by the trajectory generation described below. But a double lane change has chances that it would jerk too much (this depends on the road curvature). If the road is curving in one way, and we try to jump 2 lanes in the other direction, then there is a chance that we would violate the jerk limit. So for jerk checks, I just check that the current speed should be less than a threshold if we are doing more than a single lane change.</p>

<p>Collision feasibility is more interesting. Essentially, we want to ensure that there is a good 2 or more car length gap between our car and the other cars in the destination lane and all the intermediate lanes (in case of more than a single lane change). We should also consider in the velocity of the other cars while coming up with this window, i.e: a fast car behind us means we need more window behind us, a slow car ahead of us means we need more window ahead of us.</p>

<h2 id="trajectory-generation">Trajectory Generation</h2>
<p>This is by far the most critical and the most difficult step to implement in this entire project. The solution I implemented is inspired from <a href="https://medium.com/u/8a1f0a75e0b5">John Chen</a>: the idea of converting all coordinates to local car’s co-ordinate system to make things easier.</p>

<p>In this, I heavily depend on ttk:spline for most of the trajectory generation.</p>

<p>The Udacity simulator gives us the previous path after removing all used up points. This is a great starting point for the algorithm which essentially is:</p>

<ol>
  <li>Create a spline of the nearest surrounding waypoints in the car’s reference frame. The waypoints must be converted to the car’s reference and should be aimed for the ‘s/time’ and ‘d’ output from the behaviour planner. Let’s call it the waypointSpline. This essentially gives us the ideal path we want to be in.</li>
  <li>Create another spline with the previous path as the starting points (you could use a subset of the previous path too for more agile response). And add points from the waypointSpline into this. This spline is now the LaneTracker. This now clubs the path that we currently are with the ideal path, making a smooth trajectory from start to finish.</li>
  <li>Create another spline (see what I meant when I said heavily depend), to smoothen the velocity changes from the current velocity (can include all previous path velocities) to the destination velocity (s/time). Let’s call this VelocityTracker. This ensures that we can follow our ideal trajectory without violating jerk / speed constraints.</li>
  <li>Now we can generate the trajectory in the local car’s reference, by estimating the x using VelocityTracker for each time instant. Then use this x as input to the LaneTracker to generate the y.
 Convert these points back to the world coordinates and feed them back to the simulator, and voila you are done.</li>
</ol>

<h2 id="emergency-braking">Emergency Braking</h2>
<p>During testing the system, once two other cars in front of ours collided and came to a stand still. The fact that I was using the entire previous path as input to the LaneTracker &amp; VelocityTracker spline, meant that the car was too slow to react to this resulting in collision. So I implemented a emergency braking solution, that would ignore the previous path and hard set the trajectory to the maximum braking capable (controlled by jerk) by the car. Fortunately / Unfortunately I never got to test this on the sim, as another accident did not</p>

<h2 id="results">Results</h2>
<p>The resulting video is the following
<a href="https://www.youtube.com/watch?v=PqbAUjUfMCo" class="align-center"><img src="https://img.youtube.com/vi/PqbAUjUfMCo/0.jpg" alt="Result" /></a></p>

<h2 id="future-work">Future Work</h2>

<p>There is still a lot of things that can be done to improve this</p>

<ol>
  <li>Add in behaviour prediction for each dynamic object using multiple-model algorithms that will allow the system to react much better &amp; faster to the dynamic changes.</li>
  <li>Improve the lane scoring using other parameters and see improvements.</li>
  <li>Improve the emergency braking system and test it more (might need simulator upgrades)</li>
  <li>Incorporate Q learning and RL to weave through the traffic (also need simulator upgrades to pass images via telemetry)</li>
</ol>

<h2 id="acknowledgements">Acknowledgements</h2>

<p>Great thanks to the community. Some of these ideas are inspired from discussions on the forums / slack / etc… The stalwarts in the community such as
<a href="https://medium.com/u/8a1f0a75e0b5">John Chen</a>, <a href="https://medium.com/u/b783495cc56b">Vivek Yadav</a>
have been a continuous inspiration to all of us. Also definitely thanks to the Udacity instructors <a href="https://medium.com/u/8190c86ea791">David Silver</a> and the team from Mercedes.</p>]]></content><author><name>Mohan Karthik</name></author><category term="engineering" /><category term="machine-learning" /><category term="autonomous-vehicles" /><summary type="html"><![CDATA[This article is the write up for my Path Planning project for Term 3, of the Udacity’s Self Driving Car NanoDegreee. The entire article assumes knowledge of how the Udacity Term 3 simulator works.]]></summary></entry><entry><title type="html">Feature extraction for Vehicle Detection using HOG+</title><link href="https://mohankarthik.dev/engineering/2017/02/14/feature-extraction-for-vehicle-detection-using-hog.html" rel="alternate" type="text/html" title="Feature extraction for Vehicle Detection using HOG+" /><published>2017-02-14T04:30:00+00:00</published><updated>2017-02-14T04:30:00+00:00</updated><id>https://mohankarthik.dev/engineering/2017/02/14/feature-extraction-for-vehicle-detection-using-hog</id><content type="html" xml:base="https://mohankarthik.dev/engineering/2017/02/14/feature-extraction-for-vehicle-detection-using-hog.html"><![CDATA[<p>This is how I went about doing the Vehicle Detection project (P5) from Term 1 of the Udacity’s Self Driving Car Nanodegree program. The goals / steps of this project are the following:</p>
<ul>
  <li>Perform a Histogram of Oriented Gradients (HOG) feature extraction on a labeled training set of images and train a classifier Linear SVM classifier</li>
  <li>Optionally, you can also apply a color transform and append binned color features, as well as histograms of color, to your HOG feature vector.</li>
  <li>Note: for those first two steps don’t forget to normalize your features and randomize a selection for training and testing.</li>
  <li>Implement a sliding-window technique and use your trained classifier to search for vehicles in images.</li>
  <li>Run your pipeline on a video stream (start with the test_video.mp4 and later implement on full project_video.mp4) and create a heat map of recurring detections frame by frame to reject outliers and follow detected vehicles.</li>
  <li>Estimate a bounding box for vehicles detected.</li>
</ul>

<p>This article will cover the first two steps.</p>

<h2 id="visualizing-the-data">Visualizing the data</h2>
<p>The first step always is to see what we’ve got. And here is the data from Udacity. Some examples of cars and non-cars that we’ve are
<img src="/assets/images/2017-02-14/01.webp" alt="Car/Non-Car Image Data" class="align-center" /></p>

<p>Some things to note here are that each image is a 64x64. And there are about 8k images of each type. Which considering that the background class is pretty much everything other than car, I guess is a pretty small image set.</p>

<h2 id="image-features">Image Features</h2>
<p>The course suggests to use a combination of multiple image features. Once again we are doing this detection using traditional CV techniques as opposed to using modern CNN architectures like YOLO / SSD.</p>

<p>So we’ve the following image features along with the following parameters for each image features</p>

<ul>
  <li><strong>Spatial binning</strong> (features directly extracted from the image pixels): Color space of the image (commonly used for other features too); Size of the image to be binned</li>
  <li><strong>Color histogram</strong>: Number of histogram bins</li>
  <li><strong>Histogram of oriented gradients (HOG)</strong>: Channel used, Orientations, Pixels per Cells, Cells per block</li>
</ul>

<h2 id="choosing-the-parameters">Choosing the parameters</h2>
<p>In terms of choosing the parameters, we’ve two major rationales. One is speed, we don’t want to wait for ages for the classification to happen, and in the best case, we want it to be real time. The other is accuracy. So the parameter decisions is a trade-off between these two attributes.</p>

<h2 id="visualizing-the-parameters">Visualizing the parameters</h2>
<p>Once again the shortcut is to visualize the parameters to get an intuition of how they work.
<img src="/assets/images/2017-02-14/02.webp" alt="RGB Cars Color Histogram" class="align-center" />
<img src="/assets/images/2017-02-14/03.webp" alt="RGB Non-Cars Color Histogram" class="align-center" /></p>

<p>We can see that for the RGB color space, all the 3 channels give us a very different spectrum across the histogram. So this looks good.
<img src="/assets/images/2017-02-14/04.webp" alt="YCbCr Cars Color Histogram" class="align-center" />
<img src="/assets/images/2017-02-14/05.webp" alt="YCbCr Non-Cars Color Histogram" class="align-center" /></p>

<p>Here, the Y channel gives a good difference, but the Cb and the Cr channels look almost similar. So does not look like a good choice.
<img src="/assets/images/2017-02-14/06.webp" alt="HSV Cars Color Histogram" class="align-center" />
<img src="/assets/images/2017-02-14/07.webp" alt="HSV Non-Cars Color Histogram" class="align-center" /></p>

<p>Here, we see a decent difference in S and V channel, but not much in the H channel. So maybe in terms of color histogram, RGB and the S &amp; V channel of HSV are looking good.</p>

<p>Great! Now let’s visualize the HOG parameters.</p>

<p>The combinations used here are</p>
<ol>
  <li>Orientations = 8, Pixel per cell = (8,8), cells per block = 2</li>
  <li>Orientations = 9, Pixel per cell = (8,8), cells per block = 2</li>
  <li>Orientations = 8, Pixel per cell = (16,16), cells per block = 2</li>
  <li>Orientations = 9, Pixel per cell = (16,16), cells per block = 2</li>
  <li>Orientations = 8, Pixel per cell = (8,8), cells per block = 1</li>
  <li>Orientations = 9, Pixel per cell = (8,8), cells per block = 1</li>
  <li>Orientations = 8, Pixel per cell = (16,16), cells per block = 1</li>
  <li>Orientations = 9, Pixel per cell = (16,16), cells per block = 1</li>
</ol>

<p><img src="/assets/images/2017-02-14/08.webp" alt="HOG parameters" class="align-center" /></p>

<p>The first option looks great! Nice clear markings for the car image, and a clear difference between the car and non-car image</p>

<p>Now let’s look at the color spaces within HOG</p>

<p><img src="/assets/images/2017-02-14/09.webp" alt="HOG YCbCr" class="align-center" /></p>

<p><img src="/assets/images/2017-02-14/10.webp" alt="HOG RGB" class="align-center" /></p>

<p><img src="/assets/images/2017-02-14/11.webp" alt="HOG HSV" class="align-center" /></p>

<p>We get almost the same result as we got in the color histogram, which is a great reaffirmation for the data. The YCbCr gives a differential performance only for the Y channel. Whereas all 3 channels in RGB gives us a difference. The Hue in HSV is almost similar, but the S and V show a nice difference.</p>

<h2 id="training-the-classifier">Training the Classifier</h2>
<p>Before we train, we need to ensure that all the features are normalized. WE can use the StandardScaler in sklearn to get this to work easily.</p>

<p>Let’s actually train the SVM and check SVM’s accuracy to see if it corresponds to the data that we’ve got till. In the following experiment, I fixed the hog orientations to 8, hog pixel per cell to be 8 and cells per block to be 2. I’ve also fixed the spatial binning size to be 16x16 and the color histogram bins to be 16. The only variations are the color space.</p>
<ul>
  <li>Y channel of YCbCr (no spatial binning or color hist): 93.53%</li>
  <li>RGB (all 3)(no spatial binning or color hist): 96.07%</li>
  <li>SV channel of HSV(no spatial binning or color hist): 95.97%</li>
  <li>SV channel of HSV (with spatial binning or color hist): 98.51%</li>
  <li>HSV (all 3)(with spatial binning or color hist): 98.86%</li>
  <li>RGB (all 3)(with spatial binning or color hist): 97.73%</li>
</ul>

<p>Awesome. So we’ve got our winners. It’s HSV, where the H channel is optional (trading off speed to accuracy). So that covers the feature extraction part of the Vehicle Detection.</p>

<p>As alternatives, you can also look at a standard CNN as a feature extractor.</p>]]></content><author><name>Mohan Karthik</name></author><category term="engineering" /><category term="machine-learning" /><category term="autonomous-vehicles" /><summary type="html"><![CDATA[This is how I went about doing the Vehicle Detection project (P5) from Term 1 of the Udacity’s Self Driving Car Nanodegree program. The goals / steps of this project are the following: Perform a Histogram of Oriented Gradients (HOG) feature extraction on a labeled training set of images and train a classifier Linear SVM classifier Optionally, you can also apply a color transform and append binned color features, as well as histograms of color, to your HOG feature vector. Note: for those first two steps don’t forget to normalize your features and randomize a selection for training and testing. Implement a sliding-window technique and use your trained classifier to search for vehicles in images. Run your pipeline on a video stream (start with the test_video.mp4 and later implement on full project_video.mp4) and create a heat map of recurring detections frame by frame to reject outliers and follow detected vehicles. Estimate a bounding box for vehicles detected.]]></summary></entry></feed>