Innsbruck- Capital of the Alps

Starting as a roman army post, moving on as an aristocratic residence city and arranging the Olympic Winter Gems twice! Innsbruck has come a long way and probably can present itself as the capital of the Alps.

Innsbruck, the capital of Tirol, Austria spreads out in the Inn Valley where the river Inn makes a bend north, before continuing east. In the midst of the most alpine state of Austria, the city’s 130.000 inhabitants enjoy a thriving city and all year outdoor adventures. Innsbruck got it’s name from the first bridge across the river Inn, that was constructed in around 1170. A small tradingpost by the river soon grew and the town got its city status already in 1200.

Historic centre

Although the city is smack in the middle of the Alps, it’s sometimes overseen as a tourist destination. Sure, arriving in Tirol in winter, most people head directly for the ski slopes. Nevertheless, it’s definitely worth a visit. The main attraction all year around is the historical centre, which is well preserved. You could easily spend 2-3 hours taking in the sites here, which are all within short walking distance. No matter the time of the year, strolling around the historical centre is a delight. The narrow lanes can be crowded at time, but if you opt for an early morning stroll, you can enjoy the sights in peace.

City views

Start by getting up in the City Tower (Stadtturm) to get an overview over the city. The tower, constructed in 1450 A.D, gives you nice views of Innsbruck and the surrounding mountains. OK, you have to go up 148 stairs to reach the viewing platform, but it’s worth the effort. Since the tower is right next the old market square, you get a different impression of some of Innsbruck’s landmarks. Such as the famous Golden Roof, where the shiny appearance comes from the copper slates. The balcony with the roof was built to mark the wedding of emperor Maximillian II and Bianca Maria Sforza in 1500 A.D. The couple used the roofed balcony to watch festivals and knights tournaments.

Even though Innsbruck’s main attraction is the medieval centre, there are a few landmarks in the neighbouring streets as well. Just like Paris and Rome, Innsbruck also has a Triumphal Arch (Triumphpforte). Built in 1765 and located in Maria-Theresien-Straße, not to celebrate victory in war, but for the occasion of the wedding of Archduke Leopold to the Spanish princess, Maria Luisa.

Green retreats

The historical centre is very popular among tourists from all around the world, and especially in summer, it can get very crowded. Nonetheless, if you need to get away from the hoards there are several opportunities. Just a few steps away from the most bustling streets of the old city we found a little park to relax, next to the Jesuit Church. Moreover, if you like hanging out in parks, you could also head for Schlosspark Ambras, which has a very nice park. Especially on hot summer days, the big trees offer shady retreats and plenty of space for the kids to play around. The kids will also probably enjoy the Alpenzoo more than some boring old houses. The Zoo houses a range of animals found in Austria and the Alps.

Advertisement

Snow wonderland

In winter, Tirol and Innsbruck is all about skiing and other snow activities. Innsbruck hosted the 1964 and 1976 Winter Olympics and the slopes are reachable by cable car from the city outskirts. There are several ski resorts very near Innsbruck. Nordkette – the mountain range just north of the city can be reached by metro from the centre and then you change to a cable car in the outskirts of Innsbruck. The Nordkette mountain range is part of Austria’s largest nature park, the Karwendel Nature Park. The Nordkettebahn runs all year and you get phenomenal views from the peak near Hafelekar cable car station  at 2,269 metres above sea level.

Hiking heaven

In summer, Innsbruck is an excellent base for hiking in the surrounding mountains. Some of the cable cars are running in the summer as well, giving easy access to the mountain ranges both north and south of the city. Right in the vincinity of the city you have the Patscherkofel Cable Car which takes you up to just short of 2000 metres above sea level, where you find numerous hiking trails. Furthermore, the view from the top is simply mesmorizing. Also worth a visit is the small but interesting alpine botanic garden Alpengarten Patscherkofel not far from the cable car station , which is run by the University of Innsbruck.

Boots off

Innsbruck is more than just a hub for outdoor activities. Get your hiking or ski boots off and head for the city centre. The city is sizeable enough to have a wide range of dining, cultural and shopping activities, catering for most tastes and wallets. The historical city centre of Innsbruck, as so many others in Austria, is a very lively place. Although most mainstream shops have moved out to one of the shopping malls, there are ample of shopping possibilities in the city centre. Thus, for a rainy day or an afternoon, the city will keep you busy with indoor activities as well.

Lidar Technology || Lidar là gì vậy?

Lidar là một công nghệ khảo sát tiên tiến để đo khoảng cách tới mục tiêu bằng cách chiếu mục tiêu đó bằng một tia laze và đo các xung phản xạ bằng một cảm biến. Sự khác nhau về thời gian và bước sóng laser sau đó có thể được sử dụng để tạo các mô hình kỹ thuật số thể hiện mục tiêu trong không gian 3D. LiDAR thường được kết hợp với các loại máy ảnh để thu thập đồng thời hình ảnh của đối tượng và xây dựng lên hình ảnh 3D “như thật” của đối tượng. Lidar được sử dụng rộng rãi để tạo ra các sản phẩm đồ hoạ có độ phân giải cao, với nhiều ứng dụng cao cấp trong các ngành trắc địa, geomatics, khảo cổ, địa lý, địa chất, địa mạo, địa chấn, lâm nghiệp, vật lý, bản đồ… Công nghệ này cũng được sử dụng để kiểm soát và điều hướng cho một số phươpng tiện giao thông tự hành. Lidar đôi khi được gọi là quét laser và quét 3D, và gồm 3 loại: lidar mặt đất, hàng không và di động.

Lidar bao gồm có:

Lidar hàng không

Ưu điểm

Độ chính xác cao

LiDAR có thể thu thập dữ liệu địa hình rất chính xác trong khi bay quét ở độ cao lớn hơn độ cao bay chụp không ảnh. Độ chính xác của dữ liệu bay chụp không ảnh tỷ lệ với độ cao bay chụp trong khi độ chính xác của dữ liệu LiDAR giảm đi không đáng kể khi độ cao bay tăng lên. Hơn nữa, LiDAR thu nhận trực tiếp dữ liệu 3 chiều

Hiệu suất thu thập lớn

LiDAR chỉ cần duy nhất 1 tia laser “gần-vuông góc” với mặt đất để khảo sát địa hình. Tia laser có khả năng xuyên qua tán cây chạm tới bề mặt và phản hồi tới cảm biến trong khi chụp không ảnh lại yêu cầu hiệu ứng lập thể (cùng nhìn thấy 1 điểm trên mặt đất từ hai phía). Như vậy, LiDAR sẽ thu thập được dữ liệu bề mặt địa hình nhiều hơn, đặc biệt khi quét qua các khu vực có thực vật che phủ

Mật độ điểm dầy

LiDAR có thể thu nhận tín hiệu phản hồi đầu tiên và cuối cùng với tần suất trung bình 5.000 tới 33.000 tia/giây, do đó dữ liệu thu được cho phép lập bản đồ bề mặt địa hình và bề mặt tán cây với mật độ dữ liệu dày và độ chính xác cao. Một số hệ thống LiDAR còn cho phép thu nhận các tín hiệu phản hồi trung gian (giữa tín hiệu đầu và cuối) cho phép phân tích cấu trúc đối tượng (cấu trúc tán). Phương pháp không ảnh cũng tạo được các điểm độ cao dày nhưng phải bằng cách tăng dày thủ công (tốn kém và mất thời gian), hoặc bằng phương pháp tương quan ảnh tự động, tuy nhiên phương pháp này chỉ trích xuất được các điểm ngọn cây và nóc nhà mà không tạo ra được các điểm mặt đất

