The main robot class can only be used once within your project
Danger
The safety features included within KevinbotLib are not guaranteed to always function.
It is always recommended to add a physical emergency stop system to your robot.
The KevinbotLib main robot class is the starting point for your robotics project. It integrates many components of KevinbotLib to make it easy to design your own robot.
Features
The KevinbotLib Robot class sets up some components of KevinbotLib to make designing a robot easier. The components are listed below.
Call YourRobotClassName().run() to start the robot's execution
All the components listed above will be started up automatically 😀
Warning
It is not recommended to override the run method, or any other private method marked with the @final decorator.
Shutdown signals
Note
The shutdown signals are only supported on POSIX OSes (like Linux or macOS). They are not supported on Windows due to the lack of user signals in the NT kernel.
SIGUSR1
This will trigger a graceful system shutdown similar to CTRL-C on the console
This should leave the robot in a state where it's ready for a code restart
Info
This will cause the application to end with exit code 64
SIGUSR2
This will trigger an emergency shutdown similar to hitting space on the Control Console
Info
This will cause the application to end with exit code 65
Example
If the robot code's PID (process id) is 1234, you can run the following command to gracefully shut it down:
fromkevinbotlib.loggerimportLevelfromkevinbotlib.robotimportBaseRobotclassDemoRobot(BaseRobot):def__init__(self):super().__init__(opmodes=["TestOp1","TestOp2","TestOp3","TestOp4",],# robot's operational modeslog_level=Level.TRACE,# lowset logging levelenable_stderr_logger=True,cycle_time=20,# loop our robot code 20x per second - it is recommended to run much higher in practicemetrics_publish_timer=0,# the test robot doesn't use metrics - see the metrics_robot.py example for a metrics usage example)defrobot_start(self)->None:# runs once as the robot startssuper().robot_start()print("Starting robot...")# print statements are redirected to the KevinbotLib logging system - please don't do this in productiondefrobot_periodic(self,opmode:str,enabled:bool)->None:super().robot_periodic(opmode,enabled)print(f"OpMode {'enabled'ifenabledelse'disabled'}... {opmode}")defopmode_init(self,opmode:str,enabled:bool)->None:super().opmode_init(opmode,enabled)print(f"OpMode {'enabled'ifenabledelse'disabled'} init... {opmode}")defopmode_exit(self,opmode:str,enabled:bool)->None:super().opmode_exit(opmode,enabled)print(f"OpMode {'enabled'ifenabledelse'disabled'} exit... {opmode}")defrobot_end(self)->None:# runs as the robot propares to shutdownsuper().robot_end()print("Ending robot...")if__name__=="__main__":DemoRobot().run()
fromkevinbotlib.loggerimportLevelfromkevinbotlib.robotimportBaseRobotclassDemoRobot(BaseRobot):def__init__(self):super().__init__(opmodes=["TestOp1",],# robot's operational modeslog_level=Level.TRACE,# lowset logging levelenable_stderr_logger=True,cycle_time=20,# loop our robot code 20x per second - it is recommended to run much higher in practicemetrics_publish_timer=0,# the test robot doesn't use metrics - see the metrics_robot.py example for a metrics usage example)BaseRobot.register_estop_hook(lambda:print("E-STOP Hook 1"))# usually used for hardware shutdownsBaseRobot.register_estop_hook(lambda:print("E-STOP Hook 2"))# they will run in a thread - *MUST BE THREAD-SAFE*defrobot_start(self)->None:# runs once as the robot startssuper().robot_start()print("Starting robot...")# print statements are redirected to the KevinbotLib logging system - please don't do this in productionself.estop()defrobot_periodic(self,opmode:str,enabled:bool)->None:super().robot_periodic(opmode,enabled)print(f"OpMode {'enabled'ifenabledelse'disabled'}... {opmode}")defopmode_init(self,opmode:str,enabled:bool)->None:super().opmode_init(opmode,enabled)print(f"OpMode {'enabled'ifenabledelse'disabled'} init... {opmode}")defopmode_exit(self,opmode:str,enabled:bool)->None:super().opmode_exit(opmode,enabled)print(f"OpMode {'enabled'ifenabledelse'disabled'} exit... {opmode}")defrobot_end(self)->None:# runs as the robot propares to shutdownsuper().robot_end()print("Ending robot...")if__name__=="__main__":DemoRobot().run()
fromkevinbotlib.loggerimportLevelfromkevinbotlib.robotimportBaseRobotclassDemoRobot(BaseRobot):def__init__(self):super().__init__(opmodes=["TestMetricsRobot",],# robot's operational modeslog_level=Level.TRACE,# lowest logging levelenable_stderr_logger=True,cycle_time=5,# loop our robot code 5x per second - it is recommended to run much higher in practicemetrics_publish_timer=5.0,# how often to publish new system metrics to the control console)BaseRobot.add_basic_metrics(self,update_interval=2.0)# how fast to get new metrics internallydefrobot_start(self)->None:# runs once as the robot startssuper().robot_start()print("Starting robot...")# print statements are redirected to the KevinbotLib logging system - please don't do this in productiondefrobot_periodic(self,opmode:str,enabled:bool)->None:super().robot_periodic(opmode,enabled)print(self.metrics.getall())defopmode_init(self,opmode:str,enabled:bool)->None:super().opmode_init(opmode,enabled)print(f"OpMode {'enabled'ifenabledelse'disabled'} init... {opmode}")defopmode_exit(self,opmode:str,enabled:bool)->None:super().opmode_exit(opmode,enabled)print(f"OpMode {'enabled'ifenabledelse'disabled'} exit... {opmode}")defrobot_end(self)->None:# runs as the robot propares to shutdownsuper().robot_end()print("Ending robot...")if__name__=="__main__":DemoRobot().run()
fromkevinbotlib.loggerimportLevelfromkevinbotlib.robotimportBaseRobotclassDemoRobot(BaseRobot):def__init__(self):super().__init__(opmodes=["OpModeThatWillEnable","OpModeThatWillDisable","OpModeThatWillEStop","OpModeThatWill1stOpMode",],# robot's operational modeslog_level=Level.TRACE,# lowset logging levelenable_stderr_logger=True,cycle_time=20,# loop our robot code 20x per second - it is recommended to run much higher in practicemetrics_publish_timer=0,# the test robot doesn't use metrics - see the metrics_robot.py example for a metrics usage exampleallow_enable_without_console=True,# * allow the robot to enable without the prescence of a control console)defrobot_start(self)->None:# runs once as the robot startssuper().robot_start()print("Starting robot...")# print statements are redirected to the KevinbotLib logging system - please don't do this in productiondefrobot_periodic(self,opmode:str,enabled:bool)->None:super().robot_periodic(opmode,enabled)print(f"OpMode {'enabled'ifenabledelse'disabled'}... {opmode}")defopmode_init(self,opmode:str,enabled:bool)->None:super().opmode_init(opmode,enabled)print(f"OpMode {'enabled'ifenabledelse'disabled'} init... {opmode}")ifopmode=="OpModeThatWillEnable":self.enabled=Trueifopmode=="OpModeThatWillDisable":self.enabled=Falseifopmode=="OpModeThatWillEStop":self.estop()ifopmode=="OpModeThatWill1stOpMode":self.opmode=self.opmodes[0]defopmode_exit(self,opmode:str,enabled:bool)->None:super().opmode_exit(opmode,enabled)print(f"OpMode {'enabled'ifenabledelse'disabled'} exit... {opmode}")defrobot_end(self)->None:# runs as the robot propares to shutdownsuper().robot_end()print("Ending robot...")if__name__=="__main__":DemoRobot().run()