1 / 51

DIT 168 Industrial IT and Embedded Systems “Miniature Smart Vehicles”

Learn how to develop software for Miniature Smart Vehicles using C++, CMake, Git, Makefile, and more. Includes step-by-step instructions, code examples, and unit testing.

jtyler
Download Presentation

DIT 168 Industrial IT and Embedded Systems “Miniature Smart Vehicles”

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. DIT 168 Industrial IT and Embedded Systems “Miniature Smart Vehicles”

  2. Software Development with C++ CMake Git Makefile Source make Compiler Binary Tests Runner

  3. Software Development with C++ • Preparing your Ubuntu 16.04 LTS: sudo apt-get update sudo apt-get upgrade sudo apt-get install cmake build-essential • You might also need: sudo apt-get install git

  4. Software Development with C++ CMake Git Makefile Source make Compiler Binary Tests Runner • We start with HelloWorld: #include <iostream> int main(intargc, char** argv) { std::cout << "Hello World!" << std::endl; return 0; } • Compiling: g++ -o helloworld helloworld.cpp

  5. Software Development with C++ CMake Git Makefile Source make Compiler Binary Tests Runner • We add a CMakeLists.txt: cmake_minimum_required(VERSION 3.2) project(helloworld) add_executable(${PROJECT_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/helloworld.cpp) • Compiling: mkdir build cd build cmake .. make

  6. Software Development with C++ CMake Git Makefile Source make Compiler Binary Tests Runner Making the program more useful: #include <cstdint> #include <iostream> boolisPrime(uint16_t n) { boolretVal{true}; if (n<2 || 0 == n%2) { retVal = false; } else { for(uint16_t i{3}; (i*i) <= n; i += 2) { if (0 == n%i) { returnfalse; break; } } } returnretVal; } intmain(intargc, char** argv) { std::cout << "HelloWorld = " << isPrime(43) << std::endl; return 0; }

  7. Software Development with C++ CMake Git Makefile Source make Compiler Binary Tests Runner • Now, we need to change CMakeLists.txt to support uint16_t from a newer C++ standard: cmake_minimum_required(VERSION 3.2) project(helloworld) set(CMAKE_CXX_STANDARD 11) add_executable(${PROJECT_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/helloworld.cpp) • Compiling: mkdir build cd build cmake .. make

  8. Software Development with C++ #include "PrimeChecker.hpp" boolPrimeChecker::isPrime(uint16_t n) { boolretVal{true}; if (n<2 || 0 == n%2) { retVal = false; } else { for(uint16_t i{3}; (i*i) <= n; i += 2) { if (0 == n%i) { returnfalse; break; } } } returnretVal; } • Let’s add unit tests: wgethttps://github.com/catchorg/Catch2/releases/download/v2.1.1/catch.hpp • We need to refactor our program for testability: #ifndef PRIMECHECKER #define PRIMECHECKER #include <cstdint> classPrimeChecker { public: boolisPrime(uint16_t n); }; #endif

  9. Software Development with C++ • #include <iostream> • #include "PrimeChecker.hpp" • intmain(intargc, char** argv) { • PrimeCheckerpc; • std::cout << "Hello World = " << pc.isPrime(43) << std::endl; • return 0; • } • cmake_minimum_required(VERSION 3.2) • project(helloworld) • set(CMAKE_CXX_STANDARD 11) • add_executable(${PROJECT_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/helloworld.cpp${CMAKE_CURRENT_SOURCE_DIR}/PrimeChecker.cpp) • Let’s add unit tests: wgethttps://github.com/catchorg/Catch2/releases/download/v2.1.1/catch.hpp • We need to refactor our program for testability:

  10. Software Development with C++ CMake Git Makefile Source make Compiler Binary Tests Runner • Now, we can add a test case: #define CATCH_CONFIG_MAIN // This tells Catch to provide a main() – only do this once per test-runner #include "catch.hpp" #include "PrimeChecker.hpp" TEST_CASE("Test PrimeChecker 1.") { PrimeChecker pc; REQUIRE(pc.isPrime(5)); } • Compiling: g++ -std=c++11 -o runner TestPrimeChecker.cppPrimeChecker.cpp

  11. Software Development with C++ CMake Git Makefile Source make Compiler Binary Tests Runner Let’s , add more test cases: #define CATCH_CONFIG_MAIN // This tells Catch to provide a main() – only do this once per test-runner #include "catch.hpp" #include "PrimeChecker.hpp" TEST_CASE("Test PrimeChecker 1.") { PrimeChecker pc; REQUIRE(pc.isPrime(5)); } TEST_CASE("Test PrimeChecker 2.") { PrimeChecker pc; REQUIRE(!pc.isPrime(2)); } TEST_CASE("Test PrimeChecker 3.") { PrimeChecker pc; REQUIRE(pc.isPrime(3)); } TEST_CASE("Test PrimeChecker 4.") { PrimeChecker pc; REQUIRE(pc.isPrime(9)); }

  12. Software Development with C++ CMake Git Makefile Source make Compiler Binary Tests Runner • Compiling manually: g++ -std=c++11 -o runner TestPrimeChecker.cppPrimeChecker.cpp • Adjusting our CMakeLists.txt: cmake_minimum_required(VERSION 3.2) project(helloworld) set(CMAKE_CXX_STANDARD 11) add_executable(${PROJECT_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/helloworld.cpp ${CMAKE_CURRENT_SOURCE_DIR}/PrimeChecker.cpp) enable_testing() add_executable(${PROJECT_NAME}-Runner TestPrimeChecker.cpp ${CMAKE_CURRENT_SOURCE_DIR}/PrimeChecker.cpp) add_test(NAME ${PROJECT_NAME}-Runner COMMAND ${PROJECT_NAME}-Runner)

  13. Software Development with C++ CMake Git Makefile Source make Compiler Binary Tests Runner • Let’s improve the quality of the program: cmake_minimum_required(VERSION 3.2) project(helloworld) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Werror") add_executable(${PROJECT_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/helloworld.cpp ${CMAKE_CURRENT_SOURCE_DIR}/PrimeChecker.cpp) enable_testing() add_executable(${PROJECT_NAME}-Runner TestPrimeChecker.cpp ${CMAKE_CURRENT_SOURCE_DIR}/PrimeChecker.cpp) add_test(NAME ${PROJECT_NAME}-Runner COMMAND ${PROJECT_NAME}-Runner)

  14. Software Development with C++ CMake Git Makefile Source make Compiler Binary Tests Runner • Now, we need to fix our program: #include <iostream> #include "PrimeChecker.hpp" intmain(int /*argc*/, char** /*argv*/) { PrimeCheckerpc; std::cout << "Hello World = " << pc.isPrime(43) << std::endl; return 0; }

  15. Software Development with C++ • Let’s add communication to our program: sudo add-apt-repository ppa:chrberger/libcluon sudo apt-get update sudo apt-get install libcluon • Adjusting our CMakeLists.txt to find libcluon: cmake_minimum_required(VERSION 3.2) project(helloworld) set(CMAKE_CXX_STANDARD 11) find_package(libcluon REQUIRED) include_directories(SYSTEM ${CLUON_INCLUDE_DIRS}) add_executable(${PROJECT_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/helloworld.cpp ${CMAKE_CURRENT_SOURCE_DIR}/PrimeChecker.cpp) target_link_libraries(${PROJECT_NAME} ${CLUON_LIBRARIES}) enable_testing() add_executable(${PROJECT_NAME}-Runner TestPrimeChecker.cpp ${CMAKE_CURRENT_SOURCE_DIR}/PrimeChecker.cpp) target_link_libraries(${PROJECT_NAME}-Runner ${CLUON_LIBRARIES}) add_test(NAME ${PROJECT_NAME}-Runner COMMAND ${PROJECT_NAME}-Runner)

  16. Software Development with C++ CMake Git Makefile Source make Compiler Binary Tests Runner • Let’s add communication (sending data): #include <iostream> #include "cluon/UDPSender.hpp" #include "PrimeChecker.hpp" intmain(int /*argc*/, char** /*argv*/) { PrimeCheckerpc; std::cout << "Hello World = " << pc.isPrime(43) << std::endl; cluon::UDPSendersender{"127.0.0.1", 1234}; sender.send("Hello World!"); return 0; } • Test communication: nc -l -u 1234 ./helloworld

  17. Software Development with C++ • Let’s add communication (receiving data): #include <chrono> #include <iostream> #include "cluon/UDPSender.hpp" #include "cluon/UDPReceiver.hpp" #include "PrimeChecker.hpp" intmain(int /*argc*/, char** /*argv*/) { PrimeCheckerpc; std::cout << "Hello World = " << pc.isPrime(43) << std::endl; cluon::UDPSendersender{"127.0.0.1", 1234}; sender.send("Hello World!"); cluon::UDPReceiverreceiver("0.0.0.0", 1235, [](std::string &&data, std::string &&/*from*/, std::chrono::system_clock::time_point &&/*timepoint*/) noexcept { std::cout << "Received " << data.size() << " bytes." << std::endl; }); usingnamespacestd::literals::chrono_literals; while (receiver.isRunning()) { std::this_thread::sleep_for(1s); } return 0; }

  18. Software Development with C++ • Adjusting our CMakeLists.txt: cmake_minimum_required(VERSION 3.2) project(helloworld) set(CMAKE_CXX_STANDARD 14) find_package(libcluon REQUIRED) include_directories(SYSTEM ${CLUON_INCLUDE_DIRS}) add_executable(${PROJECT_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/helloworld.cpp ${CMAKE_CURRENT_SOURCE_DIR}/PrimeChecker.cpp) target_link_libraries(${PROJECT_NAME} ${CLUON_LIBRARIES}) enable_testing() add_executable(${PROJECT_NAME}-Runner TestPrimeChecker.cpp ${CMAKE_CURRENT_SOURCE_DIR}/PrimeChecker.cpp) target_link_libraries(${PROJECT_NAME}-Runner ${CLUON_LIBRARIES}) add_test(NAME ${PROJECT_NAME}-Runner COMMAND ${PROJECT_NAME}-Runner) • Test communication: echo "Hi there!" | nc -u 127.0.0.1 1235

  19. Software Development with C++ • Install test program: sudoapt-getinstallsocat • Let’s communicate via multicast (1-to-many): #include <chrono> #include <iostream> #include "cluon/UDPSender.hpp" #include "cluon/UDPReceiver.hpp" #include "PrimeChecker.hpp" intmain(int /*argc*/, char** /*argv*/) { PrimeCheckerpc; std::cout << "Hello World = " << pc.isPrime(43) << std::endl; cluon::UDPSendersender{"225.0.0.111", 1236}; sender.send("Hello World!"); usingnamespacestd::literals::chrono_literals; std::this_thread::sleep_for(5s); cluon::UDPReceiverreceiver("225.0.0.111", 1236, [](std::string &&data, std::string &&/*from*/, std::chrono::system_clock::time_point &&/*timepoint*/) noexcept { std::cout << "Received " << data.size() << " bytes." << std::endl; }); usingnamespacestd::literals::chrono_literals; while (receiver.isRunning()) { std::this_thread::sleep_for(1s); } return 0; }

  20. Software Development with C++ • Test communication (receiving from our program): socat UDP4-RECVFROM:1236,ip-add-membership=225.0.0.111:0.0.0.0,fork - • Test communication (sending to our program): echo "Hi there" | nc -u 225.0.0.111 1236 • Let’s test on a real network: • Connect to AP –MiniSmartVehicles on your host • Change network adapter for VirtualBox to “Bridged Network" • Test pinging a known host ping 192.168.1.102 • Run your program (…andwaitforsomeonesendingsomedata): ./helloworld

  21. Software Development with C++ • Let’s add structure to the communication: • Add a message specification message MyTestMessage1 [id = 2001] { uint16 myValue [id = 1]; } • Create C++ bindings (manual example) cluon-msc --cpp-headers --out=messages.hppmessages.odvd cluon-msc --cpp-sources --cpp-add-include-file=messages.hpp --out=messages.cppmessages.odvd

  22. Software Development with C++ • Let’s add structure to the communication: cmake_minimum_required(VERSION 3.2) project(helloworld) set(CMAKE_CXX_STANDARD 14) find_package(libcluon REQUIRED) include_directories(SYSTEM ${CLUON_INCLUDE_DIRS}) add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/messages.cpp WORKING_DIRECTORY ${CMAKE_BINARY_DIR} COMMAND cluon-msc --cpp-sources --cpp-add-include-file=messages.hpp --out=${CMAKE_BINARY_DIR}/messages.cpp ${CMAKE_CURRENT_SOURCE_DIR}/messages.odvd COMMAND cluon-msc --cpp-headers --out=${CMAKE_BINARY_DIR}/messages.hpp ${CMAKE_CURRENT_SOURCE_DIR}/messages.odvd DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/messages.odvd) include_directories(SYSTEM ${CMAKE_BINARY_DIR}) add_executable(${PROJECT_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/helloworld.cpp ${CMAKE_CURRENT_SOURCE_DIR}/PrimeChecker.cpp ${CMAKE_BINARY_DIR}/messages.cpp) target_link_libraries(${PROJECT_NAME} ${CLUON_LIBRARIES}) enable_testing() add_executable(${PROJECT_NAME}-Runner TestPrimeChecker.cpp ${CMAKE_CURRENT_SOURCE_DIR}/PrimeChecker.cpp ${CMAKE_BINARY_DIR}/messages.cpp) target_link_libraries(${PROJECT_NAME}-Runner ${CLUON_LIBRARIES}) add_test(NAME ${PROJECT_NAME}-Runner COMMAND ${PROJECT_NAME}-Runner)

  23. Software Development with C++ • Let’s add structure to the communication: #include <chrono> #include <iostream> #include "cluon/UDPSender.hpp" #include "cluon/UDPReceiver.hpp" #include "cluon/ToProtoVisitor.hpp" #include "cluon/FromProtoVisitor.hpp" #include "PrimeChecker.hpp“ #include "messages.hpp" intmain(int /*argc*/, char** /*argv*/) { PrimeCheckerpc; std::cout << "Hello World = " << pc.isPrime(43) << std::endl; cluon::UDPSendersender{"225.0.0.111", 1238}; uint16_t value; std::cout << "Enter a numberto check: "; std::cin >> value; MyTestMessage1 msg; msg.myValue(value); cluon::ToProtoVisitorencoder; msg.accept(encoder); std::stringdata{encoder.encodedData()}; sender.send(std::move(data)); usingnamespacestd::literals::chrono_literals; std::this_thread::sleep_for(5s); cluon::UDPReceiverreceiver("225.0.0.111", 1238, [](std::string &&data, std::string &&/*from*/, std::chrono::system_clock::time_point &&/*timepoint*/) noexcept { std::stringstreamsstr{data}; cluon::FromProtoVisitordecoder; decoder.decodeFrom(sstr); MyTestMessage1 receivedMsg; receivedMsg.accept(decoder); PrimeCheckerpc; std::cout << receivedMsg.myValue() << " is " << (pc.isPrime(receivedMsg.myValue()) ? "" : "not") << " a prime." << std::endl; }); usingnamespacestd::literals::chrono_literals; while (receiver.isRunning()) { std::this_thread::sleep_for(1s); } return 0; }

  24. Software Development with C++ • Details about message specification: message MyTestMessage1 [id = 2001] { ... } message MyTestMessage2 [id = 2002] { bool myValue1 [id = 1]; uint8 myValue2 [id = 2]; int8 myValue3 [id = 3]; uint16 myValue4 [id = 4]; int16 myValue5 [id = 5]; uint32 myValue6 [id = 6]; int32 myValue7 [id = 7]; uint64 myValue8 [id = 8]; int64 myValue9 [id = 9]; float myValue10 [id = 10]; double myValue11 [id = 11]; string myValue12 [id = 12]; MyTestMessage1 myValue13 [id = 13]; }

  25. Software Development with C++ • How to handle multiple messages? #include <cstdint> #include <chrono> #include <iostream> #include <sstream> #include "cluon/OD4Session.hpp" #include "cluon/Envelope.hpp" #include "PrimeChecker.hpp" #include "messages.hpp" intmain(int /*argc*/, char** /*argv*/) { PrimeCheckerpc; std::cout << "Hello World = " << pc.isPrime(43) << std::endl; cluon::OD4Session od4(111, [](cluon::data::Envelope &&envelope) noexcept { if (envelope.dataType() == 2001) { MyTestMessage1 receivedMsg = cluon::extractMessage<MyTestMessage1>(std::move(envelope)); PrimeCheckerpc; std::cout << receivedMsg.myValue() << " is " << (pc.isPrime(receivedMsg.myValue()) ? "" : "not") << " a prime." << std::endl; } }); uint16_t value; std::cout << "Enter a numberto check: "; std::cin >> value; MyTestMessage1 msg; msg.myValue(value); od4.send(msg); return 0; }

  26. Software Development with C++ • Installing Docker (https://docs.docker.com/install/linux/docker-ce/ubuntu/#install-using-the-repository): curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" sudo apt-get update sudo apt-get install docker-ce sudogroupadddocker sudousermod -aGdocker $USER groups • Logout and login docker run hello-world

  27. Software Development with C++ • Manually building with Docker: docker run --rm -ti -v $PWD:/opt/sources ubuntu:16.04 /bin/bash / # • Now, cmake fails  we need to install all dependencies into our Docker container: apt-get update apt-get install build-essential cmake apt-get install software-properties-common add-apt-repository ppa:chrberger/libcluon apt-get update apt-get install libcluon • Manually building with Docker: cd /opt/sources mkdir build && cd build cmake .. make && make test ./helloworld

  28. Software Development with C++ • Manually building with Docker: docker run --rm -ti--net=host -v $PWD:/opt/sources alpine:3.7 /bin/sh / # • Now, cmake fails again  we need to install all dependencies into our Docker container: apk update apk --no-cache add ca-certificates cmake g++ make apk add libcluon --no-cache --repository https://chrberger.github.io/libcluon/alpine/v3.7 --allow-untrusted • Manually building with Docker: cd /opt/sources mkdir build && cd build cmake .. make && make test ./helloworld

  29. Software Development with C++ • Making the changes persistent and automated – create a Dockerfile: FROM alpine:3.7 as builder MAINTAINER Christian Berger christian.berger@gu.se RUN apk update && \ apk --no-cache add \ ca-certificates \ cmake \ g++ \ make && \ apk add libcluon --no-cache --repository https://chrberger.github.io/libcluon/alpine/v3.7 --allow-untrusted ADD . /opt/sources WORKDIR /opt/sources RUN cd /opt/sources && \ mkdir build && \ cd build && \ cmake -D CMAKE_BUILD_TYPE=Release .. && \ make && make test && cphelloworld /tmp # Deploy. FROM alpine:3.7 MAINTAINER Christian Berger christian.berger@gu.se RUN apk update && \ apk add libcluon --no-cache --repository https://chrberger.github.io/libcluon/alpine/v3.7 --allow-untrusted && \ mkdir /opt WORKDIR /opt COPY --from=builder /tmp/helloworld . CMD ["/opt/helloworld"]

  30. Software Development with C++ • Running and testing the build: docker build -t myrepository/mydockerimage . docker run --rm-ti --net=host myrepository/mydockerimage • Saving a Docker image: dockersave myrepository/mydockerimage > myImage.tar • Loading a Docker image (after transferring to the car): cat myImage.tar | dockerload • Alternative: use Docker Hub: https://docs.docker.com/docker-hub/

  31. Software Development with C++ native compiler: g++ cross-compiler: arm-linux-gnueabihf-g++ emulated native compiler: g++ qemu-arm arm x86_64 x86_64 Creating code for armhf platforms • Compile directly on target platform • Running cross-compiler on host to generate code for target platform • Emulating target-platform on host to generate code

  32. Software Development with C++ • Building for armhf– new Dockerfile.armhf: FROM pipill/armhf-alpine:edge as builder MAINTAINER Christian Berger christian.berger@gu.se RUN [ "cross-build-start" ] RUN cat /etc/apk/repositories && \ echo http://dl-4.alpinelinux.org/alpine/v3.7/main > /etc/apk/repositories && \ echo http://dl-4.alpinelinux.org/alpine/v3.7/community >> /etc/apk/repositories RUN apk update && \ apk --no-cache add \ ca-certificates \ cmake \ g++ \ make && \ apk add libcluon --no-cache --repository https://chrberger.github.io/libcluon/alpine/v3.7 --allow-untrusted ADD . /opt/sources WORKDIR /opt/sources RUN cd /opt/sources && \ mkdir build && \ cd build && \ cmake -D CMAKE_BUILD_TYPE=Release .. && \ make && make test && cphelloworld /tmp RUN [ "cross-build-end" ] # Deploy. FROM pipill/armhf-alpine:edge MAINTAINER Christian Berger christian.berger@gu.se RUN [ "cross-build-start" ] RUN cat /etc/apk/repositories && \ echo http://dl-4.alpinelinux.org/alpine/v3.7/main > /etc/apk/repositories && \ echo http://dl-4.alpinelinux.org/alpine/v3.7/community >> /etc/apk/repositories RUN apk update && \ apk add libcluon --no-cache --repository https://chrberger.github.io/libcluon/alpine/v3.7 --allow-untrusted && \ mkdir /opt WORKDIR /opt COPY --from=builder /tmp/helloworld . RUN [ "cross-build-end" ] CMD ["/opt/helloworld"]

  33. Interfacing with the Vehicle OpenDaVINCI/OpenDLV Software Stack PS4Controller

  34. Interfacing with the Vehicle OpenDaVINCI/OpenDLV Software Stack Motor msg opendlv-proxy-miniature-pwm-motor opendlv-proxy-miniature-ps4controller msg Steering Servo

  35. Interfacing with the Vehicle • Docker image with the proxies: seresearch/2018-dit-168:v0.3.5-armhf • Microservices to run from OpenDaVINCI/OpenDLV software stack: • configuration file: global.buffer.memorySegmentSize = 2800000 global.buffer.numberOfMemorySegments = 4 odsupercomponent.pulsetimeack.timeout = 5000 # (in milliseconds) odsupercomponent.pulsetimeack.exclude = odcockpit odcockpit.directoriesForSharedLibaries = /opt/opendlv.miniature proxy-miniature-ps4controller.ps4controllerdevicenode = /dev/input/js0 proxy-miniature-ps4controller.deceleration.max = -1.0 proxy-miniature-ps4controller.acceleration.max = 0.25 proxy-miniature-ps4controller.steering.max = 38.0 proxy-miniature-pwm-motor.names = steering,propulsion proxy-miniature-pwm-motor.types = servo,esc proxy-miniature-pwm-motor.channels = 1,2

  36. Interfacing with the Vehicle • Docker image with the proxies: seresearch/2018-dit-168:v0.3.5-armhf • Microservices to run from OpenDaVINCI/OpenDLV software stack: • configurationfile: global.buffer.memorySegmentSize = 2800000 global.buffer.numberOfMemorySegments = 4 odsupercomponent.pulsetimeack.timeout = 5000 # (in milliseconds) odsupercomponent.pulsetimeack.exclude = odcockpit odcockpit.directoriesForSharedLibaries = /opt/opendlv.miniature proxy-miniature-ps4controller.ps4controllerdevicenode = /dev/input/js0 proxy-miniature-ps4controller.deceleration.max = -1.0 proxy-miniature-ps4controller.acceleration.max = 0.25 proxy-miniature-ps4controller.steering.max = 38.0 proxy-miniature-pwm-motor.names = steering,propulsion proxy-miniature-pwm-motor.types = servo,esc proxy-miniature-pwm-motor.channels = 1,2

  37. Interfacing with the Vehicle • Docker image with the proxies: seresearch/2018-dit-168:v0.3.5-armhf • Microservices to run from OpenDaVINCI/OpenDLV software stack for interfacing the vehicle with PS4 controller: • odsupercomponent + previous configuration file docker run --rm -ti --net=host -v $PWD:/opt/miniature.dataseresearch/2018-dit-168:v0.3.5-armhf /opt/od4/bin/odsupercomponent --cid=111 --verbose=1 --configuration=/opt/miniature.data/configuration • opendlv-proxy-miniature-pwm-motor docker run --rm -ti --net=host --privileged=true -v /sys:/sys -v /dev:/devseresearch/2018-dit-168:v0.3.5-armhf /opt/opendlv.miniature/bin/opendlv-proxy-miniature-pwm-motor --cid=111 --freq=50 --id=1 • opendlv-proxy-miniature-ps4controller docker run --rm -ti --net=host -v /dev/input/js0:/dev/input/js0seresearch/2018-dit-168:v0.3.5-armhf /opt/opendlv.miniature/bin/opendlv-proxy-miniature-ps4controller --cid=111 --freq=10

  38. Interfacing with the Vehicle with Your SW libcluon-based microservices OpenDaVINCI/OpenDLV Software Stack Motor msg <Your Software> <Your Software> opendlv-proxy-miniature-pwm-motor <Your Software> msg Steering Servo

  39. Interfacing with the Vehicle with Your SW libcluon-based microservices OpenDaVINCI/OpenDLV Software Stack Motor msg <Your Software> <Your Software> opendlv-proxy-miniature-pwm-motor <Your Software> msg Steering Servo message opendlv.proxy.GroundSteeringReading [id = 1090] { float steeringAngle [id = 1]; } message opendlv.proxy.PedalPositionReading [id = 1041] { float percent [id = 1]; }

  40. Interfacing with the Vehicle with Your SW • Handling several microservices manually  error-prone • Use docker-compose • Install on Ubuntu 16.04 LTS (cf. https://docs.docker.com/compose/install/) • sudo curl -L https://github.com/docker/compose/releases/download/1.19.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose • sudochmod +x /usr/local/bin/docker-compose • Test: docker-compose --version

  41. Interfacing with the Vehicle with Your SW • docker-compose.yml: version: '2' services: odsupercomponent: image: seresearch/2018-dit-168:v0.3.5-armhf network_mode: "host" restart: always volumes: - .:/opt/miniature.data command: "/opt/od4/bin/odsupercomponent --cid=111 --verbose=1 --configuration=/opt/miniature.data/configuration" proxy-miniature-pwm-motor: image: seresearch/2018-dit-168:v0.3.5-armhf depends_on: - odsupercomponent network_mode: "host" restart: always privileged: true volumes: - /sys/:/sys/ - /dev/:/dev/ command: "/opt/opendlv.miniature/bin/opendlv-proxy-miniature-pwm-motor --cid=111 --freq=50 --id=1" # Your microservice. proxy-miniature-ps4controller: image: YourARMHFImage network_mode: "host" restart: always command: "YourCommand"

  42. Viewing Exchanged Messages Simple web-based message viewer: • Docker image (x86_64): docker run --rm -ti --net=host -p 8080:8080 chrberger/dit168-signal-viewer:v0.0.1 --cid=111 • GitHub repository: https://github.com/chrberger/dit168-signal-viewer • If you add or change messages, simply modify messages.odvd and rebuild the message viewer.

  43. First Contact With Your Car

  44. To-Do List • Power ON • Connect your laptop to your car • Software preparation • Install, update, docker pull, git clone … • “Teach” it to run

  45. Connect to You Car Wi-Fi hotspot: BeagleBone-xxxx Password: BeagleBone On your Ubuntu: $ ping 192.168.8.1 $ ssh debian@192.168.8.1 (Default password is “temppwd”) $ rc_blink $ sudo /opt/scripts/tools/grow_partition.sh $ df -h

  46. Connect to Internet If you are using a router / Wi-Fi hotspot other than Eduroam $ connmanctl > scan wifi > services > agent on > connect wifi_[the_long_wifi_ID] > exit $ ping 8.8.8.8 When typing the long wifi ID (not the SSID), you can type first several characters and press tab for auto-complete.

  47. Connect to the Internet Solution provided by : Oleks <oleks@oleks.info> https://github.com/oleks/eduroam-wpa_supplicant • Configuration for eduroam (not yet confirmed) $ sudonano /etc/wpa_supplicant/wpa_supplicant.conf ctrl_interface_group=root ap_scan=1 eapol_version=2 update_config=0 network={ disabled=0 auth_alg=OPEN ssid="eduroam” scan_ssid=1 key_mgmt=WPA-EAP proto=WPA RSN pairwise=CCMP TKIP eap=PEAP identity="abc123@ku.dk" # Edit this, anonymous_identity="anonymous@ku.dk" # this, password=hash:36cae0f7deee765c0a46693591d10801 # and this. phase1="peaplabel=0” phase2="auth=MSCHAPV2” }

  48. Connect to the Internet Solution provided by : Oleks <oleks@oleks.info> https://github.com/oleks/eduroam-wpa_supplicant • How to cover your password $ echo -n 'password' | iconv -t utf16le | openssl md4 • How to get it work $ sudowpa_supplicant -Dwext -iwlan0 -c wpa_supplicant.conf -B (Use "$ lspci -k" and "$ ifconfig -a" to check kernel driver stated and the network interface name for yourwirelesscard) $ ping 8.8.8.8

  49. Software Preparation • apt-get update / upgrade • Install libcluon and docker • Pull the docker image "seresearch/2018-dit-168:v0.3.5-armhf" • Transfer files from your Ubuntu to the car: $ scp [file_name] debian@192.168.8.1:[target_path] "$ man scp" for details of this command • Clone the gitHub repository "https://github.com/Adam2092/DIT168Example"

  50. Before "let it go"… • Compile and Cross-compile • Run the docker image for odsupercomponent and proxy • Unplug the charger and turn on the ESC before running • In case no network connection: configure local loopback device to allow UDP multicast sessions $ sudoifconfig lo multicast $ -sudo route add -net 224.0.0.0 netmask 240.0.0.0 dev lo • Runyourcode / docker image now • Runthemindividually: Slide 37 • Runthemaltogether: Slide 41 (installdocker-composefirst) $ docker-compose -up

More Related