Thời gian thu thập linh hoạt

LiDAR cho phép thu thập dữ liệu cả ngày và đêm trong khi phương pháp không ảnh chỉ thực hiện được trong 1 khoảng thời gian hạn chế ban ngày khi ánh sáng tối ưu

Lidar mặt đất:

Các ứng dụng LiDAR mặt đất sử dụng thiết bị quét laser gắn trên các vị trí trên mặt đất, thường là các giá tripod. Công nghệ quét laser mặt đất trên giá cố định là hình thức khảo sát rất phổ biến trong các ứng dụng quy mô nhỏ như vi địa hình, các công trình, công trường… Dữ liệu đám mây điểm 3D thu được từ các loại máy quét này có thể được kết hợp với hình ảnh kỹ thuật số chụp từ cùng vị trí của máy quét để tạo mô hình 3D thực tế trong một khoảng thời gian tương đối ngắn so với các công nghệ khác. Cách thể hiện sản phẩm 3D dạng này có thể là ảnh số trùm phủ lên đám mây điểm hoặc từng điểm laser được gán mã màu theo giá trị điểm ảnh tương ứng trên sản phẩm ảnh số.

Ưu điểm
Mật độ điểm “siêu” dày
Độ chính xác rất cao
Năng suất thu thập dữ liệu cao
Gọn nhẹ, dễ triển khai

Lidar mobile:

Công nghệ mobile LiDAR là công nghệ gắn các máy quét laser lên các phương tiện đi lại như ô tô, tàu hoả… và chạy dọc các tuyến giao thông để thu thập dữ liệu với tốc độ cao, mật độ dày. Mỗi phương tiện giao thông có thể được gắn 1 hoặc nhiều bộ quét. Những máy quét này hầu như luôn luôn kết hợp với các loại thiết bị khác, chủ yếu là máy ảnh số và các hệ thống dẫn đường chuyên dụng. Ứng dụng phổ biến của công nghệ này là khảo sát các thực thể dạng tuyến như đường phố, đường dây điện, đường sắt, đường thuỷ… Ưu điểm nổi bật của giải pháp là thay vì thu thập các đối tượng một cách riêng lẻ, một mô hình 3D với đám mây điểm thể hiện tất cả các đối tượng trên tuyến sẽ được thành lập, sau đó được sử dụng để thu nhận tất cả các đối tượng cần thiết. Điều này giúp loại bỏ vấn đề thường xả ra với phương pháp truyền thống như đo đạc sót đối tượng, đồng thời tăng độ tin cậy và độ chính xác.

Ưu điểm
Khảo sát toàn diện, năng suất cao, độ chính xác cao
Giảm thiểu công khảo sát thực địa
Mật độ điểm rất cao và có nhiều sản phẩm đồng bộ ( ảnh số và đám may điểm )
Có thể chia sẻ rộng rãi cho các bộ phận nội nghiệp cùng sản xuất

Giải thích nguyên lí hoạt động của Lidar:

Nguyên tắc đằng sau LiDAR thực sự khá đơn giản. Chiếu một ánh sáng nhỏ lên một bề mặt và đo thời gian nó quay trở lại nguồn của nó. Khi bạn chiếu một ngọn đuốc lên một bề mặt mà bạn đang thực sự nhìn thấy thì ánh sáng sẽ được phản xạ và quay trở lại võng mạc của bạn. ánh sáng truyền đi rất nhanh – khoảng 300.000 km mỗi giây, 186.000 dặm mỗi giây hoặc 0,3 mét mỗi nanosecond để biến một ánh sáng trên dường như là tức thời. Tất nhiên, nó không phải! Các thiết bị cần thiết để đo lường nhu cầu này hoạt động cực kỳ nhanh. Chỉ với những tiến bộ trong công nghệ máy tính hiện đại, điều này mới trở nên khả thi.

Tính toán thực tế để đo khoảng cách mà một photon ánh sáng trở lại đã đi đến và đi từ một vật thể khá đơn giản:

Khoảng cách = (Tốc độ ánh sáng x Thời gian bay) / 2

Thiết bị LiDAR bắn ra các xung ánh sáng laze nhanh trên bề mặt, một số có tốc độ lên đến 150.000 xung mỗi giây. Một cảm biến trên thiết bị đo khoảng thời gian cần thiết để mỗi xung phản hồi trở lại. Ánh sáng di chuyển với tốc độ không đổi và đã biết để thiết bị LiDAR có thể tính toán khoảng cách giữa chính nó và mục tiêu với độ chính xác cao. Bằng cách lặp lại điều này liên tiếp, hệ thống xây dựng một ‘bản đồ’ phức tạp về bề mặt mà nó đang đo. Với LiDAR trên không, các dữ liệu khác phải được thu thập để đảm bảo độ chính xác. Khi cảm biến đang di chuyển độ cao, vị trí và hướng của thiết bị phải được bao gồm để xác định vị trí của xung laser tại thời điểm gửi đi và thời điểm quay trở lại. Thông tin bổ sung này rất quan trọng đối với tính toàn vẹn của dữ liệu. Với LiDAR trên mặt đất, một vị trí GPS duy nhất có thể được thêm vào cho mỗi vị trí nơi thiết bị được thiết lập.

Hầu hết các hệ thống LiDAR sử dụng bốn thành phần chính:

Laser

Tia laser được phân loại theo bước sóng của chúng. Laser 600-1000nm được sử dụng phổ biến hơn cho các mục đích phi khoa học, nhưng vì chúng có thể được tập trung và dễ dàng hấp thụ bởi mắt, công suất tối đa phải được giới hạn để làm cho chúng ‘an toàn cho mắt’. Laser có bước sóng 1550nm là một lựa chọn thay thế phổ biến vì chúng không bị tập trung bởi mắt và ‘an toàn cho mắt’ ở mức công suất cao hơn nhiều. Các bước sóng này được sử dụng cho mục đích phạm vi xa hơn và độ chính xác thấp hơn. Một ưu điểm khác của bước sóng 1550nm là chúng không hiển thị dưới kính nhìn ban đêm và do đó rất thích hợp cho các ứng dụng quân sự.

Hệ thống LiDAR trong không khí sử dụng laser YAG bơm điốt 1064nm trong khi hệ thống Bathymetric sử dụng laser YAG bơm điốt kép 532nm, xuyên qua nước với độ suy giảm ít hơn nhiều so với phiên bản 1064nm trong không khí. Có thể đạt được độ phân giải tốt hơn với các xung ngắn hơn với điều kiện bộ phát hiện máy thu và thiết bị điện tử có đủ băng thông để đối phó với lưu lượng dữ liệu tăng lên.

Máy quét và Quang học

Tốc độ hình ảnh có thể được phát triển bị ảnh hưởng bởi tốc độ mà nó có thể được quét vào hệ thống. Một loạt các phương pháp quét có sẵn cho các mục đích khác nhau như góc phương vị và độ cao, gương phẳng dao động kép, máy quét trục kép và gương đa giác. Loại quang học của chúng xác định độ phân giải và phạm vi có thể được phát hiện bởi một hệ thống.

Bộ tách sóng quang và thiết bị điện tử thu

Bộ tách sóng quang là thiết bị đọc và ghi lại tín hiệu đưa về hệ thống. Có hai loại công nghệ máy tách sóng quang chính, máy dò trạng thái rắn, chẳng hạn như điốt quang tuyết lở silic và bộ nhân quang.

