Last active
January 18, 2023 20:58
-
-
Save Banteel/052cfa540994bc94c4756681134a415a to your computer and use it in GitHub Desktop.
Simple Dock with ChargerMarker: Creating streamlined tactics to get Cozmo on it's charger using a printed ChargerMarker. (This script requires Python 3.7 to 3.9 to run as it uses an Asyncio Gather running 2 processes at the same time)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
# based on Copyright (c) 2016 Anki, Inc. | |
# | |
# Licensed under the Apache License, Version 2.0 (the "License"); | |
# you may not use this file except in compliance with the License. | |
# You may obtain a copy of the License in the file LICENSE.txt or at | |
# | |
# http://www.apache.org/licenses/LICENSE-2.0 | |
# | |
# Unless required by applicable law or agreed to in writing, software | |
# distributed under the License is distributed on an "AS IS" BASIS, | |
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
# See the License for the specific language governing permissions and | |
# limitations under the License. | |
# | |
# | |
# simple_dock_with_chargermarker | |
# This script will use Walls & a Charger Marker to locat the Charger while using an asyncio.gather() | |
# The Walls, FreePlay Lights, & Charger Marker can be turned off & on as needed | |
# These Definitions are Asyncio Definitions and must require a Python version that can run Asyncio scripts | |
# This script is an attempt to get Cozmo to see either the Charger or the Charger Marker at the same time | |
# This script does not require any of these options to be turned on, all you need is a Charger | |
# forked script from: cozmo_unleashed | |
# | |
# Original perpetual Cozmo_Unleashed script by AcidZebra | |
# This Script is made by VictorTagayun and is heavily slimmed down to only docking | |
# Script based on the Cozmo SDK drive_to_charger example script | |
# and raproenca's modifications of same. | |
# | |
# Additional modifications by Banteel to streamline the two 90 degree turns in one simple | |
# command that is linked to position.angle_z of object "charger" which contains all the info. | |
# Also modifications by Banteel to the goto_object by inserting a position angle into it. | |
# | |
#import required functions | |
import sys, os, datetime, random, time, math, re, threading | |
##import logging | |
import asyncio, cozmo, cozmo.objects, cozmo.util, cozmo.anim, cozmo.run | |
from cozmo.util import degrees, Angle, Distance, distance_mm, Speed, speed_mmps, Pose, pose_z_angle, rotation_z_angle | |
from cozmo.objects import CustomObject, CustomObjectMarkers, CustomObjectTypes, LightCube | |
from cozmo.behavior import BehaviorTypes | |
from cozmo.anim import Triggers | |
from cozmo.robot_alignment import RobotAlignmentTypes | |
from asyncio.tasks import create_task, gather | |
global robot, charger, freeplay, robotvolume, found_object, custom_objects, marker_time, use_cubes, use_walls | |
global use_scheduler, scheduled_days, scheduled_time | |
robot = cozmo.robot.Robot | |
custom_objects=[] | |
found_object=None | |
freeplay=0 | |
marker_time=0 | |
scheduled_days="None" | |
scheduled_time=0 | |
# | |
#============================ | |
# CONFIGURABLE VARIABLES HERE | |
#============================ | |
# | |
# BATTERY VOLTAGE THRESHOLDS | |
# | |
# lowbatvolt - when voltage drops below this Cozmo will start looking for his charger | |
# highbatvolt - when cozmo comes off your charger fully charge, this value will self-calibrate | |
# maxbatvolt - the maximum battery level as recorded when cozmo is on charger but no longer charging | |
# tweak lowbatvolt to suit your cozmo. default value is 3.65 | |
lowbatvolt = 3.65 | |
#highbatvolt= 4.04 - currently not used | |
#maxbatvolt = 4.54 - currently not used | |
# | |
# COZMO'S VOICE VOLUME | |
# what volume Cozmo should play sounds at, value between 0 and 1 | |
robotvolume = 0.05 | |
# | |
# CUBE USAGE | |
# | |
# whether or not to activate the cubes (saves battery if you don't) | |
# I almost always leave this off, he will still stack them and mess around with them | |
# some games like "block guard dog" will not come up unless the blocks are active | |
# | |
# value of 0: cubes off & cube's lights off | |
# value of 1: cubes on & enables all games | |
# value of 2: cubes on & cube's freeplay lights on & in-schedule breathing lights off | |
# value of 3: cubes on & cube's freeplay lights on & in-schedule breathing lights on | |
# value between 0 and 3 | |
use_cubes = 0 | |
# | |
# MARKER WALLS USAGE | |
# | |
# whether or not you are using printed out markers for walls on your play field | |
# if you are using walls, you will likely need to configure wall sizes to your play area | |
# values between 0 and 1 | |
use_walls = 0 | |
# | |
# SCHEDULER USAGE | |
# | |
# whether or not to use the schedule to define allowed "play times" | |
# this code is a bit rough, use at your own risk | |
# value between 0 and 1 | |
use_scheduler = 0 | |
# | |
# SCHEDULE START & STOP SETTING IN 24HR TIME FORMAT ex. 0 to 23 | |
# | |
if use_scheduler == 1: | |
# Initialize Scheduler Variables | |
global wkDS, wkDSm, wkDE, wkDEm, wkNS, wkNSm, wkNE, wkNEm, wkEDS, wkEDSm, wkEDE, wkEDEm, wkENS, wkENSm, wkENE, wkENEm, wday | |
# Week Days | |
wkDS = 20 # Week (D)ay's (S)tarting time hour, default is 7AM | |
wkDSm = 30 # Week (D)ay's (S)tarting time minute | |
wkDE = 0 # Week (D)ay's (E)nding time hour, default is 8AM | |
wkDEm = 55 # Week (D)ay's (E)nding time minute | |
# Week Day Nights | |
wkNS = 1 # Week (N)ight's (S)tarting time hour, default is 3PM | |
wkNSm = 55 # Week (N)ight's (S)tarting time minute | |
wkNE = 0 # Week (N)ight's (E)nding time hour, default is 11PM | |
wkNEm = 5 # Week (N)ight's (E)nding time minute | |
# Week End Days | |
wkEDS = 1 # Week(E)nd (D)ay's (S)tarting time hour, default is 9AM | |
wkEDSm = 10 # Week(E)nd (D)ay's (S)tarting time minute | |
wkEDE = 2 # Week(E)nd (D)ay's (E)nding time hour, default is 12PM | |
wkEDEm = 25 # Week(E)nd (D)ay's (E)nding time minute | |
# Week End Nights | |
wkENS = 3 # Week(E)nd (N)ight's (S)tarting time hour, default is 3PM | |
wkENSm = 10 # Week(E)nd (N)ight's (S)tarting time minute | |
wkENE = 0 # Week(E)nd (N)ight's (E)nding time hour, default is 11PM | |
wkENEm = 22 # Week(E)nd (N)ight's (E)nding time minute | |
# | |
#COZMO SCHEDULER DEFAULT TIME SETTINGS: | |
## Week Days | |
#wkDS = 7 # Week (D)ay's (S)tarting time hour, default is 7AM | |
#wkDSm = 15 # Week (D)ay's (S)tarting time minute | |
#wkDE = 8 # Week (D)ay's (E)nding time hour, default is 8AM | |
#wkDEm = 35 # Week (D)ay's (E)nding time minute | |
# | |
## Week Day Nights | |
#wkNS = 15 # Week (N)ight's (S)tarting time hour, default is 3PM | |
#wkNSm = 35 # Week (N)ight's (S)tarting time minute | |
#wkNE = 23 # Week (N)ight's (E)nding time hour, default is 11PM | |
#wkNEm = 15 # Week (N)ight's (E)nding time minute | |
# | |
## Week End Days | |
#wkEDS = 9 # Week(E)nd (D)ay's (S)tarting time hour, default is 9AM | |
#wkEDSm = 0 # Week(E)nd (D)ay's (S)tarting time minute | |
#wkEDE = 12 # Week(E)nd (D)ay's (E)nding time hour, default is 12PM | |
#wkEDEm = 20 # Week(E)nd (D)ay's (E)nding time minute | |
# | |
## Week End Nights | |
#wkENS = 15 # Week(E)nd (N)ight's (S)tarting time hour, default is 3PM | |
#wkENSm = 35 # Week(E)nd (N)ight's (S)tarting time minute | |
#wkENE = 23 # Week(E)nd (N)ight's (E)nding time hour, default is 11PM | |
#wkENEm = 58 # Week(E)nd (N)ight's (E)nding time minute | |
# | |
# ##### | |
# I define goto_chargermarker_pose, find_chargermarker, lookaround_behaviour, and freeplay_lookaround_behaviour | |
# separated into 4 definitions so a gather() can perform concurrent charger & chargermarker lookaround routines | |
# | |
## define goto_chargermarker_pose behaviour | |
async def goto_chargermarker_pose(robot: robot): | |
global charger, custom_objects, found_object | |
counter=0 | |
while robot.world.charger == None: | |
if str(found_object.object_type) == "CustomObjectTypes.CustomType01" and charger==None: | |
if found_object.is_visible==False: | |
try: | |
await robot.turn_in_place(degrees(found_object.pose.rotation.angle_z.degrees), num_retries=1, accel=degrees(80), angle_tolerance=None, is_absolute=True).wait_for_completed() | |
except: | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: failed to turn in place, battery %s" % str(round(robot.battery_voltage, 2))) | |
if found_object.is_visible==False: | |
raise asyncio.CancelledError() | |
try: | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: custom object found, traveling, battery %s" % str(round(robot.battery_voltage, 2))) | |
action = robot.go_to_pose(pose_z_angle(found_object.pose.position.x, found_object.pose.position.y, found_object.pose.position.z, angle_z=degrees(found_object.pose.rotation.angle_z.degrees))) | |
await action.wait_for_completed() | |
except: | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: failed to goto pose, battery %s" % str(round(robot.battery_voltage, 2))) | |
await robot.wait_for_all_actions_completed() | |
await asyncio.sleep(0.5) | |
try: | |
await robot.turn_in_place(degrees(found_object.pose.rotation.angle_z.degrees), num_retries=1, accel=degrees(80), angle_tolerance=None, is_absolute=True).wait_for_completed() | |
except: | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: failed to turn in place, battery %s" % str(round(robot.battery_voltage, 2))) | |
try: | |
await robot.set_head_angle(degrees(0)).wait_for_completed() | |
except: | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: failed to set head angle, battery %s" % str(round(robot.battery_voltage, 2))) | |
await robot.wait_for_all_actions_completed() | |
await asyncio.sleep(3) | |
if robot.world.charger != None: | |
charger = robot.world.charger | |
robot.world.charger=None | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: found charger after goto chargermarker, battery %s" % str(round(robot.battery_voltage, 2))) | |
await asyncio.sleep(0.5) | |
try: | |
await robot.turn_in_place(degrees(found_object.pose.rotation.angle_z.degrees), num_retries=1, accel=degrees(80), angle_tolerance=None, is_absolute=True).wait_for_completed() | |
except: | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: failed to turn in place, battery %s" % str(round(robot.battery_voltage, 2))) | |
try: | |
await robot.drive_straight(distance_mm(-120), speed_mmps(40)).wait_for_completed() | |
await robot.wait_for_all_actions_completed() | |
except: | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: failed to drive straight, battery %s" % str(round(robot.battery_voltage, 2))) | |
try: | |
action = robot.go_to_object(charger, distance_mm(100), RobotAlignmentTypes.LiftPlate, num_retries=3) | |
await action.wait_for_completed() | |
await robot.wait_for_all_actions_completed() | |
except: | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: failed to goto object, battery %s" % str(round(robot.battery_voltage, 2))) | |
try: | |
action = robot.go_to_object(charger, distance_mm(80), RobotAlignmentTypes.LiftPlate, num_retries=3) | |
await action.wait_for_completed() | |
await robot.wait_for_all_actions_completed() | |
except: | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: failed to goto object, battery %s" % str(round(robot.battery_voltage, 2))) | |
try: | |
action = robot.go_to_object(charger, distance_mm(60), RobotAlignmentTypes.LiftPlate, num_retries=3) | |
await action.wait_for_completed() | |
await robot.wait_for_all_actions_completed() | |
except: | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: failed to goto object, battery %s" % str(round(robot.battery_voltage, 2))) | |
raise asyncio.CancelledError() | |
if charger == None: | |
await asyncio.sleep(0.5) | |
try: | |
await robot.turn_in_place(degrees(found_object.pose.rotation.angle_z.degrees), num_retries=1, accel=degrees(80), angle_tolerance=None, is_absolute=True).wait_for_completed() | |
except: | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: failed to turn in place, battery %s" % str(round(robot.battery_voltage, 2))) | |
try: | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: can't see charger, backup a bit, battery %s" % str(round(robot.battery_voltage, 2))) | |
await robot.drive_straight(distance_mm(-80), speed_mmps(40)).wait_for_completed() | |
except: | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: failed to drive straight, battery %s" % str(round(robot.battery_voltage, 2))) | |
else: | |
await asyncio.sleep(0.5) | |
try: | |
await robot.turn_in_place(degrees(found_object.pose.rotation.angle_z.degrees), num_retries=1, accel=degrees(80), angle_tolerance=None, is_absolute=True).wait_for_completed() | |
except: | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: failed to turn in place, battery %s" % str(round(robot.battery_voltage, 2))) | |
try: | |
await robot.drive_straight(distance_mm(-40), speed_mmps(40)).wait_for_completed() | |
except: | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: failed to drive straight, battery %s" % str(round(robot.battery_voltage, 2))) | |
try: | |
await robot.turn_in_place(degrees(found_object.pose.rotation.angle_z.degrees), num_retries=1, accel=degrees(80), angle_tolerance=None, is_absolute=True).wait_for_completed() | |
except: | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: failed to turn in place, battery %s" % str(round(robot.battery_voltage, 2))) | |
await robot.wait_for_all_actions_completed() | |
try: | |
charger = await robot.world.wait_for_observed_charger(timeout=1.5, include_existing=True) | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: found charger after backup!, battery %s" % str(round(robot.battery_voltage, 2))) | |
found_object=None | |
custom_objects=[0] | |
raise asyncio.CancelledError() | |
except asyncio.TimeoutError: | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: i don't see the charger, battery %s" % str(round(robot.battery_voltage, 2))) | |
await asyncio.sleep(1) | |
if charger == None: | |
await asyncio.sleep(0.5) | |
try: | |
await robot.turn_in_place(degrees(found_object.pose.rotation.angle_z.degrees), num_retries=1, accel=degrees(80), angle_tolerance=None, is_absolute=True).wait_for_completed() | |
except: | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: failed to turn in place, battery %s" % str(round(robot.battery_voltage, 2))) | |
try: | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: can't see charger, backup a bit more, battery %s" % str(round(robot.battery_voltage, 2))) | |
await robot.drive_straight(distance_mm(-60), speed_mmps(40)).wait_for_completed() | |
except: | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: failed to drive straight, battery %s" % str(round(robot.battery_voltage, 2))) | |
else: | |
await asyncio.sleep(0.5) | |
try: | |
await robot.turn_in_place(degrees(found_object.pose.rotation.angle_z.degrees), num_retries=1, accel=degrees(80), angle_tolerance=None, is_absolute=True).wait_for_completed() | |
except: | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: failed to turn in place, battery %s" % str(round(robot.battery_voltage, 2))) | |
try: | |
await robot.drive_straight(distance_mm(-40), speed_mmps(40)).wait_for_completed() | |
except: | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: failed to drive straight, battery %s" % str(round(robot.battery_voltage, 2))) | |
await asyncio.sleep(0.5) | |
try: | |
await robot.turn_in_place(degrees(found_object.pose.rotation.angle_z.degrees), num_retries=1, accel=degrees(80), angle_tolerance=None, is_absolute=True).wait_for_completed() | |
except: | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: failed to turn in place, battery %s" % str(round(robot.battery_voltage, 2))) | |
try: | |
charger = await robot.world.wait_for_observed_charger(timeout=1.5, include_existing=True) | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: found charger after backup!, battery %s" % str(round(robot.battery_voltage, 2))) | |
found_object=None | |
custom_objects=[0] | |
raise asyncio.CancelledError() | |
except asyncio.TimeoutError: | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: i still don't see the charger, battery %s" % str(round(robot.battery_voltage, 2))) | |
await asyncio.sleep(1) | |
await robot.set_head_angle(degrees(10)).wait_for_completed() | |
await robot.wait_for_all_actions_completed() | |
await asyncio.sleep(1) | |
if found_object.is_visible==False: | |
await asyncio.sleep(0.5) | |
try: | |
await robot.turn_in_place(degrees(found_object.pose.rotation.angle_z.degrees), num_retries=1, accel=degrees(80), angle_tolerance=None, is_absolute=True).wait_for_completed() | |
except: | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: failed to turn in place, battery %s" % str(round(robot.battery_voltage, 2))) | |
try: | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: can't see chargermarker, backup a lot, battery %s" % str(round(robot.battery_voltage, 2))) | |
await robot.drive_straight(distance_mm(-70), speed_mmps(40)).wait_for_completed() | |
except: | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: failed to drive straight, battery %s" % str(round(robot.battery_voltage, 2))) | |
try: | |
charger = await robot.world.wait_for_observed_charger(timeout=1.5, include_existing=True) | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: found charger after backup!, battery %s" % str(round(robot.battery_voltage, 2))) | |
found_object=None | |
custom_objects=[0] | |
raise asyncio.CancelledError() | |
except asyncio.TimeoutError: | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: did not find charger, try again, battery %s" % str(round(robot.battery_voltage, 2))) | |
if found_object.is_visible==False: | |
raise asyncio.CancelledError() | |
await robot.wait_for_all_actions_completed() | |
if charger == None and robot.world.charger == None: | |
counter+=1 | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: chargermarker goto retry: "+str(counter)) | |
if counter > 1: | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: chargermarker goto failed, resetting, battery %s" % str(round(robot.battery_voltage, 2))) | |
found_object=None | |
custom_objects=[0] | |
raise asyncio.CancelledError() | |
found_object=None | |
custom_objects=[0] | |
robot.clear_idle_animation() | |
robot.abort_all_actions(log_abort_messages=False) | |
await asyncio.sleep(2) | |
## define look_for_chargermarker behaviour | |
async def find_chargermarker(robot: robot): | |
global charger, freeplay, found_object, custom_objects, marker_time | |
if robot.is_on_charger == 1: | |
freeplay = 0 | |
robot.clear_idle_animation() | |
robot.abort_all_actions(log_abort_messages=False) | |
robot.enable_all_reaction_triggers(False) | |
robot.world.disconnect_from_cubes() | |
raise asyncio.CancelledError() | |
end_time = time.time() + marker_time | |
while str(custom_objects[0].object_type) != "CustomObjectTypes.CustomType01": | |
try: | |
custom_objects = await robot.world.wait_until_observe_num_objects(num=1, object_type = CustomObject, timeout=30.2, include_existing=True) | |
except asyncio.CancelledError or asyncio.TimeoutError or time.time() > end_time or charger != None: | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: chargermarker routine cancelled, battery %s" % str(round(robot.battery_voltage, 2))) | |
custom_objects[0]=None | |
if charger != None: | |
break | |
raise | |
finally: | |
await asyncio.sleep(0.1) | |
if custom_objects != None and str(custom_objects[0].object_type) == "CustomObjectTypes.CustomType01": | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: found chargermarker in lookaround, battery %s" % str(round(robot.battery_voltage, 2))) | |
found_object=custom_objects[0] | |
robot.abort_all_actions(log_abort_messages=False) | |
await asyncio.sleep(0.1) | |
break | |
if time.time() > end_time: | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: unable to find chargermarker in lookaround, battery %s" % str(round(robot.battery_voltage, 2))) | |
break | |
if charger != None: | |
break | |
custom_objects[0]=None | |
for r in asyncio.all_tasks(): | |
r.cancel() | |
await asyncio.sleep(0.1) | |
raise asyncio.CancelledError() | |
## define freeplay_bahaviour | |
async def freeplay_lookaround_behaviour(robot: robot): | |
global charger, freeplay | |
if robot.is_on_charger == 1: | |
freeplay = 0 | |
robot.clear_idle_animation() | |
robot.abort_all_actions(log_abort_messages=False) | |
robot.enable_all_reaction_triggers(False) | |
robot.world.disconnect_from_cubes() | |
raise asyncio.CancelledError() | |
#try freeplay for 90 seconds, if found charger finally stop freeplay | |
try: | |
charger = await robot.world.wait_for_observed_charger(timeout=90, include_existing=True) | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: found the charger in 90seconds playtime, battery %s" % str(round(robot.battery_voltage, 2))) | |
for r in asyncio.all_tasks(): | |
r.cancel() | |
raise | |
except asyncio.TimeoutError: | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: charger not found after 90sec fallback, battery %s" % str(round(robot.battery_voltage, 2))) | |
await robot.play_anim_trigger(Triggers.CodeLabUnhappy, ignore_body_track=True).wait_for_completed() | |
#await asyncio.sleep(2) | |
await robot.set_head_angle(degrees(0)).wait_for_completed() | |
raise | |
except asyncio.CancelledError: | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: freeplay fallback routine cancelled, battery %s" % str(round(robot.battery_voltage, 2))) | |
raise | |
finally: | |
robot.clear_idle_animation() | |
await asyncio.sleep(0.5) | |
raise | |
## define lookaround_behaviour | |
async def lookaround_behaviour(robot: robot): | |
global charger, freeplay, found_object, custom_objects | |
if robot.is_on_charger == 1: | |
freeplay = 0 | |
robot.clear_idle_animation() | |
robot.abort_all_actions(log_abort_messages=False) | |
robot.enable_all_reaction_triggers(False) | |
robot.world.disconnect_from_cubes() | |
raise asyncio.CancelledError() | |
while robot.is_picked_up == True: | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: robot is flipped on back, battery %s" % str(round(robot.battery_voltage, 2))) | |
robot.enable_all_reaction_triggers(True) | |
await asyncio.sleep(10) | |
robot.enable_all_reaction_triggers(False) | |
await robot.wait_for_all_actions_completed() | |
try: | |
charger = await robot.world.wait_for_observed_charger(timeout=30, include_existing=True) | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: found charger in lookaround, battery %s" % str(round(robot.battery_voltage, 2))) | |
for r in asyncio.all_tasks(): | |
r.cancel() | |
raise | |
except asyncio.TimeoutError: | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: timedout in lookaround for charger, battery %s" % str(round(robot.battery_voltage, 2))) | |
await robot.play_anim_trigger(Triggers.CodeLabUnhappy, ignore_body_track=True).wait_for_completed() | |
await asyncio.sleep(2) | |
await robot.set_head_angle(degrees(0), in_parallel=True).wait_for_completed() | |
await robot.wait_for_all_actions_completed() | |
raise | |
except asyncio.CancelledError or str(custom_objects[0].object_type) == "CustomObjectTypes.CustomType01": | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: lookaround routine cancelled, battery %s" % str(round(robot.battery_voltage, 2))) | |
raise | |
finally: | |
# stop the behavior | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: stop lookaround, battery %s" % str(round(robot.battery_voltage, 2))) | |
robot.clear_idle_animation() | |
await asyncio.sleep(0.5) | |
raise | |
## define look for charger and goto routine | |
async def find_charger_and_goto(robot: robot): | |
global charger, freeplay, found_object, custom_objects, temp_object, marker_time, lowbatvolt, scheduled_time | |
# do we know where the charger is or not | |
if not charger: | |
# we will look around in place for the charger for 30 seconds | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: look around for charger, battery %s" % str(round(robot.battery_voltage, 2))) | |
robot.abort_all_actions(False) | |
robot.clear_idle_animation() | |
await robot.wait_for_all_actions_completed() | |
await robot.play_anim_trigger(Triggers.SparkIdle, ignore_body_track=True).wait_for_completed() | |
await asyncio.sleep(2) | |
#await robot.wait_for_all_actions_completed() | |
await robot.set_head_angle(degrees(0)).wait_for_completed() | |
robot.move_lift(-3) | |
marker_time=30.0 | |
#robot.start_behavior(cozmo.robot.behavior.BehaviorTypes.LookAroundInPlace) | |
robot.start_behavior(BehaviorTypes.LookAroundInPlace) | |
try: | |
await gather( | |
create_task( | |
lookaround_behaviour(robot)), | |
create_task( | |
find_chargermarker(robot)), | |
return_exceptions=True | |
) | |
except asyncio.CancelledError: | |
pass | |
robot.start_behavior(BehaviorTypes.LookAroundInPlace).stop() | |
await asyncio.sleep(3) | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: look around stopped, battery %s" % str(round(robot.battery_voltage, 2))) | |
robot.clear_idle_animation() | |
await robot.wait_for_all_actions_completed() | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: waited for all actions completed, battery %s" % str(round(robot.battery_voltage, 2))) | |
await asyncio.sleep(2) | |
robot.abort_all_actions(False) | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: aborted all actions, battery %s" % str(round(robot.battery_voltage, 2))) | |
if found_object != None and charger==None: | |
try: | |
await goto_chargermarker_pose(robot) | |
except asyncio.CancelledError: | |
pass | |
# Charger location and docking handling here | |
if charger: | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: docking mode, moving to charger, battery %s" % str(round(robot.battery_voltage, 2))) | |
while (robot.is_on_charger == 0): | |
# check to make sure we didn't get here from a battery spike | |
if (robot.battery_voltage > lowbatvolt + 0.03) and (scheduled_time == 1): | |
raise asyncio.CancelledError() | |
#break | |
# Yes! Attempt to drive near to the charger, and then stop. | |
robot.clear_idle_animation() | |
await robot.wait_for_all_actions_completed() | |
await robot.play_anim_trigger(Triggers.CodeLabChatty, ignore_body_track=True, ignore_head_track=True).wait_for_completed() | |
await asyncio.sleep(1) | |
await robot.wait_for_all_actions_completed() | |
robot.move_lift(-3) | |
await robot.set_head_angle(degrees(0)).wait_for_completed() | |
# If you are running Cozmo on carpet, try turning these num_retries up to 4 or 5 | |
try: | |
action = robot.go_to_object(charger, distance_mm(160), RobotAlignmentTypes.LiftPlate, num_retries=3) | |
await action.wait_for_completed() | |
finally: | |
pass | |
try: | |
action = robot.go_to_object(charger, distance_mm(100), RobotAlignmentTypes.LiftPlate, num_retries=3) | |
await action.wait_for_completed() | |
finally: | |
pass | |
try: | |
action = robot.go_to_object(charger, distance_mm(80), RobotAlignmentTypes.LiftPlate, num_retries=3) | |
await action.wait_for_completed() | |
finally: | |
pass | |
try: | |
action = robot.go_to_object(charger, distance_mm(60), RobotAlignmentTypes.LiftPlate, num_retries=3) | |
await action.wait_for_completed() | |
finally: | |
pass | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: straighten out, backup, and reposition, battery %s" % str(round(robot.battery_voltage, 2))) | |
try: | |
await robot.turn_in_place(degrees(charger.pose.rotation.angle_z.degrees), num_retries=3, accel=degrees(80), angle_tolerance=None, is_absolute=True).wait_for_completed() | |
finally: | |
pass | |
try: | |
await robot.drive_straight(distance_mm(-70), speed_mmps(40)).wait_for_completed() | |
finally: | |
pass | |
try: | |
action = robot.go_to_object(charger, distance_mm(100), RobotAlignmentTypes.LiftPlate, num_retries=3) | |
await action.wait_for_completed() | |
finally: | |
pass | |
try: | |
action = robot.go_to_object(charger, distance_mm(60), RobotAlignmentTypes.LiftPlate, num_retries=3) | |
await action.wait_for_completed() | |
finally: | |
pass | |
try: | |
action = robot.go_to_object(charger, distance_mm(40), RobotAlignmentTypes.LiftPlate, num_retries=3) | |
await action.wait_for_completed() | |
finally: | |
pass | |
# we should be right in front of the charger, can we see it? | |
await asyncio.sleep(1) | |
if (charger.is_visible == False): | |
#we know where the charger is | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: can't see charger, position is still known, battery %s" % str(round(robot.battery_voltage, 2))) | |
await robot.play_anim_trigger(Triggers.CodeLabSurprise, ignore_body_track=True, ignore_head_track=True).wait_for_completed() | |
await asyncio.sleep(1) | |
await robot.wait_for_all_actions_completed() | |
await robot.set_head_angle(degrees(0)).wait_for_completed() | |
await robot.turn_in_place(degrees(charger.pose.rotation.angle_z.degrees), accel=degrees(80), angle_tolerance=None, is_absolute=True).wait_for_completed() | |
if (charger.is_visible == False): | |
# we don't know where the charger is anymore | |
charger = None | |
robot.world.charger = None | |
found_object = None | |
custom_objects = [0] | |
temp_object = None | |
await robot.play_anim_trigger(Triggers.ReactToPokeReaction, ignore_body_track=True, ignore_head_track=True, ignore_lift_track=True).wait_for_completed() | |
await asyncio.sleep(1) | |
await robot.wait_for_all_actions_completed() | |
await robot.drive_straight(distance_mm(-70), speed_mmps(50)).wait_for_completed() | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: charger not found, clearing charger map location. battery %s" % str(round(robot.battery_voltage, 2))) | |
await asyncio.sleep(1) | |
break | |
try: | |
action = robot.go_to_object(charger, distance_mm(110), RobotAlignmentTypes.LiftPlate, num_retries=3) | |
await action.wait_for_completed() | |
finally: | |
pass | |
try: | |
action = robot.go_to_object(charger, distance_mm(80), RobotAlignmentTypes.LiftPlate, num_retries=3) | |
await action.wait_for_completed() | |
finally: | |
pass | |
await robot.turn_in_place(degrees(charger.pose.rotation.angle_z.degrees), accel=degrees(80), angle_tolerance=None, is_absolute=True).wait_for_completed() | |
i = random.randint(1, 100) | |
if i >= 85: | |
await robot.play_anim_trigger(Triggers.FeedingReactToShake_Normal, ignore_body_track=True, ignore_head_track=True).wait_for_completed() | |
await asyncio.sleep(2) | |
await robot.wait_for_all_actions_completed() | |
# Now in position. Turn around and drive backwards | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: docking, battery %s" % str(round(robot.battery_voltage, 2))) | |
await asyncio.sleep(2.5) | |
if robot.is_animating: | |
robot.clear_idle_animation() | |
robot.abort_all_actions(log_abort_messages=True) | |
await robot.wait_for_all_actions_completed() | |
await robot.wait_for_all_actions_completed() | |
await robot.turn_in_place(degrees(charger.pose.rotation.angle_z.degrees - 180), accel=degrees(100), angle_tolerance=None, is_absolute=True).wait_for_completed() | |
await robot.wait_for_all_actions_completed() | |
await asyncio.sleep(0.1) | |
await robot.play_anim_trigger(cozmo.anim.Triggers.CubePounceFake, ignore_body_track=True, ignore_lift_track=True, ignore_head_track=True).wait_for_completed() | |
await robot.set_head_angle(degrees(0)).wait_for_completed() | |
await robot.wait_for_all_actions_completed() | |
#robot.clear_idle_animation() | |
await asyncio.sleep(1) | |
backup_count = 0 | |
while robot.is_on_charger == 0: | |
try: | |
await robot.backup_onto_charger(max_drive_time=2) | |
backup_count+=1 | |
await asyncio.sleep(0.4) | |
if robot.is_on_charger == 1: | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: Robot is on Charger, battery %s" % str(round(robot.battery_voltage, 2))) | |
robot.enable_all_reaction_triggers(False) | |
break | |
elif backup_count == 6: | |
robot.enable_all_reaction_triggers(False) | |
break | |
except robot.is_on_charger == 1: | |
robot.stop_all_motors() | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: Contact! Stop all motors, battery %s" % str(round(robot.battery_voltage, 2))) | |
await robot.wait_for_all_actions_completed() | |
await robot.wait_for_all_actions_completed() | |
# check if we're now docked | |
if robot.is_on_charger: | |
# Yes! we're docked! | |
await robot.wait_for_all_actions_completed() | |
await robot.play_anim("anim_sparking_success_02").wait_for_completed() | |
await robot.wait_for_all_actions_completed() | |
await robot.set_head_angle(degrees(0)).wait_for_completed() | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: I am now docked, battery %s" % str(round(robot.battery_voltage, 2))) | |
robot.set_all_backpack_lights(cozmo.lights.off_light) | |
await robot.play_anim("anim_gotosleep_getin_01").wait_for_completed() | |
await robot.play_anim("anim_gotosleep_sleeping_01").wait_for_completed() | |
else: | |
# No, we missed. Drive forward, turn around, and try again | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: failed to dock with charger, battery %s" % str(round(robot.battery_voltage, 2))) | |
await robot.wait_for_all_actions_completed() | |
await robot.play_anim_trigger(Triggers.AskToBeRightedRight, ignore_body_track=True).wait_for_completed() | |
await robot.wait_for_all_actions_completed() | |
#robot.move_lift(-3) | |
#await robot.set_head_angle(degrees(0)).wait_for_completed() | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: drive forward, turn around, and try again, battery %s" % str(round(robot.battery_voltage, 2))) | |
await robot.turn_in_place(degrees(charger.pose.rotation.angle_z.degrees-180), accel=degrees(80), angle_tolerance=None, is_absolute=True).wait_for_completed() | |
await robot.drive_straight(distance_mm(90), speed_mmps(90)).wait_for_completed() | |
await robot.drive_straight(distance_mm(90), speed_mmps(90)).wait_for_completed() | |
await robot.turn_in_place(degrees(charger.pose.rotation.angle_z.degrees), num_retries=3, accel=degrees(100), angle_tolerance=None, is_absolute=True).wait_for_completed() | |
await robot.set_head_angle(degrees(0)).wait_for_completed() | |
await asyncio.sleep(1) | |
if (charger.is_visible == False): | |
# we know where the charger is | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: can't see charger after turnaround, try again, battery %s" % str(round(robot.battery_voltage, 2))) | |
await robot.play_anim_trigger(Triggers.CodeLabSurprise, ignore_body_track=True, ignore_head_track=True).wait_for_completed() | |
#await robot.wait_for_all_actions_completed() | |
await robot.set_head_angle(degrees(0)).wait_for_completed() | |
await asyncio.sleep(0.1) | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print (charger) | |
try: | |
action = robot.go_to_object(charger, distance_mm(110), RobotAlignmentTypes.LiftPlate, num_retries=3) | |
await action.wait_for_completed() | |
finally: | |
pass | |
try: | |
action = robot.go_to_object(charger, distance_mm(80), RobotAlignmentTypes.LiftPlate, num_retries=3) | |
await action.wait_for_completed() | |
finally: | |
pass | |
await robot.turn_in_place(degrees(charger.pose.rotation.angle_z.degrees), num_retries=3, accel=degrees(80), angle_tolerance=None, is_absolute=True).wait_for_completed() | |
if (charger.is_visible == False): | |
# we lost the charger, clearing all map variables | |
charger = None | |
robot.world.charger = None | |
found_object = None | |
custom_objects = [0] | |
temp_object = None | |
await robot.play_anim_trigger(Triggers.ReactToPokeReaction, ignore_body_track=True, ignore_head_track=True, ignore_lift_track=True).wait_for_completed() | |
#await robot.wait_for_all_actions_completed() | |
await robot.drive_straight(distance_mm(-100), speed_mmps(50)).wait_for_completed() | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: charger lost while docking, clearing map. battery %s" % str(round(robot.battery_voltage, 2))) | |
await asyncio.sleep(1) | |
break | |
else: | |
# we have not managed to find the charger. Falling back to freeplay. | |
charger = None | |
#await robot.wait_for_all_actions_completed() | |
await robot.play_anim_trigger(Triggers.ReactToPokeReaction, ignore_body_track=True, ignore_head_track=True, ignore_lift_track=True).wait_for_completed() | |
#await robot.wait_for_all_actions_completed() | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: charger not found, fallback to 90seconds of freeplay, battery %s" % str(round(robot.battery_voltage, 2))) | |
#try freeplay for 90 seconds, if found charger finally stop freeplay | |
marker_time=90.0 | |
robot.enable_all_reaction_triggers(True) | |
robot.start_freeplay_behaviors() | |
try: | |
await gather( | |
create_task( | |
freeplay_lookaround_behaviour(robot)), | |
create_task( | |
find_chargermarker(robot)), | |
return_exceptions=True | |
) | |
except asyncio.CancelledError: | |
pass | |
robot.stop_freeplay_behaviors() | |
if found_object != None and charger==None: | |
try: | |
await goto_chargermarker_pose(robot) | |
except asyncio.CancelledError: | |
pass | |
robot.move_lift(-3) | |
robot.enable_all_reaction_triggers(False) | |
#after 90 seconds end freeplay | |
# | |
# Cozmo's Scheduler resting time | |
# | |
async def cozmo_resting(robot: robot): | |
if (robot.is_on_charger == 1) and (robot.is_charging == 1): | |
# In here we make Cozmo do on or off Charger things while Charging for fun | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: charging, waiting for scheduled playtime, battery %s" % str(round(robot.battery_voltage, 2))) | |
i = random.randint(1, 100) | |
if i >= 97: | |
await robot.play_anim("anim_guarddog_fakeout_02").wait_for_completed() | |
elif i >= 85: | |
await robot.play_anim("anim_gotosleep_sleeploop_01").wait_for_completed() | |
await asyncio.sleep(3) | |
robot.set_all_backpack_lights(cozmo.lights.green_light) | |
await asyncio.sleep(3) | |
robot.set_all_backpack_lights(cozmo.lights.off_light) | |
elif (robot.is_on_charger == 1) and (robot.is_charging == 0): | |
# In here we make Cozmo do on or off Charger things while Charged for fun | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: Charged! waiting for scheduled playtime, battery %s" % str(round(robot.battery_voltage, 2))) | |
i = random.randint(1, 100) | |
if i >= 97: | |
await robot.play_anim("anim_guarddog_fakeout_02").wait_for_completed() | |
elif i >= 85: | |
await robot.play_anim("anim_gotosleep_sleeploop_01").wait_for_completed() | |
await asyncio.sleep(3) | |
robot.set_all_backpack_lights(cozmo.lights.green_light) | |
await asyncio.sleep(3) | |
robot.set_all_backpack_lights(cozmo.lights.off_light) | |
elif (robot.is_on_charger == 0) and (robot.is_charging == 0) and scheduled_days == "Resting": | |
robot.stop_freeplay_behaviors() | |
await find_charger_and_goto(robot) | |
# | |
# Scheduler | |
# | |
async def scheduler(robot: robot): | |
global use_scheduler, nowtime, wday, scheduled_days, scheduled_time | |
global wkDS, wkDSm, wkDE, wkDEm, wkNS, wkNSm, wkNE, wkNEm, wkEDS, wkEDSm, wkEDE, wkEDEm, wkENS, wkENSm, wkENE, wkENEm | |
wday = nowtime.tm_wday # 0 is Monday, 6 is Sunday | |
#TempTime = datetime.datetime.now().timetuple() | |
# Display Time Tuple for scripting usage purposes | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: Full timetuple() is: "+str(nowtime)) | |
print("State: Week Day Number is: "+str(wday)) | |
while True: | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: Scheduled days: "+str(scheduled_days)+", battery %s" % str(round(robot.battery_voltage, 2))) | |
#weekday mornings | |
if (wday < 5 and nowtime.tm_hour > wkDS or wday < 5 and (wkDE < wkDS and nowtime.tm_hour > wkDS or nowtime.tm_hour == wkDS and nowtime.tm_min >= wkDSm and nowtime.tm_sec >= 10)) and (nowtime.tm_hour < wkDE or wkDE < wkDS and nowtime.tm_hour > wkDE or nowtime.tm_hour == wkDE and nowtime.tm_min <= wkDEm and nowtime.tm_sec <= 10): | |
scheduled_days = "WeekDayMorn" | |
scheduled_time = 1 | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: Weekday Morning Time is: "+str(nowtime.tm_hour)+":"+str(nowtime.tm_min)+", battery %s" % str(round(robot.battery_voltage, 2))) | |
await cozmo_unleashed(robot) | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: weekday scheduled loop complete, battery %s" % str(round(robot.battery_voltage, 2))) | |
break | |
#weekday evenings | |
elif (wday < 5 and nowtime.tm_hour > wkNS or wday < 5 and (wkNE < wkNS and nowtime.tm_hour > wkNS or nowtime.tm_hour == wkNS and nowtime.tm_min >= wkNSm and nowtime.tm_sec >= 10)) and (nowtime.tm_hour < wkNE or wkNE < wkNS and nowtime.tm_hour > wkNE or nowtime.tm_hour == wkNE and nowtime.tm_min <= wkNEm and nowtime.tm_sec <= 10): | |
scheduled_days = "WeekDayEve" | |
scheduled_time = 1 | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: Weekday Night Time is: "+str(nowtime.tm_hour)+":"+str(nowtime.tm_min)+", battery %s" % str(round(robot.battery_voltage, 2))) | |
await cozmo_unleashed(robot) | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: weeknight scheduled loop complete, battery %s" % str(round(robot.battery_voltage, 2))) | |
break | |
#weekend mornings | |
elif (wday >= 5 and nowtime.tm_hour > wkEDS or wday >= 5 and (wkEDS < wkEDE and nowtime.tm_hour > wkEDS or nowtime.tm_hour == wkEDS and nowtime.tm_min >= wkEDSm and nowtime.tm_sec >= 10)) and (nowtime.tm_hour < wkEDE or wkEDE < wkEDS and nowtime.tm_hour > wkEDE or nowtime.tm_hour == wkEDE and nowtime.tm_min <= wkEDEm and nowtime.tm_sec <= 10): | |
scheduled_days = "WeekEndMorn" | |
scheduled_time = 1 | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: Weekend Morning Time is: "+str(nowtime.tm_hour)+":"+str(nowtime.tm_min)+", battery %s" % str(round(robot.battery_voltage, 2))) | |
await cozmo_unleashed(robot) | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: weekend scheduled loop complete, battery %s" % str(round(robot.battery_voltage, 2))) | |
break | |
#weekend evenings | |
elif (wday >= 5 and nowtime.tm_hour > wkENS or wday >= 5 and (wkENS < wkENE and nowtime.tm_hour > wkENS or nowtime.tm_hour == wkENS and nowtime.tm_min >= wkENSm and nowtime.tm_sec >= 10)) and (nowtime.tm_hour < wkENE or wkENE < wkENS and nowtime.tm_hour > wkENE or nowtime.tm_hour == wkENE and nowtime.tm_min <= wkENEm and nowtime.tm_sec <= 10): | |
scheduled_days = "WeekEndEve" | |
scheduled_time = 1 | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: Weekend Evening Time is: "+str(nowtime.tm_hour)+":"+str(nowtime.tm_min)+", battery %s" % str(round(robot.battery_voltage, 2))) | |
await cozmo_unleashed(robot) | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: weekend scheduled loop complete, battery %s" % str(round(robot.battery_voltage, 2))) | |
break | |
else: | |
nowtime = datetime.datetime.now().timetuple() | |
scheduled_days = "Resting" | |
scheduled_time = 0 | |
await cozmo_resting(robot) | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: resting loop complete, battery %s" % str(round(robot.battery_voltage, 2))) | |
break | |
# | |
# | |
# main program | |
async def cozmo_unleashed(robot: robot): | |
global charger, freeplay, robotvolume, found_object, custom_objects, temp_object, marker_time, use_walls, use_cubes | |
global use_scheduler, nowtime, wday, scheduled_days, scheduled_time | |
if use_scheduler == 1: | |
global wkDS, wkDSm, wkDE, wkDEm, wkNS, wkNSm, wkNE, wkNEm, wkEDS, wkEDSm, wkEDE, wkEDEm, wkENS, wkENSm, wkENE, wkENEm | |
if scheduled_days=="None" or use_scheduler == 0: | |
# | |
# DEFINING MARKERS | |
# | |
# 1st 2 numbers are the width/height of the paper the printed marker is on | |
# for the 1st dimension: measure the side of the width/height, from the printed marker's edge, then | |
# multiply it by 2 then add it to the 2nd dimension | |
# 2nd 2 numbers are the width/height of the printed marker on the paper | |
# I suggest using a ruler to measure these dimensions, by the millimeter, after you print & cut them to get exact numbers | |
# define the chargermarker for the dock | |
await robot.world.define_custom_wall(CustomObjectTypes.CustomType01, CustomObjectMarkers.Hexagons2, 62, 62, 40, 40, True) | |
# these define the 4 walls of my play field, it helps Cozmo not bump into the walls | |
# you can set the use_walls variable at the top of the script to 0 if you are not using walls | |
if use_walls >= 1: | |
await robot.world.define_custom_wall(CustomObjectTypes.CustomType02, CustomObjectMarkers.Diamonds2, 800, 90, 40, 40, True) | |
await robot.world.define_custom_wall(CustomObjectTypes.CustomType03, CustomObjectMarkers.Diamonds3, 800, 90, 40, 40, True) | |
await robot.world.define_custom_wall(CustomObjectTypes.CustomType04, CustomObjectMarkers.Diamonds4, 550, 90, 40, 40, True) | |
await robot.world.define_custom_wall(CustomObjectTypes.CustomType05, CustomObjectMarkers.Diamonds5, 700, 90, 40, 40, True) | |
robot.world.charger = None | |
charger = None | |
found_object = None | |
temp_object = None | |
custom_objects=[] | |
if use_scheduler == 1: | |
nowtime = datetime.datetime.now().timetuple() | |
await robot.wait_for_all_actions_completed() | |
robot.clear_idle_animation() | |
robot.stop_all_motors() | |
robot.abort_all_actions(log_abort_messages=True) | |
robot.enable_all_reaction_triggers(False) | |
robot.enable_stop_on_cliff(True) | |
robot.world.auto_disconnect_from_cubes_at_end(True) | |
robot.set_robot_volume(robotvolume) | |
await asyncio.sleep(1) | |
if use_cubes >= 2: | |
robot.enable_freeplay_cube_lights(enable=True) | |
while True: | |
#State 1: on charger, charging | |
if (robot.is_on_charger == 1) and (robot.is_charging == 1): | |
#if scheduled_time != None: | |
# #os.system('cls' if os.name == 'nt' else 'clear') | |
# print("State: Scheduled Time Flag is: "+str(scheduled_time)) | |
freeplay=0 | |
if scheduled_time == 1: | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: charging, in scheduled playtime, battery %s" % str(round(robot.battery_voltage, 2))) | |
else: | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: charging, battery %s" % str(round(robot.battery_voltage, 2))) | |
i = random.randint(1, 100) | |
if i >= 97: | |
await robot.play_anim("anim_guarddog_fakeout_02").wait_for_completed() | |
elif i >= 85: | |
await robot.play_anim("anim_gotosleep_sleeploop_01").wait_for_completed() | |
await asyncio.sleep(3) | |
robot.set_all_backpack_lights(cozmo.lights.green_light) | |
await asyncio.sleep(3) | |
robot.set_all_backpack_lights(cozmo.lights.off_light) | |
#State 2: on charger, fully charged, get off charger | |
if (robot.is_on_charger == 1) and (robot.is_charging == 0) and (scheduled_days != "Resting") and (scheduled_time == 1 or use_scheduler == 0): | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: Charged! getting off charger, battery %s" % str(round(robot.battery_voltage, 2))) | |
robot.set_all_backpack_lights(cozmo.lights.off_light) | |
await robot.play_anim("anim_launch_altwakeup_01").wait_for_completed() | |
await asyncio.sleep(4) | |
robot.clear_idle_animation() | |
await robot.drive_off_charger_contacts(num_retries=3, in_parallel=False).wait_for_completed() | |
await asyncio.sleep(4) | |
robot.move_lift(-3) | |
try: | |
if (robot.is_on_charger == 1): | |
await robot.drive_straight(distance_mm(80), speed_mmps(25), num_retries=2).wait_for_completed() | |
finally: | |
pass | |
await asyncio.sleep(2) | |
await robot.wait_for_all_actions_completed() | |
elif use_scheduler == 1 and scheduled_days == "None": | |
await scheduler(robot) | |
#State 3: not on charger, good time play battery | default low battery is 3.65 | |
if (robot.battery_voltage > lowbatvolt) and (robot.is_on_charger == 0) and (scheduled_time == 1 or use_scheduler == 0): | |
#if scheduled_time != None: | |
# #os.system('cls' if os.name == 'nt' else 'clear') | |
# print("State: Scheduled Time Flag is: "+str(scheduled_time)) | |
if use_scheduler == 1 and scheduled_days == "None": | |
await scheduler(robot) | |
elif freeplay == 0: | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: turn on good time play battery %s" % str(round(robot.battery_voltage, 2))) | |
robot.clear_idle_animation() | |
robot.abort_all_actions(log_abort_messages=False) | |
if use_cubes == 1: | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: turn on cubes %s" % str(round(robot.battery_voltage, 2))) | |
await robot.world.connect_to_cubes() | |
await asyncio.sleep(4) | |
elif use_cubes >= 2: | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: turn on cubes and freeplay lights %s" % str(round(robot.battery_voltage, 2))) | |
robot.enable_freeplay_cube_lights(True) | |
await robot.world.connect_to_cubes() | |
await asyncio.sleep(4) | |
await robot.wait_for_all_actions_completed() | |
robot.enable_all_reaction_triggers(True) | |
robot.start_freeplay_behaviors() | |
freeplay=1 | |
elif freeplay == 1 and robot.battery_voltage > lowbatvolt - 0.03: | |
pass | |
if robot.is_picked_up == True: | |
charger = None | |
robot.world.charger = None | |
temp_object = None | |
found_object = None | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: robot delocalized during freeplay, resetting everything, battery %s" % str(round(robot.battery_voltage, 2))) | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: good battery playtime, battery %s" % str(round(robot.battery_voltage, 2))) | |
await asyncio.sleep(3) | |
#State 4: not on charger, low battery | default low battery is 3.65 | |
if (robot.battery_voltage <= lowbatvolt) and (robot.is_on_charger == 0): | |
if freeplay == 1: | |
robot.stop_freeplay_behaviors() | |
robot.clear_idle_animation() | |
robot.enable_all_reaction_triggers(False) | |
robot.abort_all_actions(log_abort_messages=False) | |
await robot.wait_for_all_actions_completed() | |
if use_cubes == 1 or use_cubes == 3: | |
await robot.world.disconnect_from_cubes() | |
await asyncio.sleep(4) | |
elif use_cubes == 2: | |
robot.enable_freeplay_cube_lights(False) | |
await robot.world.disconnect_from_cubes() | |
await asyncio.sleep(4) | |
await robot.wait_for_all_actions_completed() | |
freeplay=0 | |
await robot.play_anim_trigger(Triggers.NeedsMildLowEnergyRequest, ignore_body_track=True).wait_for_completed() | |
await asyncio.sleep(2) | |
await robot.wait_for_all_actions_completed() | |
robot.set_all_backpack_lights(cozmo.lights.blue_light) | |
await robot.set_head_angle(degrees(0)).wait_for_completed() | |
robot.move_lift(-3) | |
robot.set_idle_animation(Triggers.NeedsMildLowEnergyRequest) | |
#await robot.drive_straight(distance_mm(-30), speed_mmps(50)).wait_for_completed() | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: low battery, finding charger, battery %s" % str(round(robot.battery_voltage, 2))) | |
# charger location search | |
# see if we already know where the charger is | |
if charger != None: | |
#we know where the charger is | |
robot.move_lift(-3) | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: start docking loop, charger position known, battery %s" % str(round(robot.battery_voltage, 2))) | |
await robot.play_anim_trigger(Triggers.CodeLabSurprise, ignore_body_track=True, ignore_head_track=True).wait_for_completed() | |
await asyncio.sleep(2) | |
#await robot.wait_for_all_actions_completed() | |
await robot.set_head_angle(degrees(0)).wait_for_completed() | |
await robot.wait_for_all_actions_completed() | |
#charger = robot.world.charger | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print (charger) | |
try: | |
action = robot.go_to_object(charger, distance_mm(110), RobotAlignmentTypes.LiftPlate, num_retries=3) | |
await action.wait_for_completed() | |
finally: | |
pass | |
try: | |
action = robot.go_to_object(charger, distance_mm(80), RobotAlignmentTypes.LiftPlate, num_retries=3) | |
await action.wait_for_completed() | |
finally: | |
pass | |
await robot.turn_in_place(degrees(charger.pose.rotation.angle_z.degrees), num_retries=3, accel=degrees(80), angle_tolerance=None, is_absolute=True).wait_for_completed() | |
await asyncio.sleep(0.5) | |
elif found_object != None: | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: start of loop, chargermarker known, battery %s" % str(round(robot.battery_voltage, 2))) | |
await robot.play_anim_trigger(cozmo.anim.Triggers.CodeLabSurprise, ignore_body_track=True, ignore_head_track=True).wait_for_completed() | |
await robot.set_head_angle(degrees(0)).wait_for_completed() | |
await robot.wait_for_all_actions_completed() | |
asyncio.sleep(0.01) | |
try: | |
await goto_chargermarker_pose(robot) | |
except asyncio.CancelledError: | |
pass | |
else: | |
# we know where the charger is but we have been delocalized | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: did not find charger after clearing map, battery %s" % str(round(robot.battery_voltage, 2))) | |
## decide if we need to run find charger routines or not | |
await find_charger_and_goto(robot) | |
## end of loop routines | |
if robot.is_picked_up == True: | |
charger = None | |
robot.world.charger = None | |
temp_object = None | |
found_object = None | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: robot delocalized during freeplay, resetting charger, battery %s" % str(round(robot.battery_voltage, 2))) | |
while temp_object == None: | |
try: | |
custom_objects = await robot.world.wait_until_observe_num_objects(num=1, object_type=CustomObject, timeout=1, include_existing=True) | |
if len(custom_objects) > 0: | |
temp_object = custom_objects[0] | |
custom_objects = [] | |
if str(temp_object.object_type) != "CustomObjectTypes.CustomType01": | |
temp_object = None | |
finally: | |
if temp_object != None and str(temp_object.object_type) == "CustomObjectTypes.CustomType01": | |
if found_object == None: | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: found chargermarker in freeplay, battery %s" % str(round(robot.battery_voltage, 2))) | |
found_object = temp_object | |
temp_object = None | |
break | |
if temp_object != None and found_object != None: | |
if temp_object.pose.is_comparable(found_object.pose) == True: | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: updating chargermarker location, battery %s" % str(round(robot.battery_voltage, 2))) | |
found_object = temp_object | |
else: | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: chargermarker pose comparison failed, battery %s" % str(round(robot.battery_voltage, 2))) | |
temp_object = None | |
break | |
if robot.world.charger != None: | |
charger = robot.world.charger | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: updating charger location, battery %s" % str(round(robot.battery_voltage, 2))) | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: "+str(charger)+", battery %s" % str(round(robot.battery_voltage, 2))) | |
robot.world.charger = None | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: program loop complete, battery %s" % str(round(robot.battery_voltage, 2))) | |
await asyncio.sleep(3) | |
if use_scheduler == 1: | |
nowtime = datetime.datetime.now().timetuple() | |
if (scheduled_days == "WeekDayMorn" and (nowtime.tm_hour <= wkDS and nowtime.tm_min <= wkDSm) or (wkDE < wkDS and nowtime.tm_hour <= wkDS and nowtime.tm_min <= wkDSm)) or (scheduled_days == "WeekDayMorn" and (nowtime.tm_hour >= wkDE and nowtime.tm_min >= wkDEm) or (wkDE < wkDS and nowtime.tm_hour >= wkDE and nowtime.tm_min >= wkDEm)): | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: Weekday Morning Schedule, battery %s" % str(round(robot.battery_voltage, 2))) | |
await scheduler(robot) | |
elif (scheduled_days == "WeekDayEve" and (nowtime.tm_hour <= wkNS and nowtime.tm_min <= wkNSm) or (wkNE < wkNS and nowtime.tm_hour <= wkNS and nowtime.tm_min <= wkNSm)) or (scheduled_days == "WeekDayEve" and (nowtime.tm_hour >= wkNE and nowtime.tm_min >= wkNEm) or (wkNE < wkNS and nowtime.tm_hour >= wkNE and nowtime.tm_min >= wkNEm)): | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: Weekday Evening Schedule, battery %s" % str(round(robot.battery_voltage, 2))) | |
await scheduler(robot) | |
elif (scheduled_days == "WeekEndMorn" and (nowtime.tm_hour <= wkEDS and nowtime.tm_min <= wkEDSm) or (wkEDE < wkEDS and nowtime.tm_hour <= wkEDS and nowtime.tm_min <= wkEDSm)) or (scheduled_days == "WeekEndMorn" and (nowtime.tm_hour >= wkEDE and nowtime.tm_min >= wkEDEm) or (wkEDE < wkEDS and nowtime.tm_hour >= wkEDE and nowtime.tm_min >= wkEDEm)): | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: Weekend Schedule, battery %s" % str(round(robot.battery_voltage, 2))) | |
await scheduler(robot) | |
elif (scheduled_days == "WeekEndEve" and (nowtime.tm_hour <= wkENS and nowtime.tm_min <= wkENSm) or (wkENE < wkENS and nowtime.tm_hour <= wkENS and nowtime.tm_min <= wkENSm)) or (scheduled_days == "WeekEndEve" and (nowtime.tm_hour >= wkENE and nowtime.tm_min >= wkENEm) or (wkENE < wkENS and nowtime.tm_hour >= wkENE and nowtime.tm_min >= wkENEm)): | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: Weekend Schedule, battery %s" % str(round(robot.battery_voltage, 2))) | |
await scheduler(robot) | |
elif scheduled_days == "Resting" and scheduled_time == 0: | |
if use_cubes == 3: | |
robot.enable_freeplay_cube_lights(enable=True) | |
if robot.is_on_charger == 0: | |
robot.stop_freeplay_behaviors() | |
await asyncio.sleep(3) | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("State: Resting Time Schedule, Find Charger, battery %s" % str(round(robot.battery_voltage, 2))) | |
await find_charger_and_goto(robot) | |
else: | |
await scheduler(robot) | |
#if use_scheduler == 1: | |
# #os.system('cls' if os.name == 'nt' else 'clear') | |
# print("State: End of Loop, How did we get here?, battery %s" % str(round(robot.battery_voltage, 2))) | |
# break | |
# | |
# | |
# START THE SHOW! | |
# | |
#cozmo.robot.Robot.drive_off_charger_on_connect = False | |
#cozmo.run_program(cozmo_unleashed, use_viewer=True, force_viewer_on_top=True, show_viewer_controls=True, exit_on_connection_error=True) | |
# if you have freeglut in the same folder as this script you can change the above line to | |
#cozmo.run_program(cozmo_unleashed, use_viewer=True, use_3d_viewer=True, force_viewer_on_top=True, show_viewer_controls=True, exit_on_connection_error=True) | |
# which will give you remote control over Cozmo via WASD+QERF while the 3d window has focus | |
# --- Above ^^ is the common command for running the first def. | |
# --- Below -- is a script from acidzebra for loading the main program, that I will | |
# like to eventually use to turn into a SDK Loop that can stay running in an executed | |
# program so that if the WiFi disconnects & reconnects again, the SDK Loop will kick | |
# back in when it sees a phone with an open SDK connection again, without having to | |
# stop and restart the script manually. | |
# Run at your own RISK, using the AbstractEventLoop is dangerous. | |
async def run(sdk_conn_loop): | |
global robot | |
'''The run method runs once the Cozmo SDK is connected.''' | |
robot = await sdk_conn_loop.wait_for_robot(timeout=2) | |
try: | |
#await cozmo_unleashed(robot) | |
# ^^ this above line ^^ is the original safest call to use | |
# this connect_on_loop seems to work, though i don't think it actually reconnects | |
# the phone to cozmo as i intended it to. i'm still working on that part | |
# this AbstractEventLoop line might cause issues, use at your own risk | |
#await connect_on_loop(AbstractEventLoop.run_forever(cozmo_unleashed(robot)), sdk_conn_loop) | |
# this non-Abstract connect_on_loop is much safer, use this line below | |
await cozmo.connect_on_loop(await cozmo_unleashed(robot), sdk_conn_loop) | |
except KeyboardInterrupt as k: | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("") | |
#os.system('cls' if os.name == 'nt' else 'clear') | |
print("Exit requested by user") | |
SystemExit("Keyboard interrupt: %s" % k) | |
if __name__ == '__main__': | |
cozmo.setup_basic_logging() | |
cozmo.robot.Robot.drive_off_charger_on_connect = False # Cozmo can stay on charger for now | |
try: | |
cozmo.connect_with_tkviewer(run, force_on_top=True) | |
except cozmo.ConnectionError as e: | |
SystemExit("A connection error with viewer occurred: %s" % e) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This file, & Cozmo SDK changes in general, may require you to make these 2 line changes in your "annotate.py" file located in your "Python##\site-packages\cozmo" folder, ## is whatever version you are using:
Line 38
import collections.abc #add the .abc to the import call
Line 181
if isinstance(text, collections.abc.Iterable): #again, by adding the .abc to the collections call will solve many problems
Edit: This is a simple fix that was commented on previous Python versions & is no longer warning. It NEEDS fixing. Please do it.