From dc95794a8eca80bb2009fe3a6992d51e5c5ff9ff Mon Sep 17 00:00:00 2001 From: Atharav1805 <168408064+Atharav1805@users.noreply.github.com> Date: Tue, 4 Jun 2024 02:26:47 +0530 Subject: [PATCH 01/22] Controller node for balancing --- controller_node.py | 119 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 controller_node.py diff --git a/controller_node.py b/controller_node.py new file mode 100644 index 0000000..ea49dcc --- /dev/null +++ b/controller_node.py @@ -0,0 +1,119 @@ +#!/usr/bin/env python3 + +import numpy as np +import rclpy +from rclpy.node import Node +from custom_msgs.msg import States +from custom_msgs.msg import TorqueInput +import matplotlib.pyplot as plt +import time + + +class ControllerNode(Node): + + def __init__(self): + super().__init__('controller_node') + self.controller_node_subs = self.create_subscription(States, "/state_feedback", self.pose_callback, 10) # create a subscriber with the name controller_node_subs that subscribes to the state_feedback topic + self.controller_node_pub = self.create_publisher(TorqueInput, "/torque_input", 10) # create a publisher with the name controller_node_pub that publishes to the torque_input topic + #self.timer = self.create_timer(0.02, self.send_torque_info) # create a timer that calls the send_torque_info function every 0.01 seconds + #Set the state variables + self.theta = np.pi - (np.random.rand() - 0.5) / 2 + self.theta = (self.theta + np.pi)%(2*np.pi) - np.pi + self.theta_dot = 0 + self.torque = 0.0 + self.target_angle = np.pi + + # Create a list to store the theta and time values + self.theta_values = [] + self.time_values = [] + + self.start_time = time.time() + self.prev_time = self.start_time + self.previous_error = self.target_angle - self.theta + self.integral = 0 + + self.get_logger().info("Controller node has been started") + + #Inititalize lists to store theta and time values + + + + def pose_callback(self, msg: States): + #self.get_logger().info("Received state: " + str(msg.theta) + ", " + str(msg.theta_dot)) + self.theta = msg.theta + self.theta_dot = msg.theta_dot + + if self.theta < 0: + error = -self.target_angle - self.theta + if self.theta >= 0: + error = self.target_angle - self.theta + + self.PID(error) + self.theta_values.append(self.theta) # append the theta value to the list + self.time_values.append(time.time() - self.start_time) # append the time value to the list + + + def send_torque_info(self): # create a function that sends the torque value to the simulation + + self.torque = max(-5.0, min(5.0, self.torque)) # limit the torque value to be between -5 and 5 + + #Publish the torque value + msg = TorqueInput() # create a TorqueInput message + msg.torque_value = self.torque + self.controller_node_pub.publish(msg) # publish the torque value to the topic + self.get_logger().info("Sent torque: " + str(self.torque)) # log the torque value + + + def PID(self,error): + + # Set the PID gains + Kp = 48 + Ki = 0.01 + Kd = 0.6 + + # Compute the time difference + dt = time.time() - self.prev_time + self.prev_time = time.time() # update the previous time + + self.integral += error * dt + derivative = (error - self.previous_error) / dt + self.previous_error = error + + p = Kp * error + i = Ki * self.integral + d = Kd * derivative + + self.torque = p + i + d + self.send_torque_info() + + + def plot_graph(self): + + plt.plot(self.time_values, self.theta_values) + plt.xlabel("Time (s)") + plt.ylabel("Theta (rad)") + plt.title("Theta vs Time") + plt.grid(True) + plt.show() + + + +def main(args=None): + rclpy.init(args=args) + node = ControllerNode() + + try: + + rclpy.spin(node) + + except KeyboardInterrupt: + + node.get_logger().info("Keyboard Interrupt detected...shutting the node down") + node.plot_graph() + pass + + rclpy.shutdown() + + + + \ No newline at end of file From 005487d3997c1df78cd691bda1fe8115417e3204 Mon Sep 17 00:00:00 2001 From: Atharav1805 <168408064+Atharav1805@users.noreply.github.com> Date: Thu, 6 Jun 2024 01:53:51 +0530 Subject: [PATCH 02/22] updated dt calculation --- controller_node.py | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/controller_node.py b/controller_node.py index ea49dcc..9627bd5 100644 --- a/controller_node.py +++ b/controller_node.py @@ -27,17 +27,14 @@ def __init__(self): self.theta_values = [] self.time_values = [] - self.start_time = time.time() - self.prev_time = self.start_time + self.node_start_time = time.time() + self.prev_time = time.time() self.previous_error = self.target_angle - self.theta self.integral = 0 self.get_logger().info("Controller node has been started") - #Inititalize lists to store theta and time values - - def pose_callback(self, msg: States): #self.get_logger().info("Received state: " + str(msg.theta) + ", " + str(msg.theta_dot)) self.theta = msg.theta @@ -50,7 +47,7 @@ def pose_callback(self, msg: States): self.PID(error) self.theta_values.append(self.theta) # append the theta value to the list - self.time_values.append(time.time() - self.start_time) # append the time value to the list + self.time_values.append(time.time() - self.node_start_time) # append the time value to the list def send_torque_info(self): # create a function that sends the torque value to the simulation @@ -67,8 +64,8 @@ def send_torque_info(self): # create a function that sends the torque value to t def PID(self,error): # Set the PID gains - Kp = 48 - Ki = 0.01 + Kp = 50.0 + Ki = 0.001 Kd = 0.6 # Compute the time difference From c4adc9fe583c80646fc0130b8f0cddfa0b228ac6 Mon Sep 17 00:00:00 2001 From: Atharav1805 <168408064+Atharav1805@users.noreply.github.com> Date: Thu, 6 Jun 2024 01:56:38 +0530 Subject: [PATCH 03/22] changes initialisation of integral error --- controller_node.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controller_node.py b/controller_node.py index 9627bd5..a53b7ab 100644 --- a/controller_node.py +++ b/controller_node.py @@ -30,7 +30,7 @@ def __init__(self): self.node_start_time = time.time() self.prev_time = time.time() self.previous_error = self.target_angle - self.theta - self.integral = 0 + self.integral = 0.0 self.get_logger().info("Controller node has been started") From 2794c3596ed5128890a4c720a4cd731f30251a9a Mon Sep 17 00:00:00 2001 From: Atharav1805 <168408064+Atharav1805@users.noreply.github.com> Date: Thu, 6 Jun 2024 02:41:55 +0530 Subject: [PATCH 04/22] Controller node for simulating swing up and balance --- controller_node_swing_up.py | 147 ++++++++++++++++++++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100644 controller_node_swing_up.py diff --git a/controller_node_swing_up.py b/controller_node_swing_up.py new file mode 100644 index 0000000..4fec5a4 --- /dev/null +++ b/controller_node_swing_up.py @@ -0,0 +1,147 @@ +#!/usr/bin/env python3 + +import numpy as np +import rclpy +from rclpy.node import Node +from custom_msgs.msg import States +from custom_msgs.msg import TorqueInput +import matplotlib.pyplot as plt +import time + + +class ControllerNode(Node): + + def __init__(self): + super().__init__('controller_node') + self.controller_node_subs = self.create_subscription(States, "/state_feedback", self.pose_callback, 10) # create a subscriber with the name controller_node_subs that subscribes to the state_feedback topic + self.controller_node_pub = self.create_publisher(TorqueInput, "/torque_input", 10) # create a publisher with the name controller_node_pub that publishes to the torque_input topic + #self.timer = self.create_timer(0.02, self.send_torque_info) # create a timer that calls the send_torque_info function every 0.01 seconds + #Set the state variables + self.theta = 0 - (np.random.rand() - 0.5) / 2 + self.theta = (self.theta + np.pi)%(2*np.pi) - np.pi + self.theta_dot = 0 + self.torque = 0.0 + self.target_angle = np.pi + + # Create a list to store the theta and time values + self.theta_values = [] + self.time_values = [] + + self.start_time = time.time() + self.prev_time = self.start_time + self.previous_error = self.target_angle - self.theta + self.integral = 0.0 + + self.previous_theta = self.theta + self.previous_torque = 5.0 + + self.swing_up_complete = False + + + self.get_logger().info("Controller node has been started") + + + + + + def pose_callback(self, msg: States): + #self.get_logger().info("Received state: " + str(msg.theta) + ", " + str(msg.theta_dot)) + self.theta = msg.theta + self.theta_dot = msg.theta_dot + + if self.swing_up_complete == False: + self.swing_up() + + if abs(self.theta) >= np.pi -0.25 : + self.swing_up_complete = True + + if self.swing_up_complete == True: + self.PID_balance() + + self.theta_values.append(self.theta) # append the theta value to the list + self.time_values.append(time.time() - self.start_time) # append the time value to the list + + + def swing_up(self): + + if abs(self.theta - self.previous_theta) >= 0.5: + self.torque = 0.0 + + elif abs(self.theta) < np.pi / 1.5: + if abs(self.theta - self.previous_theta) < 0.05: + self.previous_torque *= -1 + self.torque = self.previous_torque + + self.send_torque_info() + + + def send_torque_info(self): # create a function that sends the torque value to the simulation + + self.torque = max(-5.0, min(5.0, self.torque)) # limit the torque value to be between -5 and 5 + + #Publish the torque value + msg = TorqueInput() # create a TorqueInput message + msg.torque_value = self.torque + self.controller_node_pub.publish(msg) # publish the torque value to the topic + self.get_logger().info("Sent torque: " + str(self.torque)) # log the torque value + + + def PID_balance(self): + + # Set the PID gains + Kp = 50.0 + Ki = 0.01 + Kd = 0.6 + + if self.theta < 0: + error = -self.target_angle - self.theta + if self.theta >= 0: + error = self.target_angle - self.theta + + # Compute the time difference + dt = time.time() - self.prev_time + self.prev_time = time.time() # update the previous time + + self.integral += error * dt + derivative = (error - self.previous_error) / dt + self.previous_error = error + + p = Kp * error + i = Ki * self.integral + d = Kd * derivative + + self.torque = p + i + d + self.send_torque_info() + + + def plot_graph(self): + + plt.plot(self.time_values, self.theta_values) + plt.xlabel("Time (s)") + plt.ylabel("Theta (rad)") + plt.title("Theta vs Time") + plt.grid(True) + plt.show() + + + +def main(args=None): + rclpy.init(args=args) + node = ControllerNode() + + try: + + rclpy.spin(node) + + except KeyboardInterrupt: + + node.get_logger().info("Keyboard Interrupt detected...shutting the node down") + node.plot_graph() + node.destroy_node() + + + rclpy.shutdown() + + + + \ No newline at end of file From 7f9e84d4b3b79f43e17ba2c79302c669c29a044f Mon Sep 17 00:00:00 2001 From: Atharav1805 <168408064+Atharav1805@users.noreply.github.com> Date: Sat, 8 Jun 2024 05:56:37 +0530 Subject: [PATCH 05/22] Add files via upload --- controller_node.py | 6 ++++-- controller_node_swing_up.py | 13 +++++++------ 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/controller_node.py b/controller_node.py index a53b7ab..5bdd0ea 100644 --- a/controller_node.py +++ b/controller_node.py @@ -40,6 +40,8 @@ def pose_callback(self, msg: States): self.theta = msg.theta self.theta_dot = msg.theta_dot + + if self.theta < 0: error = -self.target_angle - self.theta if self.theta >= 0: @@ -77,10 +79,10 @@ def PID(self,error): self.previous_error = error p = Kp * error - i = Ki * self.integral + #i = Ki * self.integral d = Kd * derivative - self.torque = p + i + d + self.torque = p + d # calculate the torque value self.send_torque_info() diff --git a/controller_node_swing_up.py b/controller_node_swing_up.py index 4fec5a4..16c0acd 100644 --- a/controller_node_swing_up.py +++ b/controller_node_swing_up.py @@ -52,8 +52,9 @@ def pose_callback(self, msg: States): if self.swing_up_complete == False: self.swing_up() - if abs(self.theta) >= np.pi -0.25 : + if abs(self.theta) >= np.pi -0.4 : self.swing_up_complete = True + self.get_logger().info("Swing up complete") if self.swing_up_complete == True: self.PID_balance() @@ -64,7 +65,7 @@ def pose_callback(self, msg: States): def swing_up(self): - if abs(self.theta - self.previous_theta) >= 0.5: + if abs(self.theta - self.previous_theta) >= 0.4: self.torque = 0.0 elif abs(self.theta) < np.pi / 1.5: @@ -90,8 +91,8 @@ def PID_balance(self): # Set the PID gains Kp = 50.0 - Ki = 0.01 - Kd = 0.6 + #Ki = 0.01 + Kd = 6.0 if self.theta < 0: error = -self.target_angle - self.theta @@ -107,10 +108,10 @@ def PID_balance(self): self.previous_error = error p = Kp * error - i = Ki * self.integral + #i = Ki * self.integral d = Kd * derivative - self.torque = p + i + d + self.torque = p + d self.send_torque_info() From 8351440923b628d62c2f28542aade67b3fdfe155 Mon Sep 17 00:00:00 2001 From: Atharav1805 <168408064+Atharav1805@users.noreply.github.com> Date: Tue, 11 Jun 2024 17:47:41 +0530 Subject: [PATCH 06/22] Updated PID gains --- controller_node.py | 6 +++--- controller_node_swing_up.py | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/controller_node.py b/controller_node.py index 5bdd0ea..e33ea44 100644 --- a/controller_node.py +++ b/controller_node.py @@ -68,7 +68,7 @@ def PID(self,error): # Set the PID gains Kp = 50.0 Ki = 0.001 - Kd = 0.6 + Kd = 6.0 # Compute the time difference dt = time.time() - self.prev_time @@ -79,10 +79,10 @@ def PID(self,error): self.previous_error = error p = Kp * error - #i = Ki * self.integral + i = Ki * self.integral d = Kd * derivative - self.torque = p + d # calculate the torque value + self.torque = p + i + d # calculate the torque value self.send_torque_info() diff --git a/controller_node_swing_up.py b/controller_node_swing_up.py index 16c0acd..eaa739a 100644 --- a/controller_node_swing_up.py +++ b/controller_node_swing_up.py @@ -91,7 +91,7 @@ def PID_balance(self): # Set the PID gains Kp = 50.0 - #Ki = 0.01 + Ki = 0.01 Kd = 6.0 if self.theta < 0: From 1eea8bdd9eeb84b4998dd992a302911391602e5b Mon Sep 17 00:00:00 2001 From: Atharav1805 <168408064+Atharav1805@users.noreply.github.com> Date: Tue, 11 Jun 2024 18:29:23 +0530 Subject: [PATCH 07/22] Create Results.md --- Results.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 Results.md diff --git a/Results.md b/Results.md new file mode 100644 index 0000000..bae0254 --- /dev/null +++ b/Results.md @@ -0,0 +1,7 @@ +1. Balance: +[balance.webm](https://github.com/Atharav1805/Inverted-pendulum-problems-Atharav/assets/168408064/9e45ce17-7df3-47fb-a1ae-0e2064d48eb7) +![graph_balance](https://github.com/Atharav1805/Inverted-pendulum-problems-Atharav/assets/168408064/cafd3725-003c-4873-a124-6810d496d66b) + +2. Swing up: +[swing_up.webm](https://github.com/Atharav1805/Inverted-pendulum-problems-Atharav/assets/168408064/6b9a9d66-65b0-4451-b2da-1e59e2cfc1bd) +![graph 2 - swing up](https://github.com/Atharav1805/Inverted-pendulum-problems-Atharav/assets/168408064/24006527-40cf-475a-bc8a-4237c8220786) From 73a0a74f0a9b4efd96f3b75857910aee0c1ab666 Mon Sep 17 00:00:00 2001 From: Atharav1805 <168408064+Atharav1805@users.noreply.github.com> Date: Tue, 11 Jun 2024 18:32:15 +0530 Subject: [PATCH 08/22] Update Results.md --- Results.md | 47 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 41 insertions(+), 6 deletions(-) diff --git a/Results.md b/Results.md index bae0254..d7cd7f3 100644 --- a/Results.md +++ b/Results.md @@ -1,7 +1,42 @@ -1. Balance: -[balance.webm](https://github.com/Atharav1805/Inverted-pendulum-problems-Atharav/assets/168408064/9e45ce17-7df3-47fb-a1ae-0e2064d48eb7) -![graph_balance](https://github.com/Atharav1805/Inverted-pendulum-problems-Atharav/assets/168408064/cafd3725-003c-4873-a124-6810d496d66b) +# Inverted Pendulum Problems -2. Swing up: -[swing_up.webm](https://github.com/Atharav1805/Inverted-pendulum-problems-Atharav/assets/168408064/6b9a9d66-65b0-4451-b2da-1e59e2cfc1bd) -![graph 2 - swing up](https://github.com/Atharav1805/Inverted-pendulum-problems-Atharav/assets/168408064/24006527-40cf-475a-bc8a-4237c8220786) +This repository contains solutions to various inverted pendulum problems. Below are two scenarios: Balancing and Swing Up. Each scenario includes a video demonstration and a corresponding performance graph. + +## 1. Balance + +### Video Demonstration +[![Balance](https://img.youtube.com/vi/9e45ce17-7df3-47fb-a1ae-0e2064d48eb7/0.jpg)](https://github.com/Atharav1805/Inverted-pendulum-problems-Atharav/assets/168408064/9e45ce17-7df3-47fb-a1ae-0e2064d48eb7) + + + +### Performance Graph +![Graph: Balance](https://github.com/Atharav1805/Inverted-pendulum-problems-Atharav/assets/168408064/cafd3725-003c-4873-a124-6810d496d66b) + +## 2. Swing Up + +### Video Demonstration +[![Swing Up](https://img.youtube.com/vi/6b9a9d66-65b0-4451-b2da-1e59e2cfc1bd/0.jpg)](https://github.com/Atharav1805/Inverted-pendulum-problems-Atharav/assets/168408064/6b9a9d66-65b0-4451-b2da-1e59e2cfc1bd) + + + +### Performance Graph +![Graph: Swing Up](https://github.com/Atharav1805/Inverted-pendulum-problems-Atharav/assets/168408064/24006527-40cf-475a-bc8a-4237c8220786) + +## Getting Started + +To run these simulations, clone this repository and follow the instructions provided in the respective folders. + +### Prerequisites + +- Python 3.x +- [Other dependencies] + +### Installation + +```bash +git clone https://github.com/Atharav1805/Inverted-pendulum-problems-Atharav.git +cd Inverted-pendulum-problems-Atharav From 8dc5850d92ee20a6bb85f7cdab0be05ddeb56636 Mon Sep 17 00:00:00 2001 From: Atharav1805 <168408064+Atharav1805@users.noreply.github.com> Date: Tue, 11 Jun 2024 18:33:13 +0530 Subject: [PATCH 09/22] Update Results.md --- Results.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Results.md b/Results.md index d7cd7f3..b5f069c 100644 --- a/Results.md +++ b/Results.md @@ -7,9 +7,7 @@ This repository contains solutions to various inverted pendulum problems. Below ### Video Demonstration [![Balance](https://img.youtube.com/vi/9e45ce17-7df3-47fb-a1ae-0e2064d48eb7/0.jpg)](https://github.com/Atharav1805/Inverted-pendulum-problems-Atharav/assets/168408064/9e45ce17-7df3-47fb-a1ae-0e2064d48eb7) - + ### Performance Graph ![Graph: Balance](https://github.com/Atharav1805/Inverted-pendulum-problems-Atharav/assets/168408064/cafd3725-003c-4873-a124-6810d496d66b) From ac59d1508bcb3fd04daf260d4029e65972b96f27 Mon Sep 17 00:00:00 2001 From: Atharav1805 <168408064+Atharav1805@users.noreply.github.com> Date: Tue, 11 Jun 2024 18:34:03 +0530 Subject: [PATCH 10/22] Update Results.md --- Results.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Results.md b/Results.md index b5f069c..16b4e23 100644 --- a/Results.md +++ b/Results.md @@ -5,9 +5,10 @@ This repository contains solutions to various inverted pendulum problems. Below ## 1. Balance ### Video Demonstration -[![Balance](https://img.youtube.com/vi/9e45ce17-7df3-47fb-a1ae-0e2064d48eb7/0.jpg)](https://github.com/Atharav1805/Inverted-pendulum-problems-Atharav/assets/168408064/9e45ce17-7df3-47fb-a1ae-0e2064d48eb7) - + ### Performance Graph ![Graph: Balance](https://github.com/Atharav1805/Inverted-pendulum-problems-Atharav/assets/168408064/cafd3725-003c-4873-a124-6810d496d66b) @@ -15,7 +16,7 @@ This repository contains solutions to various inverted pendulum problems. Below ## 2. Swing Up ### Video Demonstration -[![Swing Up](https://img.youtube.com/vi/6b9a9d66-65b0-4451-b2da-1e59e2cfc1bd/0.jpg)](https://github.com/Atharav1805/Inverted-pendulum-problems-Atharav/assets/168408064/6b9a9d66-65b0-4451-b2da-1e59e2cfc1bd) +