Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 39 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,44 @@
# ROS2-Jazzy-Tutorials
A repository containing tutorials for ROS2 Jazzy release with a focus on Robotics projects and labs.

## Week 1 - Pose Estimation
This week covers the pose estimation lectures and also incooperates 5 lab assignments.
The given Jupyter notebook covers the basic tools of `Numpy` and `Matplotlib` which are used to perform the transformations and visualize them respectively.
## Prerequisites
You should have the following installed:
- ROS2 Jazzy
- Gazebo

The `task.ipynb` jupyter notebook contains the lab assignments. Implement the solutions to complete the give lab tasks
## URDF
This section contains tutorials related to URDF (Unified Robot Description Format) files, which are used to describe the physical properties of a robot.
- **URDF Basics**: An introduction to URDF, its structure, and how to create a simple URDF file.
- **URDF with Gazebo**: A tutorial on how to use URDF files with Gazebo for simulation.

Create a package for this robot as we've discussed in previous sessions. Within the package directory, create a folder named `urdf` and place the URDF file inside it. Use the same file names for your ease. If you choose different filenames make sure to make changes appropriately in all required files including the launch files. The structure of the packages should look like this:

```
your_package/
├── urdf/
│ └── robot.xacro
│ └── robot.gazebo
├── launch/
│ └── your_robot.launch.py
├── src/
│ └── your_robot_node.cpp
├── worlds/
│ └── four_walls.world
├── package.xml
└── CMakeLists.txt
```

The files in the `robot` directory in this branch contain partially completed URDF files. You can use these as a starting point for your own robot. The final output should be a complete URDF file that describes a four-wheeled robot with a camera, a sonar sensor and a lidar sensor.

Next you should write a control node to make the robot randomly traverse within a four walled area without making any collisions. This should be done from scratch using the values taken from the sensors by subscribing to the topics. You can control the robot using the `geometry_msgs/Twist` message type. The node should subscribe to the camera, sonar and lidar topics and publish to the `cmd_vel` topic.

Finally, to launch the robot in Gazebo you should create a launch file. A partially completed launch file is provided in the `launch` directory. You can use this as a starting point for your own launch file. The final output should be a launch file that launches the robot in Gazebo with the URDF file and the control node.


## Tasks
1. **Create a URDF file**: Create a URDF file for a four-wheeled robot with a camera, sonar sensor, and lidar sensor.
2. **Write a control node**: Write a control node that makes the robot randomly traverse within a four-walled area without making any collisions.
3. **Create a launch file**: Create a launch file that launches the robot in Gazebo with the URDF file and the control node.
4. **Test the robot**: Test the robot in Gazebo and make sure it is working as expected.
5. **Document the process**: Document the process of creating the URDF file, control node, and launch file. Include any challenges faced and how they were overcome.

