Skip to content

Commit

Permalink
Merge branch 'master' of github.com:UBC-Thunderbots/Software into net…
Browse files Browse the repository at this point in the history
…work-manager
  • Loading branch information
itsarune committed Nov 16, 2024
2 parents 369e050 + 81ec083 commit 8284a3b
Show file tree
Hide file tree
Showing 49 changed files with 1,139 additions and 640 deletions.
2 changes: 1 addition & 1 deletion docs/software-architecture-and-design.md
Original file line number Diff line number Diff line change
Expand Up @@ -534,7 +534,7 @@ Thunderscope has a field visualizer that uses [PyQtGraph's 3D graphics system](h
### Layers
We organize our graphics into "layers" so that we can toggle the visibility of different parts of our visualization. Each layer is responsible for visualizing a specific portion of our AI (e.g. vision data, path planning, passing, etc.). A layer can also handle layer-specific functionality; for instance, `GLWorldLayer` lets the user place or kick the ball using the mouse. The base class for a layer is [`GLLayer`](../src/software/thunderscope/gl/layers/gl_layer.py).

A `GLLayer` is in fact a `GLGraphicsItem` that is added to the scenegraph. When we add or remove `GLGraphicsItem`s to a `GLLayer`, we're actually setting the `GLLayer` as the parent of the `GLGraphicsItem`; this is because the scenegraph has a tree-like structure. In theory, `GLLayer`s could also be nested within one another.
A `GLLayer` is in fact a `GLGraphicsItem` that is added to the scenegraph. When we add or remove `GLGraphicsItem`s to a `GLLayer`, we're actually setting the `GLLayer` as the parent of the `GLGraphicsItem`; this is because the scenegraph has a hierarchical tree-like structure. `GLLayer`s can also be nested within one another, i.e. a `GLLayer` can be added as a child of another `GLLayer`.

# Simulator
The `Simulator` is what we use for physics simulation to do testing when we don't have access to real field. In terms of the architecture, the `Simulator` "simulates" the following components' functionalities:
Expand Down
1 change: 1 addition & 0 deletions environment_setup/setup_software.sh
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ virtualenv_opt_args=""
if [[ $(lsb_release -rs) == "24.04" ]]; then
host_software_packages+=(python3-pyqt6)
host_software_packages+=(pyqt6-dev-tools)
host_software_packages+=(python3-pyqt6.qtsvg)

virtualenv_opt_args="--system-site-packages"
fi
Expand Down
1 change: 0 additions & 1 deletion environment_setup/ubuntu20_requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,4 @@ iterfzf==0.5.0.20.0
python-Levenshtein==0.25.1
psutil==5.9.0
PyOpenGL==3.1.6
qt-material==2.12
ruff==0.5.5
1 change: 0 additions & 1 deletion environment_setup/ubuntu22_requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,4 @@ python-Levenshtein==0.25.1
psutil==5.9.0
PyOpenGL==3.1.6
numpy==1.26.4
qt-material==2.12
ruff==0.5.5
1 change: 0 additions & 1 deletion environment_setup/ubuntu24_requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,4 @@ iterfzf==0.5.0.20.0
python-Levenshtein==0.25.1
psutil==5.9.0
PyOpenGL==3.1.6
qt-material==2.12
ruff==0.5.5
16 changes: 9 additions & 7 deletions src/proto/message_translation/power_frame_msg.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,12 +118,12 @@ TbotsProto_PowerStatus inline createNanoPbPowerStatus(
/**
* Converts a google protobuf power control msg to its nanopb representation
*
* @param google_control protobuf message to convert
* @param power_control protobuf message to convert
* @return a nanopb power control msg matching provided protobuf
*/

TbotsProto_PowerPulseControl inline createNanoPbPowerPulseControl(
const TbotsProto::PowerControl& google_control, double kick_coeff, int kick_constant,
const TbotsProto::PowerControl& power_control, double kick_coeff, int kick_constant,
int chip_pulse_width)
{
TbotsProto_PowerPulseControl nanopb_control =
Expand All @@ -133,15 +133,17 @@ TbotsProto_PowerPulseControl inline createNanoPbPowerPulseControl(
kick_constant = std::min(kick_constant, MAX_KICK_CONSTANT);
kick_coeff = std::min(kick_coeff, MAX_KICK_COEFFICIENT);

switch (google_control.chicker().chicker_command_case())
switch (power_control.chicker().chicker_command_case())
{
case TbotsProto::PowerControl::ChickerControl::kKickSpeedMPerS:
nanopb_control.chicker.which_chicker_command =
TbotsProto_PowerPulseControl_ChickerControl_kick_pulse_width_tag;
// TODO (#3193): refactor kick pulse width calculation out into seperate
// function
nanopb_control.chicker.chicker_command.kick_pulse_width =
static_cast<uint32_t>(
kick_constant *
std::exp(kick_coeff * google_control.chicker().kick_speed_m_per_s()));
std::exp(kick_coeff * power_control.chicker().kick_speed_m_per_s()));
break;
case TbotsProto::PowerControl::ChickerControl::kChipDistanceMeters:
nanopb_control.chicker.which_chicker_command =
Expand All @@ -151,7 +153,7 @@ TbotsProto_PowerPulseControl inline createNanoPbPowerPulseControl(
case TbotsProto::PowerControl::ChickerControl::kAutoChipOrKick:
nanopb_control.chicker.which_chicker_command =
TbotsProto_PowerPulseControl_ChickerControl_auto_chip_or_kick_tag;
switch (google_control.chicker().auto_chip_or_kick().auto_chip_or_kick_case())
switch (power_control.chicker().auto_chip_or_kick().auto_chip_or_kick_case())
{
case TbotsProto::AutoChipOrKick::kAutokickSpeedMPerS:
nanopb_control.chicker.chicker_command.auto_chip_or_kick
Expand All @@ -160,7 +162,7 @@ TbotsProto_PowerPulseControl inline createNanoPbPowerPulseControl(
nanopb_control.chicker.chicker_command.auto_chip_or_kick
.auto_chip_or_kick.autokick_pulse_width = static_cast<uint32_t>(
kick_constant *
std::exp(kick_coeff * google_control.chicker()
std::exp(kick_coeff * power_control.chicker()
.auto_chip_or_kick()
.autokick_speed_m_per_s()));
break;
Expand All @@ -179,7 +181,7 @@ TbotsProto_PowerPulseControl inline createNanoPbPowerPulseControl(
default:
break;
}
switch (google_control.geneva_slot())
switch (power_control.geneva_slot())
{
case TbotsProto::Geneva::LEFT:
nanopb_control.geneva_slot = TbotsProto_Geneva_Slot_LEFT;
Expand Down
24 changes: 12 additions & 12 deletions src/proto/message_translation/power_frame_msg_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,26 @@
#include <gtest/gtest.h>
#include <proto/power_frame_msg.nanopb.h>

TEST(PowerFrameMsgTest, google_to_nanopb)
TEST(PowerFrameMsgTest, proto_to_nanopb)
{
auto google_control = TbotsProto::PowerControl();
google_control.mutable_chicker()->set_chip_distance_meters(3);
auto nanopb_control = createNanoPbPowerPulseControl(google_control, 0, 0, 100);
auto power_control = TbotsProto::PowerControl();
power_control.mutable_chicker()->set_chip_distance_meters(3);
auto nanopb_control = createNanoPbPowerPulseControl(power_control, 0, 0, 100);
EXPECT_EQ(nanopb_control.chicker.which_chicker_command,
TbotsProto_PowerPulseControl_ChickerControl_chip_pulse_width_tag);
EXPECT_EQ(nanopb_control.chicker.chicker_command.chip_pulse_width, 100);

google_control.mutable_chicker()->set_kick_speed_m_per_s(5);
nanopb_control = createNanoPbPowerPulseControl(google_control, 0.3, 300, 0);
power_control.mutable_chicker()->set_kick_speed_m_per_s(5);
nanopb_control = createNanoPbPowerPulseControl(power_control, 0.3, 300, 0);
EXPECT_EQ(nanopb_control.chicker.which_chicker_command,
TbotsProto_PowerPulseControl_ChickerControl_kick_pulse_width_tag);
EXPECT_EQ(nanopb_control.chicker.chicker_command.kick_pulse_width,
static_cast<int>(300 * std::exp(0.3 * 5)));

google_control.mutable_chicker()
power_control.mutable_chicker()
->mutable_auto_chip_or_kick()
->set_autokick_speed_m_per_s(4);
nanopb_control = createNanoPbPowerPulseControl(google_control, 0.1, 3, 0);
nanopb_control = createNanoPbPowerPulseControl(power_control, 0.1, 3, 0);
EXPECT_EQ(nanopb_control.chicker.which_chicker_command,
TbotsProto_PowerPulseControl_ChickerControl_auto_chip_or_kick_tag);
EXPECT_EQ(
Expand All @@ -32,10 +32,10 @@ TEST(PowerFrameMsgTest, google_to_nanopb)
.autokick_pulse_width,
static_cast<int>(3 * std::exp(4 * 0.1)));

google_control.mutable_chicker()
power_control.mutable_chicker()
->mutable_auto_chip_or_kick()
->set_autokick_speed_m_per_s(6);
nanopb_control = createNanoPbPowerPulseControl(google_control, 10000, 10000, 0);
nanopb_control = createNanoPbPowerPulseControl(power_control, 10000, 10000, 0);
EXPECT_EQ(nanopb_control.chicker.which_chicker_command,
TbotsProto_PowerPulseControl_ChickerControl_auto_chip_or_kick_tag);
EXPECT_EQ(
Expand All @@ -45,10 +45,10 @@ TEST(PowerFrameMsgTest, google_to_nanopb)
.autokick_pulse_width,
static_cast<int>(MAX_KICK_CONSTANT * std::exp(6 * MAX_KICK_COEFFICIENT)));

google_control.mutable_chicker()
power_control.mutable_chicker()
->mutable_auto_chip_or_kick()
->set_autochip_distance_meters(2);
nanopb_control = createNanoPbPowerPulseControl(google_control, 0, 0, 200);
nanopb_control = createNanoPbPowerPulseControl(power_control, 0, 0, 200);
EXPECT_EQ(nanopb_control.chicker.which_chicker_command,
TbotsProto_PowerPulseControl_ChickerControl_auto_chip_or_kick_tag);
EXPECT_EQ(
Expand Down
7 changes: 4 additions & 3 deletions src/shared/constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,10 @@ static const unsigned int MAX_ROBOT_IDS_PER_SIDE = 8;
// The total number of possible robot ids between two teams
static const unsigned int MAX_ROBOT_IDS = MAX_ROBOT_IDS_PER_SIDE * 2;

// How many robots are allowed in each division
static const unsigned int DIV_A_NUM_ROBOTS = 11;
static const unsigned int DIV_B_NUM_ROBOTS = 6;

// The maximum time in seconds given to Full System to cleanly exit the process.
static const double MAX_TIME_TO_EXIT_FULL_SYSTEM_SEC = 0.5;

Expand All @@ -173,9 +177,6 @@ static const double MAX_CAPACITOR_VOLTAGE = 250.0 + 50.0; // +50v headroom

static const unsigned int ROBOT_CHIP_ANGLE_DEGREES = 45;
static const double CHICKER_TIMEOUT = 3 * MILLISECONDS_PER_SECOND;
// How many robots are allowed in each division
static const unsigned DIV_A_NUM_ROBOTS = 11;
static const unsigned DIV_B_NUM_ROBOTS = 6;

// Kick Spd to Pulse Width Safety Constraint Constants

Expand Down
21 changes: 12 additions & 9 deletions src/software/embedded/thunderloop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ void Thunderloop::runLoop()
struct timespec current_time;
struct timespec last_chipper_fired;
struct timespec last_kicker_fired;
struct timespec prev_iter_start_time;

// Input buffer
TbotsProto::PrimitiveSet new_primitive_set;
Expand All @@ -165,11 +166,15 @@ void Thunderloop::runLoop()
clock_gettime(CLOCK_MONOTONIC, &last_world_received_time);
clock_gettime(CLOCK_MONOTONIC, &last_chipper_fired);
clock_gettime(CLOCK_MONOTONIC, &last_kicker_fired);

double loop_duration_seconds = 0.0;
clock_gettime(CLOCK_MONOTONIC, &prev_iter_start_time);

for (;;)
{
struct timespec time_since_prev_iter;
clock_gettime(CLOCK_MONOTONIC, &current_time);
ScopedTimespecTimer::timespecDiff(&current_time, &prev_iter_start_time,
&time_since_prev_iter);
prev_iter_start_time = current_time;
{
// Wait until next shot
//
Expand Down Expand Up @@ -321,9 +326,11 @@ void Thunderloop::runLoop()
ScopedTimespecTimer timer(&poll_time);

ZoneNamedN(_tracy_motor_service, "Thunderloop: Poll MotorService", true);
double time_since_prev_iter_sec =
getMilliseconds(time_since_prev_iter) * SECONDS_PER_MILLISECOND;

motor_status_ = motor_service_->poll(direct_control_.motor_control(),
loop_duration_seconds);
time_since_prev_iter_sec);
}
thunderloop_status_.set_motor_service_poll_time_ms(
getMilliseconds(poll_time));
Expand Down Expand Up @@ -364,12 +371,8 @@ void Thunderloop::runLoop()
thunderloop_status_.set_iteration_time_ms(loop_duration_ns /
NANOSECONDS_PER_MILLISECOND);

// Make sure the iteration can fit inside the period of the loop
loop_duration_seconds =
static_cast<double>(loop_duration_ns) * SECONDS_PER_NANOSECOND;

// Calculate next shot taking into account how long this iteration took
next_shot.tv_nsec += interval - static_cast<long int>(loop_duration_ns);
// Calculate next shot (which is an absolute time)
next_shot.tv_nsec += interval;
timespecNorm(next_shot);

FrameMarkEnd(TracyConstants::THUNDERLOOP_FRAME_MARKER);
Expand Down
4 changes: 2 additions & 2 deletions src/software/field_tests/field_test_fixture.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from software.thunderscope.proto_unix_io import ProtoUnixIO
from software.thunderscope.binary_context_managers.full_system import FullSystem
from software.thunderscope.binary_context_managers.game_controller import Gamecontroller
from software.logger.logger import createLogger
from software.logger.logger import create_logger


from software.thunderscope.thunderscope_config import configure_field_test_view
Expand All @@ -22,7 +22,7 @@
from software.thunderscope.estop_helpers import get_estop_config
from software.py_constants import *

logger = createLogger(__name__)
logger = create_logger(__name__)

WORLD_BUFFER_TIMEOUT = 5.0
PROCESS_BUFFER_DELAY_S = 0.01
Expand Down
4 changes: 2 additions & 2 deletions src/software/field_tests/movement_robot_field_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
from software.field_tests.field_test_fixture import *

from software.simulated_tests.simulated_test_fixture import *
from software.logger.logger import createLogger
from software.logger.logger import create_logger
import math

logger = createLogger(__name__)
logger = create_logger(__name__)


# TODO 2908: Support running this test in both simulator or field mode
Expand Down
4 changes: 2 additions & 2 deletions src/software/field_tests/pivot_kick_field_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
from software.field_tests.field_test_fixture import *

from software.simulated_tests.simulated_test_fixture import *
from software.logger.logger import createLogger
from software.logger.logger import create_logger

logger = createLogger(__name__)
logger = create_logger(__name__)


def test_pivot_kick(field_test_runner):
Expand Down
10 changes: 5 additions & 5 deletions src/software/logger/logger.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import logging
from logging import Logger, basicConfig, getLogger, INFO

logging.basicConfig(
level=logging.INFO,
basicConfig(
level=INFO,
format="%(asctime)s - [%(levelname)s] - [%(threadName)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s",
)


def createLogger(name):
def create_logger(name) -> Logger:
"""Create a logger given the name of the logger
:return: A Logger
"""
return logging.getLogger(name)
return getLogger(name)
4 changes: 2 additions & 2 deletions src/software/networking/unix/threaded_unix_listener.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
import queue
import socketserver
from threading import Thread
from software.logger.logger import createLogger
from software.logger.logger import create_logger
from software import py_constants

logger = createLogger(__name__)
logger = create_logger(__name__)


class ThreadedUnixListener:
Expand Down
4 changes: 2 additions & 2 deletions src/software/simulated_tests/simulated_test_fixture.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@
from software.thunderscope.binary_context_managers.game_controller import Gamecontroller
from software.thunderscope.thunderscope_config import configure_simulated_test_view

from software.logger.logger import createLogger
from software.logger.logger import create_logger

logger = createLogger(__name__)
logger = create_logger(__name__)

LAUNCH_DELAY_S = 0.1
WORLD_BUFFER_TIMEOUT = 0.5
Expand Down
8 changes: 5 additions & 3 deletions src/software/simulated_tests/tbots_test_runner.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
from proto.import_all_protos import *
from software.logger.logger import createLogger
from software.logger.logger import create_logger
from software.thunderscope.thread_safe_buffer import ThreadSafeBuffer
from proto.ssl_gc_common_pb2 import Team
from abc import abstractmethod


logger = createLogger(__name__)
logger = create_logger(__name__)


class TbotsTestRunner:
Expand Down Expand Up @@ -128,13 +128,15 @@ def set_play(self, play: Play, is_friendly: bool):

fs_proto_unix_io.send_proto(Play, play)

@abstractmethod
def set_worldState(self, worldstate: WorldState):
"""Sets the worldstate for the given team
:param worldstate: the worldstate proto to use
"""
raise NotImplementedError("abstract class method called set_worldstate")

@abstractmethod
def run_test(
self,
always_validation_sequence_set=[[]],
Expand Down
5 changes: 5 additions & 0 deletions src/software/simulated_tests/validation.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
import software.python_bindings as tbots_cpp
from proto.validation_pb2 import *

from abc import abstractmethod


class Validation:
"""A validation function"""

@abstractmethod
def get_validation_status(self, world) -> ValidationStatus:
raise NotImplementedError("get_validation_status is not implemented")

@abstractmethod
def get_validation_type(self, world) -> ValidationType:
raise NotImplementedError("get_validation_type is not implemented")

@abstractmethod
def get_validation_geometry(self, world) -> ValidationGeometry:
raise NotImplementedError("get_validation_geometry is not implemented")

Expand Down
Loading

0 comments on commit 8284a3b

Please sign in to comment.