345 lines
22 KiB
PL/PgSQL
345 lines
22 KiB
PL/PgSQL
-- Rebuild the shared base course as a two-week NAV2 curriculum.
|
|
-- Target: courses.slug = 'futuredrive-autonomy-basic'
|
|
|
|
BEGIN;
|
|
|
|
CREATE TEMP TABLE target_course AS
|
|
SELECT id
|
|
FROM courses
|
|
WHERE slug = 'futuredrive-autonomy-basic';
|
|
|
|
DO $$
|
|
BEGIN
|
|
IF (SELECT count(*) FROM target_course) <> 1 THEN
|
|
RAISE EXCEPTION 'Expected exactly one futuredrive-autonomy-basic course';
|
|
END IF;
|
|
END $$;
|
|
|
|
-- Existing module IDs are replaced, so their student repository/score rows cascade.
|
|
DELETE FROM course_student_week_progress
|
|
WHERE course_id IN (SELECT id FROM target_course);
|
|
|
|
DELETE FROM instructor_curriculum_week_overrides
|
|
WHERE course_id IN (SELECT id FROM target_course);
|
|
|
|
DELETE FROM course_environment_profiles
|
|
WHERE course_id IN (SELECT id FROM target_course);
|
|
|
|
DELETE FROM course_week_maps
|
|
WHERE course_id IN (SELECT id FROM target_course);
|
|
|
|
DELETE FROM course_week_modules
|
|
WHERE week_id IN (SELECT id FROM course_weeks WHERE course_id IN (SELECT id FROM target_course));
|
|
|
|
DELETE FROM course_week_topics
|
|
WHERE week_id IN (SELECT id FROM course_weeks WHERE course_id IN (SELECT id FROM target_course));
|
|
|
|
DELETE FROM course_week_practices
|
|
WHERE week_id IN (SELECT id FROM course_weeks WHERE course_id IN (SELECT id FROM target_course));
|
|
|
|
DELETE FROM course_week_references
|
|
WHERE week_id IN (SELECT id FROM course_weeks WHERE course_id IN (SELECT id FROM target_course));
|
|
|
|
DELETE FROM course_weeks
|
|
WHERE course_id IN (SELECT id FROM target_course)
|
|
AND week > 2;
|
|
|
|
UPDATE courses
|
|
SET
|
|
title = 'NAV2 기반 자율주행 교육 과정',
|
|
subtitle = 'ROS2, 시뮬레이션, SLAM부터 경로 계획과 제어까지',
|
|
description = 'ROS2와 NAV2 기반 시뮬레이션 및 플랫폼 실습을 통해 자율주행 시스템의 핵심 흐름을 학습하고 팀 프로젝트로 검증합니다.'
|
|
WHERE id IN (SELECT id FROM target_course);
|
|
|
|
UPDATE course_weeks
|
|
SET
|
|
title = 'ROS2 & Simulation',
|
|
tags = ARRAY['MK-mini', '진행중'],
|
|
progress = 0,
|
|
state = 'current',
|
|
duration = '1주',
|
|
github = 'https://github.com/ros-navigation/navigation2',
|
|
overview = 'ROS2 통신 구조와 Gazebo 시뮬레이션 환경을 구성하고, LiDAR SLAM·위치추정·경로 계획·제어까지 NAV2 자율주행 파이프라인을 실습합니다.',
|
|
deliverable = 'NAV2 모듈 소스 변경 내역, SLAM 결과 맵, 목표 지점 주행 검증 화면 및 실행 로그를 제출합니다.',
|
|
requires_source_submission = true
|
|
WHERE course_id IN (SELECT id FROM target_course) AND week = 1;
|
|
|
|
UPDATE course_weeks
|
|
SET
|
|
title = 'Autonomy Studio 팀 프로젝트',
|
|
tags = ARRAY['MK-mini', '진행예정'],
|
|
progress = 0,
|
|
state = 'locked',
|
|
duration = '1주',
|
|
github = 'https://github.com/ros-navigation/navigation2',
|
|
overview = '3~4인 팀으로 자율주행 알고리즘이 필요한 문제 상황을 정의하고, 센서 구성과 NAV2 모듈을 조합해 시뮬레이션과 플랫폼에서 검증합니다.',
|
|
deliverable = '팀 프로젝트 소스, 시스템 구성도, 시뮬레이션 및 플랫폼 주행 검증 결과, 발표 자료를 제출합니다.',
|
|
requires_source_submission = true
|
|
WHERE course_id IN (SELECT id FROM target_course) AND week = 2;
|
|
|
|
INSERT INTO course_weeks (course_id, week, title, tags, progress, state, duration, github, overview, deliverable, requires_source_submission)
|
|
SELECT id, 1, 'ROS2 & Simulation', ARRAY['MK-mini', '진행중'], 0, 'current', '1주',
|
|
'https://github.com/ros-navigation/navigation2',
|
|
'ROS2 통신 구조와 Gazebo 시뮬레이션 환경을 구성하고, LiDAR SLAM·위치추정·경로 계획·제어까지 NAV2 자율주행 파이프라인을 실습합니다.',
|
|
'NAV2 모듈 소스 변경 내역, SLAM 결과 맵, 목표 지점 주행 검증 화면 및 실행 로그를 제출합니다.', true
|
|
FROM target_course
|
|
WHERE NOT EXISTS (SELECT 1 FROM course_weeks WHERE course_id = target_course.id AND week = 1);
|
|
|
|
INSERT INTO course_weeks (course_id, week, title, tags, progress, state, duration, github, overview, deliverable, requires_source_submission)
|
|
SELECT id, 2, 'Autonomy Studio 팀 프로젝트', ARRAY['MK-mini', '진행예정'], 0, 'locked', '1주',
|
|
'https://github.com/ros-navigation/navigation2',
|
|
'3~4인 팀으로 자율주행 알고리즘이 필요한 문제 상황을 정의하고, 센서 구성과 NAV2 모듈을 조합해 시뮬레이션과 플랫폼에서 검증합니다.',
|
|
'팀 프로젝트 소스, 시스템 구성도, 시뮬레이션 및 플랫폼 주행 검증 결과, 발표 자료를 제출합니다.', true
|
|
FROM target_course
|
|
WHERE NOT EXISTS (SELECT 1 FROM course_weeks WHERE course_id = target_course.id AND week = 2);
|
|
|
|
INSERT INTO course_week_topics (week_id, title, detail, sort_order)
|
|
SELECT w.id, topic.title, topic.detail, topic.sort_order
|
|
FROM course_weeks w
|
|
CROSS JOIN (
|
|
VALUES
|
|
(1, 'ROS2 기초', 'ROS Topic, Service, Action 통신과 TF 정의, ROS2 패키지 및 tree 구조를 실습합니다.'),
|
|
(2, 'Sensor Processing', 'LiDAR와 카메라 등 센서 데이터 처리 흐름과 Calibration 기초를 확인합니다.'),
|
|
(3, 'Simulation 환경 구축 Part 1', 'Gazebo 월드, 로봇 모델, 센서 토픽을 구성해 시뮬레이션 실습 환경을 만듭니다.'),
|
|
(4, 'Simulation 환경 구축 Part 2', '시뮬레이션에서 활용할 수 있는 모빌리티 플랫폼과 실행 모듈 구성을 점검합니다.'),
|
|
(5, 'LiDAR SLAM', '센서 데이터와 SLAM 알고리즘을 활용해 자율주행용 2D Map을 구축합니다.'),
|
|
(6, 'LiDAR Localization', '구축한 Map과 실시간 LiDAR 데이터를 이용해 현재 위치를 추정합니다.'),
|
|
(7, 'Parameter Tuning', '모듈 파라미터를 변경하고 결과를 비교해 알고리즘을 튜닝합니다.'),
|
|
(8, '[심화] Camera based SLAM', '카메라 기반 Map 구축과 위치인식의 입력·출력 구조를 분석합니다.'),
|
|
(9, 'Occupancy Map', '장애물 인식을 위한 Occupancy Map과 costmap 반영 과정을 실습합니다.'),
|
|
(10, 'Planning', '장애물 충돌 없이 목표 지점으로 이동하기 위한 전역·지역 경로 계획을 실습합니다.'),
|
|
(11, 'Control', '생성한 경로를 추종하도록 속도 명령을 만들고 주행 결과를 검증합니다.'),
|
|
(12, '[심화] 딥러닝 기반 객체 인식', '딥러닝 기반 객체 인식 결과를 자율주행 데이터 흐름에 반영하는 방법을 학습합니다.')
|
|
) AS topic(sort_order, title, detail)
|
|
WHERE w.course_id IN (SELECT id FROM target_course) AND w.week = 1;
|
|
|
|
INSERT INTO course_week_topics (week_id, title, detail, sort_order)
|
|
SELECT w.id, topic.title, topic.detail, topic.sort_order
|
|
FROM course_weeks w
|
|
CROSS JOIN (
|
|
VALUES
|
|
(1, '프로젝트 주제와 역할 분담', '팀별 자율주행 문제 상황과 목표, 역할, 검증 기준을 정의합니다.'),
|
|
(2, '센서·모듈 구성 설계', '센서 입력과 NAV2 모듈 조합, ROS 토픽 및 실행 순서를 설계합니다.'),
|
|
(3, '알고리즘 구현과 튜닝', 'SLAM, Localization, Planning, Control 파라미터를 수정하고 성능을 비교합니다.'),
|
|
(4, '시뮬레이션·플랫폼 검증', 'Gazebo 시뮬레이션과 실제 플랫폼에서 주행 시나리오를 검증합니다.'),
|
|
(5, '결과 제출과 발표', '소스, 실행 로그, 검증 결과를 정리해 팀 프로젝트 결과를 제출하고 발표합니다.')
|
|
) AS topic(sort_order, title, detail)
|
|
WHERE w.course_id IN (SELECT id FROM target_course) AND w.week = 2;
|
|
|
|
INSERT INTO course_week_practices (week_id, title, description, sort_order)
|
|
SELECT w.id, practice.title, practice.description, practice.sort_order
|
|
FROM course_weeks w
|
|
CROSS JOIN (
|
|
VALUES
|
|
(1, 'ROS2와 Gazebo 실행 환경', 'Topic, Service, Action, TF를 확인하고 TurtleBot3 Gazebo 환경을 실행합니다.'),
|
|
(2, 'LiDAR SLAM과 Localization', '맵을 생성·저장하고 저장된 맵에서 AMCL 기반 위치추정을 검증합니다.'),
|
|
(3, '경로 계획과 제어', '목표 지점을 설정하고 장애물 회피, 경로 계획, 제어 명령을 비교합니다.')
|
|
) AS practice(sort_order, title, description)
|
|
WHERE w.course_id IN (SELECT id FROM target_course) AND w.week = 1;
|
|
|
|
INSERT INTO course_week_practices (week_id, title, description, sort_order)
|
|
SELECT w.id, practice.title, practice.description, practice.sort_order
|
|
FROM course_weeks w
|
|
CROSS JOIN (
|
|
VALUES
|
|
(1, '팀 자율주행 시나리오 구현', '팀별 시나리오에 맞춰 NAV2 모듈을 구성하고 소스를 수정합니다.'),
|
|
(2, '통합 주행 검증', '시뮬레이션과 플랫폼에서 재현 가능한 주행 결과를 확보합니다.')
|
|
) AS practice(sort_order, title, description)
|
|
WHERE w.course_id IN (SELECT id FROM target_course) AND w.week = 2;
|
|
|
|
WITH module_definitions(category, name, folder_name, template_repository_url, prebuilt_artifacts, default_parameters, docker_image) AS (
|
|
VALUES
|
|
('Simulator', 'NAV2-Gazebo', '[lms-nav2-gazebo-simulator]nav2-simulator_v1.0.0_ws', 'http://localhost:3000/templates/lms-nav2-gazebo-simulator.git',
|
|
jsonb_build_array(jsonb_build_object('url', 'https://pub-ca72c40797144462bdb7d200c215d361.r2.dev/studio-artifacts/modules/lms-nav2-gazebo-simulator/1.0.0/prebuilt/latest/lms-nav2-gazebo-simulator-build-install.tar.zst', 'type', 'build-install', 'fileName', 'lms-nav2-gazebo-simulator-build-install.tar.zst', 'checksumSha256', 'e30919d278a71159dd72be20a78af7671ab7642cb331ccef757ed25e7a9c723b', 'architecture', 'amd64', 'required', false, 'extractPath', '.')), jsonb_build_array('gui:=false'), 'future-nav2-gazebo:humble'),
|
|
('Vehicle', 'NAV2-TurtleBot3Burger', '[lms-nav2-gazebo-vehicle]nav2-vehicle_v1.0.0_ws', 'http://localhost:3000/templates/lms-nav2-gazebo-vehicle.git',
|
|
jsonb_build_array(jsonb_build_object('url', 'https://pub-ca72c40797144462bdb7d200c215d361.r2.dev/studio-artifacts/modules/lms-nav2-gazebo-vehicle/1.0.0/prebuilt/latest/lms-nav2-gazebo-vehicle-build-install.tar.zst', 'type', 'build-install', 'fileName', 'lms-nav2-gazebo-vehicle-build-install.tar.zst', 'checksumSha256', '42e8179172c178978e5ae5d48e189164f6b8a5030fdaa0eba497ca86a97e96bb', 'architecture', 'amd64', 'required', false, 'extractPath', '.')), jsonb_build_array('sim_mode:=true', 'platform:=turtlebot3', 'level:=2d'), 'future-nav2-gazebo:humble'),
|
|
('Map', 'NAV2-Map', '[lms-nav2-gazebo-map]nav2-map_v1.0.0_ws', 'http://localhost:3000/templates/lms-nav2-gazebo-map.git',
|
|
jsonb_build_array(jsonb_build_object('url', 'https://pub-ca72c40797144462bdb7d200c215d361.r2.dev/studio-artifacts/modules/lms-nav2-gazebo-map/1.0.0/prebuilt/latest/lms-nav2-gazebo-map-build-install.tar.zst', 'type', 'build-install', 'fileName', 'lms-nav2-gazebo-map-build-install.tar.zst', 'checksumSha256', 'f409ce54c40aeeed8cf3fc06251c2e321887b3ec5f5827dfb74897a62780582f', 'architecture', 'amd64', 'required', false, 'extractPath', '.')), '[]'::jsonb, 'future-nav2-gazebo:humble'),
|
|
('Localization', 'NAV2-SLAM', '[lms-nav2-gazebo-slam]nav2-slam_v1.0.0_ws', 'http://localhost:3000/templates/lms-nav2-gazebo-slam.git',
|
|
jsonb_build_array(jsonb_build_object('url', 'https://pub-ca72c40797144462bdb7d200c215d361.r2.dev/studio-artifacts/modules/lms-nav2-gazebo-slam/1.0.0/prebuilt/latest/lms-nav2-gazebo-slam-build-install.tar.zst', 'type', 'build-install', 'fileName', 'lms-nav2-gazebo-slam-build-install.tar.zst', 'checksumSha256', '186f2aa926eb41140b2783507b521083536aee3be716cf55c591a32250ec0fce', 'architecture', 'amd64', 'required', false, 'extractPath', '.')), '[]'::jsonb, 'future-nav2-gazebo:humble'),
|
|
('Localization', 'NAV2-Localization', '[lms-nav2-gazebo-localization]nav2-localization_v1.0.0_ws', 'http://localhost:3000/templates/lms-nav2-gazebo-localization.git',
|
|
jsonb_build_array(jsonb_build_object('url', 'https://pub-ca72c40797144462bdb7d200c215d361.r2.dev/studio-artifacts/modules/lms-nav2-gazebo-localization/1.0.0/prebuilt/latest/lms-nav2-gazebo-localization-build-install.tar.zst', 'type', 'build-install', 'fileName', 'lms-nav2-gazebo-localization-build-install.tar.zst', 'checksumSha256', '44c8d50205f001a196870d03f44d435582b96c51eb4445e50cc8db6203b2c0c9', 'architecture', 'amd64', 'required', false, 'extractPath', '.')), jsonb_build_array('localization_mode:=amcl'), 'future-nav2-gazebo:humble'),
|
|
('Perception', 'NAV2-Perception', '[lms-nav2-gazebo-perception]nav2-perception_v1.0.0_ws', 'http://localhost:3000/templates/lms-nav2-gazebo-perception.git',
|
|
jsonb_build_array(jsonb_build_object('url', 'https://pub-ca72c40797144462bdb7d200c215d361.r2.dev/studio-artifacts/modules/lms-nav2-gazebo-perception/1.0.0/prebuilt/latest/lms-nav2-gazebo-perception-build-install.tar.zst', 'type', 'build-install', 'fileName', 'lms-nav2-gazebo-perception-build-install.tar.zst', 'checksumSha256', '23c6523d98506caee9e982741c1c806f9f58581aba777af58eadc7cd5fca1432', 'architecture', 'amd64', 'required', false, 'extractPath', '.')), jsonb_build_array('sim_mode:=true'), 'future-nav2-gazebo:humble'),
|
|
('Planning', 'NAV2-Planning', '[lms-nav2-gazebo-planning]nav2-planning_v1.0.0_ws', 'http://localhost:3000/templates/lms-nav2-gazebo-planning.git',
|
|
jsonb_build_array(jsonb_build_object('url', 'https://pub-ca72c40797144462bdb7d200c215d361.r2.dev/studio-artifacts/modules/lms-nav2-gazebo-planning/1.0.0/prebuilt/latest/lms-nav2-gazebo-planning-build-install.tar.zst', 'type', 'build-install', 'fileName', 'lms-nav2-gazebo-planning-build-install.tar.zst', 'checksumSha256', 'e00bf99178e610ba6c70ef1e2fb8150082d3f74f557a89177a6a93a183f761ef', 'architecture', 'amd64', 'required', false, 'extractPath', '.')), '[]'::jsonb, 'future-nav2-gazebo:humble'),
|
|
('Control', 'NAV2-Control', '[lms-nav2-gazebo-control]nav2-control_v1.0.0_ws', 'http://localhost:3000/templates/lms-nav2-gazebo-control.git',
|
|
jsonb_build_array(jsonb_build_object('url', 'https://pub-ca72c40797144462bdb7d200c215d361.r2.dev/studio-artifacts/modules/lms-nav2-gazebo-control/1.0.0/prebuilt/latest/lms-nav2-gazebo-control-build-install.tar.zst', 'type', 'build-install', 'fileName', 'lms-nav2-gazebo-control-build-install.tar.zst', 'checksumSha256', 'd8d17e333c67c8b27864428d12befbfbd2bfc1a4ab84f8cb17bbe6ba5b9401fe', 'architecture', 'amd64', 'required', false, 'extractPath', '.')), jsonb_build_array('sim_mode:=true', 'robot:=turtlebot3'), 'future-nav2-gazebo:humble'),
|
|
('Vehicle', 'NAV2-MKMini', '[lms-nav2-mkmini]nav2-mkmini_v1.0.0_ws', 'http://localhost:3000/templates/lms-nav2-mkmini.git',
|
|
jsonb_build_array(jsonb_build_object('url', 'https://pub-ca72c40797144462bdb7d200c215d361.r2.dev/studio-artifacts/modules/lms-nav2-mkmini/1.0.0/prebuilt/amd64/lms-nav2-mkmini-build-install-amd64.tar.zst', 'type', 'build-install', 'fileName', 'lms-nav2-mkmini-build-install-amd64.tar.zst', 'checksumSha256', '6094d2aa5188a28153452aec08e28870984b36c1bc0c06fec8091901f6d26856', 'architecture', 'amd64', 'required', false, 'extractPath', '.')), jsonb_build_array('sim_mode:=false', 'platform:=mkmini', 'level:=2d'), 'future-nav2:humble-jetson_orin')
|
|
)
|
|
INSERT INTO course_week_modules (week_id, sort_order, category, name, folder_name, template_repository_url, source_type, prebuilt_artifacts, default_parameters, docker_image)
|
|
SELECT w.id, row_number() OVER (PARTITION BY w.id ORDER BY module_definitions.folder_name), category, name, folder_name, template_repository_url, 'GIT', prebuilt_artifacts, default_parameters, docker_image
|
|
FROM course_weeks w
|
|
CROSS JOIN module_definitions
|
|
WHERE w.course_id IN (SELECT id FROM target_course) AND w.week IN (1, 2);
|
|
|
|
INSERT INTO course_environment_profiles (course_id, week, platform_key, profile_type, name, config, enabled, created_at, updated_at)
|
|
SELECT target_course.id, weeks.week, environment.platform_key, environment.profile_type,
|
|
environment.name, environment.config, true, now(), now()
|
|
FROM target_course
|
|
CROSS JOIN (VALUES (1), (2)) AS weeks(week)
|
|
CROSS JOIN (
|
|
VALUES
|
|
(
|
|
'NAV2',
|
|
'NAV2',
|
|
'로컬',
|
|
jsonb_build_object(
|
|
'type', 'NAV2',
|
|
'target', 'local',
|
|
'viewer', jsonb_build_object('stack', 'nav2'),
|
|
'bridge', jsonb_build_object(
|
|
'name', 'nav2-ros-bridge',
|
|
'port', 8765,
|
|
'image', 'slam-ros-bridge:latest',
|
|
'env', jsonb_build_object('ROBOT_STACK', 'nav2')
|
|
),
|
|
'runtimeImages', jsonb_build_array(jsonb_build_object(
|
|
'url', 'https://pub-ca72c40797144462bdb7d200c215d361.r2.dev/studio-artifacts/runtime-images/nav2/gazebo/latest/future-nav2-gazebo-humble.tar.zst',
|
|
'image', 'future-nav2-gazebo:humble',
|
|
'fileName', 'future-nav2-gazebo-humble.tar.zst',
|
|
'required', true,
|
|
'checksumSha256', '54230e039c1fa5dc82615cef3828c5acae7b8bea8e921b70cfdc5351d8301644'
|
|
))
|
|
)
|
|
),
|
|
(
|
|
'PLATFORM',
|
|
'PLATFORM',
|
|
'플랫폼',
|
|
jsonb_build_object(
|
|
'type', 'PLATFORM',
|
|
'target', 'remote-jetson',
|
|
'runtimeKind', 'real',
|
|
'viewer', jsonb_build_object('stack', 'nav2'),
|
|
'bridge', jsonb_build_object(
|
|
'name', 'nav2-ros-bridge',
|
|
'port', 8765,
|
|
'image', 'slam-ros-bridge:latest',
|
|
'env', jsonb_build_object('ROBOT_STACK', 'nav2')
|
|
),
|
|
'runtimeImages', jsonb_build_array(
|
|
jsonb_build_object(
|
|
'url', 'https://pub-ca72c40797144462bdb7d200c215d361.r2.dev/studio-artifacts/runtime-images/slam-ros-bridge/jetson-orin/latest/slam-ros-bridge-jetson-orin.tar.zst?v=0659d4cf5578',
|
|
'image', 'slam-ros-bridge:jetson_orin',
|
|
'fileName', 'slam-ros-bridge-jetson-orin.tar.zst',
|
|
'required', true,
|
|
'checksumSha256', '0659d4cf5578c43bc9c25e4a4fc5d226ccd5b7bec43becfdff83b5390717114e'
|
|
),
|
|
jsonb_build_object(
|
|
'url', 'https://pub-ca72c40797144462bdb7d200c215d361.r2.dev/studio-artifacts/runtime-images/nav2/jetson-orin/latest/future-nav2-humble-jetson-orin.tar.zst',
|
|
'image', 'future-nav2:humble-jetson_orin',
|
|
'fileName', 'future-nav2-humble-jetson-orin.tar.zst',
|
|
'required', true
|
|
)
|
|
)
|
|
)
|
|
)
|
|
) AS environment(platform_key, profile_type, name, config);
|
|
|
|
-- Viewer mode belongs to the selected map, not the platform environment.
|
|
UPDATE course_environment_profiles profile
|
|
SET config = profile.config::jsonb #- '{viewer,mode}'
|
|
WHERE profile.course_id IN (SELECT id FROM target_course);
|
|
|
|
-- Real-platform modules need the Jetson NAV2 runtime in addition to the
|
|
-- visualization bridge image. The desktop app downloads this artifact on
|
|
-- demand before starting a remote module.
|
|
UPDATE course_environment_profiles profile
|
|
SET config = jsonb_set(
|
|
profile.config::jsonb,
|
|
'{runtimeImages}',
|
|
COALESCE(profile.config::jsonb->'runtimeImages', '[]'::jsonb) || jsonb_build_array(jsonb_build_object(
|
|
'url', 'https://pub-ca72c40797144462bdb7d200c215d361.r2.dev/studio-artifacts/runtime-images/nav2/jetson-orin/latest/future-nav2-humble-jetson-orin.tar.zst',
|
|
'image', 'future-nav2:humble-jetson_orin',
|
|
'fileName', 'future-nav2-humble-jetson-orin.tar.zst',
|
|
'required', true
|
|
)),
|
|
true
|
|
)
|
|
WHERE profile.course_id IN (SELECT id FROM target_course)
|
|
AND profile.platform_key = 'PLATFORM'
|
|
AND NOT (COALESCE(profile.config::jsonb->'runtimeImages', '[]'::jsonb) @> '[{"image":"future-nav2:humble-jetson_orin"}]'::jsonb);
|
|
|
|
-- Local simulation gets all Gazebo modules. Platform profiles only receive modules applicable to their workflow.
|
|
UPDATE course_environment_profiles profile
|
|
SET config = profile.config::jsonb || jsonb_build_object('moduleSet', jsonb_build_object(
|
|
'target', CASE WHEN profile.platform_key = 'NAV2' THEN 'local' ELSE 'platform' END,
|
|
'includeUnlisted', false,
|
|
'modules', COALESCE((
|
|
SELECT jsonb_agg(jsonb_build_object('id', module.id) ORDER BY module.sort_order)
|
|
FROM course_weeks week
|
|
JOIN course_week_modules module ON module.week_id = week.id
|
|
WHERE week.course_id = profile.course_id
|
|
AND week.week = profile.week
|
|
AND (
|
|
(profile.platform_key = 'NAV2' AND module.folder_name LIKE '[lms-nav2-gazebo-%')
|
|
OR (profile.platform_key = 'PLATFORM' AND module.folder_name NOT IN (
|
|
'[lms-nav2-gazebo-simulator]nav2-simulator_v1.0.0_ws',
|
|
'[lms-nav2-gazebo-vehicle]nav2-vehicle_v1.0.0_ws',
|
|
'[lms-nav2-gazebo-gui]nav2-rviz2_v1.0.0_ws'
|
|
))
|
|
)
|
|
), '[]'::jsonb)
|
|
))
|
|
WHERE profile.course_id IN (SELECT id FROM target_course)
|
|
AND profile.platform_key IN ('NAV2', 'PLATFORM');
|
|
|
|
-- Control runs with TurtleBot3/Gazebo defaults locally, but uses MK-mini and the ARM64 image on a platform.
|
|
UPDATE course_environment_profiles profile
|
|
SET config = jsonb_set(profile.config::jsonb, '{moduleSet,modules}', (
|
|
SELECT jsonb_agg(
|
|
CASE WHEN item->>'id' = control_module.id::text THEN item || jsonb_build_object(
|
|
'defaultParameters', jsonb_build_array('sim_mode:=false', 'robot:=mkmini'),
|
|
'dockerImage', 'future-nav2:humble-jetson_orin'
|
|
) ELSE item END
|
|
)
|
|
FROM jsonb_array_elements(profile.config->'moduleSet'->'modules') AS item
|
|
CROSS JOIN LATERAL (
|
|
SELECT module.id
|
|
FROM course_weeks week
|
|
JOIN course_week_modules module ON module.week_id = week.id
|
|
WHERE week.course_id = profile.course_id
|
|
AND week.week = profile.week
|
|
AND module.name = 'NAV2-Control'
|
|
) AS control_module
|
|
), true)
|
|
WHERE profile.course_id IN (SELECT id FROM target_course)
|
|
AND profile.platform_key = 'PLATFORM';
|
|
|
|
-- The 2D perception module defaults to Gazebo in the course module list.
|
|
-- Override only that value for the real platform; the other added modules
|
|
-- retain their own compatible base parameters.
|
|
UPDATE course_environment_profiles profile
|
|
SET config = jsonb_set(profile.config::jsonb, '{moduleSet,modules}', (
|
|
SELECT jsonb_agg(
|
|
CASE WHEN item->>'id' = perception_module.id::text THEN item || jsonb_build_object(
|
|
'defaultParameters', jsonb_build_array('sim_mode:=false')
|
|
) ELSE item END
|
|
)
|
|
FROM jsonb_array_elements(profile.config->'moduleSet'->'modules') AS item
|
|
CROSS JOIN LATERAL (
|
|
SELECT module.id
|
|
FROM course_weeks week
|
|
JOIN course_week_modules module ON module.week_id = week.id
|
|
WHERE week.course_id = profile.course_id
|
|
AND week.week = profile.week
|
|
AND module.name = 'NAV2-Perception'
|
|
) AS perception_module
|
|
), true)
|
|
WHERE profile.course_id IN (SELECT id FROM target_course)
|
|
AND profile.platform_key = 'PLATFORM';
|
|
|
|
INSERT INTO course_week_maps (id, course_id, week, map_key, sort_order, created_at, updated_at)
|
|
SELECT gen_random_uuid(), target_course.id, weeks.week, map.map_key, map.sort_order, now(), now()
|
|
FROM target_course
|
|
CROSS JOIN (VALUES (1), (2)) AS weeks(week)
|
|
CROSS JOIN (VALUES ('nav2-turtlebot3-world', 1), ('nav2-turtlebot3-house', 2)) AS map(map_key, sort_order);
|
|
|
|
UPDATE instructor_curriculum_settings
|
|
SET active_week = 1, active_learning_step = 'ROS2 기초'
|
|
WHERE course_id IN (SELECT id FROM target_course);
|
|
|
|
COMMIT;
|