AI 개념의 시작: 움직이게 만들어요
자동차와 유사한 모델이 하나 있습니다. 수학 함수를 어떻게 사용해야 전진하고 방향을 바꿀 수 있을지를 조사하세요
탐색을 위한 질문
• 수학 함수를 사용하여 방향을 변경하려면 어떻게 해야 할까요?
준비
• 스파이크 프라임 허브가 충전되어 있는지 확인하세요(특히 블루투스로 연결되어 있는 경우).
관심유도
(그룹 토의, 5분)
운전자가 자동차를 어떻게 움직이게 하는지에 대한 대화를 통해 학생들의 관심을 불러일으켜주세요.
운전자가 자동차의 움직임을 제어하는 여러 가지 방법을 논의할 수 있도록 학생들을 이끌어주세요. 예를 들어, 자동차를 앞이나 뒤로 움직일 수도 있고, 차를 멈출 수도 있으며, 여러 가지 각도로 차의 방향을 왼쪽이나 오른쪽으로 돌릴 수도 있겠죠.
학생들에게 수업에 사용할 드라이빙 베이스 모델의 비디오를 보여주고, 어떻게 해야 자동차와 비슷하게 움직일 수 있을지 생각해보게 하세요. 훈련 캠프 1 수업의 비디오가 도움이 될 것입니다. 비디오는 다음 사이트에서 볼 수 있습니다.
https://education.lego.com/en-us/lessons/prime-competition-ready/training-camp-1-driving-around#ignite-a-discussion.
비디오의 내용에 대해 학생들과 이야기를 나눠보세요.
탐구
(소규모 그룹, 20분)
학생들에게 여러 유형의 교통수단 중에서 자동차와 유사한 모델을 한 가지 조사하게 하세요.
학생들에게 스파이크 앱의 조립 섹션을 찾아 열게 하세요. 드라이빙 베이스 모델의 조립 가이드가 제시되어 있을 것입니다. 하세요. 드라이빙 베이스 모델을 조립하게 하세요. 조립 가이드는 https://education.lego.com/en-us/support/spike-prime/building-instructions 페이지에서도 볼 수 있습니다.
학생들에게 파이썬 프로그래밍 캔버스에서 새 프로젝트를 열게 하세요. 혹시 프로그래밍 영역에 이미 코드가 들어 있다면 일단 그것부터 다 지우고, 허브를 연결하게 하세요.
학생들에게 프로그래밍을 이용해 드라이빙 베이스를 움직일 방법을 생각해보라고 하세요. 모터를 프로그래밍해서 차량이 전진, 후진 및 방향 전환을 할 수 있도록 프로그램을 작성해야 합니다. 학생들이 프로그램의 작성과 관련하여 도움을 필요로 할 경우, ‘AI 개념의 시작: 자전거 교통수단 데이터’ 수업의 샘플 프로그램을 살펴보라고 하세요. 이 프로그램에서와 마찬가지로, 학생들이 더하기(속도를 높임)와 빼기(속도를 늦춤)를 위한 방법을 프로그램에 포함시켜야 합니다.
자동차와 같은 탑승기계를 운전할 때 속도 제한을 준수해야 한다는 점을 학생들에게 상기시켜주세요. 나아가 전진 이동에 그치지 말고 일종의 속도계 삼아 모델의 허브에 드라이빙 베이스의 속도가 표시되도록 하라는 과제를 학생들에게 내려보세요.
샘플 프로그램:
from hub import port, light_matrix, button
import runloop
import motor_pair
async def main():
driving_velocity = 250
# 모터를 페어링합니다
motor_pair.pair(motor_pair.PAIR_1, port.C, port.D)
# ride 함수를 정의합니다
async def ride():
await light_matrix.write(str(driving_velocity))
await motor_pair.move_for_degrees(motor_pair.PAIR_1, 720, 0, velocity = driving_velocity)
# 전진 및 속도 설정에 관한 조건을 설정합니다
while True:
if button.pressed(button.LEFT):
driving_velocity -= 50
await ride()
await runloop.sleep_ms(3000)
elif button.pressed(button.RIGHT):
driving_velocity += 50
await ride()
await runloop.sleep_ms(3000)
runloop.run(main())
학생들에게 시간을 주고 프로그램을 살펴보게 하세요. 프로그램이 실행되는 동안 오른쪽 및/또는 왼쪽 버튼을 계속해서 누르면 어떤 일이 벌어질까요? 값이 50씩 늘거나 줄면서 드라이빙 베이스가 이동을 계속하겠죠. 허브의 속도 표시가 매번 어떻게 새로 바뀌는지 관찰해보세요.
이동하기
자동차가 직선으로만 달리는 경우는 사실 그리 많지 않습니다. 그러니 방향을 바꾸면서 이동하는 것이 가능하도록 프로그램을 수정해야겠죠. 수학 함수를 사용하여 회전 방법을 설정하는 것이 바람직한 방법이라는 것을 학생들에게 알려주세요.
샘플 프로그램:
from hub import port, light_matrix, button
import runloop
import motor_pair
import motor
async def main():
# 초기 주행 속도를 정의합니다
driving_velocity = 250
# 선회 거리를 정의합니다
turning_left = -360
turning_right = 360
# 모터를 페어링합니다
motor_pair.pair(motor_pair.PAIR_1, port.C, port.D)
# ride 및 turn 함수를 정의합니다
async def ride():
await light_matrix.write(str(driving_velocity))
await motor_pair.move_for_degrees(motor_pair.PAIR_1, 720, 0, velocity = driving_velocity)
async def turn_left():
await light_matrix.write(str(turning_left/4))
await motor.run_for_degrees(port.C, turning_left, 250)
async def turn_right():
await light_matrix.write(str(turning_right/4))
await motor.run_for_degrees(port.D, turning_right, 250)
# 전진 및 속도 설정에 관한 조건을 설정합니다
while True:
await ride()
if button.pressed(button.LEFT):
driving_velocity -= 50
turning_left -= 360
await turn_left()
await runloop.sleep_ms(3000)
elif button.pressed(button.RIGHT):
driving_velocity += 50
turning_right += 360
await turn_right()
await runloop.sleep_ms(3000)
runloop.run(main())
설명
(그룹 전체, 5분)
프로그램이 어떻게 작동했는지에 대해 학생들과 이야기를 나눠보세요. 이런 질문을 던져보세요.
• 프로그램에서 속도 값을 계속 더하거나 빼는 것을 허용하는 이유가 뭘까요?
• 어떻게 하였기에 선회하거나 방향을 바꾸면서 이동하는 동작이 포함되도록 프로그램을 수정할 수 있었나요?
• 버튼을 누르지 않았는데도 드라이브 베이스가 계속 이동했던 이유가 무엇일까요?
선회 값을 표시함에 있어 수학 함수를 이용해 바퀴 회전의 실제 각도를 드라이빙 베이스의 선회 값으로 변환한다는 점에 주목하세요. 즉, 한 개의 모터가 360도 회전한다는 것은 바퀴가 온전하게 한 바퀴를 회전함을 뜻하며, 이로 인해 드라이빙 베이스가 90도 선회합니다. 수학 계산을 사용하면 360/n=90의 답을 쉽게 구할 수 있으며, 이번 예제의 경우는 n=4입니다. 프로그램을 읽어보세요. light_matrix.write(str(turning_left/4))와 light_matrix.write(str(turning_right/4)) 행에 이 수학 함수가 사용되었죠?
다듬기
(소규모 그룹, 10분)
학생들에게 프로그램의 버그를 찾아보라고 하세요.
학생들에게 아래의 프로그램과 오류 메시지를 보여주고, 버그를 수정하거나 누락된 코드를 보완하기 위해 각각의 코드에서 무얼 바꿔야 할지를 논의하게 하세요. 학생들이 각자 프로그램에 입력을 하든 학급 전체가 함께 검토를 하든 큰 상관은 없으나, 가급적이면 학급 전원이 함께 수정하고 변경을 마칠 때마다 프로그램이 올바르게 실행되는지 확인하도록 하세요.
디버그 활동 1:
프로그램에서 오류를 찾아내세요. 프로그램을 실행하고 프로그램의 해당 부분을 읽어서 뭔가 작동을 하기 전까지는 오류가 눈에 띄지 않을 수도 있다는 점을 학생들에게 상기시켜주시고요.
from hub import port, light_matrix, button
import runloop
import motor_pair
async def main():
driving_velocity = 250
# 모터를 페어링합니다
motor_pair.pair(motor_pair.PAIR_1, port.C, port.D)
# ride 함수를 정의합니다
async def ride():
await light_matrix.write(str(driving_velocity))
await motor_pair.move_for_degrees(motor_pair.PAIR_1, 0, velocity = driving_velocity)
# 전진 및 속도 설정에 관한 조건을 설정합니다
while True:
if button.pressed(button.LEFT):
driving_velocity -= 50
await ride()
await runloop.sleep_ms(3000)
elif button.pressed(button.RIGHT):
driving_velocity += 50
await ride()
await runloop.sleep_ms(3000)
runloop.run(main())
Error Message:
Traceback (most recent call last):
File "drive base 1", line 27, in <module>
File "drive base 1", line 19, in main
File "drive base 1", line 13, in ride
TypeError: function missing 1 required positional arguments
오류 메시지는 잘못된 여러 개의 행을 모두 참조하여 보여주며, 실제로 오류가 포함된 바로 그 하나의 행을 짚어주지는 않습니다. 13번째 행을 보세요. 드라이빙 베이스가 얼마나 전진 이동해야 하는지 알려주는 각도 값이 빠져 있죠? 따라서 이 코드 행을 await motor_pair.move_for_degrees(motor_pair.PAIR_1, 720, 0, velocity = driving_velocity)로 바꿔주어야 합니다.
디버그 활동 2:
프로그램에서 오류를 찾아내세요. 프로그램을 실행하고 프로그램의 해당 부분을 읽어서 뭔가 작동을 하기 전까지는 오류가 눈에 띄지 않을 수도 있다는 점을 학생들에게 상기시켜주시고요.
from hub import port, light_matrix, button
import runloop
import motor_pair
driving_velocity = 250
async def main():
# 모터를 페어링합니다
motor_pair.pair(motor_pair.PAIR_1, port.C, port.D)
# ride 함수를 정의합니다
async def ride():
await light_matrix.write(str(driving_velocity))
await motor_pair.move_for_degrees(motor_pair.PAIR_1, 720, 0, velocity = driving_velocity)
# 전진 및 속도 설정에 관한 조건을 설정합니다
while True:
if button.pressed(button.LEFT):
driving_velocity -= 50
await ride()
await runloop.sleep_ms(3000)
elif button.pressed(button.RIGHT):
driving_velocity += 50
await ride()
await runloop.sleep_ms(3000)
runloop.run(main())
Error Message:
Traceback (most recent call last):
File "drive base 1", line 29, in <module>
File "drive base 1", line 25, in main
NameError: local variable referenced before assignment
보시다시피, 뭐든 버튼을 하나 누르기 전에는 오류 메시지가 나타나지 않죠. 학생들이 20번째 행에 오류가 있다는 것을 알아차릴 수 있어야 합니다. 이 오류 메시지는 지역 변수가 할당되기도 전에 참조된다는 것을 말해줍니다. 프로그램의 오타 때문에 프로그램이 잘못된 위치에 설정된 변수를 참조하려다 보니 이렇게 된 것이죠. 이 변수는 main 함수에서 정의되어야 합니다.
평가
(그룹 실습, 5분)
교사 관찰:
학생들과 프로그램에 대해 토의를 진행하세요.
이런 질문을 던져보세요.
• 수학 함수를 어떻게 이용하여 드라이빙 베이스가 직선 또는 선회 이동하는 방식을 변경할 수 있었나요?
• 복잡한 프로그램을 작성하는 중에 어떤 오류가 발생할 수 있을까요? 이러한 오류를 디버깅하기 위한 전략으로 어떤 것들이 있을까요?
• 하나의 모터 대신 드라이빙 베이스를 사용하여 선회를 일으킬 방법이 있을까요?
자기 평가:
학생들에게 다음 질문에 대한 답을 기록장에 적으라고 하세요.
• 오늘 프로그램에 여러 개의 수학 함수를 사용하는 방법에 대해 무엇을 배웠는가?
• 좋은 팀원의 특성은 무엇이며, 오늘 내가 그중 몇 가지를 보여주었는가?
• 학생들에게 오늘의 시간 관리에 대해 1-3점 척도로 자기 평가를 해보라고 하세요.
• 학생들에게 오늘의 재료(부품) 관리에 대해 1-3점 척도로 자기 평가를 해보라고 하세요.
교사 지원
학생 과제:
• 전진하고 방향을 바꾸도록 드라이빙 베이스를 프로그래밍합니다
• 수학 함수를 이용해 프로그램을 작성합니다
• 학생이 즉각 사용 가능한 상태의 스파이크 프라임 세트
• 스파이크 앱이 설치된 장치
• 학생용 기록장
CSTA
2-CS-02 Design projects that combine hardware and software components to collect and exchange data.
2-AP-10 Use flowcharts and/or pseudocode to address complex problems as algorithms
2-AP-13 Decompose problems and subproblems into parts to facilitate the design, implementation, and review of programs.
2-AP-16 Incorporate existing code, media, and libraries into original programs, and give attribution.
2-AP-17 Systematically test and refine programs using a range of test cases.
2-AP-19 Document programs in order to make them easier to follow, test, and debug.