Hệ thống định vị và dẫn đường

Khi một cảm biến LiDAR được gắn trên một nền tảng di động như vệ tinh, máy bay hoặc ô tô, cần phải xác định vị trí tuyệt đối và hướng của cảm biến để giữ lại dữ liệu có thể sử dụng được. Hệ thống Định vị Toàn cầu cung cấp thông tin địa lý chính xác về vị trí của cảm biến và Đơn vị đo lường quán tính (IMU) ghi lại hướng chính xác của cảm biến tại vị trí đó. Hai thiết bị này cung cấp phương pháp chuyển dữ liệu cảm biến thành các điểm tĩnh để sử dụng trong nhiều hệ thống khác nhau.

Cảm ơn các bạn đã quan tâm, nếu có câu hỏi gì xin để lại trong phần bình luận.

Which programing language you should learn in 2021

Programming languages and computer coding have made life simpler for us. Whether it’s automobiles, banks, home appliances, or hospitals, every aspect of our lives depends on codes. No wonder, coding is one of the core skills required by most well-paying jobs today. Coding skills are especially of value in the IT, data analytics, research, web designing, and engineering segments. 

So, which programming languages will continue to be in demand in 2020 and beyond? How many languages should you know to pursue your dream career? We will attempt to answer these tricky questions in this post. 

The ever-growing list of programming languages and protocols can make it tough for programmers and developers to pick any one language that’s most suitable for their jobs or project at hand. Ideally, every programmer should have knowledge of a language that’s close to the system (C, Go, or C++), a language that’s object-oriented (Java or Python), a functional programming language (Scala), and a powerful scripting language (Python and JavaScript). 

Whether you are aiming at joining a Fortune 500 firm or desire to pursue a work-from-home career in programming, it’s important to know what’s hot in the industry. Here are a few programming languages we recommend for coders who want to make it big in 2020. 
 
Job hunting? Sign up for alerts about the latest openings in tech from our Jobs Board
 

1.  Python

 
Python continues to be one of the best programming languages every developer should learn this year. The language is easy-to-learn and offers a clean and well-structured code, making it powerful enough to build a decent web application. 

Python can be used for web and desktop applications, GUI-based desktop applications, machine learning, data science, and network servers. The programming language enjoys immense community support and offers several open-source libraries, frameworks, and modules that make application development a cakewalk.

For instance, Python offers Django and Flask, popular libraries for web development and TensorFlow, Keras, and SciPy for data science applications. 

Though Python has been around for a while, it makes sense to learn this language in 2020 as it can help you get a job or a freelance project quickly, thereby accelerating your career growth. 
 

2.  Kotlin


 
Kotlin is a general-purpose programming language with type inference. It is designed to be completely interoperable with Java. Moreover, from the time Android announced it as its first language, Kotlin offers features that developers ask for. It effortlessly combines object-oriented and functional programming features within it.

kotlin

(Image: Source)

The effortless interoperation between Java and Kotlin makes Android development faster and enjoyable. Since Kotlin addresses the major issues surfaced in Java, several Java apps are rewritten in Kotlin. For instance, brands like Coursera and Pinterest have already moved to Kotlin due to strong tooling support.  

As most businesses move to Kotlin, Google is bound to promote this language more than Java. Hence, Kotlin has a strong future in the Android app development ecosystem.

Kotlin is an easy-to-learn, open-source, and swift language for Android app development that removes any adoption-related barriers. You can use it for Android development, web development, desktop development, and server-side development. Therefore, it’s a must-learn language for programmers and Android app developers in 2020. 
 

3.  Java

 
Java is celebrating its 24th birthday this year and has been one of the most popular programming languages used for developing server-side applications. Java is a practical choice for  developing Android apps as it can be used to create highly functional programs and platforms. 

This object-oriented programming language does not require a specific hardware infrastructure, is easily manageable, and has a good level of security. Moreover, it is easier to learn Java in comparison to languages such as C and C++. No wonder, nearly 90 percent of Fortune 500 firms rely on Java for their desktop applications and backend development projects. 

java

Despite its industry age, the Java is incredibly stable and not heading for retirement anytime soon. This makes Java one of the most desirable languages among programmers in 2020. 
 

4.  JavaScript/ NodeJS

 
JavaScript (also known as NodeJS) is a popular language among developers who need to work on server-side and client-side programming. It is compatible with several other programming languages, allowing you to create animations, set up buttons, and manage multimedia. 

Owing to its high speed and regular annual updates, JavaScript is an ultimate hit in the IT domain. Reputed firms like Netflix, Uber, PayPal, and several startups use JavaScript to create dynamic web pages that are secure and fast. In fact, the 2018 Developer Skills Report by HackerRank shares that JavaScript is the top programming skill required by companies today. 

(Image Credit: Source)

JavaScript is omnipresent in today’s digital environment. Hence, learning this language makes complete sense. 
 

5.  TypeScript

 
TypeScript, a superset of JavaScript is an object-oriented language that was introduced to extend the capabilities of JS. The language makes it easy for developers to write and maintain codes. TypeScript offers a complete description of each component of the code and can be used for developing large applications with a strict syntax and fewer errors. 

Further, it is well-structured and easy to learn. Its extended toolbox makes application development quick. Owing to the benefits it offers, TypeScript is expected to supercede JS in 2020, making it one of the most sought-after programming languages in the future. 
 

6.  Go

 
Go is fairly a new system-level programming language that has a focused vocabulary and simple scoping rules. It blends the best aspects of functional programming and object-oriented styles. Go is the fastest-growing language on Github, meant to replace languages like Java and C++. 

Stack Overflow survey reveals that Go is the fifth most preferred language among developers today. This is because, Go solves issues like slow compilation and execution in large distributed software systems. 

(Image Credit: Source)

This speed advantage has made Go a critical component of cloud infrastructure. So, if you are planning to work in a serverless ecosystem, Go is the language for you. 
 

7.  Swift

 
Swift is a general-purpose compiled programming language developed by Apple that offers developers a simple and cohesive syntax. It is deeply influenced by Python and Ruby that’s fast, secure, and easy-to-learn. Owning to its versatility and practical applications, Swift has replaced Objective-C as the main language for Apple-related applications. 

Further, since Swift is promoted by Apple, its popularity and community support is increasing. In fact, a study of the top 110 apps on the app store showed that 42 percent of apps are already using Swift. 

swift

(Image Credit: Source)

Coders with little or zero experience can use Swift Playgrounds to learn the language, experiment with complex codes, and work on native iOS and macOS apps. Swift is the premiere coding language that helps developers create iOS apps within a short time. The programming language opens several opportunities for new programmers, allowing them to make it big in the world of app development. 

There is a giant market out there for iOS and you definitely want to be a part of it. If you are eyeing this burgeoning market, Swift is the language you should learn in 2020. 
 
Summing Up
 
Nearly all coders have an insatiable thirst for learning new languages. However, knowing which languages are gaining popularity and can ensure a better career growth will help you prioritize learning them first. Use the information shared in this post to make an informed decision in this matter. 

And more than programming language is nowadays programmer should understand about system administrator, Linux command, Docker, monitoring and testing, because these are very important for your carrier.

Authors:
Truong Thanh Nguyen/ Github: thanh118
Software Developer/ DevOps (Autonomous Driving and Machine Learning)Follow 100 follower · 16 following ·

Frankfurt am Main, Germany
master-engineer.com
@T12Thanh

