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)
+
+
+2. Swing up:
+[swing_up.webm](https://github.com/Atharav1805/Inverted-pendulum-problems-Atharav/assets/168408064/6b9a9d66-65b0-4451-b2da-1e59e2cfc1bd)
+
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)
-
+# Inverted Pendulum Problems
-2. Swing up:
-[swing_up.webm](https://github.com/Atharav1805/Inverted-pendulum-problems-Atharav/assets/168408064/6b9a9d66-65b0-4451-b2da-1e59e2cfc1bd)
-
+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
+[](https://github.com/Atharav1805/Inverted-pendulum-problems-Atharav/assets/168408064/9e45ce17-7df3-47fb-a1ae-0e2064d48eb7)
+
+
+
+### Performance Graph
+
+
+## 2. Swing Up
+
+### Video Demonstration
+[](https://github.com/Atharav1805/Inverted-pendulum-problems-Atharav/assets/168408064/6b9a9d66-65b0-4451-b2da-1e59e2cfc1bd)
+
+
+
+### Performance Graph
+
+
+## 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
[](https://github.com/Atharav1805/Inverted-pendulum-problems-Atharav/assets/168408064/9e45ce17-7df3-47fb-a1ae-0e2064d48eb7)
-
+
### Performance Graph

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
-[](https://github.com/Atharav1805/Inverted-pendulum-problems-Atharav/assets/168408064/9e45ce17-7df3-47fb-a1ae-0e2064d48eb7)
-
+
### Performance Graph

@@ -15,7 +16,7 @@ This repository contains solutions to various inverted pendulum problems. Below
## 2. Swing Up
### Video Demonstration
-[](https://github.com/Atharav1805/Inverted-pendulum-problems-Atharav/assets/168408064/6b9a9d66-65b0-4451-b2da-1e59e2cfc1bd)
+