75 changes: 62 additions & 13 deletions Week1/task.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
},
{
"cell_type": "code",
"execution_count": 2,
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
Expand Down Expand Up @@ -45,10 +45,17 @@
" Output: resulting coordinates after rotating V by theta and translating by U\n",
" \"\"\"\n",
"\n",
" # Your code here\n",
" #your code here\n",
" pass"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
Expand All @@ -61,7 +68,7 @@
},
{
"cell_type": "code",
"execution_count": 6,
"execution_count": 3,
"metadata": {},
"outputs": [
{
Expand All @@ -85,6 +92,7 @@
"metadata": {},
"outputs": [],
"source": [
"\n",
"# Homogenous 3D Transformation\n",
"def homogenous_transform_3D(V:np.ndarray, U:np.ndarray, theta:dict) -> np.ndarray:\n",
" \"\"\"\n",
Expand All @@ -95,7 +103,7 @@
" Output: resulting coordinates after rotating V by theta and translating by U\n",
" \"\"\"\n",
"\n",
" # Your code here\n",
" #your code here\n",
" pass"
]
},
Expand All @@ -111,9 +119,24 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 7,
"metadata": {},
"outputs": [],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"=== Testing 3D Homogeneous Transformation Implementation ===\n",
"✅ Combined 3D transform: translation(5,5,5) + rotation(90° about z)\n",
"✅ Pure 3D translation: no rotation\n",
"✅ Pure rotation about x-axis\n",
"✅ Combined rotations about x, y, and z axes\n",
"✅ Rotations with Negative Translation\n",
"✅ Rotations by odd angles with Translation\n"
]
}
],
"source": [
"lab_tester.test_homogeneous_transform_3d(homogenous_transform_3D)"
]
Expand All @@ -134,6 +157,7 @@
"metadata": {},
"outputs": [],
"source": [
"\n",
"# Chain transformations\n",
"def chain_transforms(V:np.ndarray, transforms:list) -> np.ndarray:\n",
" \"\"\"\n",
Expand All @@ -143,24 +167,49 @@
" Output: resulting coordinates after appyling the transforms in the given order\n",
" \"\"\"\n",
"\n",
" # Your code here\n",
" #your code here\n",
" pass"
]
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 9,
"metadata": {},
"outputs": [],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"=== Testing Chain Transformations Implementation ===\n",
"✅ Chain of two translations\n",
"✅ Translation followed by rotation\n",
"✅ Complex chain of transformations\n",
"✅ Chain of identity transformations\n",
"✅ Complex transformations\n"
]
}
],
"source": [
"lab_tester.test_chain_transformations(chain_transforms)"
]
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 10,
"metadata": {},
"outputs": [],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"=== Test Summary ===\n",
"Passed: 19/19 tests\n",
"🎉 All tests passed!\n"
]
}
],
"source": [
"# Summary of test results\n",
"lab_tester.print_summary()"
Expand All @@ -174,7 +223,7 @@
],
"metadata": {
"kernelspec": {
"display_name": ".venv",
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
Expand All @@ -188,7 +237,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.12.3"
"version": "3.13.2"
}
},
"nbformat": 4,
Expand Down
87 changes: 87 additions & 0 deletions launch/simulation.launch.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
from launch import LaunchDescription
from launch.actions import IncludeLaunchDescription, ExecuteProcess
from launch.launch_description_sources import PythonLaunchDescriptionSource
from launch_ros.actions import Node
from launch.substitutions import FindExecutable, PathJoinSubstitution
from launch_ros.substitutions import FindPackageShare


def generate_launch_description():
pkg_name = FindPackageShare("pkg_name")
# Xacro command to generate URDF
xacro_command = [
PathJoinSubstitution([FindExecutable(name="xacro")]),
" ",
PathJoinSubstitution([pkg_name, "urdf", "robot.xacro"]),
]

return LaunchDescription(
[
# TODO: Create the control node
# Node
# Load Gazebo world
IncludeLaunchDescription(
PythonLaunchDescriptionSource(
[
PathJoinSubstitution(
[
FindPackageShare("gazebo_ros"),
"launch",
"gazebo.launch.py",
]
)
]
),
# TODO: Provide the correct values for the argumentsarguments
launch_arguments={
"world": PathJoinSubstitution(
[pkg_name, "worlds", "four_walls.world"]
),
"paused": "false",
"use_sim_time": "true",
"gui": "true",
"headless": "false",
"debug": "false",
}.items(),
),
# Robot description parameter
ExecuteProcess(
cmd=[
"ros2",
"param",
"set",
"/robot_state_publisher",
"robot_description",
PathJoinSubstitution([FindExecutable(name="xacro")]),
PathJoinSubstitution([pkg_name, "urdf", "robot.xacro"]),
],
shell=True,
),
Node(
package="robot_state_publisher",
executable="robot_state_publisher",
output="screen",
parameters=[{"robot_description": PathJoinSubstitution([pkg_name, "urdf", "robot.xacro"])}],
),

Node(
package="gazebo_ros",
executable="spawn_entity.py",
arguments=["-topic", "robot_description", "-entity", "four_wheel_robot"],
output="screen",
),
Node(
package="four_wheel_bot_control",
executable="controller",
name="controller_node",
output="screen",
)



# TODO: Create the robot state publisher node
# Robot state publisher
# TODO: Spawn the robot in Gazebo
# Spawn robot in Gazebo
]
)
Loading