blob: 683d5d10eb0cf34fd38331790f85690331b98ac9 [file] [log] [blame]
#include <inttypes.h>
#include "aos/linux_code/init.h"
#include "aos/common/logging/logging.h"
#include "aos/common/util/wrapping_counter.h"
#include "aos/common/time.h"
#include "aos/common/logging/queue_logging.h"
#include "aos/common/controls/output_check.q.h"
#include "bbb/sensor_reader.h"
#include "bot3/control_loops/drivetrain/drivetrain.q.h"
#include "bot3/control_loops/drivetrain/drivetrain_constants.h"
#include "bot3/queues/to_log.q.h"
#include "bot3/shifter_hall_effect.h"
#include "frc971/queues/other_sensors.q.h"
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
using ::bot3::control_loops::drivetrain;
using ::frc971::sensors::gyro_reading;
using ::aos::util::WrappingCounter;
namespace bot3 {
namespace {
double drivetrain_translate(int32_t in) {
return static_cast<double>(in)
/ (256.0 /*cpr*/ * 4.0 /*quad*/)
* (18.0 / 50.0 /*output stage*/) * (64.0 / 24.0 /*encoder gears*/)
// * constants::GetValues().drivetrain_encoder_ratio
* (3.5 /*wheel diameter*/ * 2.54 / 100.0 * M_PI) * -1.0;
}
static const double kVcc = 5.15;
// Translates values from the ADC into voltage.
double adc_translate(uint16_t in) {
if (false) {
// This is the simple theoretical math.
static const uint16_t kMaximumValue = 0x3FF;
static const double kR1 = 5, kR2 = 6.65;
const double raw =
(kVcc * static_cast<double>(in) / static_cast<double>(kMaximumValue));
return (raw * (kR1 + kR2) - (kVcc / 2) * kR2) / kR1;
} else {
// This is from a linear regression calculated with some actual data points.
static const double kM = 0.012133, kB = -3.6813;
return static_cast<double>(in) * kM + kB;
}
}
double battery_translate(uint16_t in_high, uint16_t in_low) {
const double high = adc_translate(in_high), low = adc_translate(in_low);
static const double kDividerBig = 5.55, kDividerSmall = 2.66;
return (high - low) * (kDividerBig + kDividerSmall) / kDividerSmall +
kDividerBig / kDividerSmall * kVcc;
}
double gyro_translate(int64_t in) {
return in / 16.0 / 1000.0 / (180.0 / M_PI);
}
double hall_translate(const constants::ShifterHallEffect & k,
uint16_t in_value) {
double out = (in_value - static_cast<double>(k.low)) /
static_cast<double>(k.high - k.low);
return out;
}
void PacketReceived(const ::bbb::DataStruct *data,
const ::aos::time::Time &cape_timestamp) {
::aos::time::TimeFreezer time_freezer;
::frc971::logging_structs::CapeReading reading_to_log(
cape_timestamp, static_cast<uint16_t>(sizeof(*data)),
data->main.low_left_drive_hall, data->main.high_left_drive_hall,
data->main.low_right_drive_hall, data->main.high_right_drive_hall);
LOG_STRUCT(DEBUG, "cape reading", reading_to_log);
bool bad_gyro;
// TODO(brians): Switch to LogInterval for these things.
if (data->uninitialized_gyro) {
LOG(DEBUG, "uninitialized gyro\n");
bad_gyro = true;
} else if (data->zeroing_gyro) {
LOG(DEBUG, "zeroing gyro\n");
bad_gyro = true;
} else if (data->bad_gyro) {
LOG(ERROR, "bad gyro\n");
bad_gyro = true;
} else if (data->old_gyro_reading) {
LOG(WARNING, "old/bad gyro reading\n");
bad_gyro = true;
} else {
bad_gyro = false;
}
if (!bad_gyro) {
gyro_reading.MakeWithBuilder()
.angle(gyro_translate(data->gyro_angle))
.Send();
}
if (data->analog_errors != 0) {
LOG(WARNING, "%" PRIu8 " analog errors\n", data->analog_errors);
}
if (data->main.output_check_pulse_length != 0) {
auto message = ::aos::controls::output_check_received.MakeMessage();
// TODO(brians): Fix this math to match what the cRIO actually does.
// It's close but not quite right.
message->pulse_length =
static_cast<double>(data->main.output_check_pulse_length) / 10000.0;
if (message->pulse_length > 2.7) {
LOG(WARNING, "insane PWM pulse length %fms\n", message->pulse_length);
} else {
// TODO(danielp): Send the actual pulse length if we ever add that cable.
message->pwm_value = 1.0;
LOG_STRUCT(DEBUG, "received", *message);
message.Send();
}
}
drivetrain.position.MakeWithBuilder()
.right_encoder(drivetrain_translate(data->main.right_drive))
.left_encoder(-drivetrain_translate(data->main.left_drive))
.left_shifter_position(hall_translate(control_loops::kBot3LeftDriveShifter,
data->main.low_left_drive_hall))
.right_shifter_position(hall_translate(control_loops::kBot3RightDriveShifter,
data->main.low_right_drive_hall))
.battery_voltage(battery_translate(data->main.battery_voltage_high,
data->main.battery_voltage_low))
.Send();
}
} // namespace
} // namespace bot3
int main() {
::aos::Init(::bbb::SensorReader::kRelativePriority);
::bbb::SensorReader reader("comp");
while (true) {
::bot3::PacketReceived(reader.ReadPacket(), reader.GetCapeTimestamp());
}
::aos::Cleanup();
}