What is Pointer in C/C++ and How we understand it!

Pointers

In earlier chapters, variables have been explained as locations in the computer’s memory which can be accessed by their identifier (their name). This way, the program does not need to care about the physical address of the data in memory; it simply uses the identifier whenever it needs to refer to the variable.

For a C++ program, the memory of a computer is like a succession of memory cells, each one byte in size, and each with a unique address. These single-byte memory cells are ordered in a way that allows data representations larger than one byte to occupy memory cells that have consecutive addresses.

This way, each cell can be easily located in the memory by means of its unique address. For example, the memory cell with the address 1776 always follows immediately after the cell with address 1775 and precedes the one with 1777, and is exactly one thousand cells after 776 and exactly one thousand cells before 2776.

When a variable is declared, the memory needed to store its value is assigned a specific location in memory (its memory address). Generally, C++ programs do not actively decide the exact memory addresses where its variables are stored. Fortunately, that task is left to the environment where the program is run – generally, an operating system that decides the particular memory locations on runtime. However, it may be useful for a program to be able to obtain the address of a variable during runtime in order to access data cells that are at a certain position relative to it.

Address-of operator (&)

The address of a variable can be obtained by preceding the name of a variable with an ampersand sign (&), known as address-of operator. For example:

 
foo = &myvar;

This would assign the address of variable myvar to foo; by preceding the name of the variable myvar with the address-of operator (&), we are no longer assigning the content of the variable itself to foo, but its address.

The actual address of a variable in memory cannot be known before runtime, but let’s assume, in order to help clarify some concepts, that myvar is placed during runtime in the memory address 1776.

In this case, consider the following code fragment:

1
2
3
myvar = 25;
foo = &myvar;
bar = myvar;

The values contained in each variable after the execution of this are shown in the following diagram:

First, we have assigned the value 25 to myvar (a variable whose address in memory we assumed to be 1776).

The second statement assigns foo the address of myvar, which we have assumed to be 1776.

Finally, the third statement, assigns the value contained in myvar to bar. This is a standard assignment operation, as already done many times in earlier chapters.

The main difference between the second and third statements is the appearance of the address-of operator (&).

The variable that stores the address of another variable (like foo in the previous example) is what in C++ is called a pointer. Pointers are a very powerful feature of the language that has many uses in lower level programming. A bit later, we will see how to declare and use pointers.

Dereference operator (*)

As just seen, a variable which stores the address of another variable is called a pointer. Pointers are said to “point to” the variable whose address they store.

An interesting property of pointers is that they can be used to access the variable they point to directly. This is done by preceding the pointer name with the dereference operator (*). The operator itself can be read as “value pointed to by”.

Therefore, following with the values of the previous example, the following statement:

 
baz = *foo;

This could be read as: “baz equal to value pointed to by foo“, and the statement would actually assign the value 25 to baz, since foo is 1776, and the value pointed to by 1776 (following the example above) would be 25.


It is important to clearly differentiate that foo refers to the value 1776, while *foo (with an asterisk * preceding the identifier) refers to the value stored at address 1776, which in this case is 25. Notice the difference of including or not including the dereference operator (I have added an explanatory comment of how each of these two expressions could be read):

1
2
baz = foo;   // baz equal to foo (1776)
baz = *foo;  // baz equal to value pointed to by foo (25)  

The reference and dereference operators are thus complementary:

  • & is the address-of operator, and can be read simply as “address of”
  • * is the dereference operator, and can be read as “value pointed to by”

Thus, they have sort of opposite meanings: An address obtained with & can be dereferenced with *.

Earlier, we performed the following two assignment operations:

1
2
myvar = 25;
foo = &myvar;

Right after these two statements, all of the following expressions would give true as result:

1
2
3
4
myvar == 25
&myvar == 1776
foo == 1776
*foo == 25

The first expression is quite clear, considering that the assignment operation performed on myvar was myvar=25. The second one uses the address-of operator (&), which returns the address of myvar, which we assumed it to have a value of 1776. The third one is somewhat obvious, since the second expression was true and the assignment operation performed on foo was foo=&myvar. The fourth expression uses the dereference operator (*) that can be read as “value pointed to by”, and the value pointed to by foo is indeed 25.

So, after all that, you may also infer that for as long as the address pointed to by foo remains unchanged, the following expression will also be true:

 
*foo == myvar

Declaring pointers

Due to the ability of a pointer to directly refer to the value that it points to, a pointer has different properties when it points to a char than when it points to an int or a float. Once dereferenced, the type needs to be known. And for that, the declaration of a pointer needs to include the data type the pointer is going to point to.

The declaration of pointers follows this syntax:

type * name;

where type is the data type pointed to by the pointer. This type is not the type of the pointer itself, but the type of the data the pointer points to. For example:

1
2
3
int * number;
char * character;
double * decimals;

These are three declarations of pointers. Each one is intended to point to a different data type, but, in fact, all of them are pointers and all of them are likely going to occupy the same amount of space in memory (the size in memory of a pointer depends on the platform where the program runs). Nevertheless, the data to which they point to do not occupy the same amount of space nor are of the same type: the first one points to an int, the second one to a char, and the last one to a double. Therefore, although these three example variables are all of them pointers, they actually have different types: int*char*, and double* respectively, depending on the type they point to.

Note that the asterisk (*) used when declaring a pointer only means that it is a pointer (it is part of its type compound specifier), and should not be confused with the dereference operator seen a bit earlier, but which is also written with an asterisk (*). They are simply two different things represented with the same sign.

Let’s see an example on pointers:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// my first pointer
#include <iostream>
using namespace std;

int main ()
{
  int firstvalue, secondvalue;
  int * mypointer;

  mypointer = &firstvalue;
  *mypointer = 10;
  mypointer = &secondvalue;
  *mypointer = 20;
  cout << "firstvalue is " << firstvalue << '\n';
  cout << "secondvalue is " << secondvalue << '\n';
  return 0;
}
firstvalue is 10
secondvalue is 20

Notice that even though neither firstvalue nor secondvalue are directly set any value in the program, both end up with a value set indirectly through the use of mypointer. This is how it happens:

First, mypointer is assigned the address of firstvalue using the address-of operator (&). Then, the value pointed to by mypointer is assigned a value of 10. Because, at this moment, mypointer is pointing to the memory location of firstvalue, this in fact modifies the value of firstvalue.

In order to demonstrate that a pointer may point to different variables during its lifetime in a program, the example repeats the process with secondvalue and that same pointer, mypointer.

Here is an example a little bit more elaborated:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// more pointers
#include <iostream>
using namespace std;

int main ()
{
  int firstvalue = 5, secondvalue = 15;
  int * p1, * p2;

  p1 = &firstvalue;  // p1 = address of firstvalue
  p2 = &secondvalue; // p2 = address of secondvalue
  *p1 = 10;          // value pointed to by p1 = 10
  *p2 = *p1;         // value pointed to by p2 = value pointed to by p1
  p1 = p2;           // p1 = p2 (value of pointer is copied)
  *p1 = 20;          // value pointed to by p1 = 20
  
  cout << "firstvalue is " << firstvalue << '\n';
  cout << "secondvalue is " << secondvalue << '\n';
  return 0;
}
firstvalue is 10
secondvalue is 20

Each assignment operation includes a comment on how each line could be read: i.e., replacing ampersands (&) by “address of”, and asterisks (*) by “value pointed to by”.

