Repository: WPI-MMR/gym_solo

Issue:
Create Never Ending Termination
A couple of PRs have this issue (#33, #35), but if a user wants to run gym indefinitely, they would need to create a `TimeBasedTermination` with a really big number. While that works, it's pretty jank and we should just make a `NoTermination` which just goes on forever instead.

Discussion:

Patch:
diff --git a/examples/solo8_vanilla/interactive_pos_control.py b/examples/solo8_vanilla/interactive_pos_control.py
index 8773e53..446e3c4 100644
--- a/examples/solo8_vanilla/interactive_pos_control.py
+++ b/examples/solo8_vanilla/interactive_pos_control.py
@@ -17,8 +17,7 @@ if __name__ == '__main__':
 
   env.obs_factory.register_observation(obs.TorsoIMU(env.robot))
   env.reward_factory.register_reward(1,rewards.UprightReward(env.robot))
-  env.termination_factory.register_termination(
-    terms.TimeBasedTermination(10000000))
+  env.termination_factory.register_termination(terms.PerpetualTermination())
 
   joint_params = []
   num_joints = env.client.getNumJoints(env.robot)
diff --git a/examples/solo8_vanilla/observation_dump.py b/examples/solo8_vanilla/observation_dump.py
index 68bdde0..3dc3df9 100644
--- a/examples/solo8_vanilla/observation_dump.py
+++ b/examples/solo8_vanilla/observation_dump.py
@@ -19,8 +19,7 @@ if __name__ == '__main__':
 
   env.obs_factory.register_observation(obs.TorsoIMU(env.robot))
   env.reward_factory.register_reward(1,rewards.UprightReward(env.robot))
-  env.termination_factory.register_termination(
-    terms.TimeBasedTermination(100000000))
+  env.termination_factory.register_termination(terms.PerpetualTermination())
 
   try:
     print("""\n
diff --git a/gym_solo/core/termination.py b/gym_solo/core/termination.py
index 6135f8a..72a7b33 100644
--- a/gym_solo/core/termination.py
+++ b/gym_solo/core/termination.py
@@ -80,4 +80,19 @@ class TimeBasedTermination(Termination):
     Otherwise return false.
     """
     self.step_delta += 1
-    return self.step_delta > self.max_step_delta 
\ No newline at end of file
+    return self.step_delta > self.max_step_delta 
+
+
+class PerpetualTermination(Termination):
+  """Termination condition that never ends. Useful for demos / testing."""
+  def reset(self):
+    """Unneeded."""
+    pass
+
+  def is_terminated(self) -> bool:
+    """Always returns that the episode is *not* terminated.
+
+    Returns:
+      bool: False
+    """
+    return False
\ No newline at end of file


Test patch:
diff --git a/gym_solo/core/test_termination_conditions.py b/gym_solo/core/test_termination_conditions.py
index bad6698..a6979b4 100644
--- a/gym_solo/core/test_termination_conditions.py
+++ b/gym_solo/core/test_termination_conditions.py
@@ -27,4 +27,13 @@ class TestTimeBasedTermination(unittest.TestCase):
         self.assertEqual(i+1, term.step_delta)
 
       self.assertEqual(True, term.is_terminated())
-      self.assertEqual(max_step_delta + 1, term.step_delta)
\ No newline at end of file
+      self.assertEqual(max_step_delta + 1, term.step_delta)
+
+
+class TestPerpetualTermination(unittest.TestCase):
+  def test_is_terminated(self):
+    term = termination.PerpetualTermination()
+
+    # Arbitrary count, just need to ensure that always returns False
+    for i in range(1000): 
+      self.assertFalse(term.is_terminated())
\ No newline at end of file