diff --git a/content-testing/schemas.js b/content-testing/schemas.js index be35a548b..26fda3568 100644 --- a/content-testing/schemas.js +++ b/content-testing/schemas.js @@ -130,7 +130,7 @@ const baseVideosSchema = strictObject({ name: string().required(), url: string().url() }).required() - ).required() + ) }); const videosSchema = baseVideosSchema.concat( diff --git a/content/tracks/index.json b/content/tracks/index.json index 5c097ca8e..d8608958f 100644 --- a/content/tracks/index.json +++ b/content/tracks/index.json @@ -10,12 +10,13 @@ "algorithmic-botany", "coding-in-the-cabana", "coding-together-apple-ii", - "mastodon", + "robot-controllers", "discord-bots", + "p5-tips-and-tricks", + "transformations-in-p5", "livestreams", "neural-networks", "noise", - "p5-tips-and-tricks", "physics-libraries", "pi-day", "pixels", @@ -24,10 +25,10 @@ "supershapes", "teachable-machine", "topics-in-native-javascript", - "transformations-in-p5", "games", "web-sockets-and-p5js", "webgl", + "mastodon", "archive" ] } diff --git a/content/tracks/side-tracks/livestreams/index.json b/content/tracks/side-tracks/livestreams/index.json index e11a5ec26..7a152d678 100644 --- a/content/tracks/side-tracks/livestreams/index.json +++ b/content/tracks/side-tracks/livestreams/index.json @@ -2,6 +2,8 @@ "title": "Coding Train Live!", "description": "This side track is a collection of select livestreams.", "videos": [ + "robot-controllers/robot-controller-1", + "robot-controllers/robot-controller-2", "livestreams/genuary-2025", "livestreams/page-not-found", "livestreams/creative_coding_ai_agent", diff --git a/content/tracks/side-tracks/robot-controllers/index.json b/content/tracks/side-tracks/robot-controllers/index.json new file mode 100644 index 000000000..70d3b4227 --- /dev/null +++ b/content/tracks/side-tracks/robot-controllers/index.json @@ -0,0 +1,5 @@ +{ + "title": "Robot Controllers", + "description": "A side track featuring livestreams about robot controllers with Dr", + "videos": ["robot-controllers/robot-controller-1", "robot-controllers/robot-controller-2"] +} diff --git a/content/videos/robot-controllers/robot-controller-1/images/cart-pole.jpg b/content/videos/robot-controllers/robot-controller-1/images/cart-pole.jpg new file mode 100644 index 000000000..bbf40c51f Binary files /dev/null and b/content/videos/robot-controllers/robot-controller-1/images/cart-pole.jpg differ diff --git a/content/videos/robot-controllers/robot-controller-1/index.json b/content/videos/robot-controllers/robot-controller-1/index.json new file mode 100644 index 000000000..2293c2be0 --- /dev/null +++ b/content/videos/robot-controllers/robot-controller-1/index.json @@ -0,0 +1,93 @@ +{ + "title": "Robot Controllers Part 1: PID (with Dr. Christian Hubicki)", + "description": "In this live stream, Dr. Christian Hubicki and I team up to build a PID Controller, first in python and then in p5.js! We apply the controller to the classic 'cart pole' problem, attempting to balance an inverted pendulum.", + "videoId": "fWQWX9-8_sA", + "date": "2022-07-16", + "canonicalTrack": "robot-controllers", + "languages": ["Python", "p5.js", "matter.js"], + "topics": ["robotics", "PID controller", "p5.js", "python", "simulation", "physics", "robot control", "matter.js", "cart pole"], + "canContribute": true, + "relatedChallenges": ["138-angry-birds-with-matterjs", "62-plinko-with-matterjs"], + "timestamps": [ + { "time": "0:00:00", "title": "Waiting to Start" }, + { "time": "0:04:38", "title": "Welcome!" }, + { "time": "0:07:30", "title": "Introducing Dr. Christian Hubicki" }, + { "time": "0:09:49", "title": "Christian's Introductory Presentation" }, + { "time": "0:14:48", "title": "How to Follow Along" }, + { "time": "0:16:22", "title": "PID Controller Lecture" }, + { "time": "0:44:09", "title": "Coding in Python!" }, + { "time": "1:23:58", "title": "Introducing p5.js and matter.js" }, + { "time": "1:37:18", "title": "Coding in p5.js!" }, + { "time": "2:48:30", "title": "It works!" }, + { "time": "2:49:19", "title": "Wrapping up and next steps" } + ], + "codeExamples": [ + { + "title": "Base Python Code", + "description": "The starter Python code in a Deepnote notebook.", + "image": "cart-pole.jpg", + "urls": { "other": "https://tinyurl.com/cart-pole" } + }, + { + "title": "Final Python Code", + "description": "The final Python code with the completed PID controller.", + "image": "cart-pole.jpg", + "urls": { "other": "https://tinyurl.com/cartpole-control" } + }, + { + "title": "PID Controller", + "description": "The p5.js and matter.js implementation of the balancing robot.", + "image": "cart-pole.jpg", + "urls": { "p5": "https://editor.p5js.org/codingtrain/sketches/sB1glTRe7" } + }, + { + "title": "PID Controller", + "description": "The full GitHub repository for this project, including the interactive p5.js demo.", + "image": "cart-pole.jpg", + "urls": { "other": "https://github.com/CodingTrain/Robot-Controllers" } + } + ], + "groupLinks": [ + { + "title": "References", + "links": [ + { + "icon": "🔗", + "title": "Dr. Christian Hubicki", + "description": "Assistant Professor of Robotics at FAMU-FSU College of Engineering.", + "url": "https://www.christianhubicki.com/" + }, + { + "icon": "🤖", + "title": "Optimal Robotics Laboratory", + "url": "https://www.optimalroboticslab.com/", + "description": "Dr. Christian Hubicki's lab at FAMU-FSU College of Engineering." + }, + { + "icon": "▶️", + "title": "YouTube", + "url": "https://www.youtube.com/channel/UCqSfzxT0dcpEPMtVguwzATg", + "description": "Dr. Hubicki's YouTube channel." + } + ] + }, + { + "title": "Videos", + "links": [ + { + "icon": "🚂", + "title": "Robot Controllers Part 2", + "url": "/tracks/robot-controllers/robot-controllers/robot-controller-2", + "description": "The second part of this series, where we coded a simulation of a hopping robot." + }, + { + "icon": "🚂", + "title": "Introduction to Matter.js", + "url": "/tracks/the-nature-of-code-2/noc/6-physics-libraries/1-matterjs-introduction", + "description": "This video is an introduction to the physics engine Matter.js, a 2D JavaScript physics library that supports rigid body collisions and constraints." + } + ] + } + ], + "credits": [] +} diff --git a/content/videos/robot-controllers/robot-controller-2/images/1d-hopper-a.jpg b/content/videos/robot-controllers/robot-controller-2/images/1d-hopper-a.jpg new file mode 100644 index 000000000..679c1d36c Binary files /dev/null and b/content/videos/robot-controllers/robot-controller-2/images/1d-hopper-a.jpg differ diff --git a/content/videos/robot-controllers/robot-controller-2/images/1d-hopper-b.jpg b/content/videos/robot-controllers/robot-controller-2/images/1d-hopper-b.jpg new file mode 100644 index 000000000..cfddde353 Binary files /dev/null and b/content/videos/robot-controllers/robot-controller-2/images/1d-hopper-b.jpg differ diff --git a/content/videos/robot-controllers/robot-controller-2/images/1d-spring.jpg b/content/videos/robot-controllers/robot-controller-2/images/1d-spring.jpg new file mode 100644 index 000000000..3b255d277 Binary files /dev/null and b/content/videos/robot-controllers/robot-controller-2/images/1d-spring.jpg differ diff --git a/content/videos/robot-controllers/robot-controller-2/images/2d-hopper.jpg b/content/videos/robot-controllers/robot-controller-2/images/2d-hopper.jpg new file mode 100644 index 000000000..188710118 Binary files /dev/null and b/content/videos/robot-controllers/robot-controller-2/images/2d-hopper.jpg differ diff --git a/content/videos/robot-controllers/robot-controller-2/images/matlab-hopper.png b/content/videos/robot-controllers/robot-controller-2/images/matlab-hopper.png new file mode 100644 index 000000000..267b6ddca Binary files /dev/null and b/content/videos/robot-controllers/robot-controller-2/images/matlab-hopper.png differ diff --git a/content/videos/robot-controllers/robot-controller-2/index.json b/content/videos/robot-controllers/robot-controller-2/index.json new file mode 100644 index 000000000..3cc355fe9 --- /dev/null +++ b/content/videos/robot-controllers/robot-controller-2/index.json @@ -0,0 +1,114 @@ +{ + "title": "Robot Controllers Part 2: Raibert Hopper (with Dr. Christian Hubicki", + "description": "In this livestream, I'm rejoined by Dr. Christian Hubicki to continue our series on robot controllers. Dr. Hubicki gives a presentation on the history of legged robots (like ASIMO and Boston Dynamics) and the principles behind the Raibert Hopper. Then, we attempt to implement a 1D hopping robot simulation in p5.js using a PID controller.", + "videoId": "3FeySIv-gFM", + "canonicalTrack": "robot-controllers", + "date": "2025-08-24", + "languages": ["p5.js", "MATLAB"], + "topics": ["robotics", "p5.js", "PID controller", "Raibert hopper", "simulation", "physics", "legged locomotion", "robot control"], + "canContribute": true, + "relatedChallenges": ["160-spring-forces"], + "timestamps": [ + { "time": "0:00:00", "title": "Waiting to Start" }, + { "time": "0:05:17", "title": "Welcome to The Coding Train" }, + { "time": "0:08:35", "title": "Revisiting Part 1 from 2022" }, + { "time": "0:10:13", "title": "Introducing Dr. Christian Hubicki" }, + { "time": "0:20:10", "title": "Dr. Hubicki's Presentation: How to Make a Robot Hop" }, + { "time": "0:24:00", "title": "History of Legged Locomotion: Safety vs. Agility" }, + { "time": "0:27:09", "title": "The 'Safety First' Approach (ZMP, ASIMO)" }, + { "time": "0:30:34", "title": "The 'Agility First' Approach (Mark Raibert, Boston Dynamics)" }, + { "time": "0:38:17", "title": "Whiteboard Explanation: PID Controllers" }, + { "time": "0:51:30", "title": "Whiteboard Explanation: The Raibert Hopper Controller" }, + { "time": "0:58:07", "title": "Transition to Coding in p5.js" }, + { "time": "1:03:04", "title": "Connecting to Nature of Code and Steering Behaviors" }, + { "time": "1:10:40", "title": "Starting with the p5.js Spring Simulation Code" }, + { "time": "1:24:27", "title": "Implementing Hopping Phases (Stance vs. Flight)" }, + { "time": "1:48:01", "title": "Implementing the PID Controller for Hopping Height" }, + { "time": "2:09:59", "title": "Reviewing a Pre-made, Working 1D Hopper Example" }, + { "time": "2:16:40", "title": "Previewing a 2D Hopper Starter Code" }, + { "time": "2:23:04", "title": "Where to Find Dr. Christian Hubicki" }, + { "time": "2:24:53", "title": "What's Next for The Coding Train" }, + { "time": "2:29:43", "title": "Outro and Goodbyes" } + ], + "codeExamples": [ + { + "title": "1D Raibert Hopper", + "description": "The p5.js sketch for a 1D hopping robot that we coded together during the livestream.", + "image": "1d-hopper-a.jpg", + "urls": { "p5": "https://editor.p5js.org/codingtrain/sketches/CjfAtvdGx" } + }, + { + "title": "1D Raibert Hopper", + "description": "A organized and commented p5.js implementation of the 1D Raibert hopper controller.", + "image": "1d-hopper-b.jpg", + "urls": { "p5": "https://editor.p5js.org/codingtrain/sketches/EYOfSWBaF" } + }, + { + "title": "1D Spring Simulation", + "description": "The starter code for the 1D spring simulation used at the beginning of the coding session.", + "image": "1d-spring.jpg", + "urls": { "p5": "https://editor.p5js.org/codingtrain/sketches/EhhzPIB-h" } + }, + { + "title": "2D Hopper", + "description": "A starter p5.js sketch for a 2D hopper, ready for a controller to be implemented.", + "image": "2d-hopper.jpg", + "urls": { "p5": "https://editor.p5js.org/codingtrain/sketches/W_hxT-8ST" } + }, + { + "title": "MATLAB Raibert Hopper", + "description": "A MATLAB implementation by Dr. Christian Hubicki.", + "image": "matlab-hopper.png", + "urls": { "other": "https://gist.github.com/shiffman/9eea780b9cada3725887d26ed174d49e" } + } + ], + "groupLinks": [ + { + "title": "References", + "links": [ + { + "icon": "🔗", + "title": "Dr. Christian Hubicki's", + "url": "https://www.christianhubicki.com/", + "description": "Dr. Hubicki's personal website." + }, + { + "icon": "🤖", + "title": "Optimal Robotics Lab", + "url": "https://www.optimalroboticslab.com/", + "description": "The research group run by Dr. Christian Hubicki at the FAMU-FSU College of Engineering." + }, + { + "icon": "📖", + "title": "The Nature of Code", + "url": "https://natureofcode.com/", + "description": "My book on simulating natural systems, which covers concepts like vectors, forces, and springs." + } + ] + }, + { + "title": "Videos", + "links": [ + { + "icon": "🚂", + "title": "Robot Controllers Part 1", + "url": "/tracks/robot-controllers/robot-controllers/robot-controller-1", + "description": "The first part of this series, where we coded a simulation of an inverted pendulum on a cart." + }, + { + "icon": "🚂", + "title": "Steering Behaviors", + "url": "/tracks/the-nature-of-code-2/noc/5-autonomous-agents/1-steering-agents", + "description": "This video covers steering behaviors, which are algorithms for autonomous agents to navigate their environment." + }, + { + "icon": "🚂", + "title": "Scalar Projection", + "url": "/tracks/the-nature-of-code-2/noc/5-autonomous-agents/6-scalar-projection", + "description": "This video covers scalar projection, used in the spring damping code." + } + ] + } + ], + "credits": [] +}