Notice that there are expressions with pointers p1 and p2, both with and without the dereference operator (*). The meaning of an expression using the dereference operator (*) is very different from one that does not. When this operator precedes the pointer name, the expression refers to the value being pointed, while when a pointer name appears without this operator, it refers to the value of the pointer itself (i.e., the address of what the pointer is pointing to).

Another thing that may call your attention is the line:

 
int * p1, * p2;

This declares the two pointers used in the previous example. But notice that there is an asterisk (*) for each pointer, in order for both to have type int* (pointer to int). This is required due to the precedence rules. Note that if, instead, the code was:

 
int * p1, p2;

p1 would indeed be of type int*, but p2 would be of type int. Spaces do not matter at all for this purpose. But anyway, simply remembering to put one asterisk per pointer is enough for most pointer users interested in declaring multiple pointers per statement. Or even better: use a different statement for each variable.

Pointers and arrays

The concept of arrays is related to that of pointers. In fact, arrays work very much like pointers to their first elements, and, actually, an array can always be implicitly converted to the pointer of the proper type. For example, consider these two declarations:

1
2
int myarray [20];
int * mypointer;

The following assignment operation would be valid:

 
mypointer = myarray;

After that, mypointer and myarray would be equivalent and would have very similar properties. The main difference being that mypointer can be assigned a different address, whereas myarray can never be assigned anything, and will always represent the same block of 20 elements of type int. Therefore, the following assignment would not be valid:

 
myarray = mypointer;

Let’s see an example that mixes arrays and pointers:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// more pointers
#include <iostream>
using namespace std;

int main ()
{
  int numbers[5];
  int * p;
  p = numbers;  *p = 10;
  p++;  *p = 20;
  p = &numbers[2];  *p = 30;
  p = numbers + 3;  *p = 40;
  p = numbers;  *(p+4) = 50;
  for (int n=0; n<5; n++)
    cout << numbers[n] << ", ";
  return 0;
}
10, 20, 30, 40, 50,

Pointers and arrays support the same set of operations, with the same meaning for both. The main difference being that pointers can be assigned new addresses, while arrays cannot.

In the chapter about arrays, brackets ([]) were explained as specifying the index of an element of the array. Well, in fact these brackets are a dereferencing operator known as offset operator. They dereference the variable they follow just as * does, but they also add the number between brackets to the address being dereferenced. For example:

1
2
a[5] = 0;       // a [offset of 5] = 0
*(a+5) = 0;     // pointed to by (a+5) = 0  

These two expressions are equivalent and valid, not only if a is a pointer, but also if a is an array. Remember that if an array, its name can be used just like a pointer to its first element.

Pointer initialization

Pointers can be initialized to point to specific locations at the very moment they are defined:

1
2
int myvar;
int * myptr = &myvar;

The resulting state of variables after this code is the same as after:

1
2
3
int myvar;
int * myptr;
myptr = &myvar;

When pointers are initialized, what is initialized is the address they point to (i.e., myptr), never the value being pointed (i.e., *myptr). Therefore, the code above shall not be confused with:

1
2
3
int myvar;
int * myptr;
*myptr = &myvar;

Which anyway would not make much sense (and is not valid code).

The asterisk (*) in the pointer declaration (line 2) only indicates that it is a pointer, it is not the dereference operator (as in line 3). Both things just happen to use the same sign: *. As always, spaces are not relevant, and never change the meaning of an expression.

Pointers can be initialized either to the address of a variable (such as in the case above), or to the value of another pointer (or array):

1
2
3
int myvar;
int *foo = &myvar;
int *bar = foo;

Pointer arithmetics

To conduct arithmetical operations on pointers is a little different than to conduct them on regular integer types. To begin with, only addition and subtraction operations are allowed; the others make no sense in the world of pointers. But both addition and subtraction have a slightly different behavior with pointers, according to the size of the data type to which they point.

When fundamental data types were introduced, we saw that types have different sizes. For example: char always has a size of 1 byte, short is generally larger than that, and int and long are even larger; the exact size of these being dependent on the system. For example, let’s imagine that in a given system, char takes 1 byte, short takes 2 bytes, and long takes 4.

Suppose now that we define three pointers in this compiler:

1
2
3
char *mychar;
short *myshort;
long *mylong;

and that we know that they point to the memory locations 10002000, and 3000, respectively.

Therefore, if we write:

1
2
3
++mychar;
++myshort;
++mylong;

mychar, as one would expect, would contain the value 1001. But not so obviously, myshort would contain the value 2002, and mylong would contain 3004, even though they have each been incremented only once. The reason is that, when adding one to a pointer, the pointer is made to point to the following element of the same type, and, therefore, the size in bytes of the type it points to is added to the pointer.


This is applicable both when adding and subtracting any number to a pointer. It would happen exactly the same if we wrote:

1
2
3
mychar = mychar + 1;
myshort = myshort + 1;
mylong = mylong + 1;

Regarding the increment (++) and decrement (--) operators, they both can be used as either prefix or suffix of an expression, with a slight difference in behavior: as a prefix, the increment happens before the expression is evaluated, and as a suffix, the increment happens after the expression is evaluated. This also applies to expressions incrementing and decrementing pointers, which can become part of more complicated expressions that also include dereference operators (*). Remembering operator precedence rules, we can recall that postfix operators, such as increment and decrement, have higher precedence than prefix operators, such as the dereference operator (*). Therefore, the following expression:

 
*p++

is equivalent to *(p++). And what it does is to increase the value of p (so it now points to the next element), but because ++ is used as postfix, the whole expression is evaluated as the value pointed originally by the pointer (the address it pointed to before being incremented).

Essentially, these are the four possible combinations of the dereference operator with both the prefix and suffix versions of the increment operator (the same being applicable also to the decrement operator):

1
2
3
4
*p++   // same as *(p++): increment pointer, and dereference unincremented address
*++p   // same as *(++p): increment pointer, and dereference incremented address
++*p   // same as ++(*p): dereference pointer, and increment the value it points to
(*p)++ // dereference pointer, and post-increment the value it points to 

A typical -but not so simple- statement involving these operators is:

 
*p++ = *q++;

Because ++ has a higher precedence than *, both p and q are incremented, but because both increment operators (++) are used as postfix and not prefix, the value assigned to *p is *q before both p and q are incremented. And then both are incremented. It would be roughly equivalent to:

1
2
3
*p = *q;
++p;
++q;

Like always, parentheses reduce confusion by adding legibility to expressions.

Pointers and const

Pointers can be used to access a variable by its address, and this access may include modifying the value pointed. But it is also possible to declare pointers that can access the pointed value to read it, but not to modify it. For this, it is enough with qualifying the type pointed to by the pointer as const. For example:

1
2
3
4
5
int x;
int y = 10;
const int * p = &y;
x = *p;          // ok: reading p
*p = x;          // error: modifying p, which is const-qualified 

Here p points to a variable, but points to it in a const-qualified manner, meaning that it can read the value pointed, but it cannot modify it. Note also, that the expression &y is of type int*, but this is assigned to a pointer of type const int*. This is allowed: a pointer to non-const can be implicitly converted to a pointer to const. But not the other way around! As a safety feature, pointers to const are not implicitly convertible to pointers to non-const.

One of the use cases of pointers to const elements is as function parameters: a function that takes a pointer to non-const as parameter can modify the value passed as argument, while a function that takes a pointer to const as parameter cannot.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// pointers as arguments:
#include <iostream>
using namespace std;

void increment_all (int* start, int* stop)
{
  int * current = start;
  while (current != stop) {
    ++(*current);  // increment value pointed
    ++current;     // increment pointer
  }
}

