cd2025 協同產品設計實習

  • Home
    • SMap
    • reveal
    • blog
  • About
    • Summary
      • Tasks
      • Closing
      • Shooter
    • Product
    • Control
    • CPS
    • AI
    • Project
  • Topics
    • Wink
      • Fossil
    • Topic1
      • w1
      • Portable
      • repo
      • SSH
      • list
      • IPv6
    • Topic2
      • Compile
      • Onshape
    • Topic3
      • Fourbar2
      • boomer
    • Topic4
      • ROS2
  • HW
    • HW1
    • HW2
    • HW3
  • Exam
    • Exam1
    • Exam2
    • Exam3
  • Final
    • Webots
    • Rotate
  • Tutorial
    • Fourbar
      • w10
    • Stage1
      • Tutorial1
      • Tutorial2
    • Stage2
      • Tutorial3
      • Distancesensor
      • Tutorial4
      • Tutorial5
    • Stage3
      • Tutorial6
      • Tutorial7
      • Stream
      • Webots Server
    • Solvespace
      • Learn_Solvs
    • Mecanum
    • Pyslvs-UI
    • PICSimLab
    • Fossil SCM
    • Leo Editor
    • uv
    • Old
  • Brython
Exam3 << Previous Next >> Webots

Final

Final Report (30%) - 利用網頁內容進行簡報並提交 pdf 格式書面報告, 完成後填回自評表單

參考資料:

cd2025_final_project_w16.7z

three_digit_counter_w16.7z

cd2025_final_project_w17.7z

cd2025_w17_rotate_angle.7z (按下 a 旋轉 -30 deg, 按下 z 旋轉 30 deg)

cd2025_w17_move_and_face.7z (按下 m 先轉向 (3, 3), 前進至 (3, 3) 後面向 (0, 0))

cd2025_w18_move_and_face.7z (按下 j 或 k 可側向移動)  

手動投球:

w17.wbt

自動投球:

w17_auto_loop.wbt

counter_supervisor.py

from controller import Supervisor

SEGMENTS = [
    [1,1,1,1,1,1,0], # 0
    [0,1,1,0,0,0,0], # 1
    [1,1,0,1,1,0,1], # 2
    [1,1,1,1,0,0,1], # 3
    [0,1,1,0,0,1,1], # 4
    [1,0,1,1,0,1,1], # 5
    [1,0,1,1,1,1,1], # 6
    [1,1,1,0,0,0,0], # 7
    [1,1,1,1,1,1,1], # 8
    [1,1,1,1,0,1,1], # 9
]
DIGIT_MATERIALS = [
    ['a3mat', 'b3mat', 'c3mat', 'd3mat', 'e3mat', 'f3mat', 'g3mat'], # 百
    ['a2mat', 'b2mat', 'c2mat', 'd2mat', 'e2mat', 'f2mat', 'g2mat'], # 十
    ['a1mat', 'b1mat', 'c1mat', 'd1mat', 'e1mat', 'f1mat', 'g1mat'], # 個
]
ON_COLOR = [0, 1, 0]
OFF_COLOR = [0.05, 0.05, 0.05]

def set_digit(supervisor, digit_index, value):
    segs = SEGMENTS[value]
    for i, seg_on in enumerate(segs):
        mat_node = supervisor.getFromDef(DIGIT_MATERIALS[digit_index][i])
        if mat_node:
            mat_node.getField('diffuseColor').setSFColor(ON_COLOR if seg_on else OFF_COLOR)
        else:
            print(f"找不到 {DIGIT_MATERIALS[digit_index][i]} 這個DEF")

def set_display(supervisor, value):
    value = max(0, min(999, int(value)))
    h = value // 100
    t = (value // 10) % 10
    u = value % 10
    set_digit(supervisor, 0, h)
    set_digit(supervisor, 1, t)
    set_digit(supervisor, 2, u)

supervisor = Supervisor()
timestep = int(supervisor.getBasicTimeStep())

score = 0
receiver = supervisor.getDevice("score_receiver")
receiver.enable(timestep)

while supervisor.step(timestep) != -1:
    while receiver.getQueueLength() > 0:
        data = receiver.getString()
        # 目前 data 接受值包含字串(元) a, m, k 與數字received_score
        # 只有接收到數字時才進行得分累加
        if data.isdigit():
            try:
                received_score = int(data)
                score += received_score
                print(f"收到得分訊息: +{received_score}, 總分: {score}")
            except Exception as e:
                print("訊息格式錯誤:", e)
        receiver.nextPacket()
    set_display(supervisor, score)

Robot 與 Supervisor 節點的結合應用: basketball_game_w13.7z 中的 basketball_game.wbt 啟動後直接觸動投籃動作, 並在籃球通過籃框感測器時列出 "得分".

send_command_from_emitter.wbt 啟動後, 由 supervisor 操縱的下列程式送出指令訊號, 交由場景中的 Robot 主體執行:

send_command_from_emitter.py:

from controller import Supervisor

def run_supervisor():
    # Create the Supervisor instance
    supervisor = Supervisor()

    # Get simulation time step
    timestep = int(supervisor.getBasicTimeStep())

    # Get the emitter for sending commands
    emitter = supervisor.getDevice("emitter")  # Ensure the emitter is defined in your world file
    if emitter is None:
        print("Error: Could not find emitter device")
        return

    # Main control loop
    while supervisor.step(timestep) != -1:

        # Send motor position command to the robot
        motor_position = 38 * 3.14159 / 180  # Motor position in radians
        message = f"SET_POSITION:{motor_position}"  # Construct the command message
        emitter.send(message.encode("utf-8"))  # Send the message via the emitter

if __name__ == "__main__":
    run_supervisor()

robot_controller.py 中的接收命令程式:

from controller import Robot, Receiver

def run_robot():
    # Create the Robot instance
    robot = Robot()

    # Get simulation time step
    timestep = int(robot.getBasicTimeStep())

    # Get the motor device
    motor = robot.getDevice("motor1")  # Replace "motor1" with the actual motor name
    if motor is None:
        print("Error: Could not find motor device")
        return

    # Get the receiver for receiving commands
    receiver = robot.getDevice("receiver")  # Ensure the receiver is defined in your world file
    if receiver is None:
        print("Error: Could not find receiver device")
        return
    receiver.enable(timestep)

    # Main control loop
    while robot.step(timestep) != -1:
        # Process received messages
        if receiver.getQueueLength() > 0:
            message = receiver.getString() # Receive the message
            receiver.nextPacket()  # Move to the next packet

            # Parse the command message
            if message.startswith("SET_POSITION:"):
                position = float(message.split(":")[1])  # Extract the desired position
                motor.setPosition(position)  # Set the motor position

if __name__ == "__main__":
    run_robot()

此一作法可以利用 supervisor 統整發球機制與投球機構的作動, 例如: 在發球機構啟動之前, 利用 supervisor 模式讓籃球停球在特定位置, 用來控制球拍打後的運動距離.

一旦確定投球機構與球的起始位置之間關係後, 再調整投球機構的持球零件外型設計.

另外, basketball_game_w13_supervisor.wbt 的設計方法, 則僅利用 supervisor 模式負責發球, 之後的擊球機構則完全由 Robot 的 controller 程式控制, 除了啟動場景模擬後的第一次擊球由程式直接控制外, 之後使用者按下 m 鍵機構會回復原始位置, 按下 k 鍵則觸動轉動特定轉角, 按下 a 鍵則由 supervisor 控制程式在特定位置發球.


Exam3 << Previous Next >> Webots

Copyright © All rights reserved | This template is made with by Colorlib