diff --git a/ros_midterm/CMakeLists.txt b/ros_midterm/CMakeLists.txt
new file mode 100644
index 0000000..d06837c
--- /dev/null
+++ b/ros_midterm/CMakeLists.txt
@@ -0,0 +1,41 @@
+cmake_minimum_required(VERSION 3.8)
+project(ros_midterm)
+
+if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
+ add_compile_options(-Wall -Wextra -Wpedantic)
+endif()
+
+# find dependencies
+find_package(ament_cmake REQUIRED)
+find_package(rclcpp REQUIRED)
+find_package(std_msgs REQUIRED)
+find_package(sensor_msgs REQUIRED)
+find_package(geometry_msgs REQUIRED)
+
+#imu_sub
+add_executable(imu_sub src/imu_sub.cpp)
+ament_target_dependencies(imu_sub rclcpp sensor_msgs)
+
+#cmd_pub
+add_executable(cmd_pub src/cmd_pub.cpp)
+ament_target_dependencies(cmd_pub rclcpp geometry_msgs)
+
+#install
+install(TARGETS
+ imu_sub
+ cmd_pub
+ DESTINATION lib/${PROJECT_NAME})
+
+if(BUILD_TESTING)
+ find_package(ament_lint_auto REQUIRED)
+ # the following line skips the linter which checks for copyrights
+ # comment the line when a copyright and license is added to all source files
+ set(ament_cmake_copyright_FOUND TRUE)
+ # the following line skips cpplint (only works in a git repo)
+ # comment the line when this package is in a git repo and when
+ # a copyright and license is added to all source files
+ set(ament_cmake_cpplint_FOUND TRUE)
+ ament_lint_auto_find_test_dependencies()
+endif()
+
+ament_package()
diff --git a/ros_midterm/package.xml b/ros_midterm/package.xml
new file mode 100644
index 0000000..c7f3bf0
--- /dev/null
+++ b/ros_midterm/package.xml
@@ -0,0 +1,23 @@
+
+
+
+ ros_midterm
+ 0.0.0
+ ROS2 midterm exam 11/18/2025
+ ros
+ Apache-2.0
+
+ ament_cmake
+
+ rclcpp
+ std_msgs
+ sensor_msgs
+ geometry_msgs
+
+ ament_lint_auto
+ ament_lint_common
+
+
+ ament_cmake
+
+
diff --git a/ros_midterm/src/cmd_pub.cpp b/ros_midterm/src/cmd_pub.cpp
new file mode 100644
index 0000000..00b180f
--- /dev/null
+++ b/ros_midterm/src/cmd_pub.cpp
@@ -0,0 +1,42 @@
+#include "rclcpp/rclcpp.hpp"
+#include "geometry_msgs/msg/twist.hpp"
+#include
+
+class CmdPublisher : public rclcpp::Node
+{
+public:
+ CmdPublisher() : Node("cmd_pub"), gen_(rd_()), dis_(-2.0, 2.0)
+ {
+ publisher_ = this->create_publisher("/cmd_vel", 10);
+ timer_ = this->create_wall_timer(
+ std::chrono::seconds(1),
+ std::bind(&CmdPublisher::timer_callback, this));
+
+ RCLCPP_INFO(this->get_logger(), "CMD Publisher node started");
+ }
+
+private:
+ void timer_callback()
+ {
+ auto message = geometry_msgs::msg::Twist();
+ message.angular.z = dis_(gen_);
+
+ RCLCPP_INFO(this->get_logger(), "Publishing Angular Velocity Z: %.4f rad/s",
+ message.angular.z);
+ publisher_->publish(message);
+ }
+
+ rclcpp::Publisher::SharedPtr publisher_;
+ rclcpp::TimerBase::SharedPtr timer_;
+ std::random_device rd_;
+ std::mt19937 gen_;
+ std::uniform_real_distribution<> dis_;
+};
+
+int main(int argc, char * argv[])
+{
+ rclcpp::init(argc, argv);
+ rclcpp::spin(std::make_shared());
+ rclcpp::shutdown();
+ return 0;
+}
diff --git a/ros_midterm/src/imu_sub.cpp b/ros_midterm/src/imu_sub.cpp
new file mode 100644
index 0000000..42bdd74
--- /dev/null
+++ b/ros_midterm/src/imu_sub.cpp
@@ -0,0 +1,31 @@
+#include "rclcpp/rclcpp.hpp"
+#include "sensor_msgs/msg/imu.hpp"
+
+class ImuSubscriber : public rclcpp::Node
+{
+public:
+ ImuSubscriber() : Node("imu_sub")
+ {
+ subscription_ = this->create_subscription(
+ "/imu", 10, std::bind(&ImuSubscriber::imu_callback, this, std::placeholders::_1));
+
+ RCLCPP_INFO(this->get_logger(), "IMU Subscriber node started");
+ }
+
+private:
+ void imu_callback(const sensor_msgs::msg::Imu::SharedPtr msg)
+ {
+ RCLCPP_INFO(this->get_logger(), "Angular Velocity Z: %.4f rad/s",
+ msg->angular_velocity.z);
+ }
+
+ rclcpp::Subscription::SharedPtr subscription_;
+};
+
+int main(int argc, char * argv[])
+{
+ rclcpp::init(argc, argv);
+ rclcpp::spin(std::make_shared());
+ rclcpp::shutdown();
+ return 0;
+}