-
Nhan Luong authoredNhan Luong authored
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
<!DOCTYPE html>
<html lang="en" class="js csstransforms3d">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="Hugo 0.115.3">
<meta name="description" content="">
<link rel="icon" href="/images/favicon.svg" type="image/svg">
<title>Introduction :: digital.auto playground documentation</title>
<link href="/css/nucleus.css?1720169700" rel="stylesheet">
<link href="/css/fontawesome-all.min.css?1720169700" rel="stylesheet">
<link href="/css/hybrid.css?1720169700" rel="stylesheet">
<link href="/css/featherlight.min.css?1720169700" rel="stylesheet">
<link href="/css/perfect-scrollbar.min.css?1720169700" rel="stylesheet">
<link href="/css/auto-complete.css?1720169700" rel="stylesheet">
<link href="/css/atom-one-dark-reasonable.css?1720169700" rel="stylesheet">
<link href="/css/theme.css?1720169700" rel="stylesheet">
<link href="/css/tabs.css?1720169700" rel="stylesheet">
<link href="/css/hugo-theme.css?1720169700" rel="stylesheet">
<link href="/css/theme-green.css?1720169700" rel="stylesheet">
<link href="/css/playground.css?1720169700" rel="stylesheet">
<script src="/js/jquery-3.3.1.min.js?1720169700"></script>
<style>
:root #header + #content > #left > #rlblock_left{
display:none !important;
}
</style>
<head>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-QSPHHE9ZTS"></script>
<script>
var doNotTrack = false;
if (!doNotTrack) {
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-QSPHHE9ZTS', { 'anonymize_ip': false });
}
</script>
<script type="application/javascript">
var doNotTrack = false;
if (!doNotTrack) {
window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)};ga.l=+new Date;
ga('create', 'G-QSPHHE9ZTS', 'auto');
ga('send', 'pageview');
}
</script>
<script async src='https://www.google-analytics.com/analytics.js'></script>
</head>
</head>
<body class="" data-url="/basics/intro/">
<nav id="sidebar" class="showVisitedLinks">
<div id="header-wrapper">
<div id="header">
<p style="font-size: x-large; color: #ffffff; margin: 0 0 10px 0">digital.auto</p>
<a id="logo" href="/">
<svg
width="146"
height="88"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xml:space="preserve"
overflow="hidden"
>
<defs>
<clipPath id="clip0"><rect x="959" y="543" width="146" height="88" /></clipPath>
</defs>
<g clip-path="url(#clip0)" transform="translate(-959 -543)">
<path
d="M141.968 30.6699C139.838 28.7275 136.875 26.5443 133.024 24.8301 134.962 23.2332 136.591 21.148 137.821 19.2867 138.414 18.387 138.7 17.3743 138.7 16.3722 138.7 14.6665 137.875 12.9928 136.348 11.9737 134.318 10.6241 131.619 10.8267 129.837 12.4875 126.794 15.3296 125.212 20.1268 124.617 22.31 123.786 22.1671 122.927 22.0541 122.042 21.9689L121.775 22.2098 121.775 22.2098C121.775 22.2098 112.492 7.90572 112.492 7.90572 109.277 2.95505 103.838 0 97.9388 0L53.7772 0C51.4192 0 49.1208 0.965828 47.4706 2.65017L37.1066 13.2295 10.0122 13.2295C10.0122 13.2295 10.0122 13.2295 10.0122 13.2295 9.43015 11.0548 7.44733 9.44934 5.09139 9.44934 2.28345 9.44934-0.00213207 11.7328-0.00213207 14.5429-0.00213207 17.3529 2.28132 19.6364 5.09139 19.6364 7.44733 19.6364 9.43015 18.0309 10.0122 15.8562L38.211 15.8562 49.3468 4.48801C50.5066 3.30471 52.1228 2.62458 53.7794 2.62458L97.941 2.62458C102.947 2.62458 107.563 5.1319 110.288 9.33208L119.807 24.0029 119.807 24.0029C119.807 24.0029 100.216 41.8547 100.216 41.8547 99.5784 42.4368 98.7448 42.7587 97.8834 42.7587L68.9853 42.7587 68.9853 56.2973 62.8002 56.2973 50.5152 43.3365 22.6895 43.3365C22.1075 41.1618 20.1246 39.5563 17.7687 39.5563 14.9607 39.5563 12.6752 41.8398 12.6752 44.6498 12.6752 47.4599 14.9586 49.7434 17.7687 49.7434 20.1246 49.7434 22.1075 48.1379 22.6895 45.9632L49.3809 45.9632 61.6659 58.9241 68.981 58.9241 68.981 59.5019 118.933 59.5019C118.933 59.5019 113.398 65.0367 112.183 72.4627L68.981 72.3284 68.981 76.552 65.8874 76.552 52.9265 63.3204 24.2182 63.3204C24.2182 63.3204 24.2182 63.3204 24.2182 63.3204 23.6361 61.1457 21.6533 59.5402 19.2974 59.5402 16.4894 59.5402 14.2039 61.8237 14.2039 64.6338 14.2039 67.4438 16.4873 69.7273 19.2974 69.7273 21.6533 69.7273 23.6361 68.1218 24.2182 65.9471L51.8221 65.9471 62.2117 76.552 31.5973 76.552C31.0152 74.3773 29.0324 72.7719 26.6765 72.7719 23.8685 72.7719 21.583 75.0553 21.583 77.8654 21.583 80.6755 23.8664 82.9589 26.6765 82.9589 29.0324 82.9589 31.0152 81.3535 31.5973 79.1787L68.9789 79.1787 68.9789 79.8909 112.72 79.8909 113.268 81.4707C114.475 84.9694 117.769 87.3169 121.471 87.3169L133.363 87.3169C137.346 87.3169 141.071 85.3554 143.329 82.0741L143.412 81.9568C143.915 81.2213 144.203 80.3663 144.241 79.4772L145.989 40.3708C146.151 36.7036 144.685 33.1473 141.968 30.672ZM5.09352 17.0118C3.73326 17.0118 2.62671 15.9053 2.62671 14.545 2.62671 13.1847 3.73326 12.0782 5.09352 12.0782 6.45378 12.0782 7.56033 13.1847 7.56033 14.545 7.56033 15.9053 6.45378 17.0118 5.09352 17.0118ZM17.7687 47.1188C16.4084 47.1188 15.3019 46.0122 15.3019 44.652 15.3019 43.2917 16.4084 42.1852 17.7687 42.1852 19.1289 42.1852 20.2355 43.2917 20.2355 44.652 20.2355 46.0122 19.1289 47.1188 17.7687 47.1188ZM19.2995 67.1006C17.9392 67.1006 16.8327 65.994 16.8327 64.6338 16.8327 63.2735 17.9392 62.1669 19.2995 62.1669 20.6598 62.1669 21.7663 63.2735 21.7663 64.6338 21.7663 65.994 20.6598 67.1006 19.2995 67.1006ZM26.6807 80.3322C25.3205 80.3322 24.2139 79.2256 24.2139 77.8654 24.2139 76.5051 25.3205 75.3986 26.6807 75.3986 28.041 75.3986 29.1476 76.5051 29.1476 77.8654 29.1476 79.2256 28.041 80.3322 26.6807 80.3322ZM134.097 38.2707C132.86 40.0787 130.939 42.1255 128.052 43.5518 126.549 44.2938 124.886 44.6541 123.21 44.6541L111.612 44.6541C110.514 44.6541 109.62 43.7608 109.62 42.6628 109.62 40.1469 110.505 37.7078 112.132 35.7847 115.665 31.6101 122.272 24.9794 127.711 26.2927 129.945 26.8321 131.589 27.7148 132.792 28.6956 135.664 31.0387 136.186 35.209 134.097 38.2707Z"
fill="#FFFFFF"
transform="matrix(1 0 0 1.00702 959 543.037)"
/>
<path
d="M94.7535 38.9785C96.6681 38.9785 98.5081 38.2366 99.8854 36.9062L113.264 23.9922 68.981 23.9922 68.981 24.0306 48.2509 24.0306C47.622 21.6768 45.3513 19.9924 42.7459 20.2824 40.4177 20.5425 38.5329 22.4273 38.2707 24.7555 37.9253 27.8257 40.3281 30.4353 43.3301 30.4353 45.686 30.4353 47.6689 28.8299 48.2509 26.6552L68.981 26.6552 68.981 38.9785 94.7535 38.9785ZM43.3301 27.8107C41.9698 27.8107 40.8633 26.7042 40.8633 25.3439 40.8633 23.9837 41.9698 22.8771 43.3301 22.8771 44.6904 22.8771 45.7969 23.9837 45.7969 25.3439 45.7969 26.7042 44.6904 27.8107 43.3301 27.8107Z"
fill="#FFFFFF"
transform="matrix(1 0 0 1.00702 959 543.037)"
/>
</g>
</svg>
</a>
</div>
<div class="searchbox">
<label for="search-by"><i class="fas fa-search"></i></label>
<input data-search-input id="search-by" type="search" placeholder="Search...">
<span data-search-clear=""><i class="fas fa-times"></i></span>
</div>
<script type="text/javascript" src="/js/lunr.min.js?1720169700"></script>
<script type="text/javascript" src="/js/auto-complete.js?1720169700"></script>
<script type="text/javascript">
var baseurl = "\/";
</script>
<script type="text/javascript" src="/js/search.js?1720169700"></script>
</div>
<div class="highlightable">
<ul class="topics">
<li data-nav-id="/basics/" title="Getting Started" class="dd-item
parent
">
<a href="/basics/">
<b>1. </b>Getting Started
<i class="fas fa-check read-icon"></i>
</a>
<ul>
<li data-nav-id="/basics/overview/" title="Overview" class="dd-item ">
<a href="/basics/overview/">
Overview
<i class="fas fa-check read-icon"></i>
</a>
</li>
<li data-nav-id="/basics/login/" title="Login" class="dd-item ">
<a href="/basics/login/">
Login
<i class="fas fa-check read-icon"></i>
</a>
</li>
<li data-nav-id="/basics/intro/" title="Introduction" class="dd-item active">
<a href="/basics/intro/">
Introduction
<i class="fas fa-check read-icon"></i>
</a>
</li>
<li data-nav-id="/basics/play/" title="Playing with Prototypes" class="dd-item ">
<a href="/basics/play/">
Playing with Prototypes
<i class="fas fa-check read-icon"></i>
</a>
</li>
<li data-nav-id="/basics/experiment/" title="Experiment" class="dd-item ">
<a href="/basics/experiment/">
Experiment
<i class="fas fa-check read-icon"></i>
</a>
</li>
</ul>
</li>
<li data-nav-id="/engaged/" title="Build Your First Prototype" class="dd-item
">
<a href="/engaged/">
<b>2. </b>Build Your First Prototype
<i class="fas fa-check read-icon"></i>
</a>
<ul>
<li data-nav-id="/engaged/helloworld/" title="Create 'Hello World' Prototype" class="dd-item ">
<a href="/engaged/helloworld/">
Create 'Hello World' Prototype
<i class="fas fa-check read-icon"></i>
</a>
</li>
<li data-nav-id="/engaged/3dcar/" title="Using 'General 3D Car Model' Widget" class="dd-item ">
<a href="/engaged/3dcar/">
Using 'General 3D Car Model' Widget
<i class="fas fa-check read-icon"></i>
</a>
</li>
<li data-nav-id="/engaged/simplelandingai/" title="Using 'Simple LandingAI' Widget" class="dd-item ">
<a href="/engaged/simplelandingai/">
Using 'Simple LandingAI' Widget
<i class="fas fa-check read-icon"></i>
</a>
</li>
<li data-nav-id="/engaged/vss_basic/" title="Vehicle API" class="dd-item ">
<a href="/engaged/vss_basic/">
Vehicle API
<i class="fas fa-check read-icon"></i>
</a>
</li>
<li data-nav-id="/engaged/widget_basic/" title="Using builtin widget" class="dd-item ">
<a href="/engaged/widget_basic/">
Using builtin widget
<i class="fas fa-check read-icon"></i>
</a>
</li>
<li data-nav-id="/engaged/create_custom_widget/" title="Create custom widget" class="dd-item ">
<a href="/engaged/create_custom_widget/">
Create custom widget
<i class="fas fa-check read-icon"></i>
</a>
</li>
</ul>
</li>
<li data-nav-id="/campaign/" title="Campaign" class="dd-item
">
<a href="/campaign/">
<b>3. </b>Campaign
<i class="fas fa-check read-icon"></i>
</a>
<ul>
<li data-nav-id="/campaign/gen-ai-awards-2024/" title="GenAI Awards 2024" class="dd-item
">
<a href="/campaign/gen-ai-awards-2024/">
GenAI Awards 2024
<i class="fas fa-check read-icon"></i>
</a>
<ul>
<li data-nav-id="/campaign/gen-ai-awards-2024/1-getting-started/" title="Getting started" class="dd-item ">
<a href="/campaign/gen-ai-awards-2024/1-getting-started/">
Getting started
<i class="fas fa-check read-icon"></i>
</a>
</li>
<li data-nav-id="/campaign/gen-ai-awards-2024/2-onboarding/" title="Onboarding" class="dd-item ">
<a href="/campaign/gen-ai-awards-2024/2-onboarding/">
Onboarding
<i class="fas fa-check read-icon"></i>
</a>
</li>
<li data-nav-id="/campaign/gen-ai-awards-2024/3-access-aws-bedrock/" title="Access AWS Bedrock console" class="dd-item ">
<a href="/campaign/gen-ai-awards-2024/3-access-aws-bedrock/">
Access AWS Bedrock console
<i class="fas fa-check read-icon"></i>
</a>
</li>
<li data-nav-id="/campaign/gen-ai-awards-2024/4-build-first-genai/" title="Build your GenAI" class="dd-item ">
<a href="/campaign/gen-ai-awards-2024/4-build-first-genai/">
Build your GenAI
<i class="fas fa-check read-icon"></i>
</a>
</li>
<li data-nav-id="/campaign/gen-ai-awards-2024/5-submit-your-genai/" title="Submit your genAI" class="dd-item ">
<a href="/campaign/gen-ai-awards-2024/5-submit-your-genai/">
Submit your genAI
<i class="fas fa-check read-icon"></i>
</a>
</li>
<li data-nav-id="/campaign/gen-ai-awards-2024/6-update-genai/" title="Update your submission" class="dd-item ">
<a href="/campaign/gen-ai-awards-2024/6-update-genai/">
Update your submission
<i class="fas fa-check read-icon"></i>
</a>
</li>
<li data-nav-id="/campaign/gen-ai-awards-2024/7-use-genai/" title="Use GenAI on playground" class="dd-item ">
<a href="/campaign/gen-ai-awards-2024/7-use-genai/">
Use GenAI on playground
<i class="fas fa-check read-icon"></i>
</a>
</li>
</ul>
</li>
</ul>
</li>
<li data-nav-id="/advanced/" title="Advanced" class="dd-item
">
<a href="/advanced/">
<b>4. </b>Advanced
<i class="fas fa-check read-icon"></i>
</a>
<ul>
<li data-nav-id="/advanced/architecture/" title="Architecture" class="dd-item ">
<a href="/advanced/architecture/">
Architecture
<i class="fas fa-check read-icon"></i>
</a>
</li>
<li data-nav-id="/advanced/how-python-javascript-works/" title="How Python-Javascript works" class="dd-item ">
<a href="/advanced/how-python-javascript-works/">
How Python-Javascript works
<i class="fas fa-check read-icon"></i>
</a>
</li>
<li data-nav-id="/advanced/genaiwidget/" title="How GenAI works on playground?" class="dd-item ">
<a href="/advanced/genaiwidget/">
How GenAI works on playground?
<i class="fas fa-check read-icon"></i>
</a>
</li>
<li data-nav-id="/advanced/socket-io-provider/" title="Socket.IO Integration" class="dd-item ">
<a href="/advanced/socket-io-provider/">
Socket.IO Integration
<i class="fas fa-check read-icon"></i>
</a>
</li>
<li data-nav-id="/advanced/playground_n_soafee/" title="Cloud native experiment with playground" class="dd-item ">
<a href="/advanced/playground_n_soafee/">
Cloud native experiment with playground
<i class="fas fa-check read-icon"></i>
</a>
</li>
<li data-nav-id="/advanced/ai_sdv_app/" title="AI SdV Application" class="dd-item
">
<a href="/advanced/ai_sdv_app/">
AI SdV Application
<i class="fas fa-check read-icon"></i>
</a>
<ul>
<li data-nav-id="/advanced/ai_sdv_app/ai_app_on_pg/" title="AI App Concept" class="dd-item ">
<a href="/advanced/ai_sdv_app/ai_app_on_pg/">
AI App Concept
<i class="fas fa-check read-icon"></i>
</a>
</li>
<li data-nav-id="/advanced/ai_sdv_app/ai_getting_started/" title="AI with playground" class="dd-item ">
<a href="/advanced/ai_sdv_app/ai_getting_started/">
AI with playground
<i class="fas fa-check read-icon"></i>
</a>
</li>
</ul>
</li>
</ul>
</li>
<li data-nav-id="/insider/" title="Under the Hood" class="dd-item
">
<a href="/insider/">
<b>5. </b>Under the Hood
<i class="fas fa-check read-icon"></i>
</a>
</li>
<li data-nav-id="/dreamkit/" title="dreamKIT" class="dd-item
">
<a href="/dreamkit/">
<b>6. </b>dreamKIT
<i class="fas fa-check read-icon"></i>
</a>
<ul>
<li data-nav-id="/dreamkit/overview/" title="Overview dreamKIT" class="dd-item ">
<a href="/dreamkit/overview/">
Overview dreamKIT
<i class="fas fa-check read-icon"></i>
</a>
</li>
<li data-nav-id="/dreamkit/architecture/" title="Architecture" class="dd-item ">
<a href="/dreamkit/architecture/">
Architecture
<i class="fas fa-check read-icon"></i>
</a>
</li>
<li data-nav-id="/dreamkit/retrofit_kit/" title="Co-Creation Challenge Vehicle KIT" class="dd-item ">
<a href="/dreamkit/retrofit_kit/">
Co-Creation Challenge Vehicle KIT
<i class="fas fa-check read-icon"></i>
</a>
</li>
<li data-nav-id="/dreamkit/working/" title="Working" class="dd-item
">
<a href="/dreamkit/working/">
Working
<i class="fas fa-check read-icon"></i>
</a>
<ul>
<li data-nav-id="/dreamkit/working/ecuplugplay/" title="ECU Plug and Play" class="dd-item
">
<a href="/dreamkit/working/ecuplugplay/">
ECU Plug and Play
<i class="fas fa-check read-icon"></i>
</a>
<ul>
<li data-nav-id="/dreamkit/working/ecuplugplay/ecu-how-to-identify-your-ecu/" title="Identify your ECU with dreamKIT" class="dd-item ">
<a href="/dreamkit/working/ecuplugplay/ecu-how-to-identify-your-ecu/">
Identify your ECU with dreamKIT
<i class="fas fa-check read-icon"></i>
</a>
</li>
<li data-nav-id="/dreamkit/working/ecuplugplay/ecu-how-to-develop-sdv-applications/" title="Develop SDV applications to interact with your ECUs" class="dd-item ">
<a href="/dreamkit/working/ecuplugplay/ecu-how-to-develop-sdv-applications/">
Develop SDV applications to interact with your ECUs
<i class="fas fa-check read-icon"></i>
</a>
</li>
</ul>
</li>
<li data-nav-id="/dreamkit/working/deployment/" title="Playground to dreamKIT" class="dd-item ">
<a href="/dreamkit/working/deployment/">
Playground to dreamKIT
<i class="fas fa-check read-icon"></i>
</a>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<section id="shortcuts">
<h3>More</h3>
<ul>
<li>
<a class="padding" href="https://github.com/digital-auto/playground"><i class='fab fa-github'></i> Github repo</a>
</li>
<li>
<a class="padding" href="https://www.youtube.com/@sdvpg"><i class='fas fa-camera'></i> Showcases</a>
</li>
</ul>
</section>
<section id="prefooter">
<hr/>
<ul>
<li><a class="padding" href="#" data-clear-history-toggle=""><i class="fas fa-history fa-fw"></i> Clear History</a></li>
</ul>
</section>
<section id="footer">
<p>Built with <a href="https://github.com/matcornic/hugo-theme-learn"><i class="fas fa-heart"></i></a> from <a href="https://getgrav.org">Grav</a> and <a href="https://gohugo.io/">Hugo</a></p>
</section>
</div>
</nav>
<section id="body">
<div id="overlay"></div>
<div class="padding highlightable">
<div>
<div id="top-bar">
<div id="top-github-link">
<a class="github-link" title='Edit this page' href="https://github.com/digital-auto/playground/tree/main/docs/content/basics/intro.md" target="blank">
<i class="fas fa-code-branch"></i>
<span id="top-github-link-text">Edit this page</span>
</a>
</div>
<div id="breadcrumbs" itemscope="" itemtype="http://data-vocabulary.org/Breadcrumb">
<span id="sidebar-toggle-span">
<a href="#" id="sidebar-toggle" data-sidebar-toggle="">
<i class="fas fa-bars"></i>
</a>
</span>
<span id="toc-menu"><i class="fas fa-list-alt"></i></span>
<span class="links">
<a href='/'></a> > <a href='/basics/'>Getting Started</a> > Introduction
</span>
</div>
<div class="progress">
<div class="wrapper">
<nav id="TableOfContents">
<ul>
<li>
<ul>
<li><a href="#what-is-playgrounddigitalauto">What is playground.digital.auto?</a></li>
<li><a href="#why-playgrounddigitalauto">Why playground.digital.auto?</a></li>
<li><a href="#value-streams">Value streams</a></li>
<li><a href="#digital-and-physical-value-stream">Digital and physical value stream</a></li>
<li><a href="#code-evolution-in-the-digital-value-stream">Code evolution in the digital value stream</a></li>
<li><a href="#vss-python-api">VSS Python API</a></li>
<li><a href="#getset-functions">get()/set() functions</a></li>
<li><a href="#event-listeners">Event listeners</a></li>
<li><a href="#playground-architecture">Playground architecture</a></li>
<li><a href="#playground-plugins">Playground plugins</a></li>
<li><a href="#simulators">Simulators</a></li>
<li><a href="#widgets">Widgets</a></li>
<li><a href="#default-widget-style">Default Widget Style</a></li>
<li><a href="#using-plugins">Using plugins</a></li>
<li><a href="#implementing-plugins">Implementing plugins</a></li>
<li><a href="#simulator">Simulator</a></li>
<li><a href="#widgets-config">Widgets Config</a></li>
<li><a href="#summary">Summary</a></li>
</ul>
</li>
</ul>
</nav>
</div>
</div>
</div>
</div>
<div id="head-tags">
</div>
<div id="body-inner">
<h1>
Introduction
</h1>
<h3 id="what-is-playgrounddigitalauto">What is playground.digital.auto?</h3>
<p>The playground.digital.auto is a cloud-based, rapid prototyping environment for new, SDV-enabled features. The prototypes are built against real-world vehicle APIs and can be seamlessly migrated to automotive runtimes, such as Eclipse Velocitas. The playground is open and free to use at <a href="https://digitalauto.netlify.app/">playground.digital.auto</a>.</p>
<p>The playground is designed to foster continuous, customer-centric digital innovation. By supporting the new way of thinking and working digital first, digital.auto enables developers to deliver fast tangible results and early validation. Prototypes are developed in Python. To interact with vehicle sensors and actuators, the COVESA <a href="https://wiki.covesa.global/display/WIK4/VSS+-+Vehicle+Signal+Specification">Vehicle Signal Specification (VSS)</a> is used. In the browser environment of the playground, the vehicle sensors and actuators are mocked, using simple test values. Access to VSS in Python is provided via the emerging VSS Python mapping, as defined by the <a href="https://projects.eclipse.org/projects/automotive.velocitas">Eclipse Velocitas</a> project (part of Eclipse SdV). As we will discuss in the following, access to more sophisticated vehicle simulation environments or even real sensors and actuators is possible via a cloud bridge mechanism.</p>
<p>Also, please check out the following additional resources:</p>
<ul>
<li><a href="https://drive.google.com/file/d/1qYfakx6E592PWBtPzAc_m_LrmBsvaI9K/view">Overview video</a> of digital.auto playground</li>
<li><a href="https://drive.google.com/file/d/1Z-tv5COhmX-lQGtHMSUZWLuvv5PoFAFR/view">Introduction</a> to digital.auto playground plugin development</li>
<li>digital.auto playground <a href="https://playground-plugins.netlify.app/">widget documentation</a></li>
</ul>
<p><img src="./HomePage.png" alt="playground.digital.auto"></p>
<h3 id="why-playgrounddigitalauto">Why playground.digital.auto?</h3>
<p>The playground.digital.auto enables early prototyping which has two main benefits:</p>
<ul>
<li>
<p><strong>Customer-centric innovation from the start:</strong> Early customer feedback helps to learn which ideas have highest potential for customer value creation. This helps minimizing investments in unpopular features. Fine-tuning the customer journey design early is key for customer acceptance. Of course this does not mean that the software should not constantly be improved later on, even after the start of production. After all, this is why DevOps pipelines with OTA for remote vehicle updates are currently being established.</p>
</li>
<li>
<p><strong>Fast delivery of tangible, validated results:</strong> Doing early prototyping also has many benefits from the development perspective: Having a functional mockup early on in the development cycle helps improving transparency between business/IT, across regional and organizational boundaries. It also helps to validate architecture decisions early on, as well as to have a consistent enterprise architecture across all features. Finally, being able to identify API requirements as early as possible is key, because providing an API which encapsulates hardware usually has a very long lead time. This is especially true for hardware and APIs coming from external suppliers.</p>
</li>
</ul>
<p><img src="./Value_of_early_prototyping.png" alt="value_of_early_prototype"></p>
<h3 id="value-streams">Value streams</h3>
<p>The following is looking at both, <strong>the digital and physical value stream</strong> in digital.auto, followed by a discussion of the evolution of code in the digital value stream.</p>
<h3 id="digital-and-physical-value-stream">Digital and physical value stream</h3>
<p>The digital.auto playground is designed to support the general philosophy of digital.auto, which is assuming two distinct value streams, moving at different speeds: The physical and the digital value stream. These two value streams are de-coupled via a Hardware Abstraction Layer (HAL), which is encapsulating the complexities of vehicle physics, embedded systems, and bus systems. Software components developed in the digital value stream are accessing vehicle functions via well defined interfaces (e.g. VSS). This de-coupling allows components north and south of the API to be (more or less) seamlessly interchanged. For example, a prototype in the playground can first run against simple test values provided by VSS mock implementations in the playground. Next, one might plug in a real vehicle simulation, running south of the API, and providing a more realistic system behavior. Finally, the simulation will be replaced by hardware with real sensors and actuators - starting with a breadboard, and eventually the final vehicle.</p>
<p><img src="./Value_Streams.png" alt="value"></p>
<p>Similarly, north of the API, new SdV features can initially be developed in Python in the playground. Next, the SdV prototype code can be deployed to a professional development environment - as provided, for example, by <a href="https://projects.eclipse.org/projects/automotive.velocitas">Eclipse Velocitas</a>. In this environment, the new SdV feature can first be tested in the cloud, before finally being deployed on a vehicle computer.</p>
<h3 id="code-evolution-in-the-digital-value-stream">Code evolution in the digital value stream</h3>
<p>In order for the SdV code not to break when moving from the playground to the real development environment, the VSS Python APIs are currently being standardized by the Eclipse community. This allows to migrate code more easily between different environments. For example, as described in the figure below, an SdV function might initially be implemented as a prototype in the digital.auto playground. After the initial customer validation, the decision is made to migrate the code from the prototyping environment to the professional development environment, including proper support for CI/CD. This can be done easily because of the standardization of the Python APIs. In fact, the next release of the playground will have built-in support to deploy into Eclipse Velocitas by creating a complete Velocitas project in GitHub, based on the initial prototype.</p>
<p><img src="./Deployment_and_code_evolution.png" alt="value"></p>
<blockquote>
<p>One important note: Even if the final target language for the production system is not Python - but maybe C++ or Rust - having a Python prototype for early vehicle tests is extremely valuable, because it helps getting an end-to-end implementation done quickly, and stabilizing the APIs between the distributed components.</p>
</blockquote>
<h3 id="vss-python-api">VSS Python API</h3>
<p>The VSS API is organized in a strict tree hierarchy. The nodes of the VSS tree are called branches. The leaves in the tree are representing sensors, actuators, and attributes. An example for a sensor representation in VSS looks like this:</p>
<pre tabindex="0"><code>Vehicle.Cabin.Seat.Row1.Pos1.IsBelted
</code></pre><p>This VSS API or data point will return a boolean value, indicating whether the belt is engaged. Please note that the VSS API catalogue can be adapted for individual vehicle instances - for example, supporting vehicles with different numbers of seat rows.</p>
<p>An example for an actuator in VSS is shown in the following:</p>
<pre tabindex="0"><code>Vehicle.Cabin.Seat.Row1.Pos1.BackrestRecline
</code></pre><p>This API will control the seat z-axis depends on seat tilt.</p>
<h3 id="getset-functions">get()/set() functions</h3>
<p>Using the VSS API in Python is straight forward. For example, to get the current state of a seat belt, the following code can be used:</p>
<pre tabindex="0"><code>from ACME_Car_EV_v01 import Vehicle
vehicle = Vehicle()
vehicle.Cabin.Seat.Row1.Pos1.IsBelted.get()
</code></pre><p>The <strong>get()</strong> function will simply return the current state of the <em>IsBelted</em> sensor represented by the corresponding Python object in the digital.auto playground library.</p>
<p>Not very surprisingly, to control an actuator, a <strong>set()</strong> API is provided in Pyhton, e.g.:</p>
<pre tabindex="0"><code>vehicle.Cabin.Seat.Row1.Pos1.BackrestRecline.set(25)
</code></pre><p>However, as straight-forward as this code actually looks like, the logic behind it is not as straight forward - the reason being that this API is supposed to control a physical device, which might not react immediately to the request (or maybe not at all). From the <a href="https://covesa.github.io/vehicle_signal_specification/rule_set/data_entry/sensor_actuator/">VSS specification</a>: <em>“Actuators are used to control the desired value of a property. Some properties in a vehicle cannot change instantly. A typical example is position of a seat or a window. Reading a value of an actuator shall return the current actual value, e.g. the current position of the seat, rather than the wanted/desired position. A typical example could be if someone wants to change the position of a seat from 0 to 100. This can be changed by setting the corresponding actuator to 100. If the actuator is read directly after the set request it will still return 0 as it might take some seconds before the seat reaches the wanted position of 100. If the seat by some reason is blocked or cannot be moved due to safety reasons it might never reach the wanted position. It is up to the vehicle to decide how long time it shall try to reach the desired value and what to do if it needs to give up.”</em></p>
<p>Even though <em>BackrestRecline</em> is encapsulating an actuator, its current value can be read using <strong>get()</strong>:</p>
<pre tabindex="0"><code>vehicle.Cabin.Seat.Row1.Pos1.BackrestRecline.get()
</code></pre><p>However, as per the above discussing please note that it might not be 100% clear what the return value is actually indicating. Note that there is work going on at the moment to support APIs which differentiate between the actual value vs the intended value of an actuator.</p>
<p>Finally, please also note that the current version of VSS used here is not supporting meta data in the API that could be used to support additional service level, including real-time requirements, request priorization, etc. This means that the SdV code using VSS currently is aiming at applications which are labeled as “QM”, according to the <a href="https://en.wikipedia.org/wiki/Automotive_Safety_Integrity_Level">ASIL</a> standard - meaning the code does not support any of the higher ASIL safety levels, such as ASIL A, B, C or D.</p>
<h3 id="event-listeners">Event listeners</h3>
<p>When dealing with sensor data - even for mocked sensors - it can often make sense to use a more event-driven model, instead of constantly polling the sensor. To support this, the Python API for VSS is supporting a simple event-driven programming model. Using the <strong>subscribe()</strong> method, a callback function can be associated with a sensor. This function will be called every time a new value is available.</p>
<p>In the following code sample, a new function <em>on_hood_is_open_changed</em> is defined, and then associated with <em><strong>vehicle.Body.Hood.IsOpen</strong></em> via the <strong>subscribe()</strong> method. After this, a mock wiper is turned on to MEDIUM speed. Next, the mock hood is opened. This will result in <em>on_hood_is_open_changed</em> being called, which in turn will turn the wipers off.</p>
<pre tabindex="0"><code>def on_hood_is_open_changed(IsOpen: bool):
if IsOpen:
vehicle.Body.Windshield.Front.Wiping.Mode.set(vehicle.Body.Windshield.Front.Wiping.Mode.OFF)
vehicle.Body.Hood.IsOpen.subscribe(on_hood_is_open_changed)
vehicle.Body.Windshield.Front.Wiping.Mode.set(vehicle.Body.Windshield.Front.Wiping.Mode.MEDIUM)
vehicle.Body.Hood.IsOpen.set(True)
</code></pre><h3 id="playground-architecture">Playground architecture</h3>
<p>The following provides an overview of the playground architecture, as well as the key elements of the plugin concept.</p>
<p>The digital.auto playground is designed to allow execution of SdV Python code against the standard VSS Python API. The SdV Python code is executed in the browser, against a set of Python objects representing the VSS API. To ensure a good user experience, the playground also has to support easy manipulation of the HTML Document Object Model (DOM), as well as remote interaction with the cloud. Since most browser development is done in JavaScript these days, the playground supports a plug-in mechanism which is implemented in JavaScript. This means that the SdV Prototypes in Pyhton are really interacting with VSS objects which are implemented in JavaScript. This way, a vehicle mockup can easily be built using browser-native tools. The mechanism used here is a Python-to-JavaScript bridge, which is translating between the SdV functions in Python and the plug-ins in JavaScript.</p>
<p><img src="./Playground_Architecture.png" alt="value"></p>
<p>The playground is trying to maximize re-use. This is happening on two levels:</p>
<ul>
<li>Widgets: Re-useable Java Script artefacts for visualization of <em>any</em> kind of sensor</li>
<li>Plug-Ins: Sensor-specific UI elements, i.e. they are mapping specific sensor values to generic widgets</li>
</ul>
<p>The figure below describes how to get from widget to plug-in and eventually to the creation of custom dashboards using specific plug-ins.</p>
<p><img src="./DashboardConfig.png" alt="value"></p>
<h3 id="playground-plugins">Playground plugins</h3>
<p>Plugins for the digital.auto playground are usually providing a mockup and a visualization of a specific vehicle feature, exposed via VSS. An example could be a Google maps plugin, which is visualizing the vehicle’s current position by accessing <em><strong>Vehicle.CurrentLocation</strong></em>.</p>
<p>A plugin can provide two things:</p>
<ul>
<li>Widgets which are providing the UX to visualize the behavior represented by one or more VSS APIs</li>
<li>Simulators which are implementing VSS APIs</li>
</ul>
<p>An SdV prototype that wants to make use of a plugin must do two things:</p>
<ul>
<li>Import the plugin Python library</li>
<li>Configure the plugins used (especially the UX layout)</li>
</ul>
<p>Plugins can be combined in different ways. For example, an SdV prototype might import the Google maps plugin to visualize the vehicle`s position on a map, plus another plugin which is actually implementing <em><strong>Vehicle.CurrentLocation</strong></em>. Or, the UX and the VSS implementation might be combined in one plugin, depending on the design.
<img src="./Plugin_Overview.png" alt="plugin_overview"></p>
<p>The digital.auto project is aiming to build up a rich plug-in library over time. However, often it will be required to implement dedicated plugins for a specific prototype. To support this, the plugin mechanism in the playground is open, both for plugin consumption as well as provisioning.</p>
<p>For the implementer of a plugin, the following provides more detailed instructions for doing so.</p>
<h3 id="simulators">Simulators</h3>
<p>By default, the VSS Python API is providing an implementation which provides a very basic functionality: the <strong>get()</strong> functions are returning the current value (initialized randomly). The <strong>set()</strong> functions are storing the value passed to them.</p>
<p>Simulators are providing a way to change this functionality. They allow plug-in developers to implement more specific functions for a given VSS sensors, actuator, or attribute. For example, a get function could communicate with a remote service in the cloud to receive the current sensor value. This can be any cloud, assuming that Cross-Origin Resource Sharing (CORS) or an alternative mechanism is used.</p>
<p>A simulator can also be combined with a widget, e.g. to visualize a new sensor value.</p>
<h3 id="widgets">Widgets</h3>
<p>Widgets can use the built-in grid area of the playground to visualize vehicle functions, or even provide an interactive experience - using standard browser functionality. The grid is divided into 5x2 grid cells. A widget can occupy 1 or more grid cells, always assuming a rectangular shape.</p>
<p>The grid mechanism is designed as simple as possible (we wanted to avoid the complexities of a full-blown portal server), yet giving a lot of flexibility. Each widget is mapped to an iFrame, meaning that a widget can use all functionalities which an iFrame supports.</p>
<p>When designing a widget, using the right size must be ensured. For example, the ideal size for a 2x1 box video in the grid would be: 1080x756</p>
<p>It doesn’t need to be exact, but</p>
<ul>
<li>Any size smaller would need to be centered, with space on all sides.</li>
<li>Any size larger would appear the exact same, but would take more time to load.</li>
<li>Any change in ratio would mean extra space (either horizontally or vertically)</li>
</ul>
<h3 id="default-widget-style">Default Widget Style</h3>
<p>Ideally, different widgets should use a similar style, so that if multiple widgets from different source are combined, they provide a consistent use experience. To achieve this, digital.auto recommends the following:</p>
<ul>
<li>Use the following font: <a href="https://www.w3schools.com/cssref/css_websafe_fonts.php">https://www.w3schools.com/cssref/css_websafe_fonts.php</a></li>
<li>Use only the colors defined on the following table, plus black/white
<img src="./Digital.auto_colors.png" alt="Digital.auto_colors"></li>
</ul>
<h3 id="using-plugins">Using plugins</h3>
<p>In order to use a plugin, it needs to be imported and configured. The configuration is necessary so that the playground understands which prototypes should be used, and how to map them to the playground`s grid-based widget layout. The following example is configuring the use of two plugins, InstrumentPanel and SmartPhone:</p>
<pre tabindex="0"><code>[
{
"boxes": [2, 3],
"plugin": "InstrumentPanel",
"widget": "Speedometer"
},
{
"boxes": [1],
"plugin": "SmartPhone",
"widget": "Image"
}
]
</code></pre><p>In this example, SmartPhone will occupy the first position in the playground grid, the Instrument panel the 2nd and 3rd.</p>
<p>In order now to use these plugins in Python, the SdV prototype has to import <strong>plugins</strong>, like in the following example:</p>
<pre tabindex="0"><code>from ACME_Car_ICE_v01 import Vehicle
import plugins
plugins.SmartPhone.set_text("Added text to SmartPhone")
vehicle = Vehicle()
await vehicle.Cabin.InstrumentPanel.Status.set(f"TEXT IN InstrumentPanel")
</code></pre><p>In this example, a text is added via a proprietary API to a the mockup of a Smart Phone. This is because a Smart Phone is not part of VSS. Next, a text is added to <em><strong>Vehicle.Cabin.InstrumentPanel.Status</strong></em>. In this case, <em>InstrumentPanel.Status</em> was added to the VSS API as a Wishlist-Item, because this could actually make sense from a VSS perspective.</p>
<h3 id="implementing-plugins">Implementing plugins</h3>
<p>A plugin is made up of a Python module with one default exported function, that takes two deconstructed object parameters: <strong>widgets</strong> and <strong>simulator</strong>. Both are described in the following:</p>
<h4 id="widgets-1">Widgets</h4>
<p>Widgets has one method, <strong>register</strong> that allows you to register widgets that can used by all the prototypes in the model through the Widgets Config:</p>
<pre tabindex="0"><code>register(widget_name: string, onActivate: (container: Container) => undefined | WidgetDeactivateFunction) => undefined
</code></pre><h5 id="container">Container</h5>
<p>Container has 3 properties:</p>
<table>
<thead>
<tr>
<th>#</th>
<th>Argument</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td><code>injectHTML(html: string) => void</code></td>
<td>injectHTML is used to inject html in the box, essentially setting its innerHTML</td>
</tr>
<tr>
<td>2</td>
<td><code>injectNode(node: Node) => void</code></td>
<td>injectNode is used to inject an HTML Node (element or fragment) in the box. This is usually needed for complex use cases that injectHTML can’t be used for, like event listeners.</td>
</tr>
<tr>
<td>3</td>
<td>window</td>
<td>The window object of the container iframe.</td>
</tr>
</tbody>
</table>
<p><strong>WidgetDeactivateFunction() => void</strong></p>
<p>The deactivate function is executed whenever a widget is removed from the grid. This is useful for clearing stuff such as intervals</p>
<h3 id="simulator">Simulator</h3>
<pre tabindex="0"><code>simulator(api: string, method: "get" | "set" | "subscribe", func: SimulatorModifier) => void
</code></pre><p>Simulator is a function that let’s you override any VSS API’s get , set and subscribe methods</p>
<p>It accepts 3 parameters:</p>
<ol>
<li><em>api</em> : The name of the VSS API to override, for example: Vehicle.Body.Hood.IsOpen</li>
<li><em>method</em> : The method to override, this can be only one of get, set, or subscribe.</li>
<li><em>func</em> : The modifier that is run when the API method is called, of SimulatorModifier type</li>
</ol>
<p><strong>SimulatorModifer</strong> is called with two deconstructed object parameters:</p>
<ol>
<li><em>args</em> : Array of arguments passed in the Python code to the method, converted to equivalent JS types.</li>
<li><em>prevReturnValue</em> : The return value this method would return if the prevReturnValue is undefined.
Multiple plugins can each attach multiple modifiers to a method, all these modifiers will be called in the same order they were attached.</li>
</ol>
<p>The return value of the previous modifier will be passed to <strong>prevReturnValue</strong>.</p>
<h3 id="widgets-config">Widgets Config</h3>
<p>The widgets config is a JSON array of <strong>GridItem</strong> objects specified in the code tab of the prototype.</p>
<p>GridItem has 3 properties:</p>
<ol>
<li>
<p><em>boxes</em>: (number[]): The boxes this grid item should occupy. Boxes must be adjacent (horizontally or vertically) and for
now, a grid item can occupy a maximum of 2 boxes.</p>
</li>
<li>
<p><em>plugin</em>: (string): The name of the plugin for this widget. This is the plugin name specified when creating a plugin.</p>
</li>
<li>
<p><em>widget</em>: (string): The widget name. This is specified in the plugin code when registering a widget</p>
</li>
</ol>
<h3 id="summary">Summary</h3>
<p>The following provides an overview of all elements involved: A vehicle model in the playground includes one instance of a VSS catalogue (e.g. the YAML definition file with all the VSS definitions), n number of plugin implementations, and n number of SdV prototypes.</p>
<p>The VSS catalogue can be extended to use VSS Wishlist items, defined ad-hoc by different prototypes. digital.auto and COVESA are currently working on a way to submit items from the VSS Wishlist to the COVESA process for standardization of VSS.</p>
<p>Plugins are defining simulators and widgets. Widgets are providing the UX for simulators (defined in the same of other plugins). In the future, each plugin will be associated with one SdV prototype for documentation purposes, as well as for defining the VSS wishlist APIs which might be required by the plugin.</p>
<p>SdV prototypes are using plugins. In order to use a plugin, the configuration will have to state where exactly the required widgets should be played on the prototype-specific version of the playground grid.</p>
<p><img src="./All_Playground_Elements.png" alt="Playground_Element"></p>
<footer class="footline">
</footer>
</div>
</div>
<div id="navigation">
<a class="nav nav-prev" href="/basics/login/" title="Login"> <i class="fa fa-chevron-left"></i></a>
<a class="nav nav-next" href="/basics/play/" title="Playing with Prototypes" style="margin-right: 0px;"><i class="fa fa-chevron-right"></i></a>
</div>
</section>
<div style="left: -1000px; overflow: scroll; position: absolute; top: -1000px; border: none; box-sizing: content-box; height: 200px; margin: 0px; padding: 0px; width: 200px;">
<div style="border: none; box-sizing: content-box; height: 200px; margin: 0px; padding: 0px; width: 200px;"></div>
</div>
<script src="/js/clipboard.min.js?1720169700"></script>
<script src="/js/perfect-scrollbar.min.js?1720169700"></script>
<script src="/js/perfect-scrollbar.jquery.min.js?1720169700"></script>
<script src="/js/jquery.sticky.js?1720169700"></script>
<script src="/js/featherlight.min.js?1720169700"></script>
<script src="/js/highlight.pack.js?1720169700"></script>
<script>hljs.initHighlightingOnLoad();</script>
<script src="/js/modernizr.custom-3.6.0.js?1720169700"></script>
<script src="/js/learn.js?1720169700"></script>
<script src="/js/hugo-learn.js?1720169700"></script>
<script src="/mermaid/mermaid.js?1720169700"></script>
<script>
mermaid.initialize({ startOnLoad: true });
</script>
</body>
</html>