void print_all (const int* start, const int* stop)
{
  const int * current = start;
  while (current != stop) {
    cout << *current << '\n';
    ++current;     // increment pointer
  }
}

int main ()
{
  int numbers[] = {10,20,30};
  increment_all (numbers,numbers+3);
  print_all (numbers,numbers+3);
  return 0;
}
11
21
31

Note that print_all uses pointers that point to constant elements. These pointers point to constant content they cannot modify, but they are not constant themselves: i.e., the pointers can still be incremented or assigned different addresses, although they cannot modify the content they point to.

And this is where a second dimension to constness is added to pointers: Pointers can also be themselves const. And this is specified by appending const to the pointed type (after the asterisk):

1
2
3
4
5
int x;
      int *       p1 = &x;  // non-const pointer to non-const int
const int *       p2 = &x;  // non-const pointer to const int
      int * const p3 = &x;  // const pointer to non-const int
const int * const p4 = &x;  // const pointer to const int 

The syntax with const and pointers is definitely tricky, and recognizing the cases that best suit each use tends to require some experience. In any case, it is important to get constness with pointers (and references) right sooner rather than later, but you should not worry too much about grasping everything if this is the first time you are exposed to the mix of const and pointers. More use cases will show up in coming chapters.

To add a little bit more confusion to the syntax of const with pointers, the const qualifier can either precede or follow the pointed type, with the exact same meaning:

1
2
const int * p2a = &x;  //      non-const pointer to const int
int const * p2b = &x;  // also non-const pointer to const int 

As with the spaces surrounding the asterisk, the order of const in this case is simply a matter of style. This chapter uses a prefix const, as for historical reasons this seems to be more extended, but both are exactly equivalent. The merits of each style are still intensely debated on the internet.

Pointers and string literals

As pointed earlier, string literals are arrays containing null-terminated character sequences. In earlier sections, string literals have been used to be directly inserted into cout, to initialize strings and to initialize arrays of characters.

But they can also be accessed directly. String literals are arrays of the proper array type to contain all its characters plus the terminating null-character, with each of the elements being of type const char (as literals, they can never be modified). For example:

 
const char * foo = "hello"; 

This declares an array with the literal representation for "hello", and then a pointer to its first element is assigned to foo. If we imagine that "hello" is stored at the memory locations that start at address 1702, we can represent the previous declaration as:


Note that here foo is a pointer and contains the value 1702, and not 'h', nor "hello", although 1702 indeed is the address of both of these.

The pointer foo points to a sequence of characters. And because pointers and arrays behave essentially in the same way in expressions, foo can be used to access the characters in the same way arrays of null-terminated character sequences are. For example:

1
2
*(foo+4)
foo[4]

Both expressions have a value of 'o' (the fifth element of the array).

Pointers to pointers

C++ allows the use of pointers that point to pointers, that these, in its turn, point to data (or even to other pointers). The syntax simply requires an asterisk (*) for each level of indirection in the declaration of the pointer:

1
2
3
4
5
6
char a;
char * b;
char ** c;
a = 'z';
b = &a;
c = &b;

This, assuming the randomly chosen memory locations for each variable of 72308092, and 10502, could be represented as:


With the value of each variable represented inside its corresponding cell, and their respective addresses in memory represented by the value under them.

The new thing in this example is variable c, which is a pointer to a pointer, and can be used in three different levels of indirection, each one of them would correspond to a different value:

  • c is of type char** and a value of 8092
  • *c is of type char* and a value of 7230
  • **c is of type char and a value of 'z'

void pointers

The void type of pointer is a special type of pointer. In C++, void represents the absence of type. Therefore, void pointers are pointers that point to a value that has no type (and thus also an undetermined length and undetermined dereferencing properties).

This gives void pointers a great flexibility, by being able to point to any data type, from an integer value or a float to a string of characters. In exchange, they have a great limitation: the data pointed to by them cannot be directly dereferenced (which is logical, since we have no type to dereference to), and for that reason, any address in a void pointer needs to be transformed into some other pointer type that points to a concrete data type before being dereferenced.

One of its possible uses may be to pass generic parameters to a function. For example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// increaser
#include <iostream>
using namespace std;

void increase (void* data, int psize)
{
  if ( psize == sizeof(char) )
  { char* pchar; pchar=(char*)data; ++(*pchar); }
  else if (psize == sizeof(int) )
  { int* pint; pint=(int*)data; ++(*pint); }
}

int main ()
{
  char a = 'x';
  int b = 1602;
  increase (&a,sizeof(a));
  increase (&b,sizeof(b));
  cout << a << ", " << b << '\n';
  return 0;
}
y, 1603

sizeof is an operator integrated in the C++ language that returns the size in bytes of its argument. For non-dynamic data types, this value is a constant. Therefore, for example, sizeof(char) is 1, because char has always a size of one byte.

Invalid pointers and null pointers

In principle, pointers are meant to point to valid addresses, such as the address of a variable or the address of an element in an array. But pointers can actually point to any address, including addresses that do not refer to any valid element. Typical examples of this are uninitialized pointers and pointers to nonexistent elements of an array:

1
2
3
4
int * p;               // uninitialized pointer (local variable)

int myarray[10];
int * q = myarray+20;  // element out of bounds 

Neither p nor q point to addresses known to contain a value, but none of the above statements causes an error. In C++, pointers are allowed to take any address value, no matter whether there actually is something at that address or not. What can cause an error is to dereference such a pointer (i.e., actually accessing the value they point to). Accessing such a pointer causes undefined behavior, ranging from an error during runtime to accessing some random value.

But, sometimes, a pointer really needs to explicitly point to nowhere, and not just an invalid address. For such cases, there exists a special value that any pointer type can take: the null pointer value. This value can be expressed in C++ in two ways: either with an integer value of zero, or with the nullptr keyword:

1
2
int * p = 0;
int * q = nullptr;

Here, both p and q are null pointers, meaning that they explicitly point to nowhere, and they both actually compare equal: all null pointers compare equal to other null pointers. It is also quite usual to see the defined constant NULL be used in older code to refer to the null pointer value:

 
int * r = NULL;

NULL is defined in several headers of the standard library, and is defined as an alias of some null pointer constant value (such as 0 or nullptr).

Do not confuse null pointers with void pointers! A null pointer is a value that any pointer can take to represent that it is pointing to “nowhere”, while a void pointer is a type of pointer that can point to somewhere without a specific type. One refers to the value stored in the pointer, and the other to the type of data it points to.

Pointers to functions

C++ allows operations with pointers to functions. The typical use of this is for passing a function as an argument to another function. Pointers to functions are declared with the same syntax as a regular function declaration, except that the name of the function is enclosed between parentheses () and an asterisk (*) is inserted before the name:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// pointer to functions
#include <iostream>
using namespace std;

int addition (int a, int b)
{ return (a+b); }

int subtraction (int a, int b)
{ return (a-b); }

int operation (int x, int y, int (*functocall)(int,int))
{
  int g;
  g = (*functocall)(x,y);
  return (g);
}

int main ()
{
  int m,n;
  int (*minus)(int,int) = subtraction;

  m = operation (7, 5, addition);
  n = operation (20, m, minus);
  cout <<n;
  return 0;
}
8

In the example above, minus is a pointer to a function that has two parameters of type int. It is directly initialized to point to the function subtraction:

 
int (* minus)(int,int) = subtraction;

YOLO-You only look once

