9999 Light
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights
    • Engagement control
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Versions and GitHub Sync Note Insights Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       owned this note    owned this note      
    Published Linked with GitHub
    1
    Subscribed
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    Subscribe
    # Section 2 - 徒手搓一台電動車竟然那麼容易!自動駕駛前奏曲 課前閱讀:[機器人作業系統能幫我寫作業嗎?ROS 2 究竟是何方神聖](https://hackmd.io/@Lani0516/BJptJP06ke) ## 課程講師 | OP & ED | Fusion |Unity | ROS2 Installation | ROS2 Navigation | |:-------:|:------:|:-----------------:|:---------------:|:------:| | 劉文恩 | 黃德彥 | 陳俊光 | 覃家璿 | 官子恩 | ## 最低硬體需求 ### windows 作業系統:windows 10 64-bit 處理器:Intel core i5-4570 記憶體:16 GB 記憶體 儲存空間:30 GB 可用空間 ### macOS 處理器:Apple M1 記憶體:8 GB 記憶體 儲存空間:30 GB 可用空間 ### linux 作業系統:任意 硬體要求:同 windows、macOS >[!Warning] 要對自己系統的 Package Manager、CLI 指令有一定了解 例如:Ubuntu(apt)、CentOS (yum) ## 預先安裝內容(請務必於上課前自行安裝完畢!) {%preview https://hackmd.io/@RgFC-jP-Qp6J6fJ4BTqdgQ/S1fvJsUa1l %} {%preview https://hackmd.io/@RgFC-jP-Qp6J6fJ4BTqdgQ/Syk0aUDa1x %} > Linux 跟 Mac 大同小異,但套件管理工具要使用系統自帶的,不能使用 Homebrew ## Fusion #### 前情提要 由於在本次工作坊中並不會花太多的時間著墨,因此已經幫大家把模型設立好了,但是如果想要自己嘗試建構模型,可點擊 [fusion360建造urdf車子後匯入unity](https://youtu.be/080UAkOeeUM?si=7oUKPX7KqXpkSWQG) 如果沒有要自行建造, [urdf_model](https://github.com/screamlab/urdf_model) 就是我們提供的模型,請先確認是否已經git clone。 ### Find URDF folder 如果是直接使用提供的模型,請打開Powershell後進入`urdf_model`的資料夾。 1. 在`urdf_model`中進入`fourWheelCar_description`資料夾 ```bash cd fourWheelLidar_3DModel_urdf/fourWheelCar_description ``` 2. 輸入`ls`檢查是否有這三個檔案在裡面 - `urdf` - `meshes` - `launch` ![image](https://hackmd.io/_uploads/B10kTT5pkl.png) 3. 輸入 `pwd` 或 `Get-location` 查詢當前位置,並複製下來。 ``` pwd ``` ### Export URDF 1. 打開新的powershell分頁,進到`fusion_xacro2urdf2unity`資料夾。 2. 將`xacro2urdf.py`複製到剛剛提到的資料夾。這個python腳本是用來將 `xacro` 格式的文件轉換為 `urdf` 格式的文件 ```bash python xacro2urdf.py /path/to/your/folder ``` 請將`/path/to/your/folder`的部分改為先前複製的路經。 如果成功的話,應該會跳出success的字樣。 ![image](https://hackmd.io/_uploads/SJlyvRoa1x.png) 3. 如果想確認的話,在`fourWheelCar_description` 檔案中輸入 `ls` 應該就會看到 `fourWheelCar_to_unity` 資料夾了。 ### 自行建構模型(這裡有[示範影片](https://youtu.be/ctNzWya31cA?si=XJce-DJDW1mnEaIw)) >[!Note] 以下部分提供給有安裝fusion且使用自己的模型的人參考,urdf_model內的模型已轉換完畢,若使用此模型可跳過這個部分。 #### 將URDF export複製到fusion上 請到`fusion2urdf folder`的資料夾裡輸入以下指令: (這個指令讓fusion能夠export Ros2,省下一些步驟) Windows: ```bash Copy-Item ".\URDF_Exporter\" -Destination "${env:APPDATA}\Autodesk\Autodesk Fusion 360\API\Scripts\" -Recurse ``` Mac: ```bash cp -r ./URDF_Exporter "$HOME/Library/Application Support/Autodesk/Autodesk Fusion 360/API/Scripts/" ``` #### 輸出URDF檔 1. 打開fusion自行製作的模型。 在上方的UTILITIES介面找到ADD-INS,點進去後選擇Scripts and Add-Ins ![Screenshot 2025-04-04 012730](https://hackmd.io/_uploads/HkQzJGaT1x.png) 2. 打開Scripts and Add-Ins後,選擇URDF_Exporter_Ros2(這是前面Copt-item得到的) ![Screenshot 2025-04-04 013139](https://hackmd.io/_uploads/B1q8kzTp1x.png) 3. 按下Run之後,應該就會跳出儲存畫面。(建議新增資料夾方便整理) 4. 儲存後如果有跳出success的畫面就代表成功了。 ![Screenshot 2025-04-04 013647](https://hackmd.io/_uploads/rkOTyfaTye.png) #### Copy address 打開儲存的fusion資料夾,找到`urdf` `meshes` `launch`三個檔案。 >[!tip] 應該會在 xxx_to_description 的資料夾找到 如果是透過檔案總管找到資料夾的話,可以在資料夾上方按右鍵,即可copy address 舉個例子,如果自行製作了 cat_description,在確認有 `urdf` `meshes` `launch`三個檔案後,在上方`cat_description` 按下右鍵即可找到複製路徑的選項。 ![image](https://hackmd.io/_uploads/H1WlYAoTyx.png) 這樣在xacro轉urdf時會輸入:(只是範例) ```bash python xacro2urdf.py C:\Users\Desktop\fusion\cat_description ``` 一樣也會跳出success的畫面。 ## Unity setting ### Unity pkg install #### how to import a package into Unity: 1. 打開 Unity 2. 點選上方工作欄的 Window → Package Manager 3. 點擊左上方的 `+` 符號 4. 選擇 `Install package from git URL` 5. 輸入 `https://github.com/Unity-Technologies/URDF-Importer.git?path=/com.unity.robotics.urdf-importer#v0.5.2` 並點擊 `install` ![image](https://hackmd.io/_uploads/BJVrUGhpJl.png) #### Install NuGet 我們需要 NuGet 裡面的 WebSocketSharp,它是連接 ROS 所需的套件 1. 在 [NuGetForUnity 的網頁](https://openupm.com/packages/com.github-glitchenzo.nugetforunity/#close) 點擊 `Manual installation` 2. 將裡面的資料填入 Unity 上方工作欄的 Edit → Project Settings → Package Manager `中的 New Scoped Registry` 裡後,點擊 `Save` ![image](https://hackmd.io/_uploads/SJZV6A1R1g.png) 3. 點選 Unity 上方工作欄的 Window → Package Manager 4. 點擊左上方的 `+` 符號 5. 選擇 `Install package from git URL` 6. 輸入 `com.github-glitchenzo.nugetforunity` 並點擊 `install` > [!Tip] NuGet 的安裝也可以參考 [安裝教學](https://tedliou.com/unity/nuget/) 7. 下載完成 NuGet 之後,點選上方工作欄的 NuGet → Manage NuGet Packages ![image](https://hackmd.io/_uploads/BJX_D2PT1e.png) 8. 搜尋 WebSocketSharp,安裝 WebSocketSharp-netstandard ![image](https://hackmd.io/_uploads/HkGMd3Dp1g.png) ### Import URDF 1. 在 Project 一欄中打開 urdf 檔案資料夾 ![image](https://hackmd.io/_uploads/SJStFNWaJl.png) 2. 把 `xxx_to_unity` 資料夾裡面的 `xxx_description` 資料夾和 `xxx.urdf` 放進 urdf 資料夾 4. 接著(以fourWheelCar為例),對 xxx(.urdf) 點擊右鍵,選擇 `Import Robot from Selected URDF file` ![image](https://hackmd.io/_uploads/B1Hoj2D6yg.png) 4. 點擊 Import URDF (如果電腦是 arm64 系統,`Mesh Decomposer` 要選擇 `Unity`) ![image](https://hackmd.io/_uploads/Skc7h3Pp1x.png) 5. 將 `Urdf Robot (Script)` 和 `Controller (Script)` 關閉 ![image](https://hackmd.io/_uploads/rygfQhaDpJg.png) 6. 確認每個輪子的 `Articulationbody` 都是開啟的 (如果有輪子的話),且 `Anchor Rotation` 的數值都相同 ![image](https://hackmd.io/_uploads/HJ5P26D6ye.png) ## ROS2 ### 練習範例 1. 進入 wsl 3. 進入 `pros_app` 資料夾中,輸入指令來創建 `compose_my_bridge_network` ```bash python3 ./control.py -s ``` 並選擇 `rosbridge_server.sh` 對應的數字 3. 改為進入 `pros_car` 資料夾中,執行指令 ```bash ./car_control.sh ``` 4. 進入 `src` 資料夾中並創建 `myPkg` ```bash= cd src ros2 pkg create myPkg --build-type ament_python --dependencies rclpy ``` 5. 回到 `workspaces` 資料夾,並編譯 ```bash= colcon build . ./install/setup.bash ``` >[!tip] 也可以改為輸入 `r` 來編譯 6. 進入 `src/myPkg/myPkg` 中,並創建 `nodeA` 和 `nodeB` 兩個檔案 ```bash= cd src/myPkg/mypkg touch nodeA.py nodeB.py ``` 7. 進入VSCode下載remote Development 8. 於 `nodeA` 中,輸入程式 ```py= import rclpy from rclpy.node import Node from std_msgs.msg import String class MinimalPublisher(Node): def __init__(self): super().__init__('minimal_publisher') self.publisher_ = self.create_publisher(String, 'HelloTopic', 10) timer_period = 0.5 # seconds self.timer = self.create_timer(timer_period, self.timer_callback) self.i = 0 def timer_callback(self): msg = String() msg.data = 'Hello World: %d' % self.i self.publisher_.publish(msg) self.i += 1 def main(args=None): rclpy.init(args=args) minimal_publisher = MinimalPublisher() rclpy.spin(minimal_publisher) # Destroy the node explicitly # (optional - otherwise it will be done automatically # when the garbage collector destroys the node object) minimal_publisher.destroy_node() rclpy.shutdown() if __name__ == '__main__': main() ``` 並於 `nodeB` 中,輸入程式 ```py= import rclpy from rclpy.node import Node from std_msgs.msg import String class MinimalSubscriber(Node): def __init__(self): super().__init__("minimal_subscriber") self.subscription = self.create_subscription( String, "HelloTopic", self.listener_callback, 10 ) self.subscription # prevent unused variable warning def listener_callback(self, msg): self.get_logger().info('I heard: "%s"' % msg.data) def main(args=None): rclpy.init(args=args) minimal_subscriber = MinimalSubscriber() rclpy.spin(minimal_subscriber) # Destroy the node explicitly # (optional - otherwise it will be done automatically # when the garbage collector destroys the node object) minimal_subscriber.destroy_node() rclpy.shutdown() if __name__ == "__main__": main() ``` 9. 在 (`src/myPkg/`)`setup.py` 中,將 `entry_points={}` 改成 ```py= entry_points={ "console_scripts": [ "publishNode = myPkg.nodeA:main", "subscribeNode = myPkg.nodeB:main", ], }, ``` 10. 回到 workspaces 資料夾,並編譯 ```bash r ``` 11. 開啟兩個 wsl 並分別執行以下兩個指令來啟動 `nodeA` 和 `nodeB` ```bash ros2 run myPkg publishNode ``` ```bash ros2 run myPkg subscribeNode ``` 可以使用第7步的 `Remote Development` 來執行 ### Nav 1. 進入 `pros_app` 資料夾(在WSL),並執行指令 ```bash python3 ./control.py -s ``` 然後選擇 ./slam_unity.sh (應該是第2選項) ![image](https://hackmd.io/_uploads/rkjDOr-a1g.png) 2. 打開 Unity 3. 於`cd pros_car` 資料夾中,輸入 ```bash ./car_control.sh ``` 4. 用 `r` 進行編譯 ```bash r ``` 5. 執行指令來打開選單 ```bash ros2 run pros_car_py robot_control ``` 並選擇 `Control Vehicle` 來控制車輛(按enter即可) ![image](https://hackmd.io/_uploads/rJXGtBWTye.png) 6. 在 Unity 中執行檔案 ![螢幕擷取畫面 2025-03-26 171846](https://hackmd.io/_uploads/BkqCLrb6kx.png) 以下是控制車輛的指令 `w` : Forward `s` : Backward `e` : Counterclockwise `r` : Counterclock `z`: Stop `q` : Quit ### Foxglove 1. 打開 foxglove (並且註冊你的帳號) 2. 在 foxglove 中點擊左側工作欄裡面的 `Open connection..` ![image](https://hackmd.io/_uploads/r1B40gI01g.png) 3. 選擇 `Rosbridge` 後點擊 `Open` ![image](https://hackmd.io/_uploads/HyTDRg8RJx.png) 4.在display frame(展示坐標系)項目中選擇map ![uploads_1](https://hackmd.io/_uploads/SJ9Dk1vR1g.png) 5.將其中map以及scan選項打開,並將點的大小調至20(推薦)附近 6.回到操作選單並進行操作開車子繞地圖一遍(最快直接繞外圍一圈),用以掃描地圖 7.當掃描完整個地圖後,在 `pros_app` 選單中選擇 `store_map.sh` 儲存地圖 (使用`store_map.sh` 時,`slam_unity.sh` 必須也在運行中) ![uploads_2](https://hackmd.io/_uploads/Hypjl1vA1x.png) 儲存完畢後 `store_map.sh` 會顯示 `儲存成功` ### Tips * Unity中的button可以reset車子的位置 * 若foxglove的地圖掃描出現問題,可以重開slam_unity.sh 輸入d 然後重新選擇slam_unity.sh並按下Unity的button即可 8.接下來,在選單中輸入d,關閉所有運行中的容器,接著開啟localization_unity,載入剛才掃描的map ![uploads_3](https://hackmd.io/_uploads/SJ0kzywAye.png) 9.回到unity終點及button,若無法點擊則直接重新運行 10.再來要定localize方位 [影片示範](https://www.youtube.com/watch?v=kxmSMe_qW5o) 影片中藍色箭頭先點擊自身再來點擊前進方向(w方向) ![uploads_4](https://hackmd.io/_uploads/rJD971w0yx.png) 11.打開於左下角publish(發布)並將途中話題改為/goal_pose ![uploads_6](https://hackmd.io/_uploads/BJog4yP0Jg.png) 12.點擊publish 2D pose(/goal_pose) ![uploads_7](https://hackmd.io/_uploads/Bk6BVkPR1l.png) 將隨之出現的粉色箭頭點基在你想設定的目的地 ![螢幕擷取畫面 2025-04-12 025049](https://hackmd.io/_uploads/SybiEJwR1g.png) 將左方plan選項開啟,起點至終點的路徑就會被自動規劃好 ![螢幕擷取畫面 2025-04-12 025148](https://hackmd.io/_uploads/HynRNkwRJe.png) 13.切換控制面板置自動導航面板 ![螢幕擷取畫面 2025-04-12 025324](https://hackmd.io/_uploads/BkdESJPA1g.png) ![螢幕擷取畫面 2025-04-12 025301](https://hackmd.io/_uploads/SJfXB1vAyx.png) 選擇manual_auto_nav ![螢幕擷取畫面 2025-04-12 025406](https://hackmd.io/_uploads/rJtvSyDA1x.png)點擊任意鍵即可 ### Tips 如果導航方向錯誤,至unity fourwheelcar下的lidar_v1_1將rotation改成180度讓方向正確 ![螢幕擷取畫面 2025-04-12 025644](https://hackmd.io/_uploads/HJ4ZLJP0ye.png) ## UNIX 指令簡介 ### 檔案整理 > 如果你下載了一系列資源以後,試圖在 Windows Terminal 的小黑窗裡面找到他們,你可能會用到以下指令 - 顯示所在資料夾 ```bash pwd ``` - 顯示目前目錄內容 ```bash ls ``` - 進入目錄 ```bash cd [相對/絕對目錄] ``` - 建立新目錄 ```bash mkdir [欲建立的目錄名稱] ``` - 刪除空目錄 ```bash rmdir [欲刪除的目錄名稱] ``` - 建立檔案 ```bash touch [欲建立的檔案名稱] ``` - 刪除檔案 ```bash rm [欲刪除的檔案名稱] ``` - 複製檔案/目錄 ```bash cp [來源][目標] ``` - 移動檔案/目錄 ```bash mv [來源][目標] ``` ### 至於剩下沒有教的... 你可以: ```bash man [指令名稱] ``` ###### ~~man what can i say~~ 來查詢指令說明

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully