mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-19 00:41:43 +00:00
SCRIPT: wpiformat
This commit is contained in:
committed by
Peter Johnson
parent
ae6bdc9d25
commit
2109161534
@@ -22,13 +22,16 @@ AprilTagFieldLayout::AprilTagFieldLayout(std::string_view path) {
|
||||
throw std::runtime_error(fmt::format("Cannot open file: {}", path));
|
||||
}
|
||||
|
||||
wpi::util::json json = wpi::util::json::parse(fileBuffer.value()->GetCharBuffer());
|
||||
wpi::util::json json =
|
||||
wpi::util::json::parse(fileBuffer.value()->GetCharBuffer());
|
||||
|
||||
for (const auto& tag : json.at("tags").get<std::vector<AprilTag>>()) {
|
||||
m_apriltags[tag.ID] = tag;
|
||||
}
|
||||
m_fieldWidth = wpi::units::meter_t{json.at("field").at("width").get<double>()};
|
||||
m_fieldLength = wpi::units::meter_t{json.at("field").at("length").get<double>()};
|
||||
m_fieldWidth =
|
||||
wpi::units::meter_t{json.at("field").at("width").get<double>()};
|
||||
m_fieldLength =
|
||||
wpi::units::meter_t{json.at("field").at("length").get<double>()};
|
||||
}
|
||||
|
||||
AprilTagFieldLayout::AprilTagFieldLayout(std::vector<AprilTag> apriltags,
|
||||
@@ -64,8 +67,9 @@ void AprilTagFieldLayout::SetOrigin(OriginPosition origin) {
|
||||
SetOrigin(wpi::math::Pose3d{});
|
||||
break;
|
||||
case OriginPosition::kRedAllianceWallRightSide:
|
||||
SetOrigin(wpi::math::Pose3d{wpi::math::Translation3d{m_fieldLength, m_fieldWidth, 0_m},
|
||||
wpi::math::Rotation3d{0_deg, 0_deg, 180_deg}});
|
||||
SetOrigin(wpi::math::Pose3d{
|
||||
wpi::math::Translation3d{m_fieldLength, m_fieldWidth, 0_m},
|
||||
wpi::math::Rotation3d{0_deg, 0_deg, 180_deg}});
|
||||
break;
|
||||
default:
|
||||
throw std::invalid_argument("Invalid origin");
|
||||
@@ -101,7 +105,8 @@ void AprilTagFieldLayout::Serialize(std::string_view path) {
|
||||
output.flush();
|
||||
}
|
||||
|
||||
void wpi::apriltag::to_json(wpi::util::json& json, const AprilTagFieldLayout& layout) {
|
||||
void wpi::apriltag::to_json(wpi::util::json& json,
|
||||
const AprilTagFieldLayout& layout) {
|
||||
std::vector<AprilTag> tagVector;
|
||||
tagVector.reserve(layout.m_apriltags.size());
|
||||
for (const auto& pair : layout.m_apriltags) {
|
||||
@@ -109,12 +114,13 @@ void wpi::apriltag::to_json(wpi::util::json& json, const AprilTagFieldLayout& la
|
||||
}
|
||||
|
||||
json = wpi::util::json{{"field",
|
||||
{{"length", layout.m_fieldLength.value()},
|
||||
{"width", layout.m_fieldWidth.value()}}},
|
||||
{"tags", tagVector}};
|
||||
{{"length", layout.m_fieldLength.value()},
|
||||
{"width", layout.m_fieldWidth.value()}}},
|
||||
{"tags", tagVector}};
|
||||
}
|
||||
|
||||
void wpi::apriltag::from_json(const wpi::util::json& json, AprilTagFieldLayout& layout) {
|
||||
void wpi::apriltag::from_json(const wpi::util::json& json,
|
||||
AprilTagFieldLayout& layout) {
|
||||
layout.m_apriltags.clear();
|
||||
for (const auto& tag : json.at("tags").get<std::vector<AprilTag>>()) {
|
||||
layout.m_apriltags[tag.ID] = tag;
|
||||
@@ -164,6 +170,7 @@ AprilTagFieldLayout AprilTagFieldLayout::LoadField(AprilTagField field) {
|
||||
return json.get<AprilTagFieldLayout>();
|
||||
}
|
||||
|
||||
AprilTagFieldLayout wpi::apriltag::LoadAprilTagLayoutField(AprilTagField field) {
|
||||
AprilTagFieldLayout wpi::apriltag::LoadAprilTagLayoutField(
|
||||
AprilTagField field) {
|
||||
return AprilTagFieldLayout::LoadField(field);
|
||||
}
|
||||
|
||||
@@ -47,8 +47,8 @@ static wpi::math::Transform3d MakePose(const apriltag_pose_t& pose) {
|
||||
return {};
|
||||
}
|
||||
return {wpi::math::Translation3d{wpi::units::meter_t{pose.t->data[0]},
|
||||
wpi::units::meter_t{pose.t->data[1]},
|
||||
wpi::units::meter_t{pose.t->data[2]}},
|
||||
wpi::units::meter_t{pose.t->data[1]},
|
||||
wpi::units::meter_t{pose.t->data[2]}},
|
||||
wpi::math::Rotation3d{OrthogonalizeRotationMatrix(
|
||||
Eigen::Map<Eigen::Matrix<double, 3, 3, Eigen::RowMajor>>{
|
||||
pose.R->data})}};
|
||||
@@ -130,8 +130,9 @@ AprilTagPoseEstimate AprilTagPoseEstimator::EstimateOrthogonalIteration(
|
||||
return rv;
|
||||
}
|
||||
|
||||
static wpi::math::Transform3d DoEstimate(const apriltag_detection_t* detection,
|
||||
const AprilTagPoseEstimator::Config& config) {
|
||||
static wpi::math::Transform3d DoEstimate(
|
||||
const apriltag_detection_t* detection,
|
||||
const AprilTagPoseEstimator::Config& config) {
|
||||
auto info = MakeDetectionInfo(detection, config);
|
||||
apriltag_pose_t pose;
|
||||
estimate_tag_pose(&info, &pose);
|
||||
|
||||
@@ -517,7 +517,8 @@ Java_org_wpilib_vision_apriltag_jni_AprilTagJNI_estimatePoseHomography
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AprilTagPoseEstimator estimator({wpi::units::meter_t{tagSize}, fx, fy, cx, cy});
|
||||
AprilTagPoseEstimator estimator(
|
||||
{wpi::units::meter_t{tagSize}, fx, fy, cx, cy});
|
||||
return MakeJObject(env, estimator.EstimateHomography(harr));
|
||||
}
|
||||
|
||||
@@ -553,7 +554,8 @@ Java_org_wpilib_vision_apriltag_jni_AprilTagJNI_estimatePoseOrthogonalIteration
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AprilTagPoseEstimator estimator({wpi::units::meter_t{tagSize}, fx, fy, cx, cy});
|
||||
AprilTagPoseEstimator estimator(
|
||||
{wpi::units::meter_t{tagSize}, fx, fy, cx, cy});
|
||||
return MakeJObject(env,
|
||||
estimator.EstimateOrthogonalIteration(harr, carr, nIters));
|
||||
}
|
||||
@@ -590,7 +592,8 @@ Java_org_wpilib_vision_apriltag_jni_AprilTagJNI_estimatePose
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AprilTagPoseEstimator estimator({wpi::units::meter_t{tagSize}, fx, fy, cx, cy});
|
||||
AprilTagPoseEstimator estimator(
|
||||
{wpi::units::meter_t{tagSize}, fx, fy, cx, cy});
|
||||
return MakeJObject(env, estimator.Estimate(harr, carr));
|
||||
}
|
||||
|
||||
|
||||
@@ -23,10 +23,10 @@ namespace wpi::apriltag {
|
||||
*
|
||||
* The JSON format contains two top-level objects, "tags" and "field".
|
||||
* The "tags" object is a list of all AprilTags contained within a layout. Each
|
||||
* AprilTag serializes to a JSON object containing an ID and a wpi::math::Pose3d. The
|
||||
* "field" object is a descriptor of the size of the field in meters with
|
||||
* "width" and "length" values. This is to account for arbitrary field sizes
|
||||
* when transforming the poses.
|
||||
* AprilTag serializes to a JSON object containing an ID and a
|
||||
* wpi::math::Pose3d. The "field" object is a descriptor of the size of the
|
||||
* field in meters with "width" and "length" values. This is to account for
|
||||
* arbitrary field sizes when transforming the poses.
|
||||
*
|
||||
* Pose3ds in the JSON are measured using the normal FRC coordinate system, NWU
|
||||
* with the origin at the bottom-right corner of the blue alliance wall.
|
||||
@@ -73,7 +73,8 @@ class WPILIB_DLLEXPORT AprilTagFieldLayout {
|
||||
* @param fieldWidth Width of field the layout is representing.
|
||||
*/
|
||||
AprilTagFieldLayout(std::vector<AprilTag> apriltags,
|
||||
wpi::units::meter_t fieldLength, wpi::units::meter_t fieldWidth);
|
||||
wpi::units::meter_t fieldLength,
|
||||
wpi::units::meter_t fieldWidth);
|
||||
|
||||
/**
|
||||
* Returns the length of the field the layout is representing.
|
||||
|
||||
@@ -65,7 +65,8 @@ class WPILIB_DLLEXPORT AprilTagPoseEstimator {
|
||||
* @param detection Tag detection
|
||||
* @return Pose estimate
|
||||
*/
|
||||
wpi::math::Transform3d EstimateHomography(const AprilTagDetection& detection) const;
|
||||
wpi::math::Transform3d EstimateHomography(
|
||||
const AprilTagDetection& detection) const;
|
||||
|
||||
/**
|
||||
* Estimates the pose of the tag using the homography method described in [1].
|
||||
@@ -73,7 +74,8 @@ class WPILIB_DLLEXPORT AprilTagPoseEstimator {
|
||||
* @param homography Homography 3x3 matrix data
|
||||
* @return Pose estimate
|
||||
*/
|
||||
wpi::math::Transform3d EstimateHomography(std::span<const double, 9> homography) const;
|
||||
wpi::math::Transform3d EstimateHomography(
|
||||
std::span<const double, 9> homography) const;
|
||||
|
||||
/**
|
||||
* Estimates the pose of the tag. This returns one or two possible poses for
|
||||
@@ -135,7 +137,7 @@ class WPILIB_DLLEXPORT AprilTagPoseEstimator {
|
||||
* @return Pose estimate
|
||||
*/
|
||||
wpi::math::Transform3d Estimate(std::span<const double, 9> homography,
|
||||
std::span<const double, 8> corners) const;
|
||||
std::span<const double, 8> corners) const;
|
||||
|
||||
private:
|
||||
Config m_config;
|
||||
|
||||
@@ -15,9 +15,10 @@ using namespace wpi::apriltag;
|
||||
|
||||
TEST(AprilTagJsonTest, DeserializeMatches) {
|
||||
auto layout = AprilTagFieldLayout{
|
||||
std::vector{
|
||||
AprilTag{1, wpi::math::Pose3d{}},
|
||||
AprilTag{3, wpi::math::Pose3d{0_m, 1_m, 0_m, wpi::math::Rotation3d{0_deg, 0_deg, 0_deg}}}},
|
||||
std::vector{AprilTag{1, wpi::math::Pose3d{}},
|
||||
AprilTag{3, wpi::math::Pose3d{0_m, 1_m, 0_m,
|
||||
wpi::math::Rotation3d{
|
||||
0_deg, 0_deg, 0_deg}}}},
|
||||
54_ft, 27_ft};
|
||||
|
||||
AprilTagFieldLayout deserialized;
|
||||
|
||||
@@ -16,18 +16,21 @@ using namespace wpi::apriltag;
|
||||
TEST(AprilTagPoseSetOriginTest, TransformationMatches) {
|
||||
auto layout = AprilTagFieldLayout{
|
||||
std::vector<AprilTag>{
|
||||
AprilTag{1,
|
||||
wpi::math::Pose3d{0_ft, 0_ft, 0_ft, wpi::math::Rotation3d{0_deg, 0_deg, 0_deg}}},
|
||||
AprilTag{
|
||||
2, wpi::math::Pose3d{4_ft, 4_ft, 4_ft, wpi::math::Rotation3d{0_deg, 0_deg, 180_deg}}}},
|
||||
1, wpi::math::Pose3d{0_ft, 0_ft, 0_ft,
|
||||
wpi::math::Rotation3d{0_deg, 0_deg, 0_deg}}},
|
||||
AprilTag{2, wpi::math::Pose3d{4_ft, 4_ft, 4_ft,
|
||||
wpi::math::Rotation3d{0_deg, 0_deg,
|
||||
180_deg}}}},
|
||||
54_ft, 27_ft};
|
||||
|
||||
layout.SetOrigin(
|
||||
AprilTagFieldLayout::OriginPosition::kRedAllianceWallRightSide);
|
||||
|
||||
auto mirrorPose =
|
||||
wpi::math::Pose3d{54_ft, 27_ft, 0_ft, wpi::math::Rotation3d{0_deg, 0_deg, 180_deg}};
|
||||
auto mirrorPose = wpi::math::Pose3d{
|
||||
54_ft, 27_ft, 0_ft, wpi::math::Rotation3d{0_deg, 0_deg, 180_deg}};
|
||||
EXPECT_EQ(mirrorPose, *layout.GetTagPose(1));
|
||||
mirrorPose = wpi::math::Pose3d{50_ft, 23_ft, 4_ft, wpi::math::Rotation3d{0_deg, 0_deg, 0_deg}};
|
||||
mirrorPose = wpi::math::Pose3d{50_ft, 23_ft, 4_ft,
|
||||
wpi::math::Rotation3d{0_deg, 0_deg, 0_deg}};
|
||||
EXPECT_EQ(mirrorPose, *layout.GetTagPose(2));
|
||||
}
|
||||
|
||||
@@ -27,20 +27,23 @@ TEST(AprilTagFieldsTest, TestLoad2022RapidReact) {
|
||||
|
||||
// Blue Hangar Truss - Hub
|
||||
auto expectedPose =
|
||||
wpi::math::Pose3d{127.272_in, 216.01_in, 67.932_in, wpi::math::Rotation3d{0_deg, 0_deg, 0_deg}};
|
||||
wpi::math::Pose3d{127.272_in, 216.01_in, 67.932_in,
|
||||
wpi::math::Rotation3d{0_deg, 0_deg, 0_deg}};
|
||||
auto maybePose = layout.GetTagPose(1);
|
||||
EXPECT_TRUE(maybePose);
|
||||
EXPECT_EQ(expectedPose, *maybePose);
|
||||
|
||||
// Blue Terminal Near Station
|
||||
expectedPose = wpi::math::Pose3d{4.768_in, 67.631_in, 35.063_in,
|
||||
expectedPose =
|
||||
wpi::math::Pose3d{4.768_in, 67.631_in, 35.063_in,
|
||||
wpi::math::Rotation3d{0_deg, 0_deg, 46.25_deg}};
|
||||
maybePose = layout.GetTagPose(5);
|
||||
EXPECT_TRUE(maybePose);
|
||||
EXPECT_EQ(expectedPose, *maybePose);
|
||||
|
||||
// Upper Hub Blue-Near
|
||||
expectedPose = wpi::math::Pose3d{332.321_in, 183.676_in, 95.186_in,
|
||||
expectedPose =
|
||||
wpi::math::Pose3d{332.321_in, 183.676_in, 95.186_in,
|
||||
wpi::math::Rotation3d{0_deg, 26.75_deg, 69_deg}};
|
||||
maybePose = layout.GetTagPose(53);
|
||||
EXPECT_TRUE(maybePose);
|
||||
|
||||
@@ -71,8 +71,9 @@ bool ReadCameraConfig(const wpi::util::json& config) {
|
||||
try {
|
||||
c.name = config.at("name").get<std::string>();
|
||||
} catch (const wpi::util::json::exception& e) {
|
||||
wpi::util::print(stderr, "config error in '{}': could not read camera name: {}\n",
|
||||
configFile, e.what());
|
||||
wpi::util::print(stderr,
|
||||
"config error in '{}': could not read camera name: {}\n",
|
||||
configFile, e.what());
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -80,9 +81,9 @@ bool ReadCameraConfig(const wpi::util::json& config) {
|
||||
try {
|
||||
c.path = config.at("path").get<std::string>();
|
||||
} catch (const wpi::util::json::exception& e) {
|
||||
wpi::util::print(stderr,
|
||||
"config error in '{}': camera '{}': could not read path: {}\n",
|
||||
configFile, c.name, e.what());
|
||||
wpi::util::print(
|
||||
stderr, "config error in '{}': camera '{}': could not read path: {}\n",
|
||||
configFile, c.name, e.what());
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -97,7 +98,7 @@ bool ReadConfig() {
|
||||
auto fileBuffer = wpi::util::MemoryBuffer::GetFile(configFile);
|
||||
if (!fileBuffer) {
|
||||
wpi::util::print(stderr, "could not open '{}': {}\n", configFile,
|
||||
fileBuffer.error().message());
|
||||
fileBuffer.error().message());
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -107,14 +108,14 @@ bool ReadConfig() {
|
||||
j = wpi::util::json::parse(fileBuffer.value()->GetCharBuffer());
|
||||
} catch (const wpi::util::json::parse_error& e) {
|
||||
wpi::util::print(stderr, "config error in '{}': byte {}: {}\n", configFile,
|
||||
e.byte, e.what());
|
||||
e.byte, e.what());
|
||||
return false;
|
||||
}
|
||||
|
||||
// top level must be an object
|
||||
if (!j.is_object()) {
|
||||
wpi::util::print(stderr, "config error in '{}': must be JSON object\n",
|
||||
configFile);
|
||||
configFile);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -122,8 +123,9 @@ bool ReadConfig() {
|
||||
try {
|
||||
team = j.at("team").get<unsigned int>();
|
||||
} catch (const wpi::util::json::exception& e) {
|
||||
wpi::util::print(stderr, "config error in '{}': could not read team number: {}\n",
|
||||
configFile, e.what());
|
||||
wpi::util::print(stderr,
|
||||
"config error in '{}': could not read team number: {}\n",
|
||||
configFile, e.what());
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -142,8 +144,9 @@ bool ReadConfig() {
|
||||
configFile, str);
|
||||
}
|
||||
} catch (const wpi::util::json::exception& e) {
|
||||
wpi::util::print(stderr, "config error in '{}': could not read ntmode: {}\n",
|
||||
configFile, e.what());
|
||||
wpi::util::print(stderr,
|
||||
"config error in '{}': could not read ntmode: {}\n",
|
||||
configFile, e.what());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,8 +158,9 @@ bool ReadConfig() {
|
||||
}
|
||||
}
|
||||
} catch (const wpi::util::json::exception& e) {
|
||||
wpi::util::print(stderr, "config error in '{}': could not read cameras: {}\n",
|
||||
configFile, e.what());
|
||||
wpi::util::print(stderr,
|
||||
"config error in '{}': could not read cameras: {}\n",
|
||||
configFile, e.what());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -37,9 +37,9 @@ CommandPtr::CommandPtr(CommandPtr&& rhs) {
|
||||
|
||||
void CommandPtr::AssertValid() const {
|
||||
if (!m_ptr) {
|
||||
throw WPILIB_MakeError(wpi::err::CommandIllegalUse,
|
||||
"Moved-from CommandPtr object used!\nMoved out at:\n{}",
|
||||
m_moveOutSite);
|
||||
throw WPILIB_MakeError(
|
||||
wpi::err::CommandIllegalUse,
|
||||
"Moved-from CommandPtr object used!\nMoved out at:\n{}", m_moveOutSite);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -285,7 +285,7 @@ void CommandScheduler::SetDefaultCommand(Subsystem* subsystem,
|
||||
CommandPtr&& defaultCommand) {
|
||||
if (!defaultCommand.get()->HasRequirement(subsystem)) {
|
||||
throw WPILIB_MakeError(wpi::err::CommandIllegalUse, "{}",
|
||||
"Default commands must require their subsystem!");
|
||||
"Default commands must require their subsystem!");
|
||||
}
|
||||
RequireUngrouped(defaultCommand.get());
|
||||
|
||||
@@ -430,11 +430,12 @@ void CommandScheduler::OnCommandFinish(Action action) {
|
||||
void CommandScheduler::RequireUngrouped(const Command* command) {
|
||||
auto stacktrace = command->GetPreviousCompositionSite();
|
||||
if (stacktrace.has_value()) {
|
||||
throw WPILIB_MakeError(wpi::err::CommandIllegalUse,
|
||||
"Commands that have been composed may not be added to "
|
||||
"another composition or scheduled individually!"
|
||||
"\nOriginally composed at:\n{}",
|
||||
stacktrace.value());
|
||||
throw WPILIB_MakeError(
|
||||
wpi::err::CommandIllegalUse,
|
||||
"Commands that have been composed may not be added to "
|
||||
"another composition or scheduled individually!"
|
||||
"\nOriginally composed at:\n{}",
|
||||
stacktrace.value());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -455,8 +456,8 @@ void CommandScheduler::RequireUngrouped(
|
||||
void CommandScheduler::RequireUngroupedAndUnscheduled(const Command* command) {
|
||||
if (IsScheduled(command)) {
|
||||
throw WPILIB_MakeError(wpi::err::CommandIllegalUse,
|
||||
"Commands that have been scheduled individually may "
|
||||
"not be added to another composition!");
|
||||
"Commands that have been scheduled individually may "
|
||||
"not be added to another composition!");
|
||||
}
|
||||
RequireUngrouped(command);
|
||||
}
|
||||
|
||||
@@ -83,7 +83,8 @@ CommandPtr cmd::DeferredProxy(wpi::util::unique_function<Command*()> supplier) {
|
||||
{});
|
||||
}
|
||||
|
||||
CommandPtr cmd::DeferredProxy(wpi::util::unique_function<CommandPtr()> supplier) {
|
||||
CommandPtr cmd::DeferredProxy(
|
||||
wpi::util::unique_function<CommandPtr()> supplier) {
|
||||
return Defer([supplier = std::move(
|
||||
supplier)]() mutable { return supplier().AsProxy(); },
|
||||
{});
|
||||
|
||||
@@ -11,8 +11,9 @@
|
||||
|
||||
using namespace wpi::cmd;
|
||||
|
||||
DeferredCommand::DeferredCommand(wpi::util::unique_function<CommandPtr()> supplier,
|
||||
Requirements requirements)
|
||||
DeferredCommand::DeferredCommand(
|
||||
wpi::util::unique_function<CommandPtr()> supplier,
|
||||
Requirements requirements)
|
||||
: m_supplier{std::move(supplier)} {
|
||||
AddRequirements(requirements);
|
||||
}
|
||||
|
||||
@@ -70,8 +70,8 @@ void ParallelCommandGroup::AddCommands(
|
||||
|
||||
if (isRunning) {
|
||||
throw WPILIB_MakeError(wpi::err::CommandIllegalUse,
|
||||
"Commands cannot be added to a CommandGroup "
|
||||
"while the group is running");
|
||||
"Commands cannot be added to a CommandGroup "
|
||||
"while the group is running");
|
||||
}
|
||||
|
||||
for (auto&& command : commands) {
|
||||
@@ -86,8 +86,8 @@ void ParallelCommandGroup::AddCommands(
|
||||
m_commands.emplace_back(std::move(command), false);
|
||||
} else {
|
||||
throw WPILIB_MakeError(wpi::err::CommandIllegalUse,
|
||||
"Multiple commands in a parallel group cannot "
|
||||
"require the same subsystems");
|
||||
"Multiple commands in a parallel group cannot "
|
||||
"require the same subsystems");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,8 +70,8 @@ void ParallelDeadlineGroup::AddCommands(
|
||||
|
||||
if (!m_finished) {
|
||||
throw WPILIB_MakeError(wpi::err::CommandIllegalUse,
|
||||
"Commands cannot be added to a CommandGroup "
|
||||
"while the group is running");
|
||||
"Commands cannot be added to a CommandGroup "
|
||||
"while the group is running");
|
||||
}
|
||||
|
||||
for (auto&& command : commands) {
|
||||
@@ -86,8 +86,8 @@ void ParallelDeadlineGroup::AddCommands(
|
||||
m_commands.emplace_back(std::move(command), false);
|
||||
} else {
|
||||
throw WPILIB_MakeError(wpi::err::CommandIllegalUse,
|
||||
"Multiple commands in a parallel group cannot "
|
||||
"require the same subsystems");
|
||||
"Multiple commands in a parallel group cannot "
|
||||
"require the same subsystems");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,8 +57,8 @@ void ParallelRaceGroup::AddCommands(
|
||||
|
||||
if (isRunning) {
|
||||
throw WPILIB_MakeError(wpi::err::CommandIllegalUse,
|
||||
"Commands cannot be added to a CommandGroup "
|
||||
"while the group is running");
|
||||
"Commands cannot be added to a CommandGroup "
|
||||
"while the group is running");
|
||||
}
|
||||
|
||||
for (auto&& command : commands) {
|
||||
@@ -73,8 +73,8 @@ void ParallelRaceGroup::AddCommands(
|
||||
m_commands.emplace_back(std::move(command));
|
||||
} else {
|
||||
throw WPILIB_MakeError(wpi::err::CommandIllegalUse,
|
||||
"Multiple commands in a parallel group cannot "
|
||||
"require the same subsystems");
|
||||
"Multiple commands in a parallel group cannot "
|
||||
"require the same subsystems");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,8 +11,9 @@
|
||||
using namespace wpi::cmd;
|
||||
|
||||
PrintCommand::PrintCommand(std::string_view message)
|
||||
: CommandHelper{[str = std::string(message)] { wpi::util::print("{}\n", str); },
|
||||
{}} {}
|
||||
: CommandHelper{
|
||||
[str = std::string(message)] { wpi::util::print("{}\n", str); },
|
||||
{}} {}
|
||||
|
||||
bool PrintCommand::RunsWhenDisabled() const {
|
||||
return true;
|
||||
|
||||
@@ -69,8 +69,8 @@ void SequentialCommandGroup::AddCommands(
|
||||
|
||||
if (m_currentCommandIndex != invalid_index) {
|
||||
throw WPILIB_MakeError(wpi::err::CommandIllegalUse,
|
||||
"Commands cannot be added to a CommandGroup "
|
||||
"while the group is running");
|
||||
"Commands cannot be added to a CommandGroup "
|
||||
"while the group is running");
|
||||
}
|
||||
|
||||
for (auto&& command : commands) {
|
||||
|
||||
@@ -13,16 +13,18 @@ NetworkButton::NetworkButton(wpi::nt::BooleanTopic topic)
|
||||
: NetworkButton(topic.Subscribe(false)) {}
|
||||
|
||||
NetworkButton::NetworkButton(wpi::nt::BooleanSubscriber sub)
|
||||
: Trigger([sub = std::make_shared<wpi::nt::BooleanSubscriber>(std::move(sub))] {
|
||||
return sub->GetTopic().GetInstance().IsConnected() && sub->Get();
|
||||
}) {}
|
||||
: Trigger(
|
||||
[sub = std::make_shared<wpi::nt::BooleanSubscriber>(std::move(sub))] {
|
||||
return sub->GetTopic().GetInstance().IsConnected() && sub->Get();
|
||||
}) {}
|
||||
|
||||
NetworkButton::NetworkButton(std::shared_ptr<wpi::nt::NetworkTable> table,
|
||||
std::string_view field)
|
||||
: NetworkButton(table->GetBooleanTopic(field)) {}
|
||||
|
||||
NetworkButton::NetworkButton(std::string_view table, std::string_view field)
|
||||
: NetworkButton(wpi::nt::NetworkTableInstance::GetDefault(), table, field) {}
|
||||
: NetworkButton(wpi::nt::NetworkTableInstance::GetDefault(), table, field) {
|
||||
}
|
||||
|
||||
NetworkButton::NetworkButton(wpi::nt::NetworkTableInstance inst,
|
||||
std::string_view table, std::string_view field)
|
||||
|
||||
@@ -37,7 +37,8 @@ namespace wpi::cmd {
|
||||
* @see CommandScheduler
|
||||
* @see CommandHelper
|
||||
*/
|
||||
class Command : public wpi::util::Sendable, public wpi::util::SendableHelper<Command> {
|
||||
class Command : public wpi::util::Sendable,
|
||||
public wpi::util::SendableHelper<Command> {
|
||||
public:
|
||||
~Command() override;
|
||||
|
||||
|
||||
@@ -34,8 +34,9 @@ class Subsystem;
|
||||
*
|
||||
* This class is provided by the NewCommands VendorDep
|
||||
*/
|
||||
class CommandScheduler final : public wpi::util::Sendable,
|
||||
public wpi::util::SendableHelper<CommandScheduler> {
|
||||
class CommandScheduler final
|
||||
: public wpi::util::Sendable,
|
||||
public wpi::util::SendableHelper<CommandScheduler> {
|
||||
public:
|
||||
/**
|
||||
* Returns the Scheduler instance.
|
||||
@@ -213,7 +214,7 @@ class CommandScheduler final : public wpi::util::Sendable,
|
||||
void SetDefaultCommand(Subsystem* subsystem, T&& defaultCommand) {
|
||||
if (!defaultCommand.HasRequirement(subsystem)) {
|
||||
throw WPILIB_MakeError(wpi::err::CommandIllegalUse,
|
||||
"Default commands must require their subsystem!");
|
||||
"Default commands must require their subsystem!");
|
||||
}
|
||||
SetDefaultCommandImpl(subsystem, std::make_unique<std::decay_t<T>>(
|
||||
std::forward<T>(defaultCommand)));
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
|
||||
namespace wpi::cmd::sysid {
|
||||
|
||||
using ramp_rate_t = wpi::units::unit_t<
|
||||
wpi::units::compound_unit<wpi::units::volt, wpi::units::inverse<wpi::units::second>>>;
|
||||
using ramp_rate_t = wpi::units::unit_t<wpi::units::compound_unit<
|
||||
wpi::units::volt, wpi::units::inverse<wpi::units::second>>>;
|
||||
|
||||
/** Hardware-independent configuration for a SysId test routine. */
|
||||
class Config {
|
||||
|
||||
@@ -15,7 +15,8 @@ using namespace wpi::cmd;
|
||||
class MockAddRequirements {
|
||||
public:
|
||||
MOCK_METHOD(void, AddRequirements, (Requirements), ());
|
||||
MOCK_METHOD(void, AddRequirements, ((wpi::util::SmallSet<Subsystem*, 4>)), ());
|
||||
MOCK_METHOD(void, AddRequirements, ((wpi::util::SmallSet<Subsystem*, 4>)),
|
||||
());
|
||||
MOCK_METHOD(void, AddRequirements, (Subsystem*), ());
|
||||
};
|
||||
|
||||
@@ -44,8 +45,9 @@ TEST(AddRequirementsTest, SmallSetOverloadResolution) {
|
||||
|
||||
MockAddRequirements overloadResolver;
|
||||
|
||||
EXPECT_CALL(overloadResolver,
|
||||
AddRequirements(testing::An<wpi::util::SmallSet<Subsystem*, 4>>()));
|
||||
EXPECT_CALL(
|
||||
overloadResolver,
|
||||
AddRequirements(testing::An<wpi::util::SmallSet<Subsystem*, 4>>()));
|
||||
|
||||
overloadResolver.AddRequirements(requirementsSet);
|
||||
}
|
||||
@@ -85,7 +87,7 @@ TEST(AddRequirementsTest, SpanSemantics) {
|
||||
TestSubsystem requirement2;
|
||||
|
||||
wpi::util::array<Subsystem* const, 2> requirementsArray(&requirement1,
|
||||
&requirement2);
|
||||
&requirement2);
|
||||
|
||||
RunCommand command([] {});
|
||||
command.AddRequirements(std::span{requirementsArray});
|
||||
@@ -97,7 +99,8 @@ TEST(AddRequirementsTest, SpanSemantics) {
|
||||
TEST(AddRequirementsTest, SpanDuplicatesSemantics) {
|
||||
TestSubsystem requirement;
|
||||
|
||||
wpi::util::array<Subsystem* const, 2> requirementsArray(&requirement, &requirement);
|
||||
wpi::util::array<Subsystem* const, 2> requirementsArray(&requirement,
|
||||
&requirement);
|
||||
|
||||
RunCommand command([] {});
|
||||
command.AddRequirements(std::span{requirementsArray});
|
||||
|
||||
@@ -202,8 +202,9 @@ TEST_F(SchedulerTest, ScheduleCommandPtr) {
|
||||
{
|
||||
auto commandPtr =
|
||||
TrackDestroyCommand([&destructionCounter] { destructionCounter++; })
|
||||
.AlongWith(
|
||||
wpi::cmd::InstantCommand([&runCounter] { runCounter++; }).ToPtr())
|
||||
.AlongWith(wpi::cmd::InstantCommand([&runCounter] {
|
||||
runCounter++;
|
||||
}).ToPtr())
|
||||
.Until([&finish] { return finish; });
|
||||
EXPECT_EQ(destructionCounter, 0) << "Composition should not delete command";
|
||||
|
||||
|
||||
@@ -20,7 +20,9 @@ class NetworkButtonTest : public CommandTestBase {
|
||||
inst.StartLocal();
|
||||
}
|
||||
|
||||
~NetworkButtonTest() override { wpi::nt::NetworkTableInstance::Destroy(inst); }
|
||||
~NetworkButtonTest() override {
|
||||
wpi::nt::NetworkTableInstance::Destroy(inst);
|
||||
}
|
||||
|
||||
wpi::nt::NetworkTableInstance inst;
|
||||
};
|
||||
|
||||
@@ -75,9 +75,10 @@ class SysIdRoutineTest : public ::testing::Test {
|
||||
m_sysidRoutine.Dynamic(wpi::cmd::sysid::Direction::kReverse)};
|
||||
|
||||
wpi::cmd::sysid::SysIdRoutine m_emptySysidRoutine{
|
||||
wpi::cmd::sysid::Config{std::nullopt, std::nullopt, std::nullopt, nullptr},
|
||||
wpi::cmd::sysid::Mechanism{[](wpi::units::volt_t driveVoltage) {}, nullptr,
|
||||
&m_subsystem}};
|
||||
wpi::cmd::sysid::Config{std::nullopt, std::nullopt, std::nullopt,
|
||||
nullptr},
|
||||
wpi::cmd::sysid::Mechanism{[](wpi::units::volt_t driveVoltage) {},
|
||||
nullptr, &m_subsystem}};
|
||||
|
||||
wpi::cmd::CommandPtr m_emptyRoutineForward{
|
||||
m_emptySysidRoutine.Quasistatic(wpi::cmd::sysid::Direction::kForward)};
|
||||
|
||||
@@ -27,12 +27,12 @@ int main() {
|
||||
switch (prop.GetKind()) {
|
||||
case wpi::cs::VideoProperty::kBoolean:
|
||||
wpi::util::print(" (bool): value={} default={}", prop.Get(),
|
||||
prop.GetDefault());
|
||||
prop.GetDefault());
|
||||
break;
|
||||
case wpi::cs::VideoProperty::kInteger:
|
||||
wpi::util::print(" (int): value={} min={} max={} step={} default={}",
|
||||
prop.Get(), prop.GetMin(), prop.GetMax(), prop.GetStep(),
|
||||
prop.GetDefault());
|
||||
prop.Get(), prop.GetMin(), prop.GetMax(),
|
||||
prop.GetStep(), prop.GetDefault());
|
||||
break;
|
||||
case wpi::cs::VideoProperty::kString:
|
||||
wpi::util::print(" (string): {}", prop.GetString());
|
||||
@@ -70,8 +70,8 @@ int main() {
|
||||
pixelFormat = "Unknown";
|
||||
break;
|
||||
}
|
||||
wpi::util::print(" PixelFormat:{} Width:{} Height:{} FPS:{}\n", pixelFormat,
|
||||
mode.width, mode.height, mode.fps);
|
||||
wpi::util::print(" PixelFormat:{} Width:{} Height:{} FPS:{}\n",
|
||||
pixelFormat, mode.width, mode.height, mode.fps);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,8 @@ int main() {
|
||||
camera.SetVideoMode(wpi::cs::VideoMode::kMJPEG, 320, 240, 30);
|
||||
wpi::cs::CvSink cvsink{"cvsink"};
|
||||
cvsink.SetSource(camera);
|
||||
wpi::cs::CvSource cvsource{"cvsource", wpi::cs::VideoMode::kMJPEG, 320, 240, 30};
|
||||
wpi::cs::CvSource cvsource{"cvsource", wpi::cs::VideoMode::kMJPEG, 320, 240,
|
||||
30};
|
||||
wpi::cs::MjpegServer cvMjpegServer{"cvhttpserver", 8083};
|
||||
cvMjpegServer.SetSource(cvsource);
|
||||
|
||||
@@ -27,8 +28,8 @@ int main() {
|
||||
wpi::util::print("error: {}\n", cvsink.GetError());
|
||||
continue;
|
||||
}
|
||||
wpi::util::print("got frame at time {} size ({}, {})\n", time, test.size().width,
|
||||
test.size().height);
|
||||
wpi::util::print("got frame at time {} size ({}, {})\n", time,
|
||||
test.size().width, test.size().height);
|
||||
cv::flip(test, flip, 0);
|
||||
cvsource.PutFrame(flip);
|
||||
}
|
||||
|
||||
@@ -76,12 +76,12 @@ int main(int argc, char** argv) {
|
||||
switch (prop.GetKind()) {
|
||||
case wpi::cs::VideoProperty::kBoolean:
|
||||
wpi::util::print(" (bool): value={} default={}", prop.Get(),
|
||||
prop.GetDefault());
|
||||
prop.GetDefault());
|
||||
break;
|
||||
case wpi::cs::VideoProperty::kInteger:
|
||||
wpi::util::print(" (int): value={} min={} max={} step={} default={}",
|
||||
prop.Get(), prop.GetMin(), prop.GetMax(), prop.GetStep(),
|
||||
prop.GetDefault());
|
||||
prop.Get(), prop.GetMin(), prop.GetMax(),
|
||||
prop.GetStep(), prop.GetDefault());
|
||||
break;
|
||||
case wpi::cs::VideoProperty::kString:
|
||||
wpi::util::print(" (string): {}", prop.GetString());
|
||||
|
||||
@@ -14,7 +14,8 @@ int main() {
|
||||
mjpegServer.SetSource(camera);
|
||||
wpi::cs::CvSink cvsink{"cvsink"};
|
||||
cvsink.SetSource(camera);
|
||||
wpi::cs::CvSource cvsource{"cvsource", wpi::cs::VideoMode::kMJPEG, 320, 240, 30};
|
||||
wpi::cs::CvSource cvsource{"cvsource", wpi::cs::VideoMode::kMJPEG, 320, 240,
|
||||
30};
|
||||
wpi::cs::MjpegServer cvMjpegServer{"cvhttpserver", 8082};
|
||||
cvMjpegServer.SetSource(cvsource);
|
||||
|
||||
@@ -26,8 +27,8 @@ int main() {
|
||||
wpi::util::print("error: {}\n", cvsink.GetError());
|
||||
continue;
|
||||
}
|
||||
wpi::util::print("got frame at time {} size ({}, {})\n", time, test.size().width,
|
||||
test.size().height);
|
||||
wpi::util::print("got frame at time {} size ({}, {})\n", time,
|
||||
test.size().width, test.size().height);
|
||||
cv::flip(test, flip, 0);
|
||||
cvsource.PutFrame(flip);
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ int main() {
|
||||
wpi::cs::AddListener(
|
||||
[&](const wpi::cs::RawEvent& event) {
|
||||
wpi::util::print("FPS={} MBPS={}\n", camera.GetActualFPS(),
|
||||
(camera.GetActualDataRate() / 1000000.0));
|
||||
(camera.GetActualDataRate() / 1000000.0));
|
||||
},
|
||||
wpi::cs::RawEvent::kTelemetryUpdated, false, &status);
|
||||
wpi::cs::SetTelemetryPeriod(1.0);
|
||||
|
||||
@@ -200,7 +200,8 @@ void SetSourceEnumPropertyChoices(CS_Source source, CS_Property property,
|
||||
extern "C" {
|
||||
void CS_NotifySourceError(CS_Source source, const struct WPI_String* msg,
|
||||
CS_Status* status) {
|
||||
return wpi::cs::NotifySourceError(source, wpi::util::to_string_view(msg), status);
|
||||
return wpi::cs::NotifySourceError(source, wpi::util::to_string_view(msg),
|
||||
status);
|
||||
}
|
||||
|
||||
void CS_SetSourceConnected(CS_Source source, CS_Bool connected,
|
||||
@@ -211,8 +212,8 @@ void CS_SetSourceConnected(CS_Source source, CS_Bool connected,
|
||||
void CS_SetSourceDescription(CS_Source source,
|
||||
const struct WPI_String* description,
|
||||
CS_Status* status) {
|
||||
return wpi::cs::SetSourceDescription(source, wpi::util::to_string_view(description),
|
||||
status);
|
||||
return wpi::cs::SetSourceDescription(
|
||||
source, wpi::util::to_string_view(description), status);
|
||||
}
|
||||
|
||||
CS_Property CS_CreateSourceProperty(CS_Source source,
|
||||
@@ -220,9 +221,9 @@ CS_Property CS_CreateSourceProperty(CS_Source source,
|
||||
enum CS_PropertyKind kind, int minimum,
|
||||
int maximum, int step, int defaultValue,
|
||||
int value, CS_Status* status) {
|
||||
return wpi::cs::CreateSourceProperty(source, wpi::util::to_string_view(name), kind,
|
||||
minimum, maximum, step, defaultValue, value,
|
||||
status);
|
||||
return wpi::cs::CreateSourceProperty(source, wpi::util::to_string_view(name),
|
||||
kind, minimum, maximum, step,
|
||||
defaultValue, value, status);
|
||||
}
|
||||
|
||||
CS_Property CS_CreateSourcePropertyCallback(
|
||||
|
||||
@@ -803,9 +803,9 @@ void Frame::ReleaseFrame() {
|
||||
}
|
||||
|
||||
namespace wpi::cs {
|
||||
std::unique_ptr<Image> CreateImageFromBGRA(wpi::cs::SourceImpl* source, size_t width,
|
||||
size_t height, size_t stride,
|
||||
const uint8_t* data) {
|
||||
std::unique_ptr<Image> CreateImageFromBGRA(wpi::cs::SourceImpl* source,
|
||||
size_t width, size_t height,
|
||||
size_t stride, const uint8_t* data) {
|
||||
cv::Mat finalImage{static_cast<int>(height), static_cast<int>(width), CV_8UC4,
|
||||
const_cast<uint8_t*>(data), stride};
|
||||
std::unique_ptr<Image> dest = source->AllocImage(
|
||||
|
||||
@@ -21,9 +21,9 @@ namespace wpi::cs {
|
||||
|
||||
class SourceImpl;
|
||||
|
||||
std::unique_ptr<Image> CreateImageFromBGRA(wpi::cs::SourceImpl* source, size_t width,
|
||||
size_t height, size_t stride,
|
||||
const uint8_t* data);
|
||||
std::unique_ptr<Image> CreateImageFromBGRA(wpi::cs::SourceImpl* source,
|
||||
size_t width, size_t height,
|
||||
size_t stride, const uint8_t* data);
|
||||
|
||||
class Frame {
|
||||
friend class SourceImpl;
|
||||
|
||||
@@ -164,7 +164,8 @@ wpi::net::HttpConnection* HttpCameraImpl::DeviceStreamConnect(
|
||||
if (m_nextLocation >= m_locations.size()) {
|
||||
m_nextLocation = 0;
|
||||
}
|
||||
req = wpi::net::HttpRequest{m_locations[m_nextLocation++], m_streamSettings};
|
||||
req =
|
||||
wpi::net::HttpRequest{m_locations[m_nextLocation++], m_streamSettings};
|
||||
m_streamSettingsUpdated = false;
|
||||
}
|
||||
|
||||
@@ -176,7 +177,8 @@ wpi::net::HttpConnection* HttpCameraImpl::DeviceStreamConnect(
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto connPtr = std::make_unique<wpi::net::HttpConnection>(std::move(stream), 1);
|
||||
auto connPtr =
|
||||
std::make_unique<wpi::net::HttpConnection>(std::move(stream), 1);
|
||||
wpi::net::HttpConnection* conn = connPtr.get();
|
||||
|
||||
// update m_streamConn
|
||||
@@ -195,7 +197,8 @@ wpi::net::HttpConnection* HttpCameraImpl::DeviceStreamConnect(
|
||||
}
|
||||
|
||||
// Parse Content-Type header to get the boundary
|
||||
auto [mediaType, contentType] = wpi::util::split(conn->contentType.str(), ';');
|
||||
auto [mediaType, contentType] =
|
||||
wpi::util::split(conn->contentType.str(), ';');
|
||||
mediaType = wpi::util::trim(mediaType);
|
||||
if (mediaType != "multipart/x-mixed-replace") {
|
||||
SWARNING("\"{}\": unrecognized Content-Type \"{}\"", req.host.str(),
|
||||
@@ -213,7 +216,8 @@ wpi::net::HttpConnection* HttpCameraImpl::DeviceStreamConnect(
|
||||
contentType = wpi::util::ltrim(contentType);
|
||||
auto [key, value] = wpi::util::split(keyvalue, '=');
|
||||
if (wpi::util::trim(key) == "boundary") {
|
||||
value = wpi::util::trim(wpi::util::trim(value), '"'); // value may be quoted
|
||||
value =
|
||||
wpi::util::trim(wpi::util::trim(value), '"'); // value may be quoted
|
||||
if (wpi::util::starts_with(value, "--")) {
|
||||
value = wpi::util::substr(value, 2);
|
||||
}
|
||||
@@ -369,7 +373,8 @@ void HttpCameraImpl::DeviceSendSettings(wpi::net::HttpRequest& req) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto connPtr = std::make_unique<wpi::net::HttpConnection>(std::move(stream), 1);
|
||||
auto connPtr =
|
||||
std::make_unique<wpi::net::HttpConnection>(std::move(stream), 1);
|
||||
wpi::net::HttpConnection* conn = connPtr.get();
|
||||
|
||||
// update m_settingsConn
|
||||
@@ -653,7 +658,8 @@ CS_Source CS_CreateHttpCamera(const struct WPI_String* name,
|
||||
const struct WPI_String* url,
|
||||
CS_HttpCameraKind kind, CS_Status* status) {
|
||||
return wpi::cs::CreateHttpCamera(wpi::util::to_string_view(name),
|
||||
wpi::util::to_string_view(url), kind, status);
|
||||
wpi::util::to_string_view(url), kind,
|
||||
status);
|
||||
}
|
||||
|
||||
CS_Source CS_CreateHttpCameraMulti(const struct WPI_String* name,
|
||||
@@ -664,7 +670,8 @@ CS_Source CS_CreateHttpCameraMulti(const struct WPI_String* name,
|
||||
for (int i = 0; i < count; ++i) {
|
||||
vec.emplace_back(wpi::util::to_string_view(&urls[i]));
|
||||
}
|
||||
return wpi::cs::CreateHttpCamera(wpi::util::to_string_view(name), vec, kind, status);
|
||||
return wpi::cs::CreateHttpCamera(wpi::util::to_string_view(name), vec, kind,
|
||||
status);
|
||||
}
|
||||
|
||||
CS_HttpCameraKind CS_GetHttpCameraKind(CS_Source source, CS_Status* status) {
|
||||
|
||||
@@ -28,7 +28,8 @@ namespace wpi::cs {
|
||||
class HttpCameraImpl : public SourceImpl {
|
||||
public:
|
||||
HttpCameraImpl(std::string_view name, CS_HttpCameraKind kind,
|
||||
wpi::util::Logger& logger, Notifier& notifier, Telemetry& telemetry);
|
||||
wpi::util::Logger& logger, Notifier& notifier,
|
||||
Telemetry& telemetry);
|
||||
~HttpCameraImpl() override;
|
||||
|
||||
void Start() override;
|
||||
@@ -146,8 +147,8 @@ class HttpCameraImpl : public SourceImpl {
|
||||
|
||||
class AxisCameraImpl : public HttpCameraImpl {
|
||||
public:
|
||||
AxisCameraImpl(std::string_view name, wpi::util::Logger& logger, Notifier& notifier,
|
||||
Telemetry& telemetry)
|
||||
AxisCameraImpl(std::string_view name, wpi::util::Logger& logger,
|
||||
Notifier& notifier, Telemetry& telemetry)
|
||||
: HttpCameraImpl{name, CS_HTTP_AXIS, logger, notifier, telemetry} {}
|
||||
#if 0
|
||||
void SetProperty(int property, int value, CS_Status* status) override;
|
||||
|
||||
@@ -33,8 +33,8 @@ static void def_log_func(unsigned int level, const char* file,
|
||||
return;
|
||||
}
|
||||
wpi::util::print(stderr, "CS: {}: {} ({}:{})\n", levelmsg, msg,
|
||||
// NOLINTNEXTLINE(build/include_what_you_use)
|
||||
fs::path{file}.filename().string(), line);
|
||||
// NOLINTNEXTLINE(build/include_what_you_use)
|
||||
fs::path{file}.filename().string(), line);
|
||||
}
|
||||
|
||||
Instance::Instance()
|
||||
|
||||
@@ -91,12 +91,13 @@ class Instance {
|
||||
return m_sources.GetAll(vec);
|
||||
}
|
||||
|
||||
std::span<CS_Sink> EnumerateSinkHandles(wpi::util::SmallVectorImpl<CS_Sink>& vec) {
|
||||
std::span<CS_Sink> EnumerateSinkHandles(
|
||||
wpi::util::SmallVectorImpl<CS_Sink>& vec) {
|
||||
return m_sinks.GetAll(vec);
|
||||
}
|
||||
|
||||
std::span<CS_Sink> EnumerateSourceSinks(CS_Source source,
|
||||
wpi::util::SmallVectorImpl<CS_Sink>& vec) {
|
||||
std::span<CS_Sink> EnumerateSourceSinks(
|
||||
CS_Source source, wpi::util::SmallVectorImpl<CS_Sink>& vec) {
|
||||
vec.clear();
|
||||
m_sinks.ForEach([&](CS_Sink sinkHandle, const SinkData& data) {
|
||||
if (source == data.sourceHandle.load()) {
|
||||
|
||||
@@ -146,7 +146,8 @@ static inline void ReadInto(wpi::util::raw_istream& is, std::string& buf,
|
||||
is.read(&(*buf.begin()) + oldSize, len);
|
||||
}
|
||||
|
||||
bool ReadJpeg(wpi::util::raw_istream& is, std::string& buf, int* width, int* height) {
|
||||
bool ReadJpeg(wpi::util::raw_istream& is, std::string& buf, int* width,
|
||||
int* height) {
|
||||
// in case we don't get a SOF
|
||||
*width = 0;
|
||||
*height = 0;
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
namespace wpi::util {
|
||||
class raw_istream;
|
||||
} // namespace wpi
|
||||
} // namespace wpi::util
|
||||
|
||||
namespace wpi::cs {
|
||||
|
||||
@@ -22,7 +22,8 @@ bool JpegNeedsDHT(const char* data, size_t* size, size_t* locSOF);
|
||||
|
||||
std::string_view JpegGetDHT();
|
||||
|
||||
bool ReadJpeg(wpi::util::raw_istream& is, std::string& buf, int* width, int* height);
|
||||
bool ReadJpeg(wpi::util::raw_istream& is, std::string& buf, int* width,
|
||||
int* height);
|
||||
|
||||
} // namespace wpi::cs
|
||||
|
||||
|
||||
@@ -4,9 +4,10 @@
|
||||
|
||||
#include "Log.hpp"
|
||||
|
||||
void wpi::cs::NamedLogV(wpi::util::Logger& logger, unsigned int level, const char* file,
|
||||
unsigned int line, std::string_view name,
|
||||
fmt::string_view format, fmt::format_args args) {
|
||||
void wpi::cs::NamedLogV(wpi::util::Logger& logger, unsigned int level,
|
||||
const char* file, unsigned int line,
|
||||
std::string_view name, fmt::string_view format,
|
||||
fmt::format_args args) {
|
||||
fmt::memory_buffer out;
|
||||
fmt::format_to(fmt::appender{out}, "{}: ", name);
|
||||
fmt::vformat_to(fmt::appender{out}, format, args);
|
||||
|
||||
@@ -16,9 +16,9 @@ void NamedLogV(wpi::util::Logger& logger, unsigned int level, const char* file,
|
||||
fmt::string_view format, fmt::format_args args);
|
||||
|
||||
template <typename S, typename... Args>
|
||||
inline void NamedLog(wpi::util::Logger& logger, unsigned int level, const char* file,
|
||||
unsigned int line, std::string_view name, const S& format,
|
||||
Args&&... args) {
|
||||
inline void NamedLog(wpi::util::Logger& logger, unsigned int level,
|
||||
const char* file, unsigned int line, std::string_view name,
|
||||
const S& format, Args&&... args) {
|
||||
if (logger.HasLogger() && level >= logger.min_level()) {
|
||||
NamedLogV(logger, level, file, line, name, format,
|
||||
fmt::make_format_args(args...));
|
||||
|
||||
@@ -362,9 +362,9 @@ void MjpegServerImpl::ConnThread::SendHTML(wpi::util::raw_ostream& os,
|
||||
switch (kind) {
|
||||
case CS_PROP_BOOLEAN:
|
||||
wpi::util::print(os,
|
||||
"<input id=\"{0}\" type=\"checkbox\" "
|
||||
"onclick=\"update('{0}', this.checked ? 1 : 0)\" ",
|
||||
name);
|
||||
"<input id=\"{0}\" type=\"checkbox\" "
|
||||
"onclick=\"update('{0}', this.checked ? 1 : 0)\" ",
|
||||
name);
|
||||
if (source.GetProperty(prop, &status) != 0) {
|
||||
os << "checked />\n";
|
||||
} else {
|
||||
@@ -377,12 +377,12 @@ void MjpegServerImpl::ConnThread::SendHTML(wpi::util::raw_ostream& os,
|
||||
auto max = source.GetPropertyMax(prop, &status);
|
||||
auto step = source.GetPropertyStep(prop, &status);
|
||||
wpi::util::print(os,
|
||||
"<input type=\"range\" min=\"{1}\" max=\"{2}\" "
|
||||
"value=\"{3}\" id=\"{0}\" step=\"{4}\" "
|
||||
"oninput=\"updateInt('#{0}op', '{0}', value)\" />\n",
|
||||
name, min, max, valI, step);
|
||||
wpi::util::print(os, "<output for=\"{0}\" id=\"{0}op\">{1}</output>\n", name,
|
||||
valI);
|
||||
"<input type=\"range\" min=\"{1}\" max=\"{2}\" "
|
||||
"value=\"{3}\" id=\"{0}\" step=\"{4}\" "
|
||||
"oninput=\"updateInt('#{0}op', '{0}', value)\" />\n",
|
||||
name, min, max, valI, step);
|
||||
wpi::util::print(os, "<output for=\"{0}\" id=\"{0}op\">{1}</output>\n",
|
||||
name, valI);
|
||||
break;
|
||||
}
|
||||
case CS_PROP_ENUM: {
|
||||
@@ -400,27 +400,28 @@ void MjpegServerImpl::ConnThread::SendHTML(wpi::util::raw_ostream& os,
|
||||
ch_name.push_back(wpi::util::isPrint(ch) ? ch : ' ');
|
||||
}
|
||||
wpi::util::print(os,
|
||||
"<input id=\"{0}{1}\" type=\"radio\" name=\"{0}\" "
|
||||
"value=\"{2}\" onclick=\"update('{0}', {1})\"",
|
||||
name, j, ch_name.str());
|
||||
"<input id=\"{0}{1}\" type=\"radio\" name=\"{0}\" "
|
||||
"value=\"{2}\" onclick=\"update('{0}', {1})\"",
|
||||
name, j, ch_name.str());
|
||||
if (j == valE) {
|
||||
os << " checked";
|
||||
}
|
||||
wpi::util::print(os, " /><label for=\"{}{}\">{}</label>\n", name, j,
|
||||
ch_name.str());
|
||||
ch_name.str());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CS_PROP_STRING: {
|
||||
wpi::util::SmallString<128> strval_buf;
|
||||
wpi::util::print(os,
|
||||
"<input type=\"text\" id=\"{0}box\" name=\"{0}\" "
|
||||
"value=\"{1}\" />\n",
|
||||
name, source.GetStringProperty(prop, strval_buf, &status));
|
||||
"<input type=\"text\" id=\"{0}box\" name=\"{0}\" "
|
||||
"value=\"{1}\" />\n",
|
||||
name,
|
||||
source.GetStringProperty(prop, strval_buf, &status));
|
||||
wpi::util::print(os,
|
||||
"<input type=\"button\" value =\"Submit\" "
|
||||
"onclick=\"update('{0}', {0}box.value)\" />\n",
|
||||
name);
|
||||
"<input type=\"button\" value =\"Submit\" "
|
||||
"onclick=\"update('{0}', {0}box.value)\" />\n",
|
||||
name);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -473,8 +474,8 @@ void MjpegServerImpl::ConnThread::SendHTML(wpi::util::raw_ostream& os,
|
||||
os << "unknown";
|
||||
break;
|
||||
}
|
||||
wpi::util::print(os, "</td><td>{}</td><td>{}</td><td>{}</td></tr>", mode.width,
|
||||
mode.height, mode.fps);
|
||||
wpi::util::print(os, "</td><td>{}</td><td>{}</td><td>{}</td></tr>",
|
||||
mode.width, mode.height, mode.fps);
|
||||
}
|
||||
os << "</table>\n";
|
||||
os << endRootPage << "\r\n";
|
||||
@@ -505,12 +506,14 @@ void MjpegServerImpl::ConnThread::SendJSON(wpi::util::raw_ostream& os,
|
||||
wpi::util::print(os, "\n\"name\": \"{}\"", name);
|
||||
wpi::util::print(os, ",\n\"id\": \"{}\"", prop);
|
||||
wpi::util::print(os, ",\n\"type\": \"{}\"", static_cast<int>(kind));
|
||||
wpi::util::print(os, ",\n\"min\": \"{}\"", source.GetPropertyMin(prop, &status));
|
||||
wpi::util::print(os, ",\n\"max\": \"{}\"", source.GetPropertyMax(prop, &status));
|
||||
wpi::util::print(os, ",\n\"min\": \"{}\"",
|
||||
source.GetPropertyMin(prop, &status));
|
||||
wpi::util::print(os, ",\n\"max\": \"{}\"",
|
||||
source.GetPropertyMax(prop, &status));
|
||||
wpi::util::print(os, ",\n\"step\": \"{}\"",
|
||||
source.GetPropertyStep(prop, &status));
|
||||
source.GetPropertyStep(prop, &status));
|
||||
wpi::util::print(os, ",\n\"default\": \"{}\"",
|
||||
source.GetPropertyDefault(prop, &status));
|
||||
source.GetPropertyDefault(prop, &status));
|
||||
os << ",\n\"value\": \"";
|
||||
switch (kind) {
|
||||
case CS_PROP_BOOLEAN:
|
||||
@@ -597,10 +600,10 @@ void MjpegServerImpl::ConnThread::SendJSON(wpi::util::raw_ostream& os,
|
||||
os.flush();
|
||||
}
|
||||
|
||||
MjpegServerImpl::MjpegServerImpl(std::string_view name, wpi::util::Logger& logger,
|
||||
Notifier& notifier, Telemetry& telemetry,
|
||||
std::string_view listenAddress, int port,
|
||||
std::unique_ptr<wpi::net::NetworkAcceptor> acceptor)
|
||||
MjpegServerImpl::MjpegServerImpl(
|
||||
std::string_view name, wpi::util::Logger& logger, Notifier& notifier,
|
||||
Telemetry& telemetry, std::string_view listenAddress, int port,
|
||||
std::unique_ptr<wpi::net::NetworkAcceptor> acceptor)
|
||||
: SinkImpl{name, logger, notifier, telemetry},
|
||||
m_listenAddress(listenAddress),
|
||||
m_port(port),
|
||||
@@ -813,14 +816,17 @@ void MjpegServerImpl::ConnThread::ProcessRequest() {
|
||||
// compatibility, others are for Axis camera compatibility.
|
||||
if ((pos = req.find("POST /stream")) != std::string_view::npos) {
|
||||
kind = kStream;
|
||||
parameters = wpi::util::substr(wpi::util::substr(req, req.find('?', pos + 12)), 1);
|
||||
parameters =
|
||||
wpi::util::substr(wpi::util::substr(req, req.find('?', pos + 12)), 1);
|
||||
} else if ((pos = req.find("GET /?action=stream")) !=
|
||||
std::string_view::npos) {
|
||||
kind = kStream;
|
||||
parameters = wpi::util::substr(wpi::util::substr(req, req.find('&', pos + 19)), 1);
|
||||
parameters =
|
||||
wpi::util::substr(wpi::util::substr(req, req.find('&', pos + 19)), 1);
|
||||
} else if ((pos = req.find("GET /stream.mjpg")) != std::string_view::npos) {
|
||||
kind = kStream;
|
||||
parameters = wpi::util::substr(wpi::util::substr(req, req.find('?', pos + 16)), 1);
|
||||
parameters =
|
||||
wpi::util::substr(wpi::util::substr(req, req.find('?', pos + 16)), 1);
|
||||
} else if (req.find("GET /settings") != std::string_view::npos &&
|
||||
req.find(".json") != std::string_view::npos) {
|
||||
kind = kGetSettings;
|
||||
@@ -836,7 +842,8 @@ void MjpegServerImpl::ConnThread::ProcessRequest() {
|
||||
} else if ((pos = req.find("GET /?action=command")) !=
|
||||
std::string_view::npos) {
|
||||
kind = kCommand;
|
||||
parameters = wpi::util::substr(wpi::util::substr(req, req.find('&', pos + 20)), 1);
|
||||
parameters =
|
||||
wpi::util::substr(wpi::util::substr(req, req.find('&', pos + 20)), 1);
|
||||
} else if (req.find("GET / ") != std::string_view::npos || req == "GET /\n") {
|
||||
kind = kRootPage;
|
||||
} else {
|
||||
@@ -959,11 +966,12 @@ void MjpegServerImpl::ServerThreadMain() {
|
||||
|
||||
std::scoped_lock lock(m_mutex);
|
||||
// Find unoccupied worker thread, or create one if necessary
|
||||
auto it = std::find_if(m_connThreads.begin(), m_connThreads.end(),
|
||||
[](const wpi::util::SafeThreadOwner<ConnThread>& owner) {
|
||||
auto thr = owner.GetThread();
|
||||
return !thr || !thr->m_stream;
|
||||
});
|
||||
auto it =
|
||||
std::find_if(m_connThreads.begin(), m_connThreads.end(),
|
||||
[](const wpi::util::SafeThreadOwner<ConnThread>& owner) {
|
||||
auto thr = owner.GetThread();
|
||||
return !thr || !thr->m_stream;
|
||||
});
|
||||
if (it == m_connThreads.end()) {
|
||||
m_connThreads.emplace_back();
|
||||
it = std::prev(m_connThreads.end());
|
||||
@@ -1052,13 +1060,14 @@ CS_Sink CS_CreateMjpegServer(const struct WPI_String* name,
|
||||
const struct WPI_String* listenAddress, int port,
|
||||
CS_Status* status) {
|
||||
return wpi::cs::CreateMjpegServer(wpi::util::to_string_view(name),
|
||||
wpi::util::to_string_view(listenAddress), port,
|
||||
status);
|
||||
wpi::util::to_string_view(listenAddress),
|
||||
port, status);
|
||||
}
|
||||
|
||||
void CS_GetMjpegServerListenAddress(CS_Sink sink, WPI_String* listenAddress,
|
||||
CS_Status* status) {
|
||||
wpi::cs::ConvertToC(listenAddress, wpi::cs::GetMjpegServerListenAddress(sink, status));
|
||||
wpi::cs::ConvertToC(listenAddress,
|
||||
wpi::cs::GetMjpegServerListenAddress(sink, status));
|
||||
}
|
||||
|
||||
int CS_GetMjpegServerPort(CS_Sink sink, CS_Status* status) {
|
||||
|
||||
@@ -53,7 +53,8 @@ class NotifierThread
|
||||
|
||||
} // namespace impl
|
||||
|
||||
class Notifier : public wpi::util::CallbackManager<Notifier, impl::NotifierThread> {
|
||||
class Notifier
|
||||
: public wpi::util::CallbackManager<Notifier, impl::NotifierThread> {
|
||||
friend class NotifierTest;
|
||||
|
||||
public:
|
||||
|
||||
@@ -59,7 +59,8 @@ CS_PropertyKind PropertyContainer::GetPropertyKind(int property) const {
|
||||
}
|
||||
|
||||
std::string_view PropertyContainer::GetPropertyName(
|
||||
int property, wpi::util::SmallVectorImpl<char>& buf, CS_Status* status) const {
|
||||
int property, wpi::util::SmallVectorImpl<char>& buf,
|
||||
CS_Status* status) const {
|
||||
if (!m_properties_cached && !CacheProperties(status)) {
|
||||
return {};
|
||||
}
|
||||
@@ -168,7 +169,8 @@ int PropertyContainer::GetPropertyDefault(int property,
|
||||
}
|
||||
|
||||
std::string_view PropertyContainer::GetStringProperty(
|
||||
int property, wpi::util::SmallVectorImpl<char>& buf, CS_Status* status) const {
|
||||
int property, wpi::util::SmallVectorImpl<char>& buf,
|
||||
CS_Status* status) const {
|
||||
if (!m_properties_cached && !CacheProperties(status)) {
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace wpi::util {
|
||||
class Logger;
|
||||
template <typename T>
|
||||
class SmallVectorImpl;
|
||||
} // namespace wpi
|
||||
} // namespace wpi::util
|
||||
|
||||
namespace wpi::cs {
|
||||
|
||||
@@ -52,8 +52,9 @@ class PropertyContainer {
|
||||
std::vector<std::string> GetEnumPropertyChoices(int property,
|
||||
CS_Status* status) const;
|
||||
|
||||
bool SetPropertiesJson(const wpi::util::json& config, wpi::util::Logger& logger,
|
||||
std::string_view logName, CS_Status* status);
|
||||
bool SetPropertiesJson(const wpi::util::json& config,
|
||||
wpi::util::Logger& logger, std::string_view logName,
|
||||
CS_Status* status);
|
||||
wpi::util::json GetPropertiesJsonObject(CS_Status* status);
|
||||
|
||||
protected:
|
||||
|
||||
@@ -233,8 +233,8 @@ uint64_t CS_GrabRawSinkFrameTimeoutWithFrameTime(CS_Sink sink,
|
||||
double timeout,
|
||||
uint64_t lastFrameTime,
|
||||
CS_Status* status) {
|
||||
return wpi::cs::GrabSinkFrameTimeoutLastTime(sink, *image, timeout, lastFrameTime,
|
||||
status);
|
||||
return wpi::cs::GrabSinkFrameTimeoutLastTime(sink, *image, timeout,
|
||||
lastFrameTime, status);
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
@@ -22,10 +22,10 @@ class SourceImpl;
|
||||
|
||||
class RawSinkImpl : public SinkImpl {
|
||||
public:
|
||||
RawSinkImpl(std::string_view name, wpi::util::Logger& logger, Notifier& notifier,
|
||||
Telemetry& telemetry);
|
||||
RawSinkImpl(std::string_view name, wpi::util::Logger& logger, Notifier& notifier,
|
||||
Telemetry& telemetry,
|
||||
RawSinkImpl(std::string_view name, wpi::util::Logger& logger,
|
||||
Notifier& notifier, Telemetry& telemetry);
|
||||
RawSinkImpl(std::string_view name, wpi::util::Logger& logger,
|
||||
Notifier& notifier, Telemetry& telemetry,
|
||||
std::function<void(uint64_t time)> processFrame);
|
||||
~RawSinkImpl() override;
|
||||
|
||||
|
||||
@@ -55,7 +55,8 @@ extern "C" {
|
||||
CS_Source CS_CreateRawSource(const struct WPI_String* name, CS_Bool isCv,
|
||||
const CS_VideoMode* mode, CS_Status* status) {
|
||||
return wpi::cs::CreateRawSource(wpi::util::to_string_view(name), isCv,
|
||||
static_cast<const wpi::cs::VideoMode&>(*mode), status);
|
||||
static_cast<const wpi::cs::VideoMode&>(*mode),
|
||||
status);
|
||||
}
|
||||
|
||||
void CS_PutRawSourceFrame(CS_Source source, const struct WPI_RawFrame* image,
|
||||
|
||||
@@ -20,8 +20,9 @@ namespace wpi::cs {
|
||||
|
||||
class RawSourceImpl : public ConfigurableSourceImpl {
|
||||
public:
|
||||
RawSourceImpl(std::string_view name, wpi::util::Logger& logger, Notifier& notifier,
|
||||
Telemetry& telemetry, const VideoMode& mode);
|
||||
RawSourceImpl(std::string_view name, wpi::util::Logger& logger,
|
||||
Notifier& notifier, Telemetry& telemetry,
|
||||
const VideoMode& mode);
|
||||
~RawSourceImpl() override;
|
||||
|
||||
// Raw-specific functions
|
||||
|
||||
@@ -113,7 +113,8 @@ std::string SinkImpl::GetError() const {
|
||||
return std::string{m_source->GetCurFrame().GetError()};
|
||||
}
|
||||
|
||||
std::string_view SinkImpl::GetError(wpi::util::SmallVectorImpl<char>& buf) const {
|
||||
std::string_view SinkImpl::GetError(
|
||||
wpi::util::SmallVectorImpl<char>& buf) const {
|
||||
std::scoped_lock lock(m_mutex);
|
||||
if (!m_source) {
|
||||
return "no source connected";
|
||||
@@ -221,7 +222,8 @@ std::string GetSinkError(CS_Sink sink, CS_Status* status) {
|
||||
return data->sink->GetError();
|
||||
}
|
||||
|
||||
std::string_view GetSinkError(CS_Sink sink, wpi::util::SmallVectorImpl<char>& buf,
|
||||
std::string_view GetSinkError(CS_Sink sink,
|
||||
wpi::util::SmallVectorImpl<char>& buf,
|
||||
CS_Status* status) {
|
||||
auto data = Instance::GetInstance().GetSink(sink);
|
||||
if (!data || (data->kind & SinkMask) == 0) {
|
||||
@@ -245,7 +247,8 @@ void SetSinkEnabled(CS_Sink sink, bool enabled, CS_Status* status) {
|
||||
extern "C" {
|
||||
void CS_SetSinkDescription(CS_Sink sink, const struct WPI_String* description,
|
||||
CS_Status* status) {
|
||||
return wpi::cs::SetSinkDescription(sink, wpi::util::to_string_view(description), status);
|
||||
return wpi::cs::SetSinkDescription(
|
||||
sink, wpi::util::to_string_view(description), status);
|
||||
}
|
||||
|
||||
void CS_GetSinkError(CS_Sink sink, struct WPI_String* error,
|
||||
|
||||
@@ -190,7 +190,8 @@ bool SourceImpl::SetConfigJson(std::string_view config, CS_Status* status) {
|
||||
return SetConfigJson(j, status);
|
||||
}
|
||||
|
||||
bool SourceImpl::SetConfigJson(const wpi::util::json& config, CS_Status* status) {
|
||||
bool SourceImpl::SetConfigJson(const wpi::util::json& config,
|
||||
CS_Status* status) {
|
||||
VideoMode mode;
|
||||
|
||||
// pixel format
|
||||
@@ -260,8 +261,9 @@ bool SourceImpl::SetConfigJson(const wpi::util::json& config, CS_Status* status)
|
||||
} else {
|
||||
if (mode.pixelFormat != wpi::cs::VideoMode::kUnknown) {
|
||||
SINFO("SetConfigJson: setting pixelFormat {}", mode.pixelFormat);
|
||||
SetPixelFormat(static_cast<wpi::cs::VideoMode::PixelFormat>(mode.pixelFormat),
|
||||
status);
|
||||
SetPixelFormat(
|
||||
static_cast<wpi::cs::VideoMode::PixelFormat>(mode.pixelFormat),
|
||||
status);
|
||||
}
|
||||
if (mode.width != 0 && mode.height != 0) {
|
||||
SINFO("SetConfigJson: setting width {}, height {}", mode.width,
|
||||
|
||||
@@ -32,8 +32,8 @@ class SourceImpl : public PropertyContainer {
|
||||
friend class Frame;
|
||||
|
||||
public:
|
||||
SourceImpl(std::string_view name, wpi::util::Logger& logger, Notifier& notifier,
|
||||
Telemetry& telemetry);
|
||||
SourceImpl(std::string_view name, wpi::util::Logger& logger,
|
||||
Notifier& notifier, Telemetry& telemetry);
|
||||
~SourceImpl() override;
|
||||
SourceImpl(const SourceImpl& oth) = delete;
|
||||
SourceImpl& operator=(const SourceImpl& oth) = delete;
|
||||
|
||||
@@ -35,14 +35,15 @@ extern "C" {
|
||||
|
||||
CS_Source CS_CreateUsbCameraDev(const struct WPI_String* name, int dev,
|
||||
CS_Status* status) {
|
||||
return wpi::cs::CreateUsbCameraDev(wpi::util::to_string_view(name), dev, status);
|
||||
return wpi::cs::CreateUsbCameraDev(wpi::util::to_string_view(name), dev,
|
||||
status);
|
||||
}
|
||||
|
||||
CS_Source CS_CreateUsbCameraPath(const struct WPI_String* name,
|
||||
const struct WPI_String* path,
|
||||
CS_Status* status) {
|
||||
return wpi::cs::CreateUsbCameraPath(wpi::util::to_string_view(name),
|
||||
wpi::util::to_string_view(path), status);
|
||||
wpi::util::to_string_view(path), status);
|
||||
}
|
||||
|
||||
void CS_SetUsbCameraPath(CS_Source source, const struct WPI_String* path,
|
||||
|
||||
@@ -34,7 +34,8 @@ template <typename O, typename I>
|
||||
static O* ConvertToC(std::vector<I>&& in, int* count) {
|
||||
using T = std::vector<I>;
|
||||
size_t size = in.size();
|
||||
O* out = static_cast<O*>(wpi::util::safe_malloc(size * sizeof(O) + sizeof(T)));
|
||||
O* out =
|
||||
static_cast<O*>(wpi::util::safe_malloc(size * sizeof(O) + sizeof(T)));
|
||||
*count = size;
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
out[i] = ConvertToC(in[i]);
|
||||
@@ -92,7 +93,8 @@ void CS_GetStringProperty(CS_Property property, WPI_String* value,
|
||||
|
||||
void CS_SetStringProperty(CS_Property property, const struct WPI_String* value,
|
||||
CS_Status* status) {
|
||||
return wpi::cs::SetStringProperty(property, wpi::util::to_string_view(value), status);
|
||||
return wpi::cs::SetStringProperty(property, wpi::util::to_string_view(value),
|
||||
status);
|
||||
}
|
||||
|
||||
WPI_String* CS_GetEnumPropertyChoices(CS_Property property, int* count,
|
||||
@@ -118,7 +120,8 @@ void CS_GetSourceName(CS_Source source, WPI_String* name, CS_Status* status) {
|
||||
void CS_GetSourceDescription(CS_Source source, WPI_String* description,
|
||||
CS_Status* status) {
|
||||
wpi::util::SmallString<128> buf;
|
||||
wpi::cs::ConvertToC(description, wpi::cs::GetSourceDescription(source, buf, status));
|
||||
wpi::cs::ConvertToC(description,
|
||||
wpi::cs::GetSourceDescription(source, buf, status));
|
||||
}
|
||||
|
||||
uint64_t CS_GetSourceLastFrameTime(CS_Source source, CS_Status* status) {
|
||||
@@ -142,7 +145,8 @@ CS_Bool CS_IsSourceEnabled(CS_Source source, CS_Status* status) {
|
||||
CS_Property CS_GetSourceProperty(CS_Source source,
|
||||
const struct WPI_String* name,
|
||||
CS_Status* status) {
|
||||
return wpi::cs::GetSourceProperty(source, wpi::util::to_string_view(name), status);
|
||||
return wpi::cs::GetSourceProperty(source, wpi::util::to_string_view(name),
|
||||
status);
|
||||
}
|
||||
|
||||
CS_Property* CS_EnumerateSourceProperties(CS_Source source, int* count,
|
||||
@@ -174,8 +178,8 @@ CS_Bool CS_SetSourceVideoModeDiscrete(CS_Source source,
|
||||
return wpi::cs::SetSourceVideoMode(
|
||||
source,
|
||||
wpi::cs::VideoMode{static_cast<wpi::cs::VideoMode::PixelFormat>(
|
||||
static_cast<int>(pixelFormat)),
|
||||
width, height, fps},
|
||||
static_cast<int>(pixelFormat)),
|
||||
width, height, fps},
|
||||
status);
|
||||
}
|
||||
|
||||
@@ -184,7 +188,8 @@ CS_Bool CS_SetSourcePixelFormat(CS_Source source,
|
||||
CS_Status* status) {
|
||||
return wpi::cs::SetSourcePixelFormat(
|
||||
source,
|
||||
static_cast<wpi::cs::VideoMode::PixelFormat>(static_cast<int>(pixelFormat)),
|
||||
static_cast<wpi::cs::VideoMode::PixelFormat>(
|
||||
static_cast<int>(pixelFormat)),
|
||||
status);
|
||||
}
|
||||
|
||||
@@ -200,7 +205,8 @@ CS_Bool CS_SetSourceFPS(CS_Source source, int fps, CS_Status* status) {
|
||||
CS_Bool CS_SetSourceConfigJson(CS_Source source,
|
||||
const struct WPI_String* config,
|
||||
CS_Status* status) {
|
||||
return wpi::cs::SetSourceConfigJson(source, wpi::util::to_string_view(config), status);
|
||||
return wpi::cs::SetSourceConfigJson(source, wpi::util::to_string_view(config),
|
||||
status);
|
||||
}
|
||||
|
||||
void CS_GetSourceConfigJson(CS_Source source, WPI_String* config,
|
||||
@@ -222,8 +228,8 @@ CS_Sink* CS_EnumerateSourceSinks(CS_Source source, int* count,
|
||||
CS_Status* status) {
|
||||
wpi::util::SmallVector<CS_Sink, 32> buf;
|
||||
auto handles = wpi::cs::EnumerateSourceSinks(source, buf, status);
|
||||
CS_Sink* sinks =
|
||||
static_cast<CS_Sink*>(wpi::util::safe_malloc(handles.size() * sizeof(CS_Sink)));
|
||||
CS_Sink* sinks = static_cast<CS_Sink*>(
|
||||
wpi::util::safe_malloc(handles.size() * sizeof(CS_Sink)));
|
||||
*count = handles.size();
|
||||
std::copy(handles.begin(), handles.end(), sinks);
|
||||
return sinks;
|
||||
@@ -284,12 +290,14 @@ void CS_GetSinkName(CS_Sink sink, WPI_String* name, CS_Status* status) {
|
||||
void CS_GetSinkDescription(CS_Sink sink, WPI_String* description,
|
||||
CS_Status* status) {
|
||||
wpi::util::SmallString<128> buf;
|
||||
wpi::cs::ConvertToC(description, wpi::cs::GetSinkDescription(sink, buf, status));
|
||||
wpi::cs::ConvertToC(description,
|
||||
wpi::cs::GetSinkDescription(sink, buf, status));
|
||||
}
|
||||
|
||||
CS_Property CS_GetSinkProperty(CS_Sink sink, const struct WPI_String* name,
|
||||
CS_Status* status) {
|
||||
return wpi::cs::GetSinkProperty(sink, wpi::util::to_string_view(name), status);
|
||||
return wpi::cs::GetSinkProperty(sink, wpi::util::to_string_view(name),
|
||||
status);
|
||||
}
|
||||
|
||||
CS_Property* CS_EnumerateSinkProperties(CS_Sink sink, int* count,
|
||||
@@ -305,7 +313,8 @@ CS_Property* CS_EnumerateSinkProperties(CS_Sink sink, int* count,
|
||||
|
||||
CS_Bool CS_SetSinkConfigJson(CS_Sink sink, const struct WPI_String* config,
|
||||
CS_Status* status) {
|
||||
return wpi::cs::SetSinkConfigJson(sink, wpi::util::to_string_view(config), status);
|
||||
return wpi::cs::SetSinkConfigJson(sink, wpi::util::to_string_view(config),
|
||||
status);
|
||||
}
|
||||
|
||||
void CS_GetSinkConfigJson(CS_Sink sink, WPI_String* config, CS_Status* status) {
|
||||
@@ -323,7 +332,8 @@ CS_Source CS_GetSinkSource(CS_Sink sink, CS_Status* status) {
|
||||
CS_Property CS_GetSinkSourceProperty(CS_Sink sink,
|
||||
const struct WPI_String* name,
|
||||
CS_Status* status) {
|
||||
return wpi::cs::GetSinkSourceProperty(sink, wpi::util::to_string_view(name), status);
|
||||
return wpi::cs::GetSinkSourceProperty(sink, wpi::util::to_string_view(name),
|
||||
status);
|
||||
}
|
||||
|
||||
CS_Sink CS_CopySink(CS_Sink sink, CS_Status* status) {
|
||||
@@ -464,8 +474,8 @@ void CS_ReleaseEnumeratedSources(CS_Source* sources, int count) {
|
||||
CS_Sink* CS_EnumerateSinks(int* count, CS_Status* status) {
|
||||
wpi::util::SmallVector<CS_Sink, 32> buf;
|
||||
auto handles = wpi::cs::EnumerateSinkHandles(buf, status);
|
||||
CS_Sink* sinks =
|
||||
static_cast<CS_Sink*>(wpi::util::safe_malloc(handles.size() * sizeof(CS_Sink)));
|
||||
CS_Sink* sinks = static_cast<CS_Sink*>(
|
||||
wpi::util::safe_malloc(handles.size() * sizeof(CS_Sink)));
|
||||
*count = handles.size();
|
||||
std::copy(handles.begin(), handles.end(), sinks);
|
||||
return sinks;
|
||||
|
||||
@@ -401,9 +401,9 @@ std::vector<VideoMode> EnumerateSourceVideoModes(CS_Source source,
|
||||
return data->source->EnumerateVideoModes(status);
|
||||
}
|
||||
|
||||
std::span<CS_Sink> EnumerateSourceSinks(CS_Source source,
|
||||
wpi::util::SmallVectorImpl<CS_Sink>& vec,
|
||||
CS_Status* status) {
|
||||
std::span<CS_Sink> EnumerateSourceSinks(
|
||||
CS_Source source, wpi::util::SmallVectorImpl<CS_Sink>& vec,
|
||||
CS_Status* status) {
|
||||
auto& inst = Instance::GetInstance();
|
||||
auto data = inst.GetSource(source);
|
||||
if (!data) {
|
||||
@@ -540,7 +540,8 @@ std::string GetSinkName(CS_Sink sink, CS_Status* status) {
|
||||
return std::string{data->sink->GetName()};
|
||||
}
|
||||
|
||||
std::string_view GetSinkName(CS_Sink sink, wpi::util::SmallVectorImpl<char>& buf,
|
||||
std::string_view GetSinkName(CS_Sink sink,
|
||||
wpi::util::SmallVectorImpl<char>& buf,
|
||||
CS_Status* status) {
|
||||
auto data = Instance::GetInstance().GetSink(sink);
|
||||
if (!data) {
|
||||
@@ -587,7 +588,8 @@ CS_Property GetSinkProperty(CS_Sink sink, std::string_view name,
|
||||
}
|
||||
|
||||
std::span<CS_Property> EnumerateSinkProperties(
|
||||
CS_Sink sink, wpi::util::SmallVectorImpl<CS_Property>& vec, CS_Status* status) {
|
||||
CS_Sink sink, wpi::util::SmallVectorImpl<CS_Property>& vec,
|
||||
CS_Status* status) {
|
||||
auto data = Instance::GetInstance().GetSink(sink);
|
||||
if (!data) {
|
||||
*status = CS_INVALID_HANDLE;
|
||||
@@ -873,8 +875,8 @@ std::span<CS_Source> EnumerateSourceHandles(
|
||||
return Instance::GetInstance().EnumerateSourceHandles(vec);
|
||||
}
|
||||
|
||||
std::span<CS_Sink> EnumerateSinkHandles(wpi::util::SmallVectorImpl<CS_Sink>& vec,
|
||||
CS_Status* status) {
|
||||
std::span<CS_Sink> EnumerateSinkHandles(
|
||||
wpi::util::SmallVectorImpl<CS_Sink>& vec, CS_Status* status) {
|
||||
return Instance::GetInstance().EnumerateSinkHandles(vec);
|
||||
}
|
||||
|
||||
|
||||
@@ -475,7 +475,8 @@ Java_org_wpilib_vision_camera_CameraServerJNI_createUsbCameraDev
|
||||
return 0;
|
||||
}
|
||||
CS_Status status = 0;
|
||||
auto val = wpi::cs::CreateUsbCameraDev(JStringRef{env, name}.str(), dev, &status);
|
||||
auto val =
|
||||
wpi::cs::CreateUsbCameraDev(JStringRef{env, name}.str(), dev, &status);
|
||||
CheckStatus(env, status);
|
||||
return val;
|
||||
}
|
||||
@@ -499,7 +500,7 @@ Java_org_wpilib_vision_camera_CameraServerJNI_createUsbCameraPath
|
||||
}
|
||||
CS_Status status = 0;
|
||||
auto val = wpi::cs::CreateUsbCameraPath(JStringRef{env, name}.str(),
|
||||
JStringRef{env, path}.str(), &status);
|
||||
JStringRef{env, path}.str(), &status);
|
||||
CheckStatus(env, status);
|
||||
return val;
|
||||
}
|
||||
@@ -561,7 +562,7 @@ Java_org_wpilib_vision_camera_CameraServerJNI_createHttpCameraMulti
|
||||
CS_Status status = 0;
|
||||
auto val =
|
||||
wpi::cs::CreateHttpCamera(JStringRef{env, name}.str(), vec,
|
||||
static_cast<CS_HttpCameraKind>(kind), &status);
|
||||
static_cast<CS_HttpCameraKind>(kind), &status);
|
||||
CheckStatus(env, status);
|
||||
return val;
|
||||
}
|
||||
@@ -583,9 +584,10 @@ Java_org_wpilib_vision_camera_CameraServerJNI_createRawSource
|
||||
CS_Status status = 0;
|
||||
auto val = wpi::cs::CreateRawSource(
|
||||
JStringRef{env, name}.str(), isCv,
|
||||
wpi::cs::VideoMode{static_cast<wpi::cs::VideoMode::PixelFormat>(pixelFormat),
|
||||
static_cast<int>(width), static_cast<int>(height),
|
||||
static_cast<int>(fps)},
|
||||
wpi::cs::VideoMode{
|
||||
static_cast<wpi::cs::VideoMode::PixelFormat>(pixelFormat),
|
||||
static_cast<int>(width), static_cast<int>(height),
|
||||
static_cast<int>(fps)},
|
||||
&status);
|
||||
CheckStatus(env, status);
|
||||
return val;
|
||||
@@ -770,8 +772,9 @@ Java_org_wpilib_vision_camera_CameraServerJNI_setSourceVideoMode
|
||||
CS_Status status = 0;
|
||||
auto val = wpi::cs::SetSourceVideoMode(
|
||||
source,
|
||||
wpi::cs::VideoMode(static_cast<wpi::cs::VideoMode::PixelFormat>(pixelFormat), width,
|
||||
height, fps),
|
||||
wpi::cs::VideoMode(
|
||||
static_cast<wpi::cs::VideoMode::PixelFormat>(pixelFormat), width,
|
||||
height, fps),
|
||||
&status);
|
||||
CheckStatus(env, status);
|
||||
return val;
|
||||
@@ -788,7 +791,8 @@ Java_org_wpilib_vision_camera_CameraServerJNI_setSourcePixelFormat
|
||||
{
|
||||
CS_Status status = 0;
|
||||
auto val = wpi::cs::SetSourcePixelFormat(
|
||||
source, static_cast<wpi::cs::VideoMode::PixelFormat>(pixelFormat), &status);
|
||||
source, static_cast<wpi::cs::VideoMode::PixelFormat>(pixelFormat),
|
||||
&status);
|
||||
CheckStatus(env, status);
|
||||
return val;
|
||||
}
|
||||
@@ -833,7 +837,8 @@ Java_org_wpilib_vision_camera_CameraServerJNI_setSourceConfigJson
|
||||
(JNIEnv* env, jclass, jint source, jstring config)
|
||||
{
|
||||
CS_Status status = 0;
|
||||
auto val = wpi::cs::SetSourceConfigJson(source, JStringRef{env, config}, &status);
|
||||
auto val =
|
||||
wpi::cs::SetSourceConfigJson(source, JStringRef{env, config}, &status);
|
||||
CheckStatus(env, status);
|
||||
return val;
|
||||
}
|
||||
@@ -1271,7 +1276,8 @@ Java_org_wpilib_vision_camera_CameraServerJNI_setSourceDescription
|
||||
return;
|
||||
}
|
||||
CS_Status status = 0;
|
||||
wpi::cs::SetSourceDescription(source, JStringRef{env, description}.str(), &status);
|
||||
wpi::cs::SetSourceDescription(source, JStringRef{env, description}.str(),
|
||||
&status);
|
||||
CheckStatus(env, status);
|
||||
}
|
||||
|
||||
@@ -1342,8 +1348,8 @@ Java_org_wpilib_vision_camera_CameraServerJNI_createMjpegServer
|
||||
}
|
||||
CS_Status status = 0;
|
||||
auto val = wpi::cs::CreateMjpegServer(JStringRef{env, name}.str(),
|
||||
JStringRef{env, listenAddress}.str(), port,
|
||||
&status);
|
||||
JStringRef{env, listenAddress}.str(),
|
||||
port, &status);
|
||||
CheckStatus(env, status);
|
||||
return val;
|
||||
}
|
||||
@@ -1432,7 +1438,8 @@ Java_org_wpilib_vision_camera_CameraServerJNI_getSinkProperty
|
||||
return 0;
|
||||
}
|
||||
CS_Status status = 0;
|
||||
auto val = wpi::cs::GetSinkProperty(sink, JStringRef{env, name}.str(), &status);
|
||||
auto val =
|
||||
wpi::cs::GetSinkProperty(sink, JStringRef{env, name}.str(), &status);
|
||||
CheckStatus(env, status);
|
||||
return val;
|
||||
}
|
||||
@@ -1465,7 +1472,8 @@ Java_org_wpilib_vision_camera_CameraServerJNI_setSinkConfigJson
|
||||
(JNIEnv* env, jclass, jint source, jstring config)
|
||||
{
|
||||
CS_Status status = 0;
|
||||
auto val = wpi::cs::SetSinkConfigJson(source, JStringRef{env, config}, &status);
|
||||
auto val =
|
||||
wpi::cs::SetSinkConfigJson(source, JStringRef{env, config}, &status);
|
||||
CheckStatus(env, status);
|
||||
return val;
|
||||
}
|
||||
@@ -1513,8 +1521,8 @@ Java_org_wpilib_vision_camera_CameraServerJNI_getSinkSourceProperty
|
||||
return 0;
|
||||
}
|
||||
CS_Status status = 0;
|
||||
auto val =
|
||||
wpi::cs::GetSinkSourceProperty(sink, JStringRef{env, name}.str(), &status);
|
||||
auto val = wpi::cs::GetSinkSourceProperty(sink, JStringRef{env, name}.str(),
|
||||
&status);
|
||||
CheckStatus(env, status);
|
||||
return val;
|
||||
}
|
||||
@@ -1609,7 +1617,8 @@ Java_org_wpilib_vision_camera_CameraServerJNI_setSinkDescription
|
||||
return;
|
||||
}
|
||||
CS_Status status = 0;
|
||||
wpi::cs::SetSinkDescription(sink, JStringRef{env, description}.str(), &status);
|
||||
wpi::cs::SetSinkDescription(sink, JStringRef{env, description}.str(),
|
||||
&status);
|
||||
CheckStatus(env, status);
|
||||
}
|
||||
|
||||
@@ -1630,7 +1639,7 @@ Java_org_wpilib_vision_camera_CameraServerJNI_grabRawSinkFrame
|
||||
return 0;
|
||||
}
|
||||
wpi::util::SetFrameData(env, rawFrameCls, frameObj, *frame,
|
||||
origData != frame->data);
|
||||
origData != frame->data);
|
||||
return rv;
|
||||
}
|
||||
|
||||
@@ -1648,12 +1657,12 @@ Java_org_wpilib_vision_camera_CameraServerJNI_grabRawSinkFrameTimeout
|
||||
auto origData = frame->data;
|
||||
CS_Status status = 0;
|
||||
auto rv = wpi::cs::GrabSinkFrameTimeout(static_cast<CS_Sink>(sink), *frame,
|
||||
timeout, &status);
|
||||
timeout, &status);
|
||||
if (!CheckStatus(env, status)) {
|
||||
return 0;
|
||||
}
|
||||
wpi::util::SetFrameData(env, rawFrameCls, frameObj, *frame,
|
||||
origData != frame->data);
|
||||
origData != frame->data);
|
||||
return rv;
|
||||
}
|
||||
|
||||
@@ -1801,7 +1810,8 @@ Java_org_wpilib_vision_camera_CameraServerJNI_addPolledListener
|
||||
(JNIEnv* env, jclass, jint poller, jint eventMask, jboolean immediateNotify)
|
||||
{
|
||||
CS_Status status = 0;
|
||||
auto rv = wpi::cs::AddPolledListener(poller, eventMask, immediateNotify, &status);
|
||||
auto rv =
|
||||
wpi::cs::AddPolledListener(poller, eventMask, immediateNotify, &status);
|
||||
CheckStatus(env, status);
|
||||
return rv;
|
||||
}
|
||||
@@ -1887,8 +1897,8 @@ Java_org_wpilib_vision_camera_CameraServerJNI_getTelemetryValue
|
||||
(JNIEnv* env, jclass, jint handle, jint kind)
|
||||
{
|
||||
CS_Status status = 0;
|
||||
auto val = wpi::cs::GetTelemetryValue(handle, static_cast<CS_TelemetryKind>(kind),
|
||||
&status);
|
||||
auto val = wpi::cs::GetTelemetryValue(
|
||||
handle, static_cast<CS_TelemetryKind>(kind), &status);
|
||||
CheckStatus(env, status);
|
||||
return val;
|
||||
}
|
||||
|
||||
@@ -252,9 +252,9 @@ std::string GetSourceConfigJson(CS_Source source, CS_Status* status);
|
||||
wpi::util::json GetSourceConfigJsonObject(CS_Source source, CS_Status* status);
|
||||
std::vector<VideoMode> EnumerateSourceVideoModes(CS_Source source,
|
||||
CS_Status* status);
|
||||
std::span<CS_Sink> EnumerateSourceSinks(CS_Source source,
|
||||
wpi::util::SmallVectorImpl<CS_Sink>& vec,
|
||||
CS_Status* status);
|
||||
std::span<CS_Sink> EnumerateSourceSinks(
|
||||
CS_Source source, wpi::util::SmallVectorImpl<CS_Sink>& vec,
|
||||
CS_Status* status);
|
||||
CS_Source CopySource(CS_Source source, CS_Status* status);
|
||||
void ReleaseSource(CS_Source source, CS_Status* status);
|
||||
/** @} */
|
||||
@@ -332,7 +332,8 @@ CS_Sink CreateCvSinkCallback(std::string_view name,
|
||||
*/
|
||||
CS_SinkKind GetSinkKind(CS_Sink sink, CS_Status* status);
|
||||
std::string GetSinkName(CS_Sink sink, CS_Status* status);
|
||||
std::string_view GetSinkName(CS_Sink sink, wpi::util::SmallVectorImpl<char>& buf,
|
||||
std::string_view GetSinkName(CS_Sink sink,
|
||||
wpi::util::SmallVectorImpl<char>& buf,
|
||||
CS_Status* status);
|
||||
std::string GetSinkDescription(CS_Sink sink, CS_Status* status);
|
||||
std::string_view GetSinkDescription(CS_Sink sink,
|
||||
@@ -341,7 +342,8 @@ std::string_view GetSinkDescription(CS_Sink sink,
|
||||
CS_Property GetSinkProperty(CS_Sink sink, std::string_view name,
|
||||
CS_Status* status);
|
||||
std::span<CS_Property> EnumerateSinkProperties(
|
||||
CS_Sink sink, wpi::util::SmallVectorImpl<CS_Property>& vec, CS_Status* status);
|
||||
CS_Sink sink, wpi::util::SmallVectorImpl<CS_Property>& vec,
|
||||
CS_Status* status);
|
||||
void SetSinkSource(CS_Sink sink, CS_Source source, CS_Status* status);
|
||||
CS_Property GetSinkSourceProperty(CS_Sink sink, std::string_view name,
|
||||
CS_Status* status);
|
||||
@@ -371,7 +373,8 @@ int GetMjpegServerPort(CS_Sink sink, CS_Status* status);
|
||||
void SetSinkDescription(CS_Sink sink, std::string_view description,
|
||||
CS_Status* status);
|
||||
std::string GetSinkError(CS_Sink sink, CS_Status* status);
|
||||
std::string_view GetSinkError(CS_Sink sink, wpi::util::SmallVectorImpl<char>& buf,
|
||||
std::string_view GetSinkError(CS_Sink sink,
|
||||
wpi::util::SmallVectorImpl<char>& buf,
|
||||
CS_Status* status);
|
||||
void SetSinkEnabled(CS_Sink sink, bool enabled, CS_Status* status);
|
||||
/** @} */
|
||||
@@ -437,8 +440,8 @@ std::vector<UsbCameraInfo> EnumerateUsbCameras(CS_Status* status);
|
||||
|
||||
std::span<CS_Source> EnumerateSourceHandles(
|
||||
wpi::util::SmallVectorImpl<CS_Source>& vec, CS_Status* status);
|
||||
std::span<CS_Sink> EnumerateSinkHandles(wpi::util::SmallVectorImpl<CS_Sink>& vec,
|
||||
CS_Status* status);
|
||||
std::span<CS_Sink> EnumerateSinkHandles(
|
||||
wpi::util::SmallVectorImpl<CS_Sink>& vec, CS_Status* status);
|
||||
|
||||
std::string GetHostname();
|
||||
|
||||
|
||||
@@ -107,8 +107,8 @@ class CvSink : public ImageSink {
|
||||
* with.
|
||||
*
|
||||
* @return Frame time, or 0 on error (call GetError() to obtain the error
|
||||
* message); the frame time is in the same time base as wpi::util::Now(),
|
||||
* and is in 1 us increments.
|
||||
* message); the frame time is in the same time base as
|
||||
* wpi::util::Now(), and is in 1 us increments.
|
||||
*/
|
||||
[[nodiscard]]
|
||||
uint64_t GrabFrame(cv::Mat& image, double timeout = 0.225);
|
||||
@@ -119,8 +119,8 @@ class CvSink : public ImageSink {
|
||||
* with.
|
||||
*
|
||||
* @return Frame time, or 0 on error (call GetError() to obtain the error
|
||||
* message); the frame time is in the same time base as wpi::util::Now(),
|
||||
* and is in 1 us increments.
|
||||
* message); the frame time is in the same time base as
|
||||
* wpi::util::Now(), and is in 1 us increments.
|
||||
*/
|
||||
[[nodiscard]]
|
||||
uint64_t GrabFrameNoTimeout(cv::Mat& image);
|
||||
@@ -133,8 +133,8 @@ class CvSink : public ImageSink {
|
||||
* any grabFrame*() call on the sink.
|
||||
*
|
||||
* @return Frame time, or 0 on error (call GetError() to obtain the error
|
||||
* message); the frame time is in the same time base as wpi::util::Now(),
|
||||
* and is in 1 us increments.
|
||||
* message); the frame time is in the same time base as
|
||||
* wpi::util::Now(), and is in 1 us increments.
|
||||
*/
|
||||
[[nodiscard]]
|
||||
uint64_t GrabFrameDirect(cv::Mat& image, double timeout = 0.225);
|
||||
@@ -146,8 +146,8 @@ class CvSink : public ImageSink {
|
||||
* any grabFrame*() call on the sink.
|
||||
*
|
||||
* @return Frame time, or 0 on error (call GetError() to obtain the error
|
||||
* message); the frame time is in the same time base as wpi::util::Now(),
|
||||
* and is in 1 us increments.
|
||||
* message); the frame time is in the same time base as
|
||||
* wpi::util::Now(), and is in 1 us increments.
|
||||
*/
|
||||
[[nodiscard]]
|
||||
uint64_t GrabFrameNoTimeoutDirect(cv::Mat& image);
|
||||
@@ -166,8 +166,8 @@ class CvSink : public ImageSink {
|
||||
* a new frame.
|
||||
*
|
||||
* @return Frame time, or 0 on error (call GetError() to obtain the error
|
||||
* message); the frame time is in the same time base as wpi::util::Now(),
|
||||
* and is in 1 us increments.
|
||||
* message); the frame time is in the same time base as
|
||||
* wpi::util::Now(), and is in 1 us increments.
|
||||
*/
|
||||
[[nodiscard]]
|
||||
uint64_t GrabFrameDirectLastTime(cv::Mat& image, uint64_t lastFrameTime,
|
||||
|
||||
@@ -546,8 +546,8 @@ class VideoSource {
|
||||
*/
|
||||
double GetActualFPS() const {
|
||||
m_status = 0;
|
||||
return wpi::cs::GetTelemetryAverageValue(m_handle, CS_SOURCE_FRAMES_RECEIVED,
|
||||
&m_status);
|
||||
return wpi::cs::GetTelemetryAverageValue(
|
||||
m_handle, CS_SOURCE_FRAMES_RECEIVED, &m_status);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -560,7 +560,7 @@ class VideoSource {
|
||||
double GetActualDataRate() const {
|
||||
m_status = 0;
|
||||
return wpi::cs::GetTelemetryAverageValue(m_handle, CS_SOURCE_BYTES_RECEIVED,
|
||||
&m_status);
|
||||
&m_status);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -155,8 +155,8 @@ class RawSink : public ImageSink {
|
||||
* The provided image will have three 8-bit channels stored in BGR order.
|
||||
*
|
||||
* @return Frame time, or 0 on error (call GetError() to obtain the error
|
||||
* message); the frame time is in the same time base as wpi::util::Now(),
|
||||
* and is in 1 us increments.
|
||||
* message); the frame time is in the same time base as
|
||||
* wpi::util::Now(), and is in 1 us increments.
|
||||
*/
|
||||
[[nodiscard]]
|
||||
uint64_t GrabFrame(wpi::util::RawFrame& image, double timeout = 0.225) const;
|
||||
@@ -166,8 +166,8 @@ class RawSink : public ImageSink {
|
||||
* The provided image will have three 8-bit channels stored in BGR order.
|
||||
*
|
||||
* @return Frame time, or 0 on error (call GetError() to obtain the error
|
||||
* message); the frame time is in the same time base as wpi::util::Now(),
|
||||
* and is in 1 us increments.
|
||||
* message); the frame time is in the same time base as
|
||||
* wpi::util::Now(), and is in 1 us increments.
|
||||
*/
|
||||
[[nodiscard]]
|
||||
uint64_t GrabFrameNoTimeout(wpi::util::RawFrame& image) const;
|
||||
@@ -183,8 +183,8 @@ class RawSink : public ImageSink {
|
||||
* a new frame.
|
||||
*
|
||||
* @return Frame time, or 0 on error (call GetError() to obtain the error
|
||||
* message); the frame time is in the same time base as wpi::util::Now(),
|
||||
* and is in 1 us increments.
|
||||
* message); the frame time is in the same time base as
|
||||
* wpi::util::Now(), and is in 1 us increments.
|
||||
*/
|
||||
[[nodiscard]]
|
||||
uint64_t GrabFrameLastTime(wpi::util::RawFrame& image, uint64_t lastFrameTime,
|
||||
@@ -216,7 +216,8 @@ inline RawSink::RawSink(std::string_view name,
|
||||
m_handle = CreateRawSinkCallback(name, false, processFrame, &m_status);
|
||||
}
|
||||
|
||||
inline uint64_t RawSink::GrabFrame(wpi::util::RawFrame& image, double timeout) const {
|
||||
inline uint64_t RawSink::GrabFrame(wpi::util::RawFrame& image,
|
||||
double timeout) const {
|
||||
m_status = 0;
|
||||
return GrabSinkFrameTimeout(m_handle, image, timeout, &m_status);
|
||||
}
|
||||
|
||||
@@ -20,7 +20,8 @@ void RunMainRunLoop() {
|
||||
int RunMainRunLoopTimeout(double timeout) {
|
||||
wpi::util::Event& event = GetInstance();
|
||||
bool timedOut = false;
|
||||
bool signaled = wpi::util::WaitForObject(event.GetHandle(), timeout, &timedOut);
|
||||
bool signaled =
|
||||
wpi::util::WaitForObject(event.GetHandle(), timeout, &timedOut);
|
||||
if (timedOut) {
|
||||
return 3;
|
||||
}
|
||||
|
||||
@@ -207,13 +207,17 @@ static bool GetVendorProduct(int dev, int* vendor, int* product) {
|
||||
}
|
||||
std::string_view readStr{readBuf};
|
||||
if (auto v = wpi::util::parse_integer<int>(
|
||||
wpi::util::substr(wpi::util::substr(readStr, readStr.find('v')), 1, 4), 16)) {
|
||||
wpi::util::substr(wpi::util::substr(readStr, readStr.find('v')), 1,
|
||||
4),
|
||||
16)) {
|
||||
*vendor = v.value();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
if (auto v = wpi::util::parse_integer<int>(
|
||||
wpi::util::substr(wpi::util::substr(readStr, readStr.find('p')), 1, 4), 16)) {
|
||||
wpi::util::substr(wpi::util::substr(readStr, readStr.find('p')), 1,
|
||||
4),
|
||||
16)) {
|
||||
*product = v.value();
|
||||
} else {
|
||||
return false;
|
||||
@@ -262,8 +266,10 @@ static bool GetDescriptionIoctl(const char* cpath, std::string* desc) {
|
||||
std::optional<int> vendor;
|
||||
std::optional<int> product;
|
||||
if (wpi::util::starts_with(card, "UVC Camera (") &&
|
||||
(vendor = wpi::util::parse_integer<int>(wpi::util::substr(card, 12, 4), 16)) &&
|
||||
(product = wpi::util::parse_integer<int>(wpi::util::substr(card, 17, 4), 16))) {
|
||||
(vendor =
|
||||
wpi::util::parse_integer<int>(wpi::util::substr(card, 12, 4), 16)) &&
|
||||
(product =
|
||||
wpi::util::parse_integer<int>(wpi::util::substr(card, 17, 4), 16))) {
|
||||
std::string card2 = GetUsbNameFromId(vendor.value(), product.value());
|
||||
if (!card2.empty()) {
|
||||
*desc = std::move(card2);
|
||||
@@ -566,9 +572,9 @@ void UsbCameraImpl::CameraThreadMain() {
|
||||
} else if (tsFlags == V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC) {
|
||||
SDEBUG4("Got valid monotonic time for frame");
|
||||
// we can't go directly to frametime, since the rest of cscore
|
||||
// expects us to use wpi::util::Now, which is in an arbitrary timebase
|
||||
// (see timestamp.cpp). Best I can do is (approximately) translate
|
||||
// between timebases
|
||||
// expects us to use wpi::util::Now, which is in an arbitrary
|
||||
// timebase (see timestamp.cpp). Best I can do is (approximately)
|
||||
// translate between timebases
|
||||
|
||||
// grab current time in the same timebase as buf.timestamp
|
||||
struct timespec ts;
|
||||
@@ -595,7 +601,8 @@ void UsbCameraImpl::CameraThreadMain() {
|
||||
// Can't do anything if we can't access the clock, leave default
|
||||
}
|
||||
} else if (tsFlags == V4L2_BUF_FLAG_TIMESTAMP_COPY) {
|
||||
SDEBUG4("Got valid copy time for frame - default to wpi::util::Now");
|
||||
SDEBUG4(
|
||||
"Got valid copy time for frame - default to wpi::util::Now");
|
||||
}
|
||||
|
||||
PutFrame(static_cast<VideoMode::PixelFormat>(m_mode.pixelFormat),
|
||||
@@ -1708,8 +1715,8 @@ std::vector<UsbCameraInfo> EnumerateUsbCameras(CS_Status* status) {
|
||||
}
|
||||
|
||||
unsigned int dev = 0;
|
||||
if (auto v =
|
||||
wpi::util::parse_integer<unsigned int>(wpi::util::substr(fname, 5), 10)) {
|
||||
if (auto v = wpi::util::parse_integer<unsigned int>(
|
||||
wpi::util::substr(fname, 5), 10)) {
|
||||
dev = v.value();
|
||||
} else {
|
||||
continue;
|
||||
@@ -1760,8 +1767,8 @@ std::vector<UsbCameraInfo> EnumerateUsbCameras(CS_Status* status) {
|
||||
std::string fname = fs::path{target}.filename();
|
||||
std::optional<unsigned int> dev;
|
||||
if (wpi::util::starts_with(fname, "video") &&
|
||||
(dev = wpi::util::parse_integer<unsigned int>(wpi::util::substr(fname, 5),
|
||||
10)) &&
|
||||
(dev = wpi::util::parse_integer<unsigned int>(
|
||||
wpi::util::substr(fname, 5), 10)) &&
|
||||
dev.value() < retval.size()) {
|
||||
retval[dev.value()].otherPaths.emplace_back(path.str());
|
||||
}
|
||||
|
||||
@@ -31,8 +31,9 @@ class Telemetry;
|
||||
|
||||
class UsbCameraImpl : public SourceImpl {
|
||||
public:
|
||||
UsbCameraImpl(std::string_view name, wpi::util::Logger& logger, Notifier& notifier,
|
||||
Telemetry& telemetry, std::string_view path);
|
||||
UsbCameraImpl(std::string_view name, wpi::util::Logger& logger,
|
||||
Notifier& notifier, Telemetry& telemetry,
|
||||
std::string_view path);
|
||||
~UsbCameraImpl() override;
|
||||
|
||||
void Start() override;
|
||||
|
||||
@@ -24,7 +24,8 @@ class UsbCameraListener::Impl {
|
||||
std::unique_ptr<wpi::net::EventLoopRunner> m_runner;
|
||||
};
|
||||
|
||||
UsbCameraListener::UsbCameraListener(wpi::util::Logger& logger, Notifier& notifier)
|
||||
UsbCameraListener::UsbCameraListener(wpi::util::Logger& logger,
|
||||
Notifier& notifier)
|
||||
: m_impl(std::make_unique<Impl>(notifier)) {}
|
||||
|
||||
UsbCameraListener::~UsbCameraListener() = default;
|
||||
@@ -32,22 +33,23 @@ UsbCameraListener::~UsbCameraListener() = default;
|
||||
void UsbCameraListener::Start() {
|
||||
if (!m_impl->m_runner) {
|
||||
m_impl->m_runner = std::make_unique<wpi::net::EventLoopRunner>();
|
||||
m_impl->m_runner->ExecAsync([impl = m_impl.get()](wpi::net::uv::Loop& loop) {
|
||||
auto refreshTimer = wpi::net::uv::Timer::Create(loop);
|
||||
refreshTimer->timeout.connect([notifier = &impl->m_notifier] {
|
||||
notifier->NotifyUsbCamerasChanged();
|
||||
});
|
||||
refreshTimer->Unreference();
|
||||
m_impl->m_runner->ExecAsync(
|
||||
[impl = m_impl.get()](wpi::net::uv::Loop& loop) {
|
||||
auto refreshTimer = wpi::net::uv::Timer::Create(loop);
|
||||
refreshTimer->timeout.connect([notifier = &impl->m_notifier] {
|
||||
notifier->NotifyUsbCamerasChanged();
|
||||
});
|
||||
refreshTimer->Unreference();
|
||||
|
||||
auto devEvents = wpi::net::uv::FsEvent::Create(loop);
|
||||
devEvents->fsEvent.connect([refreshTimer](const char* fn, int flags) {
|
||||
if (wpi::util::starts_with(fn, "video")) {
|
||||
refreshTimer->Start(wpi::net::uv::Timer::Time(200));
|
||||
}
|
||||
});
|
||||
devEvents->Start("/dev");
|
||||
devEvents->Unreference();
|
||||
});
|
||||
auto devEvents = wpi::net::uv::FsEvent::Create(loop);
|
||||
devEvents->fsEvent.connect([refreshTimer](const char* fn, int flags) {
|
||||
if (wpi::util::starts_with(fn, "video")) {
|
||||
refreshTimer->Start(wpi::net::uv::Timer::Time(200));
|
||||
}
|
||||
});
|
||||
devEvents->Start("/dev");
|
||||
devEvents->Unreference();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -267,7 +267,8 @@ std::unique_ptr<UsbCameraProperty> UsbCameraProperty::DeviceQuery(int fd,
|
||||
return prop;
|
||||
}
|
||||
|
||||
bool UsbCameraProperty::DeviceGet(std::unique_lock<wpi::util::mutex>& lock, int fd) {
|
||||
bool UsbCameraProperty::DeviceGet(std::unique_lock<wpi::util::mutex>& lock,
|
||||
int fd) {
|
||||
if (fd < 0) {
|
||||
return true;
|
||||
}
|
||||
@@ -313,8 +314,8 @@ bool UsbCameraProperty::DeviceSet(std::unique_lock<wpi::util::mutex>& lock,
|
||||
return DeviceSet(lock, fd, value, valueStrCopy.str());
|
||||
}
|
||||
|
||||
bool UsbCameraProperty::DeviceSet(std::unique_lock<wpi::util::mutex>& lock, int fd,
|
||||
int newValue,
|
||||
bool UsbCameraProperty::DeviceSet(std::unique_lock<wpi::util::mutex>& lock,
|
||||
int fd, int newValue,
|
||||
std::string_view newValueStr) const {
|
||||
if (!device || fd < 0) {
|
||||
return true;
|
||||
|
||||
@@ -8,7 +8,8 @@ using namespace wpi::cs;
|
||||
|
||||
class NetworkListener::Impl {};
|
||||
|
||||
NetworkListener::NetworkListener(wpi::util::Logger& logger, Notifier& notifier) {}
|
||||
NetworkListener::NetworkListener(wpi::util::Logger& logger,
|
||||
Notifier& notifier) {}
|
||||
|
||||
NetworkListener::~NetworkListener() = default;
|
||||
|
||||
|
||||
@@ -94,7 +94,8 @@ STDMETHODIMP SourceReaderCB::OnReadSample(HRESULT hrStatus, DWORD dwStreamIndex,
|
||||
|
||||
// Create a Source Reader COM Smart Object
|
||||
ComPtr<SourceReaderCB> CreateSourceReaderCB(
|
||||
std::weak_ptr<wpi::cs::UsbCameraImpl> source, const wpi::cs::VideoMode& mode) {
|
||||
std::weak_ptr<wpi::cs::UsbCameraImpl> source,
|
||||
const wpi::cs::VideoMode& mode) {
|
||||
SourceReaderCB* ptr = new SourceReaderCB(source, mode);
|
||||
ComPtr<SourceReaderCB> sourceReaderCB;
|
||||
sourceReaderCB.Attach(ptr);
|
||||
|
||||
@@ -35,7 +35,9 @@ class SourceReaderCB : public IMFSourceReaderCallback {
|
||||
IMFSample* pSample // Can be NULL
|
||||
);
|
||||
|
||||
void InvalidateCapture() { m_source = std::weak_ptr<wpi::cs::UsbCameraImpl>(); }
|
||||
void InvalidateCapture() {
|
||||
m_source = std::weak_ptr<wpi::cs::UsbCameraImpl>();
|
||||
}
|
||||
|
||||
private:
|
||||
// Destructor is private. Caller should call Release.
|
||||
@@ -48,7 +50,8 @@ class SourceReaderCB : public IMFSourceReaderCallback {
|
||||
};
|
||||
|
||||
ComPtr<SourceReaderCB> CreateSourceReaderCB(
|
||||
std::weak_ptr<wpi::cs::UsbCameraImpl> source, const wpi::cs::VideoMode& mode);
|
||||
std::weak_ptr<wpi::cs::UsbCameraImpl> source,
|
||||
const wpi::cs::VideoMode& mode);
|
||||
ComPtr<IMFSourceReader> CreateSourceReader(IMFMediaSource* mediaSource,
|
||||
IMFSourceReaderCallback* callback);
|
||||
ComPtr<IMFMediaSource> CreateVideoCaptureDevice(LPCWSTR pszSymbolicLink);
|
||||
|
||||
@@ -20,7 +20,8 @@ void RunMainRunLoop() {
|
||||
int RunMainRunLoopTimeout(double timeout) {
|
||||
wpi::util::Event& event = GetInstance();
|
||||
bool timedOut = false;
|
||||
bool signaled = wpi::util::WaitForObject(event.GetHandle(), timeout, &timedOut);
|
||||
bool signaled =
|
||||
wpi::util::WaitForObject(event.GetHandle(), timeout, &timedOut);
|
||||
if (timedOut) {
|
||||
return 3;
|
||||
}
|
||||
|
||||
@@ -39,10 +39,11 @@ namespace wpi::cs {
|
||||
class UsbCameraImpl : public SourceImpl,
|
||||
public std::enable_shared_from_this<UsbCameraImpl> {
|
||||
public:
|
||||
UsbCameraImpl(std::string_view name, wpi::util::Logger& logger, Notifier& notifier,
|
||||
Telemetry& telemetry, std::string_view path);
|
||||
UsbCameraImpl(std::string_view name, wpi::util::Logger& logger, Notifier& notifier,
|
||||
Telemetry& telemetry, int deviceId);
|
||||
UsbCameraImpl(std::string_view name, wpi::util::Logger& logger,
|
||||
Notifier& notifier, Telemetry& telemetry,
|
||||
std::string_view path);
|
||||
UsbCameraImpl(std::string_view name, wpi::util::Logger& logger,
|
||||
Notifier& notifier, Telemetry& telemetry, int deviceId);
|
||||
~UsbCameraImpl() override;
|
||||
|
||||
void Start() override;
|
||||
|
||||
@@ -58,7 +58,8 @@ class UsbCameraListener::Impl {
|
||||
std::unique_ptr<wpi::cs::WindowsMessagePump> m_messagePump;
|
||||
};
|
||||
|
||||
UsbCameraListener::UsbCameraListener(wpi::util::Logger& logger, Notifier& notifier)
|
||||
UsbCameraListener::UsbCameraListener(wpi::util::Logger& logger,
|
||||
Notifier& notifier)
|
||||
: m_impl{std::make_unique<Impl>(notifier)} {}
|
||||
|
||||
UsbCameraListener::~UsbCameraListener() {
|
||||
|
||||
@@ -85,13 +85,14 @@ class UsbCameraProperty : public PropertyImpl {
|
||||
IAMCameraControl* pProcAmp);
|
||||
bool DeviceSet(std::unique_lock<wpi::util::mutex>& lock,
|
||||
IAMCameraControl* pProcAmp) const;
|
||||
bool DeviceSet(std::unique_lock<wpi::util::mutex>& lock, IAMCameraControl* pProcAmp,
|
||||
int newValue) const;
|
||||
bool DeviceSet(std::unique_lock<wpi::util::mutex>& lock,
|
||||
IAMCameraControl* pProcAmp, int newValue) const;
|
||||
|
||||
bool DeviceGet(std::unique_lock<wpi::util::mutex>& lock, IAMVideoProcAmp* pProcAmp);
|
||||
bool DeviceGet(std::unique_lock<wpi::util::mutex>& lock,
|
||||
IAMVideoProcAmp* pProcAmp);
|
||||
bool DeviceSet(std::unique_lock<wpi::util::mutex>& lock,
|
||||
IAMVideoProcAmp* pProcAmp) const;
|
||||
bool DeviceSet(std::unique_lock<wpi::util::mutex>& lock, IAMVideoProcAmp* pProcAmp,
|
||||
int newValue) const;
|
||||
bool DeviceSet(std::unique_lock<wpi::util::mutex>& lock,
|
||||
IAMVideoProcAmp* pProcAmp, int newValue) const;
|
||||
};
|
||||
} // namespace wpi::cs
|
||||
|
||||
@@ -23,7 +23,7 @@ int main(int argc, const char** argv) {
|
||||
auto fileBuffer = wpi::util::MemoryBuffer::GetFile(argv[1]);
|
||||
if (!fileBuffer) {
|
||||
wpi::util::print(stderr, "could not open file: {}\n",
|
||||
fileBuffer.error().message());
|
||||
fileBuffer.error().message());
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
wpi::log::DataLogReader reader{std::move(*fileBuffer)};
|
||||
@@ -37,9 +37,10 @@ int main(int argc, const char** argv) {
|
||||
if (record.IsStart()) {
|
||||
wpi::log::StartRecordData data;
|
||||
if (record.GetStartData(&data)) {
|
||||
wpi::util::print("Start({}, name='{}', type='{}', metadata='{}') [{}]\n",
|
||||
data.entry, data.name, data.type, data.metadata,
|
||||
record.GetTimestamp() / 1000000.0);
|
||||
wpi::util::print(
|
||||
"Start({}, name='{}', type='{}', metadata='{}') [{}]\n", data.entry,
|
||||
data.name, data.type, data.metadata,
|
||||
record.GetTimestamp() / 1000000.0);
|
||||
if (entries.find(data.entry) != entries.end()) {
|
||||
wpi::util::print("...DUPLICATE entry ID, overriding\n");
|
||||
}
|
||||
@@ -51,7 +52,7 @@ int main(int argc, const char** argv) {
|
||||
int entry;
|
||||
if (record.GetFinishEntry(&entry)) {
|
||||
wpi::util::print("Finish({}) [{}]\n", entry,
|
||||
record.GetTimestamp() / 1000000.0);
|
||||
record.GetTimestamp() / 1000000.0);
|
||||
auto it = entries.find(entry);
|
||||
if (it == entries.end()) {
|
||||
wpi::util::print("...ID not found\n");
|
||||
@@ -64,8 +65,8 @@ int main(int argc, const char** argv) {
|
||||
} else if (record.IsSetMetadata()) {
|
||||
wpi::log::MetadataRecordData data;
|
||||
if (record.GetSetMetadataData(&data)) {
|
||||
wpi::util::print("SetMetadata({}, '{}') [{}]\n", data.entry, data.metadata,
|
||||
record.GetTimestamp() / 1000000.0);
|
||||
wpi::util::print("SetMetadata({}, '{}') [{}]\n", data.entry,
|
||||
data.metadata, record.GetTimestamp() / 1000000.0);
|
||||
auto it = entries.find(data.entry);
|
||||
if (it == entries.end()) {
|
||||
wpi::util::print("...ID not found\n");
|
||||
@@ -78,14 +79,15 @@ int main(int argc, const char** argv) {
|
||||
} else if (record.IsControl()) {
|
||||
wpi::util::print("Unrecognized control record\n");
|
||||
} else {
|
||||
wpi::util::print("Data({}, size={}) ", record.GetEntry(), record.GetSize());
|
||||
wpi::util::print("Data({}, size={}) ", record.GetEntry(),
|
||||
record.GetSize());
|
||||
auto entry = entries.find(record.GetEntry());
|
||||
if (entry == entries.end()) {
|
||||
wpi::util::print("<ID not found>\n");
|
||||
continue;
|
||||
}
|
||||
wpi::util::print("<name='{}', type='{}'> [{}]\n", entry->second.name,
|
||||
entry->second.type, record.GetTimestamp() / 1000000.0);
|
||||
entry->second.type, record.GetTimestamp() / 1000000.0);
|
||||
|
||||
// handle systemTime specially
|
||||
if (entry->second.name == "systemTime" && entry->second.type == "int64") {
|
||||
@@ -93,7 +95,7 @@ int main(int argc, const char** argv) {
|
||||
if (record.GetInteger(&val)) {
|
||||
std::time_t timeval = val / 1000000;
|
||||
wpi::util::print(" {:%Y-%m-%d %H:%M:%S}.{:06}\n",
|
||||
*std::localtime(&timeval), val % 1000000);
|
||||
*std::localtime(&timeval), val % 1000000);
|
||||
} else {
|
||||
wpi::util::print(" invalid\n");
|
||||
}
|
||||
|
||||
@@ -74,8 +74,8 @@ int main(int argc, char** argv) {
|
||||
resVec.push_back(duration_cast<microseconds>(stop - start).count());
|
||||
}
|
||||
|
||||
wpi::util::print("{}us\n",
|
||||
std::accumulate(resVec.begin(), resVec.end(), 0) / kNumRuns);
|
||||
wpi::util::print(
|
||||
"{}us\n", std::accumulate(resVec.begin(), resVec.end(), 0) / kNumRuns);
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
|
||||
@@ -509,7 +509,8 @@ void DataLog::AppendFloatArray(int entry, std::span<const float> arr,
|
||||
while ((arr.size() * 4) > kBlockSize) {
|
||||
buf = Reserve(kBlockSize);
|
||||
for (auto val : arr.subspan(0, kBlockSize / 4)) {
|
||||
wpi::util::support::endian::write32le(buf, std::bit_cast<uint32_t>(val));
|
||||
wpi::util::support::endian::write32le(buf,
|
||||
std::bit_cast<uint32_t>(val));
|
||||
buf += 4;
|
||||
}
|
||||
arr = arr.subspan(kBlockSize / 4);
|
||||
@@ -541,7 +542,8 @@ void DataLog::AppendDoubleArray(int entry, std::span<const double> arr,
|
||||
while ((arr.size() * 8) > kBlockSize) {
|
||||
buf = Reserve(kBlockSize);
|
||||
for (auto val : arr.subspan(0, kBlockSize / 8)) {
|
||||
wpi::util::support::endian::write64le(buf, std::bit_cast<uint64_t>(val));
|
||||
wpi::util::support::endian::write64le(buf,
|
||||
std::bit_cast<uint64_t>(val));
|
||||
buf += 8;
|
||||
}
|
||||
arr = arr.subspan(kBlockSize / 8);
|
||||
|
||||
@@ -469,8 +469,8 @@ struct WPI_DataLog* WPI_DataLog_CreateBackgroundWriter(
|
||||
const struct WPI_String* dir, const struct WPI_String* filename,
|
||||
double period, const struct WPI_String* extraHeader) {
|
||||
return reinterpret_cast<WPI_DataLog*>(new DataLogBackgroundWriter{
|
||||
wpi::util::to_string_view(dir), wpi::util::to_string_view(filename), period,
|
||||
wpi::util::to_string_view(extraHeader)});
|
||||
wpi::util::to_string_view(dir), wpi::util::to_string_view(filename),
|
||||
period, wpi::util::to_string_view(extraHeader)});
|
||||
}
|
||||
|
||||
struct WPI_DataLog* WPI_DataLog_CreateBackgroundWriter_Func(
|
||||
|
||||
@@ -97,7 +97,8 @@ bool DataLogRecord::GetFloat(float* value) const {
|
||||
if (m_data.size() != 4) {
|
||||
return false;
|
||||
}
|
||||
*value = std::bit_cast<float>(wpi::util::support::endian::read32le(m_data.data()));
|
||||
*value =
|
||||
std::bit_cast<float>(wpi::util::support::endian::read32le(m_data.data()));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -105,7 +106,8 @@ bool DataLogRecord::GetDouble(double* value) const {
|
||||
if (m_data.size() != 8) {
|
||||
return false;
|
||||
}
|
||||
*value = std::bit_cast<double>(wpi::util::support::endian::read64le(m_data.data()));
|
||||
*value = std::bit_cast<double>(
|
||||
wpi::util::support::endian::read64le(m_data.data()));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -142,8 +144,8 @@ bool DataLogRecord::GetFloatArray(std::vector<float>* arr) const {
|
||||
}
|
||||
arr->reserve(m_data.size() / 4);
|
||||
for (size_t pos = 0; pos < m_data.size(); pos += 4) {
|
||||
arr->push_back(
|
||||
std::bit_cast<float>(wpi::util::support::endian::read32le(&m_data[pos])));
|
||||
arr->push_back(std::bit_cast<float>(
|
||||
wpi::util::support::endian::read32le(&m_data[pos])));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -155,8 +157,8 @@ bool DataLogRecord::GetDoubleArray(std::vector<double>* arr) const {
|
||||
}
|
||||
arr->reserve(m_data.size() / 8);
|
||||
for (size_t pos = 0; pos < m_data.size(); pos += 8) {
|
||||
arr->push_back(
|
||||
std::bit_cast<double>(wpi::util::support::endian::read64le(&m_data[pos])));
|
||||
arr->push_back(std::bit_cast<double>(
|
||||
wpi::util::support::endian::read64le(&m_data[pos])));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -107,9 +107,10 @@ void DataLogReaderThread::ReadMain() {
|
||||
auto desc = m_structDb.Add(*typeStr, schema, &err);
|
||||
if (!desc) {
|
||||
wpi::util::print("could not decode struct '{}' schema '{}': {}\n", name,
|
||||
schema, err);
|
||||
schema, err);
|
||||
}
|
||||
} else if (auto filename = wpi::util::remove_prefix(name, "/.schema/proto:")) {
|
||||
} else if (auto filename =
|
||||
wpi::util::remove_prefix(name, "/.schema/proto:")) {
|
||||
// protobuf descriptor handling
|
||||
upb_Status status;
|
||||
status.ok = true;
|
||||
@@ -120,7 +121,7 @@ void DataLogReaderThread::ReadMain() {
|
||||
&status);
|
||||
if (!status.ok) {
|
||||
wpi::util::print("could not decode protobuf '{}' filename '{}'\n", name,
|
||||
*filename);
|
||||
*filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
|
||||
using namespace wpi::log;
|
||||
|
||||
static std::unique_ptr<wpi::util::raw_ostream> CheckOpen(std::string_view filename,
|
||||
std::error_code& ec) {
|
||||
static std::unique_ptr<wpi::util::raw_ostream> CheckOpen(
|
||||
std::string_view filename, std::error_code& ec) {
|
||||
auto rv = std::make_unique<wpi::util::raw_fd_ostream>(filename, ec);
|
||||
if (ec) {
|
||||
return nullptr;
|
||||
@@ -25,8 +25,9 @@ DataLogWriter::DataLogWriter(std::string_view filename, std::error_code& ec,
|
||||
std::string_view extraHeader)
|
||||
: DataLogWriter{s_defaultMessageLog, filename, ec, extraHeader} {}
|
||||
|
||||
DataLogWriter::DataLogWriter(wpi::util::Logger& msglog, std::string_view filename,
|
||||
std::error_code& ec, std::string_view extraHeader)
|
||||
DataLogWriter::DataLogWriter(wpi::util::Logger& msglog,
|
||||
std::string_view filename, std::error_code& ec,
|
||||
std::string_view extraHeader)
|
||||
: DataLogWriter{msglog, CheckOpen(filename, ec), extraHeader} {
|
||||
if (ec) {
|
||||
Stop();
|
||||
@@ -79,8 +80,9 @@ struct WPI_DataLog* WPI_DataLog_CreateWriter(
|
||||
const struct WPI_String* filename, int* errorCode,
|
||||
const struct WPI_String* extraHeader) {
|
||||
std::error_code ec;
|
||||
auto rv = reinterpret_cast<WPI_DataLog*>(new DataLogWriter{
|
||||
wpi::util::to_string_view(filename), ec, wpi::util::to_string_view(extraHeader)});
|
||||
auto rv = reinterpret_cast<WPI_DataLog*>(
|
||||
new DataLogWriter{wpi::util::to_string_view(filename), ec,
|
||||
wpi::util::to_string_view(extraHeader)});
|
||||
*errorCode = ec.value();
|
||||
return rv;
|
||||
}
|
||||
|
||||
@@ -87,8 +87,8 @@ FileLogger::~FileLogger() {
|
||||
|
||||
std::function<void(std::string_view)> FileLogger::Buffer(
|
||||
std::function<void(std::string_view)> callback) {
|
||||
return [callback,
|
||||
buf = wpi::util::SmallVector<char, 64>{}](std::string_view data) mutable {
|
||||
return [callback, buf = wpi::util::SmallVector<char, 64>{}](
|
||||
std::string_view data) mutable {
|
||||
buf.append(data.begin(), data.end());
|
||||
if (!wpi::util::contains({data.data(), data.size()}, "\n")) {
|
||||
return;
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
|
||||
namespace wpi::util {
|
||||
class Logger;
|
||||
} // namespace wpi
|
||||
} // namespace wpi::util
|
||||
|
||||
namespace wpi::log {
|
||||
|
||||
@@ -159,7 +159,8 @@ class DataLog {
|
||||
* @param timestamp Time stamp (0 to indicate now)
|
||||
*/
|
||||
template <wpi::util::ProtobufSerializable T>
|
||||
void AddProtobufSchema(wpi::util::ProtobufMessage<T>& msg, int64_t timestamp = 0) {
|
||||
void AddProtobufSchema(wpi::util::ProtobufMessage<T>& msg,
|
||||
int64_t timestamp = 0) {
|
||||
if (timestamp == 0) {
|
||||
timestamp = wpi::util::Now();
|
||||
}
|
||||
@@ -1313,8 +1314,8 @@ class StructLogEntry : public DataLogEntry {
|
||||
: m_info{std::move(info)...} {
|
||||
m_log = &log;
|
||||
log.AddStructSchema<T, I...>(info..., timestamp);
|
||||
m_entry =
|
||||
log.Start(name, wpi::util::GetStructTypeString<T>(info...), metadata, timestamp);
|
||||
m_entry = log.Start(name, wpi::util::GetStructTypeString<T>(info...),
|
||||
metadata, timestamp);
|
||||
}
|
||||
|
||||
StructLogEntry(StructLogEntry&& rhs)
|
||||
@@ -1443,7 +1444,8 @@ class StructArrayLogEntry : public DataLogEntry {
|
||||
m_log = &log;
|
||||
log.AddStructSchema<T, I...>(info..., timestamp);
|
||||
m_entry = log.Start(
|
||||
name, wpi::util::MakeStructArrayTypeString<T, std::dynamic_extent>(info...),
|
||||
name,
|
||||
wpi::util::MakeStructArrayTypeString<T, std::dynamic_extent>(info...),
|
||||
metadata, timestamp);
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
namespace wpi::util {
|
||||
class Logger;
|
||||
} // namespace wpi
|
||||
} // namespace wpi::util
|
||||
|
||||
namespace wpi::log {
|
||||
|
||||
|
||||
@@ -85,7 +85,9 @@ class DataLogReaderThread {
|
||||
return it->second;
|
||||
}
|
||||
|
||||
wpi::util::StructDescriptorDatabase& GetStructDatabase() { return m_structDb; }
|
||||
wpi::util::StructDescriptorDatabase& GetStructDatabase() {
|
||||
return m_structDb;
|
||||
}
|
||||
upb_DefPool* GetProtobufDatabase() { return m_protoPool; }
|
||||
upb_Arena* GetProtobufArena() { return m_arena; }
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
namespace wpi::util {
|
||||
class raw_ostream;
|
||||
class Logger;
|
||||
} // namespace wpi
|
||||
} // namespace wpi::util
|
||||
|
||||
namespace wpi::log {
|
||||
|
||||
@@ -62,7 +62,8 @@ class DataLogWriter final : public DataLog {
|
||||
* @param os output stream
|
||||
* @param extraHeader extra header data
|
||||
*/
|
||||
DataLogWriter(wpi::util::Logger& msglog, std::unique_ptr<wpi::util::raw_ostream> os,
|
||||
DataLogWriter(wpi::util::Logger& msglog,
|
||||
std::unique_ptr<wpi::util::raw_ostream> os,
|
||||
std::string_view extraHeader = "");
|
||||
|
||||
~DataLogWriter() final;
|
||||
|
||||
@@ -131,8 +131,8 @@ class DataLogTest : public ::testing::Test {
|
||||
public:
|
||||
wpi::util::Logger msglog;
|
||||
std::vector<uint8_t> data;
|
||||
wpi::log::DataLogWriter log{msglog,
|
||||
std::make_unique<wpi::util::raw_uvector_ostream>(data)};
|
||||
wpi::log::DataLogWriter log{
|
||||
msglog, std::make_unique<wpi::util::raw_uvector_ostream>(data)};
|
||||
};
|
||||
|
||||
TEST_F(DataLogTest, SimpleInt) {
|
||||
|
||||
@@ -41,7 +41,8 @@ static std::unique_ptr<wpi::glass::PlotProvider> gPlotProvider;
|
||||
static std::unique_ptr<wpi::glass::NetworkTablesProvider> gNtProvider;
|
||||
|
||||
static std::unique_ptr<wpi::glass::NetworkTablesModel> gNetworkTablesModel;
|
||||
static std::unique_ptr<wpi::glass::NetworkTablesSettings> gNetworkTablesSettings;
|
||||
static std::unique_ptr<wpi::glass::NetworkTablesSettings>
|
||||
gNetworkTablesSettings;
|
||||
static wpi::glass::LogData gNetworkTablesLog;
|
||||
static std::unique_ptr<wpi::glass::Window> gNetworkTablesWindow;
|
||||
static std::unique_ptr<wpi::glass::Window> gNetworkTablesInfoWindow;
|
||||
@@ -95,7 +96,8 @@ static std::string MakeTitle(NT_Inst inst, wpi::nt::Event event) {
|
||||
static void NtInitialize() {
|
||||
auto inst = wpi::nt::GetDefaultInstance();
|
||||
auto poller = wpi::nt::CreateListenerPoller(inst);
|
||||
wpi::nt::AddPolledListener(poller, inst, NT_EVENT_CONNECTION | NT_EVENT_IMMEDIATE);
|
||||
wpi::nt::AddPolledListener(poller, inst,
|
||||
NT_EVENT_CONNECTION | NT_EVENT_IMMEDIATE);
|
||||
wpi::nt::AddPolledLogger(poller, NT_LOG_INFO, 100);
|
||||
gui::AddEarlyExecute([inst, poller] {
|
||||
auto win = gui::GetSystemWindow();
|
||||
@@ -149,9 +151,10 @@ static void NtInitialize() {
|
||||
gui::AddEarlyExecute([] { gNetworkTablesModel->Update(); });
|
||||
|
||||
gNetworkTablesWindow = std::make_unique<wpi::glass::Window>(
|
||||
wpi::glass::GetStorageRoot().GetChild("NetworkTables View"), "NetworkTables");
|
||||
gNetworkTablesWindow->SetView(
|
||||
std::make_unique<wpi::glass::NetworkTablesView>(gNetworkTablesModel.get()));
|
||||
wpi::glass::GetStorageRoot().GetChild("NetworkTables View"),
|
||||
"NetworkTables");
|
||||
gNetworkTablesWindow->SetView(std::make_unique<wpi::glass::NetworkTablesView>(
|
||||
gNetworkTablesModel.get()));
|
||||
gNetworkTablesWindow->SetDefaultPos(250, 277);
|
||||
gNetworkTablesWindow->SetDefaultSize(750, 185);
|
||||
gNetworkTablesWindow->DisableRenamePopup();
|
||||
@@ -161,8 +164,9 @@ static void NtInitialize() {
|
||||
gNetworkTablesInfoWindow = std::make_unique<wpi::glass::Window>(
|
||||
wpi::glass::GetStorageRoot().GetChild("NetworkTables Info"),
|
||||
"NetworkTables Info");
|
||||
gNetworkTablesInfoWindow->SetView(wpi::glass::MakeFunctionView(
|
||||
[&] { wpi::glass::DisplayNetworkTablesInfo(gNetworkTablesModel.get()); }));
|
||||
gNetworkTablesInfoWindow->SetView(wpi::glass::MakeFunctionView([&] {
|
||||
wpi::glass::DisplayNetworkTablesInfo(gNetworkTablesModel.get());
|
||||
}));
|
||||
gNetworkTablesInfoWindow->SetDefaultPos(250, 130);
|
||||
gNetworkTablesInfoWindow->SetDefaultSize(750, 145);
|
||||
gNetworkTablesInfoWindow->SetDefaultVisibility(wpi::glass::Window::kHide);
|
||||
@@ -228,7 +232,7 @@ int main(int argc, char** argv) {
|
||||
|
||||
wpi::glass::SetStorageName("glass");
|
||||
wpi::glass::SetStorageDir(saveDir.empty() ? gui::GetPlatformSaveFileDir()
|
||||
: saveDir);
|
||||
: saveDir);
|
||||
gPlotProvider->GlobalInit();
|
||||
gui::AddInit([] { wpi::glass::ResetTime(); });
|
||||
gNtProvider->GlobalInit();
|
||||
@@ -328,12 +332,13 @@ int main(int argc, char** argv) {
|
||||
char nameBuf[32];
|
||||
const char* name = glfwGetKeyName(*gEnterKey, 0);
|
||||
if (!name) {
|
||||
wpi::util::format_to_n_c_str(nameBuf, sizeof(nameBuf), "{}", *gEnterKey);
|
||||
wpi::util::format_to_n_c_str(nameBuf, sizeof(nameBuf), "{}",
|
||||
*gEnterKey);
|
||||
|
||||
name = nameBuf;
|
||||
}
|
||||
wpi::util::format_to_n_c_str(editLabel, sizeof(editLabel), "{}###edit",
|
||||
gKeyEdit ? "(press key)" : name);
|
||||
gKeyEdit ? "(press key)" : name);
|
||||
|
||||
if (ImGui::SmallButton(editLabel)) {
|
||||
gKeyEdit = true;
|
||||
|
||||
@@ -136,8 +136,9 @@ static bool LoadWindowStorageImpl(const std::string& filename) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
return JsonToWindow(wpi::util::json::parse(fileBuffer.value()->GetCharBuffer()),
|
||||
filename.c_str());
|
||||
return JsonToWindow(
|
||||
wpi::util::json::parse(fileBuffer.value()->GetCharBuffer()),
|
||||
filename.c_str());
|
||||
} catch (wpi::util::json::parse_error& e) {
|
||||
ImGui::LogText("Error loading %s: %s", filename.c_str(), e.what());
|
||||
return false;
|
||||
@@ -154,8 +155,9 @@ static bool LoadStorageRootImpl(Context* ctx, const std::string& filename,
|
||||
}
|
||||
auto [it, createdStorage] = ctx->storageRoots.try_emplace(rootName);
|
||||
try {
|
||||
it->second.FromJson(wpi::util::json::parse(fileBuffer.value()->GetCharBuffer()),
|
||||
filename.c_str());
|
||||
it->second.FromJson(
|
||||
wpi::util::json::parse(fileBuffer.value()->GetCharBuffer()),
|
||||
filename.c_str());
|
||||
} catch (wpi::util::json::parse_error& e) {
|
||||
ImGui::LogText("Error loading %s: %s", filename.c_str(), e.what());
|
||||
if (createdStorage) {
|
||||
@@ -214,8 +216,10 @@ static wpi::util::json WindowToJson() {
|
||||
if (line[0] == '[') {
|
||||
// new section
|
||||
auto [section, subsection] = wpi::util::split(line, ']');
|
||||
section = wpi::util::drop_front(section); // drop '['; ']' was dropped by split
|
||||
subsection = wpi::util::drop_back(wpi::util::drop_front(subsection)); // drop []
|
||||
section =
|
||||
wpi::util::drop_front(section); // drop '['; ']' was dropped by split
|
||||
subsection =
|
||||
wpi::util::drop_back(wpi::util::drop_front(subsection)); // drop []
|
||||
auto& jsection = out[section];
|
||||
if (jsection.is_null()) {
|
||||
jsection = wpi::util::json::object();
|
||||
@@ -472,7 +476,7 @@ void wpi::glass::End() {
|
||||
}
|
||||
|
||||
bool wpi::glass::BeginChild(const char* str_id, const ImVec2& size, bool border,
|
||||
ImGuiWindowFlags flags) {
|
||||
ImGuiWindowFlags flags) {
|
||||
PushStorageStack(str_id);
|
||||
return ImGui::BeginChild(str_id, size, border, flags);
|
||||
}
|
||||
|
||||
@@ -20,7 +20,8 @@ std::string wpi::glass::MakeSourceId(std::string_view id, int index) {
|
||||
return fmt::format("{}[{}]", id, index);
|
||||
}
|
||||
|
||||
std::string wpi::glass::MakeSourceId(std::string_view id, int index, int index2) {
|
||||
std::string wpi::glass::MakeSourceId(std::string_view id, int index,
|
||||
int index2) {
|
||||
return fmt::format("{}[{},{}]", id, index, index2);
|
||||
}
|
||||
|
||||
|
||||
@@ -345,7 +345,8 @@ void Storage::EraseChildren() {
|
||||
});
|
||||
}
|
||||
|
||||
static bool JsonArrayToStorage(Storage::Value* valuePtr, const wpi::util::json& jarr,
|
||||
static bool JsonArrayToStorage(Storage::Value* valuePtr,
|
||||
const wpi::util::json& jarr,
|
||||
const char* filename) {
|
||||
auto& arr = jarr.get_ref<const wpi::util::json::array_t&>();
|
||||
if (arr.empty()) {
|
||||
|
||||
@@ -25,7 +25,8 @@ void wpi::glass::DisplayAnalogInput(AnalogInputModel* model, int index) {
|
||||
std::string& name = GetStorage().GetString("name");
|
||||
char label[128];
|
||||
if (!name.empty()) {
|
||||
wpi::util::format_to_n_c_str(label, sizeof(label), "{} [{}]###name", name, index);
|
||||
wpi::util::format_to_n_c_str(label, sizeof(label), "{} [{}]###name", name,
|
||||
index);
|
||||
} else {
|
||||
wpi::util::format_to_n_c_str(label, sizeof(label), "In[{}]###name", index);
|
||||
}
|
||||
@@ -48,7 +49,7 @@ void wpi::glass::DisplayAnalogInput(AnalogInputModel* model, int index) {
|
||||
}
|
||||
|
||||
void wpi::glass::DisplayAnalogInputs(AnalogInputsModel* model,
|
||||
std::string_view noneMsg) {
|
||||
std::string_view noneMsg) {
|
||||
ImGui::Text("(Use Ctrl+Click to edit value)");
|
||||
bool hasAny = false;
|
||||
bool first = true;
|
||||
|
||||
@@ -106,7 +106,7 @@ void wpi::glass::DisplayDIO(DIOModel* model, int index, bool outputsEnabled) {
|
||||
}
|
||||
|
||||
void wpi::glass::DisplayDIOs(DIOsModel* model, bool outputsEnabled,
|
||||
std::string_view noneMsg) {
|
||||
std::string_view noneMsg) {
|
||||
bool hasAny = false;
|
||||
|
||||
ImGui::PushItemWidth(ImGui::GetFontSize() * 8);
|
||||
|
||||
@@ -73,11 +73,11 @@ void wpi::glass::DisplayEncoder(EncoderModel* model) {
|
||||
std::string& name = GetStorage().GetString("name");
|
||||
char label[128];
|
||||
if (!name.empty()) {
|
||||
wpi::util::format_to_n_c_str(label, sizeof(label), "{} [{},{}]###header", name,
|
||||
chA, chB);
|
||||
wpi::util::format_to_n_c_str(label, sizeof(label), "{} [{},{}]###header",
|
||||
name, chA, chB);
|
||||
} else {
|
||||
wpi::util::format_to_n_c_str(label, sizeof(label), "Encoder[{},{}]###header", chA,
|
||||
chB);
|
||||
wpi::util::format_to_n_c_str(label, sizeof(label),
|
||||
"Encoder[{},{}]###header", chA, chB);
|
||||
}
|
||||
|
||||
// header
|
||||
@@ -159,7 +159,8 @@ void wpi::glass::DisplayEncoder(EncoderModel* model) {
|
||||
ImGui::PopItemWidth();
|
||||
}
|
||||
|
||||
void wpi::glass::DisplayEncoders(EncodersModel* model, std::string_view noneMsg) {
|
||||
void wpi::glass::DisplayEncoders(EncodersModel* model,
|
||||
std::string_view noneMsg) {
|
||||
bool hasAny = false;
|
||||
model->ForEachEncoder([&](EncoderModel& encoder, int i) {
|
||||
hasAny = true;
|
||||
|
||||
@@ -25,7 +25,8 @@ void wpi::glass::DisplayPWM(PWMModel* model, int index, bool outputsEnabled) {
|
||||
std::string& name = GetStorage().GetString("name");
|
||||
char label[128];
|
||||
if (!name.empty()) {
|
||||
wpi::util::format_to_n_c_str(label, sizeof(label), "{} [{}]###name", name, index);
|
||||
wpi::util::format_to_n_c_str(label, sizeof(label), "{} [{}]###name", name,
|
||||
index);
|
||||
} else {
|
||||
wpi::util::format_to_n_c_str(label, sizeof(label), "PWM[{}]###name", index);
|
||||
}
|
||||
@@ -39,7 +40,7 @@ void wpi::glass::DisplayPWM(PWMModel* model, int index, bool outputsEnabled) {
|
||||
}
|
||||
|
||||
void wpi::glass::DisplayPWMs(PWMsModel* model, bool outputsEnabled,
|
||||
std::string_view noneMsg) {
|
||||
std::string_view noneMsg) {
|
||||
bool hasAny = false;
|
||||
bool first = true;
|
||||
model->ForEachPWM([&](PWMModel& pwm, int i) {
|
||||
|
||||
@@ -22,7 +22,8 @@
|
||||
using namespace wpi::glass;
|
||||
|
||||
bool wpi::glass::DisplayPneumaticControlSolenoids(PneumaticControlModel* model,
|
||||
int index, bool outputsEnabled) {
|
||||
int index,
|
||||
bool outputsEnabled) {
|
||||
wpi::util::SmallVector<int, 16> channels;
|
||||
model->ForEachSolenoid([&](SolenoidModel& solenoid, int j) {
|
||||
if (auto data = solenoid.GetOutputData()) {
|
||||
@@ -49,10 +50,10 @@ bool wpi::glass::DisplayPneumaticControlSolenoids(PneumaticControlModel* model,
|
||||
char label[128];
|
||||
if (!name.empty()) {
|
||||
wpi::util::format_to_n_c_str(label, sizeof(label), "{} [{}]###header", name,
|
||||
index);
|
||||
index);
|
||||
} else {
|
||||
wpi::util::format_to_n_c_str(label, sizeof(label), "{}[{}]###header",
|
||||
model->GetName(), index);
|
||||
model->GetName(), index);
|
||||
}
|
||||
|
||||
// header
|
||||
@@ -87,9 +88,9 @@ bool wpi::glass::DisplayPneumaticControlSolenoids(PneumaticControlModel* model,
|
||||
return true;
|
||||
}
|
||||
|
||||
void wpi::glass::DisplayPneumaticControlsSolenoids(PneumaticControlsModel* model,
|
||||
bool outputsEnabled,
|
||||
std::string_view noneMsg) {
|
||||
void wpi::glass::DisplayPneumaticControlsSolenoids(
|
||||
PneumaticControlsModel* model, bool outputsEnabled,
|
||||
std::string_view noneMsg) {
|
||||
bool hasAny = false;
|
||||
model->ForEachPneumaticControl(
|
||||
[&](PneumaticControlModel& pneumaticControl, int i) {
|
||||
@@ -106,7 +107,7 @@ void wpi::glass::DisplayPneumaticControlsSolenoids(PneumaticControlsModel* model
|
||||
}
|
||||
|
||||
void wpi::glass::DisplayCompressorDevice(CompressorModel* model, int index,
|
||||
bool outputsEnabled) {
|
||||
bool outputsEnabled) {
|
||||
if (!model || !model->Exists()) {
|
||||
return;
|
||||
}
|
||||
@@ -155,7 +156,7 @@ void wpi::glass::DisplayCompressorDevice(CompressorModel* model, int index,
|
||||
}
|
||||
|
||||
void wpi::glass::DisplayCompressorsDevice(PneumaticControlsModel* model,
|
||||
bool outputsEnabled) {
|
||||
bool outputsEnabled) {
|
||||
model->ForEachPneumaticControl(
|
||||
[&](PneumaticControlModel& pneumaticControl, int i) {
|
||||
DisplayCompressorDevice(pneumaticControl.GetCompressor(), i,
|
||||
|
||||
@@ -34,9 +34,11 @@ static float DisplayChannel(PowerDistributionModel& pdp, int channel) {
|
||||
return width;
|
||||
}
|
||||
|
||||
void wpi::glass::DisplayPowerDistribution(PowerDistributionModel* model, int index) {
|
||||
void wpi::glass::DisplayPowerDistribution(PowerDistributionModel* model,
|
||||
int index) {
|
||||
char name[128];
|
||||
wpi::util::format_to_n_c_str(name, sizeof(name), "PowerDistribution[{}]", index);
|
||||
wpi::util::format_to_n_c_str(name, sizeof(name), "PowerDistribution[{}]",
|
||||
index);
|
||||
|
||||
if (CollapsingHeader(name)) {
|
||||
// temperature
|
||||
@@ -81,7 +83,7 @@ void wpi::glass::DisplayPowerDistribution(PowerDistributionModel* model, int ind
|
||||
}
|
||||
|
||||
void wpi::glass::DisplayPowerDistributions(PowerDistributionsModel* model,
|
||||
std::string_view noneMsg) {
|
||||
std::string_view noneMsg) {
|
||||
bool hasAny = false;
|
||||
model->ForEachPowerDistribution([&](PowerDistributionModel& pdp, int i) {
|
||||
hasAny = true;
|
||||
|
||||
@@ -151,28 +151,28 @@ static inline bool DeviceValueImpl(const char* name, bool readonly,
|
||||
}
|
||||
|
||||
bool wpi::glass::DeviceBoolean(const char* name, bool readonly, bool* value,
|
||||
const DataSource* source) {
|
||||
const DataSource* source) {
|
||||
return DeviceValueImpl(name, readonly, source, DeviceBooleanImpl, value);
|
||||
}
|
||||
|
||||
bool wpi::glass::DeviceDouble(const char* name, bool readonly, double* value,
|
||||
const DataSource* source) {
|
||||
const DataSource* source) {
|
||||
return DeviceValueImpl(name, readonly, source, DeviceDoubleImpl, value);
|
||||
}
|
||||
|
||||
bool wpi::glass::DeviceEnum(const char* name, bool readonly, int* value,
|
||||
const char** options, int32_t numOptions,
|
||||
const DataSource* source) {
|
||||
const char** options, int32_t numOptions,
|
||||
const DataSource* source) {
|
||||
return DeviceValueImpl(name, readonly, source, DeviceEnumImpl, value, options,
|
||||
numOptions);
|
||||
}
|
||||
|
||||
bool wpi::glass::DeviceInt(const char* name, bool readonly, int32_t* value,
|
||||
const DataSource* source) {
|
||||
const DataSource* source) {
|
||||
return DeviceValueImpl(name, readonly, source, DeviceIntImpl, value);
|
||||
}
|
||||
|
||||
bool wpi::glass::DeviceLong(const char* name, bool readonly, int64_t* value,
|
||||
const DataSource* source) {
|
||||
const DataSource* source) {
|
||||
return DeviceValueImpl(name, readonly, source, DeviceLongImpl, value);
|
||||
}
|
||||
|
||||
@@ -48,9 +48,10 @@ enum DisplayUnits { kDisplayMeters = 0, kDisplayFeet, kDisplayInches };
|
||||
// Per-frame field data (not persistent)
|
||||
struct FieldFrameData {
|
||||
wpi::math::Translation2d GetPosFromScreen(const ImVec2& cursor) const {
|
||||
return {
|
||||
wpi::units::meter_t{(std::clamp(cursor.x, min.x, max.x) - min.x) / scale},
|
||||
wpi::units::meter_t{(max.y - std::clamp(cursor.y, min.y, max.y)) / scale}};
|
||||
return {wpi::units::meter_t{(std::clamp(cursor.x, min.x, max.x) - min.x) /
|
||||
scale},
|
||||
wpi::units::meter_t{(max.y - std::clamp(cursor.y, min.y, max.y)) /
|
||||
scale}};
|
||||
}
|
||||
ImVec2 GetScreenFromPos(const wpi::math::Translation2d& pos) const {
|
||||
return {min.x + scale * pos.X().to<float>(),
|
||||
@@ -94,7 +95,9 @@ class PopupState {
|
||||
|
||||
SelectedTargetInfo* GetTarget() { return &m_target; }
|
||||
FieldObjectModel* GetInsertModel() { return m_insertModel; }
|
||||
std::span<const wpi::math::Pose2d> GetInsertPoses() const { return m_insertPoses; }
|
||||
std::span<const wpi::math::Pose2d> GetInsertPoses() const {
|
||||
return m_insertPoses;
|
||||
}
|
||||
|
||||
void Display(Field2DModel* model, const FieldFrameData& ffd);
|
||||
|
||||
@@ -282,8 +285,9 @@ static double ConvertDisplayAngle(wpi::units::degree_t v) {
|
||||
return v.value();
|
||||
}
|
||||
|
||||
static bool InputLength(const char* label, wpi::units::meter_t* v, double step = 0.0,
|
||||
double step_fast = 0.0, const char* format = "%.6f",
|
||||
static bool InputLength(const char* label, wpi::units::meter_t* v,
|
||||
double step = 0.0, double step_fast = 0.0,
|
||||
const char* format = "%.6f",
|
||||
ImGuiInputTextFlags flags = 0) {
|
||||
double dv = ConvertDisplayLength(*v);
|
||||
if (ImGui::InputDouble(label, &dv, step, step_fast, format, flags)) {
|
||||
@@ -316,8 +320,9 @@ static bool InputFloatLength(const char* label, float* v, double step = 0.0,
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool InputAngle(const char* label, wpi::units::degree_t* v, double step = 0.0,
|
||||
double step_fast = 0.0, const char* format = "%.6f",
|
||||
static bool InputAngle(const char* label, wpi::units::degree_t* v,
|
||||
double step = 0.0, double step_fast = 0.0,
|
||||
const char* format = "%.6f",
|
||||
ImGuiInputTextFlags flags = 0) {
|
||||
double dv = ConvertDisplayAngle(*v);
|
||||
if (ImGui::InputDouble(label, &dv, step, step_fast, format, flags)) {
|
||||
@@ -465,7 +470,8 @@ bool FieldInfo::LoadJson(std::span<const char> is, std::string_view filename) {
|
||||
try {
|
||||
image = j.at("field-image").get<std::string>();
|
||||
} catch (const wpi::util::json::exception& e) {
|
||||
wpi::util::print(stderr, "GUI: JSON: could not read field-image: {}\n", e.what());
|
||||
wpi::util::print(stderr, "GUI: JSON: could not read field-image: {}\n",
|
||||
e.what());
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -478,7 +484,7 @@ bool FieldInfo::LoadJson(std::span<const char> is, std::string_view filename) {
|
||||
right = j.at("field-corners").at("bottom-right").at(0).get<int>();
|
||||
} catch (const wpi::util::json::exception& e) {
|
||||
wpi::util::print(stderr, "GUI: JSON: could not read field-corners: {}\n",
|
||||
e.what());
|
||||
e.what());
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -489,7 +495,8 @@ bool FieldInfo::LoadJson(std::span<const char> is, std::string_view filename) {
|
||||
width = j.at("field-size").at(0).get<float>();
|
||||
height = j.at("field-size").at(1).get<float>();
|
||||
} catch (const wpi::util::json::exception& e) {
|
||||
wpi::util::print(stderr, "GUI: JSON: could not read field-size: {}\n", e.what());
|
||||
wpi::util::print(stderr, "GUI: JSON: could not read field-size: {}\n",
|
||||
e.what());
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -498,7 +505,8 @@ bool FieldInfo::LoadJson(std::span<const char> is, std::string_view filename) {
|
||||
try {
|
||||
unit = j.at("field-unit").get<std::string>();
|
||||
} catch (const wpi::util::json::exception& e) {
|
||||
wpi::util::print(stderr, "GUI: JSON: could not read field-unit: {}\n", e.what());
|
||||
wpi::util::print(stderr, "GUI: JSON: could not read field-unit: {}\n",
|
||||
e.what());
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -513,9 +521,9 @@ bool FieldInfo::LoadJson(std::span<const char> is, std::string_view filename) {
|
||||
int fieldHeight = m_bottom - m_top;
|
||||
if (std::abs((fieldWidth / width) - (fieldHeight / height)) > 0.3) {
|
||||
wpi::util::print(stderr,
|
||||
"GUI: Field X and Y scaling substantially different: "
|
||||
"xscale={} yscale={}\n",
|
||||
(fieldWidth / width), (fieldHeight / height));
|
||||
"GUI: Field X and Y scaling substantially different: "
|
||||
"xscale={} yscale={}\n",
|
||||
(fieldWidth / width), (fieldHeight / height));
|
||||
}
|
||||
|
||||
if (!filename.empty()) {
|
||||
@@ -772,8 +780,9 @@ bool ObjectInfo::LoadImageImpl(const std::string& fn) {
|
||||
return true;
|
||||
}
|
||||
|
||||
PoseFrameData::PoseFrameData(const wpi::math::Pose2d& pose, FieldObjectModel& model,
|
||||
size_t index, const FieldFrameData& ffd,
|
||||
PoseFrameData::PoseFrameData(const wpi::math::Pose2d& pose,
|
||||
FieldObjectModel& model, size_t index,
|
||||
const FieldFrameData& ffd,
|
||||
const DisplayOptions& displayOptions)
|
||||
: m_model{model},
|
||||
m_index{index},
|
||||
@@ -1086,7 +1095,7 @@ void FieldDisplay::Display(FieldInfo* field, Field2DModel* model,
|
||||
if (target->corner != 1) {
|
||||
gDragState.initialAngle =
|
||||
wpi::units::radian_t{std::atan2(gDragState.initialOffset.y,
|
||||
gDragState.initialOffset.x)} +
|
||||
gDragState.initialOffset.x)} +
|
||||
target->rot;
|
||||
}
|
||||
}
|
||||
@@ -1182,7 +1191,8 @@ void PopupState::Display(Field2DModel* model, const FieldFrameData& ffd) {
|
||||
void PopupState::DisplayTarget(Field2DModel* model, const FieldFrameData& ffd) {
|
||||
ImGui::Text("%s[%d]", m_target.name.c_str(),
|
||||
static_cast<int>(m_target.index));
|
||||
wpi::math::Pose2d pose{ffd.GetPosFromScreen(m_target.poseCenter), m_target.rot};
|
||||
wpi::math::Pose2d pose{ffd.GetPosFromScreen(m_target.poseCenter),
|
||||
m_target.rot};
|
||||
if (InputPose(&pose)) {
|
||||
m_target.poseCenter = ffd.GetScreenFromPos(pose.Translation());
|
||||
m_target.rot = pose.Rotation().Radians();
|
||||
@@ -1277,7 +1287,8 @@ void PopupState::DisplayInsert(Field2DModel* model) {
|
||||
}
|
||||
}
|
||||
|
||||
void wpi::glass::DisplayField2D(Field2DModel* model, const ImVec2& contentSize) {
|
||||
void wpi::glass::DisplayField2D(Field2DModel* model,
|
||||
const ImVec2& contentSize) {
|
||||
auto& storage = GetStorage();
|
||||
auto field = storage.GetData<FieldInfo>();
|
||||
if (!field) {
|
||||
|
||||
@@ -38,9 +38,10 @@ namespace {
|
||||
// Per-frame data (not persistent)
|
||||
struct FrameData {
|
||||
wpi::math::Translation2d GetPosFromScreen(const ImVec2& cursor) const {
|
||||
return {
|
||||
wpi::units::meter_t{(std::clamp(cursor.x, min.x, max.x) - min.x) / scale},
|
||||
wpi::units::meter_t{(max.y - std::clamp(cursor.y, min.y, max.y)) / scale}};
|
||||
return {wpi::units::meter_t{(std::clamp(cursor.x, min.x, max.x) - min.x) /
|
||||
scale},
|
||||
wpi::units::meter_t{(max.y - std::clamp(cursor.y, min.y, max.y)) /
|
||||
scale}};
|
||||
}
|
||||
ImVec2 GetScreenFromPos(const wpi::math::Translation2d& pos) const {
|
||||
return {min.x + scale * pos.X().to<float>(),
|
||||
@@ -67,7 +68,8 @@ class BackgroundInfo {
|
||||
void DisplaySettings();
|
||||
|
||||
void LoadImage();
|
||||
FrameData GetFrameData(ImVec2 min, ImVec2 max, wpi::math::Translation2d dims) const;
|
||||
FrameData GetFrameData(ImVec2 min, ImVec2 max,
|
||||
wpi::math::Translation2d dims) const;
|
||||
void Draw(ImDrawList* drawList, const FrameData& frameData,
|
||||
ImU32 bgColor) const;
|
||||
|
||||
@@ -184,11 +186,12 @@ void FrameData::DrawObject(ImDrawList* drawList, MechanismObjectModel& objModel,
|
||||
const wpi::math::Pose2d& pose) const {
|
||||
const char* type = objModel.GetType();
|
||||
if (std::string_view{type} == "line") {
|
||||
auto startPose =
|
||||
pose + wpi::math::Transform2d{wpi::math::Translation2d{}, objModel.GetAngle()};
|
||||
auto startPose = pose + wpi::math::Transform2d{wpi::math::Translation2d{},
|
||||
objModel.GetAngle()};
|
||||
auto endPose =
|
||||
startPose +
|
||||
wpi::math::Transform2d{wpi::math::Translation2d{objModel.GetLength(), 0_m}, 0_deg};
|
||||
wpi::math::Transform2d{
|
||||
wpi::math::Translation2d{objModel.GetLength(), 0_m}, 0_deg};
|
||||
drawList->AddLine(GetScreenFromPos(startPose.Translation()),
|
||||
GetScreenFromPos(endPose.Translation()),
|
||||
objModel.GetColor(), objModel.GetWeight());
|
||||
@@ -203,7 +206,7 @@ void FrameData::DrawGroup(ImDrawList* drawList, MechanismObjectGroup& group,
|
||||
}
|
||||
|
||||
void wpi::glass::DisplayMechanism2D(Mechanism2DModel* model,
|
||||
const ImVec2& contentSize) {
|
||||
const ImVec2& contentSize) {
|
||||
auto& storage = GetStorage();
|
||||
auto bg = storage.GetData<BackgroundInfo>();
|
||||
if (!bg) {
|
||||
|
||||
@@ -350,8 +350,9 @@ PlotSeries::Action PlotSeries::EmitPlot(PlotView& view, double now, size_t i,
|
||||
CheckSource();
|
||||
|
||||
char label[128];
|
||||
wpi::util::format_to_n_c_str(label, sizeof(label), "{}###name{}_{}", GetName(),
|
||||
static_cast<int>(i), static_cast<int>(plotIndex));
|
||||
wpi::util::format_to_n_c_str(label, sizeof(label), "{}###name{}_{}",
|
||||
GetName(), static_cast<int>(i),
|
||||
static_cast<int>(plotIndex));
|
||||
|
||||
int size = m_size;
|
||||
int offset = m_offset;
|
||||
@@ -619,7 +620,7 @@ void Plot::EmitPlot(PlotView& view, double now, bool paused, size_t i) {
|
||||
|
||||
char label[128];
|
||||
wpi::util::format_to_n_c_str(label, sizeof(label), "{}###plot{}", m_name,
|
||||
static_cast<int>(i));
|
||||
static_cast<int>(i));
|
||||
|
||||
ImPlotFlags plotFlags = (m_legend ? 0 : ImPlotFlags_NoLegend) |
|
||||
(m_crosshairs ? ImPlotFlags_Crosshairs : 0) |
|
||||
@@ -976,15 +977,16 @@ void PlotView::Settings() {
|
||||
|
||||
char name[64];
|
||||
if (!plot->GetName().empty()) {
|
||||
wpi::util::format_to_n_c_str(name, sizeof(name), "{}", plot->GetName().c_str());
|
||||
wpi::util::format_to_n_c_str(name, sizeof(name), "{}",
|
||||
plot->GetName().c_str());
|
||||
} else {
|
||||
wpi::util::format_to_n_c_str(name, sizeof(name), "Plot {}",
|
||||
static_cast<int>(i));
|
||||
static_cast<int>(i));
|
||||
}
|
||||
|
||||
char label[90];
|
||||
wpi::util::format_to_n_c_str(label, sizeof(label), "{}###header{}", name,
|
||||
static_cast<int>(i));
|
||||
static_cast<int>(i));
|
||||
|
||||
bool open = ImGui::CollapsingHeader(label);
|
||||
|
||||
@@ -1053,7 +1055,8 @@ void PlotProvider::DisplayMenu() {
|
||||
char id[32];
|
||||
size_t numWindows = m_windows.size();
|
||||
for (size_t i = 0; i <= numWindows; ++i) {
|
||||
wpi::util::format_to_n_c_str(id, sizeof(id), "Plot <{}>", static_cast<int>(i));
|
||||
wpi::util::format_to_n_c_str(id, sizeof(id), "Plot <{}>",
|
||||
static_cast<int>(i));
|
||||
|
||||
bool match = false;
|
||||
for (size_t j = 0; j < numWindows; ++j) {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user