YOLO hẳn đã rất quen thuộc với các bạn trẻ, chúng ta đã nghe từ này biết bao nhiêu lần, khi mà thằng bạn của bạn muốn đua xe đập đá mà bạn ngăn cản, nó sẽ lôi từ này để bật lại bạn, rằng mày chỉ sống có 1 lần thôi, yolo đi.

Câu đó thật ra cũng đúng trong hoàn cảnh bạn biết mình làm gì:)), và trong bài viết này mình cũng nói về YOLO, nhưng không phải về cụm từ kia, mà là một thành tựu lớn của neural network và Image Processing- YOLO( You Only Look One). Nghĩa là chỉ nhìn một lần thôi, lần đầu nghe câu này mình thấy buồn cười, thì hiển nhiên là nhìn một lần chứ mấy lần, còn thấy người đẹp muốn nhìn lại mấy lần thì nhìn chứ, ai cấm:)). Nhưng thật ra câu nói này không phải cho con người, mà là cho computer. Nếu bạn nào đã có kiến thức về Image Processing thì mời lướt qua, còn chưa thì mình diễn tả nôm na như sau: Máy tính nhìn một bức ảnh dưới dạng một ma trận số, và để thực hiện một số tính năng chỉnh sửa ảnh, đầu tiên ta phải xét đến một filter matrix hoặc còn gọi là convolution, convolution matrix này sẽ được nhân với một ô nhỏ trên cùng bên trái của tấm ảnh, sau đó ô này sẽ trượt theo chiều ngang và sau đó xuống dòng đến khi đi hết tấm ảnh. Do đó có thể nói máy tính nó không nhìn tấm ảnh một lần như chúng ta mà nó nhìn từ trái qua phải từ trên xuống dưới. Tất nhiên nhìn kĩ là tốt nhưng làm vậy rất tốn thời gian, trong khi chúng ta chỉ cần nhỉn tổng thể bức hình là có thể chỉ ra trong đó có gì, thì computer cần phải rà hàng trăm hàng ngàn tấm ảnh nhỏ mới làm được điều tương tự. YOLO ra đời để cho phép máy tính làm điều tương tự nhưng tốc độ được cải thiện đáng kể, chỉ quét một lần và nhận diện objects, cho đó nâng cao tốc độ xử lý ảnh lên đến 60 frames/s nhờ đó có thể đáp ứng nhu cầu real-time.

Dưới đây là một số chia sẻ của chính tác giả YOLO:

You only look once (YOLO) is a state-of-the-art, real-time object detection system. On a Pascal Titan X it processes images at 30 FPS and has a mAP of 57.9% on COCO test-dev.

Prior detection systems repurpose classifiers or localizers to perform detection. They apply the model to an image at multiple locations and scales. High scoring regions of the image are considered detections.

We use a totally different approach. We apply a single neural network to the full image. This network divides the image into regions and predicts bounding boxes and probabilities for each region. These bounding boxes are weighted by the predicted probabilities.

12
Comparison other detector

Về cách hoạt động của YOLO mình đã nói ở trên, còn hình bên dưới chính là kết quả hoành tráng mà nó tạo ra. Trong hình bạn có thể thất từng chiếc xe được theo dấu với những hộp bao quanh, và xác định nó là xe lên tới 99%. Không những vậy, đoạn code còn kết hợp với segmentation để nhận dạng đường biên của mỗi chiếc xe, giúp nhận diện chính xác hơn.

13

Nếu các bạn có hứng thú với đoạn code trong video bên trên, bạn có thể lấy code qua Github của mình, đoạn code được viết bằng Python và sử dụng tensorflow model.

Tóm Tắt (Sumary) Cách hoạt động của xe tự lái (Self-driving vehicle)…và robot tự hành.

Mình sẽ viết đoạn này bằng tiếng Anh, tiếng việt các bạn có thể dùng tính năng translate nằm bên phải để dịch tiếng việt nhé. Hoặc mình sẽ dịch tiếng việt bên dưới

Most of self-driving car on the world work as follow:

Cách mà một chiếc xe tự lái hoạt động được cấu trúc như biểu đồ phía dưới:

Computer Vision(Kỹ thuật xử lý ảnh) + Sensor Fusion(kết hợp sensor: các bạn tạm hiểu là cách hợp các tín hiệu cảm biến lại để đưa ra thông tin chính xác nhất) để đưa ra vị trí chính xác của xe nằm ở đâu trong map. Từ đó xe dùng các thật toán tìm đường Path Planning  để đi tới đích, bước cuối cùng là truyền lệnh cho động cơ xe để yêu cầu chạy tốc độ bao nhiêu bẻ lái như thế nào:

Tổng quát chỉ có vậy, nếu các bạn muốn hiểu chi tiết thì hãy đọc đoạn tiếng anh bên dưới(có thế translate nếu muốn)

Howcarselfdriving.png

I/ Generally

Computer vision is how we use images to figure out what the world around us look like. Sensor fusion is how we in-cooperate data from other sensor like laser, Lidars, radar, to get richer understanding out of environment. Once we’ve build this deep understanding of what the world looks like we use path planning to chart a course through the world to get us to where we would like to go. The final step is how we actually turn the sterring wheel and hit the throttle, and the brake in oder to execute the trajectory that we build during path planning.

II/ Computer Vision

Computer Vision using the camera mounted in front of the car, to detect lane and other vehicle. It looking for color and edges and gradient to find the lane on the road and then train a deep neural network to draw the bounding box around the other vehicle on the road.

Deep neural network and deep learning is exciting new part of machine leaning and artificial intelligent. And this is the way that computer can learn what cars and other object look like by simply sending them lots and lots of data they see lots of cars and this is pretty similar to what advance driving assistance system do on the road today.

II/ Sensor Fusion

Once we know what world look like by images, the next steps is augment that understanding of the world using other sensor so radar and laser to get measurement that are difficult for the camera alone to understand so things like distance between our car and other car and how fast other object in the environment moving.

A  Lidar which has an array of laser doing a 360 degrees scan to to world and seeing the different object in that environment looks like and how they move.

So once we understand both what the world look like and how to measure it and we cooperate those understanding together to get rich picture of our surrounding environment, the next step is to localize ourself in that environment.

III/ Localization

Maybe people think GPS today can localize ourself in cellphone. we absolute now where we are but it not really like that, because GPS uncertainty is about 1 to 2 meter. And in self-driving we need the absolute accuracy, because if a small mistake happen, it very dangerous for your car if you running on the hight way with 150 to 200km/h. So we have to use much sophisticated mathematical algorithm as well as hight definition map to localize our vehicle precisely in it environment to single digits centimeter level accuracy.

Using particle filter is very good way to localize a vehicle in an know environment. Measuring distance from various landmarks ans it’s figuring how far is it from these landmark and where it see the landmark and comparing that to the map and using that to figure out precisely where it is in the world , those landmark might be things like streetlight, or traffic sign, mail boxes or even manhole covers.

IV/ Path Planning

When we know how the world look like and where were are in this world, the next step is to actually chart a path plan through that world to figure out how to get where we want to go, and this is path planning. This program cerate a path planner which predict where the other vehicles on the road are going to and then figures out the maneuver our vehicle should take in response and finally build and series of way points those are the green points in the video for the car driver through that’s the trajectory the car should follow and you see if the vehicle comes up on other traffic it has to figure out should it slow down and stay in it lane or should it shift right or should shift left. And this is the type of decision that real self-driving car had to make all the time subject to constraints like speed limit and acceleration limit.

V/ Control

Final step in the pipeline is control. Control is how we actually turn the steering wheel and hit the throttle and hit the brake in oder to execute that trajectory that we build during path planning.

If you want to go in detail, you can apply to Udacity self-driving car program, there you will be learn theories, programming skill with the best professors and the best engineers form over the world

Thi Thơ

Quan San Nguyệt

Minh nguyệt xuất thiên san

Thương Mang vân hải giang

Thuỳ phong kỷ vạn lý

Suy độ Ngọc Môn quan

Hán hạ bạch đăng đạo

Hồ khuy Thanh Hải loan

Do lai chinh chiến địa

Bất kiến hữu nhân hoàn

Thú khách vọng biên sắc

Tư quy đa khổ nhan

Cao lâu ưng tử dạ

Thán tức vị ưng nhàn.

Lâm An Đề

Sơn ngoại thanh sơn lâu ngoại lâu

Tây hồ ca vũ kỷ thì vưu

Noãn phong huân đắc du nhân tuý

Trực bả Hàng Châu tác Biện Châu

Nội dung bài thơ miêu tả bối cảnh thời Nam Tống, khi mà miền bắc Trung Quốc đã hoàn toàn bị thôn tính bởi người Liêu. Nhưng triều đình hủ bại, vua tôi quan lại chỉ lo vui chơi ca hát, giới nho sĩ trong nước có lòng báo quốc nhưng lực bất tòng tâm, người ta hay nói học trò khởi nghĩa, mười năm chưa thành là vậy, giới nho sĩ mặc dù tài hoa hơn người, có hùng tâm tráng chí, nhưng họ sinh ra đã đọc sách thánh hiền, bị tam cương ngũ thường trói buộc, làm sao mà họ dám lật đổ hoàng đế vì làm vậy khác nào đạp đổ đức tin của chính mình. Từ cổ chí kim, kẻ có gan chống trời đạp đất thực ra chỉ có hai loại, thứ nhất là con nhà võ tướng danh gia, nhưng người sinh ra đã có bá khí ngút trời, thứ hai là loại đầu trộm đuôi cướp, đầu đường xó chợ, vì chúng chả có gì để mất cả, chúng chỉ nghĩ là đánh một canh bạc lớn mà thôi, thắng thì chúng làm vua mà thua thì lại làm giặc như trước, minh chứng cho điều này là Hạng Vũ và Lưu Bang. Những kẻ nho sĩ gặp vận nước nguy nan thường chỉ biết ngửa mặt lên trời than trách hoặc làm thơ mắng những kẻ họ cho là không xứng đáng cầm quyền, đó là lí do mà bài thơ trên ra đời, đại ý là ngoài núi lại núi ngoài lầu lại lầu, tây hồ trăng thanh gió mát đến nỗi làm say lòng khách , say đến nỗi quên mất giành lại kinh đô của mình mà còn tưởng Hàng Châu tươi đẹp này mới là kinh thành.

Tản mạn Xạ Điêu tam bộ khúc

Kim Dung đại hiệp mất đi để lại nỗi buồn vô hạn trong lòng người hâm mộ tiểu thuyết võ hiệp. Với những ai đọc Kim Dung, hẳn những câu thơ sau đã đi vào lòng biết bao thế hệ:

Thiên thu bá nghiệp bách chiến thành công.

Biên thanh tứ khởi Xướng đại phong.

index

Bá nghiệp ngàn năm, trải trăm trận mới dành thắng lợi

Dậy bốn phương trời, tiếng gió reo như tiếng hát mừng công

Nhưng câu thơ này đọc lên đã thấy được cả một thế giới võ hiệp đã được dựng lên một cách sinh động và đầy sắc màu. Một thế giới mà những Quách tĩnh, Hoàng Dung, Chu Bá Thông, Lệnh Hồ xung, Trương Vô Kỵ, Triệu Mẫn, Thiếu Lâm, Võ Đang, Cửu Dương thần công, Độc Cô Cửu Kiếm… tất cả làm nên một thế giới giang hồ thật đặc sắc, sinh động. Mặc dù nhiều cạm bẫy, cám dỗ nhưng vẫn có những anh hùng, đại hiệp sẵn sàng xông pha, gánh vác đại sự cho thiên hạ để rồi lưu danh thiên cổ. Dưới ngòi bút Kim Dung, nhiều bộ võ công và bí tịch đã ra đời. Ông có một trí tưởng tượng cực kì phong phú khi đã sáng tạo ra những bộ võ công có chiêu số, khẩu quyết và có sự liên kết chặt chẽ với nhau. Lối hành văn mạch lạc của Kim Dung lại càng khiến những bộ võ công kia giống như thực sự tồn tại chứ không phải hư cấu, đặc biệt ông có biệt tài lồng ghép các sự việc có thật và hư cấu với nhau, làm người đọc tưởng như mình đang đọc dã sử vậy, nhân vật trong truyện Kim Dung có mối quan hệ mật thiết, và các biến cố trong cuộc đời họ giữ được sự mạch lạc và liên tục qua các bộ truyện khác nhau. Đồng thời những nhân vật trên mặc dù là hư cấu, nhưng được lồng ghép tài tình vào các địa danh và sự kiện lịch sử có thật trong lịch sử Trung Hoa. Khi đọc truyện Kim Dung, người đọc thấy mình như hoà vào thế giới ấy, khi tình yêu, thù hận, lòng tham được làm võ lâm chí tôn, được miêu tả một cách thật đặc biệt. Trong một đoạn ỷ thiên đồ long kí có bài thơ sau

Võ lâm chí tôn, bảo đao Đồ Long

Hiệu lệnh thiên hạ, mạc cảm bất tòng

Ỷ Thiên bất xuất, thuỳ dữ tranh phong

Ba câu thơ trên đọc lên đã thấy được sự bá đạo của thanh đồ long đao, nhưng người ta cũng đặt câu hỏi, chỉ là một thanh đao, dù sắc bén đến đâu cũng làm sao có thể hiệu lệnh thiên hạ. Thực ra khi độc giả theo dõi sẽ biết rằng bí ẩn không nằm ở đao mà nằm bên trong nó, nơi mà võ mục di thư của danh tướng Nam Tống Nhạc Phi để lại cho hậu được thiết kế dấu trong bảo đao. Võ mục di thư tương truyền là cuốn binh pháp duy nhất được Nhạc Vũ Mục biên soạn và ai có nó trong tay có thể đoạt thiên hạ.

Anh hùng xạ điêu là bộ truyện đầu tiên mang cái tên kim dung sáng bừng trên văn đàn Trung Quốc. Nội dung câu chuyện được lồng ghép vào bối cảnh Trung Hoa thời Nam Tống, khi mà toàn bộ phía bắc lưu vực sông Hoàng Hà đã bị người Liêu chiếm đóng và lập ra nước Đại Liêu. Liêu quốc hùng mạnh liên tục xua quân nam hạ, muốn thôn tính Đại Tống. Thực ra lúc đó Tống triều đã suy yếu nhiều, ngay cả tổng quản thái giám Lý Thường Kiệt của nước ta cũng đem mười vạn đại quân đánh sâu vào lãnh thổ đất Tống, nhưng sau đó không thích chiếm nên rút về. may mắn là Tống quốc lực tàn nhưng chưa tận. Họ vẫn còn nhưng vị danh tướng như Dương Nghiệp, Nhạc Phi đủ sức đương đầu hoạ từ phương bắc,