diff --git a/KiwiLight - Rio Code/.gitignore b/KiwiLight - Rio Code/KiwiLightSampleCode/.gitignore similarity index 99% rename from KiwiLight - Rio Code/.gitignore rename to KiwiLight - Rio Code/KiwiLightSampleCode/.gitignore index 61f25ce..983678a 100644 --- a/KiwiLight - Rio Code/.gitignore +++ b/KiwiLight - Rio Code/KiwiLightSampleCode/.gitignore @@ -155,6 +155,7 @@ gradle-app.setting .project .settings/ bin/ +imgui.ini # End of https://www.gitignore.io/api/c++,java,linux,macos,gradle,windows,visualstudiocode diff --git a/KiwiLight - Rio Code/.vscode/launch.json b/KiwiLight - Rio Code/KiwiLightSampleCode/.vscode/launch.json similarity index 100% rename from KiwiLight - Rio Code/.vscode/launch.json rename to KiwiLight - Rio Code/KiwiLightSampleCode/.vscode/launch.json diff --git a/KiwiLight - Rio Code/.vscode/settings.json b/KiwiLight - Rio Code/KiwiLightSampleCode/.vscode/settings.json similarity index 63% rename from KiwiLight - Rio Code/.vscode/settings.json rename to KiwiLight - Rio Code/KiwiLightSampleCode/.vscode/settings.json index dc084a0..4dade9d 100644 --- a/KiwiLight - Rio Code/.vscode/settings.json +++ b/KiwiLight - Rio Code/KiwiLightSampleCode/.vscode/settings.json @@ -7,7 +7,10 @@ "**/CVS": true, "**/.DS_Store": true, "bin/": true, - ".classpath": true, - ".project": true + "**/.classpath": true, + "**/.project": true, + "**/.settings": true, + "**/.factorypath": true, + "**/*~": true } } diff --git a/KiwiLight - Rio Code/.wpilib/wpilib_preferences.json b/KiwiLight - Rio Code/KiwiLightSampleCode/.wpilib/wpilib_preferences.json similarity index 77% rename from KiwiLight - Rio Code/.wpilib/wpilib_preferences.json rename to KiwiLight - Rio Code/KiwiLightSampleCode/.wpilib/wpilib_preferences.json index e84d49c..a0a5e79 100644 --- a/KiwiLight - Rio Code/.wpilib/wpilib_preferences.json +++ b/KiwiLight - Rio Code/KiwiLightSampleCode/.wpilib/wpilib_preferences.json @@ -1,6 +1,6 @@ { "enableCppIntellisense": false, "currentLanguage": "java", - "projectYear": "2019", + "projectYear": "2020", "teamNumber": 3695 } \ No newline at end of file diff --git a/KiwiLight - Rio Code/build.gradle b/KiwiLight - Rio Code/KiwiLightSampleCode/build.gradle similarity index 77% rename from KiwiLight - Rio Code/build.gradle rename to KiwiLight - Rio Code/KiwiLightSampleCode/build.gradle index 615b79f..becc3d0 100644 --- a/KiwiLight - Rio Code/build.gradle +++ b/KiwiLight - Rio Code/KiwiLightSampleCode/build.gradle @@ -1,6 +1,6 @@ plugins { id "java" - id "edu.wpi.first.GradleRIO" version "2019.2.1" + id "edu.wpi.first.GradleRIO" version "2020.2.2" } sourceCompatibility = JavaVersion.VERSION_11 @@ -40,25 +40,29 @@ deploy { // Set this to true to enable desktop support. def includeDesktopSupport = false -// Maven central needed for JUnit -repositories { - mavenCentral() -} - // Defining my dependencies. In this case, WPILib (+ friends), and vendor libraries. // Also defines JUnit 4. dependencies { - compile wpi.deps.wpilib() - compile wpi.deps.vendor.java() + implementation wpi.deps.wpilib() + nativeZip wpi.deps.wpilibJni(wpi.platforms.roborio) + nativeDesktopZip wpi.deps.wpilibJni(wpi.platforms.desktop) + + + implementation wpi.deps.vendor.java() nativeZip wpi.deps.vendor.jni(wpi.platforms.roborio) nativeDesktopZip wpi.deps.vendor.jni(wpi.platforms.desktop) - testCompile 'junit:junit:4.12' + + testImplementation 'junit:junit:4.12' + + // Enable simulation gui support. Must check the box in vscode to enable support + // upon debugging + simulation wpi.deps.sim.gui(wpi.platforms.desktop, false) } // Setting up my Jar File. In this case, adding all libraries into the main jar ('fat jar') // in order to make them all available at runtime. Also adding the manifest so WPILib // knows where to look for our Robot Class. jar { - from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } } + from { configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } } manifest edu.wpi.first.gradlerio.GradleRIOPlugin.javaManifest(ROBOT_MAIN_CLASS) } diff --git a/KiwiLight - Rio Code/KiwiLightSampleCode/gradle/wrapper/gradle-wrapper.jar b/KiwiLight - Rio Code/KiwiLightSampleCode/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..cc4fdc2 Binary files /dev/null and b/KiwiLight - Rio Code/KiwiLightSampleCode/gradle/wrapper/gradle-wrapper.jar differ diff --git a/KiwiLight - Rio Code/gradle/wrapper/gradle-wrapper.properties b/KiwiLight - Rio Code/KiwiLightSampleCode/gradle/wrapper/gradle-wrapper.properties similarity index 92% rename from KiwiLight - Rio Code/gradle/wrapper/gradle-wrapper.properties rename to KiwiLight - Rio Code/KiwiLightSampleCode/gradle/wrapper/gradle-wrapper.properties index d08253c..d050f17 100644 --- a/KiwiLight - Rio Code/gradle/wrapper/gradle-wrapper.properties +++ b/KiwiLight - Rio Code/KiwiLightSampleCode/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=permwrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.0-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.0.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=permwrapper/dists diff --git a/KiwiLight - Rio Code/gradlew b/KiwiLight - Rio Code/KiwiLightSampleCode/gradlew similarity index 75% rename from KiwiLight - Rio Code/gradlew rename to KiwiLight - Rio Code/KiwiLightSampleCode/gradlew index af6708f..2fe81a7 100644 --- a/KiwiLight - Rio Code/gradlew +++ b/KiwiLight - Rio Code/KiwiLightSampleCode/gradlew @@ -1,5 +1,21 @@ #!/usr/bin/env sh +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + ############################################################################## ## ## Gradle start up script for UN*X @@ -28,7 +44,7 @@ APP_NAME="Gradle" APP_BASE_NAME=`basename "$0"` # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m"' +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" @@ -109,8 +125,8 @@ if $darwin; then GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" fi -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` JAVACMD=`cygpath --unix "$JAVACMD"` @@ -138,19 +154,19 @@ if $cygwin ; then else eval `echo args$i`="\"$arg\"" fi - i=$((i+1)) + i=`expr $i + 1` done case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; esac fi @@ -159,14 +175,9 @@ save () { for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done echo " " } -APP_ARGS=$(save "$@") +APP_ARGS=`save "$@"` # Collect all arguments for the java command, following the shell quoting and substitution rules eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" -# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong -if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then - cd "$(dirname "$0")" -fi - exec "$JAVACMD" "$@" diff --git a/KiwiLight - Rio Code/gradlew.bat b/KiwiLight - Rio Code/KiwiLightSampleCode/gradlew.bat similarity index 75% rename from KiwiLight - Rio Code/gradlew.bat rename to KiwiLight - Rio Code/KiwiLightSampleCode/gradlew.bat index 6d57edc..9618d8d 100644 --- a/KiwiLight - Rio Code/gradlew.bat +++ b/KiwiLight - Rio Code/KiwiLightSampleCode/gradlew.bat @@ -1,3 +1,19 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + @if "%DEBUG%" == "" @echo off @rem ########################################################################## @rem @@ -14,7 +30,7 @@ set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome diff --git a/KiwiLight - Rio Code/settings.gradle b/KiwiLight - Rio Code/KiwiLightSampleCode/settings.gradle similarity index 70% rename from KiwiLight - Rio Code/settings.gradle rename to KiwiLight - Rio Code/KiwiLightSampleCode/settings.gradle index b0f4d48..81f96ab 100644 --- a/KiwiLight - Rio Code/settings.gradle +++ b/KiwiLight - Rio Code/KiwiLightSampleCode/settings.gradle @@ -4,17 +4,19 @@ pluginManagement { repositories { mavenLocal() gradlePluginPortal() - String frcYear = '2019' + String frcYear = '2020' File frcHome if (OperatingSystem.current().isWindows()) { String publicFolder = System.getenv('PUBLIC') if (publicFolder == null) { publicFolder = "C:\\Users\\Public" } - frcHome = new File(publicFolder, "frc${frcYear}") + def homeRoot = new File(publicFolder, "wpilib") + frcHome = new File(homeRoot, frcYear) } else { def userFolder = System.getProperty("user.home") - frcHome = new File(userFolder, "frc${frcYear}") + def homeRoot = new File(userFolder, "wpilib") + frcHome = new File(homeRoot, frcYear) } def frcHomeMaven = new File(frcHome, 'maven') maven { diff --git a/KiwiLight - Rio Code/src/main/deploy/example.txt b/KiwiLight - Rio Code/KiwiLightSampleCode/src/main/deploy/example.txt similarity index 100% rename from KiwiLight - Rio Code/src/main/deploy/example.txt rename to KiwiLight - Rio Code/KiwiLightSampleCode/src/main/deploy/example.txt diff --git a/KiwiLight - Rio Code/KiwiLightSampleCode/src/main/java/frc/robot/Constants.java b/KiwiLight - Rio Code/KiwiLightSampleCode/src/main/java/frc/robot/Constants.java new file mode 100644 index 0000000..8c8c42a --- /dev/null +++ b/KiwiLight - Rio Code/KiwiLightSampleCode/src/main/java/frc/robot/Constants.java @@ -0,0 +1,42 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) 2018-2019 FIRST. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in the root directory of */ +/* the project. */ +/*----------------------------------------------------------------------------*/ + +package frc.robot; + +/** + * The Constants class provides a convenient place for teams to hold robot-wide numerical or boolean + * constants. This class should not be used for any other purpose. All constants should be + * declared globally (i.e. public static). Do not put anything functional in this class. + * + *

It is advised to statically import this class (or one of its inner classes) wherever the + * constants are needed, to reduce verbosity. + */ +public final class Constants { + /** + * Motor IDs + */ + public static final int + DRIVE_RIGHT_MASTER_ID = 1, + DRIVE_RIGHT_SLAVE_ID = 2, + DRIVE_LEFT_MASTER_ID = 3, + DRIVE_LEFT_SLAVE_ID = 4; + + /** + * KiwiLight port + */ + public static final int + KIWILIGHT_PORT = 3695; + + /** + * Motor inverts + */ + public static final boolean + DRIVE_RIGHT_MASTER_INVERT = false, + DRIVE_RIGHT_SLAVE_INVERT = false, + DRIVE_LEFT_MASTER_INVERT = true, + DRIVE_LEFT_SLAVE_INVERT = true; +} diff --git a/KiwiLight - Rio Code/KiwiLightSampleCode/src/main/java/frc/robot/Main.java b/KiwiLight - Rio Code/KiwiLightSampleCode/src/main/java/frc/robot/Main.java new file mode 100644 index 0000000..4d2951a --- /dev/null +++ b/KiwiLight - Rio Code/KiwiLightSampleCode/src/main/java/frc/robot/Main.java @@ -0,0 +1,29 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) 2018-2019 FIRST. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in the root directory of */ +/* the project. */ +/*----------------------------------------------------------------------------*/ + +package frc.robot; + +import edu.wpi.first.wpilibj.RobotBase; + +/** + * Do NOT add any static variables to this class, or any initialization at all. Unless you know what + * you are doing, do not modify this file except to change the parameter class to the startRobot + * call. + */ +public final class Main { + private Main() { + } + + /** + * Main initialization function. Do not perform any initialization here. + * + *

If you change your main robot class, change the parameter type. + */ + public static void main(String... args) { + RobotBase.startRobot(Robot::new); + } +} diff --git a/KiwiLight - Rio Code/KiwiLightSampleCode/src/main/java/frc/robot/Robot.java b/KiwiLight - Rio Code/KiwiLightSampleCode/src/main/java/frc/robot/Robot.java new file mode 100644 index 0000000..91bec9a --- /dev/null +++ b/KiwiLight - Rio Code/KiwiLightSampleCode/src/main/java/frc/robot/Robot.java @@ -0,0 +1,96 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) 2017-2019 FIRST. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in the root directory of */ +/* the project. */ +/*----------------------------------------------------------------------------*/ + +package frc.robot; + +import edu.wpi.first.wpilibj.DriverStation; +import edu.wpi.first.wpilibj.TimedRobot; +import edu.wpi.first.wpilibj2.command.Command; +import edu.wpi.first.wpilibj2.command.CommandScheduler; + +/** + * The VM is configured to automatically run this class, and to call the functions corresponding to + * each mode, as described in the TimedRobot documentation. If you change the name of this class or + * the package after creating this project, you must also update the build.gradle file in the + * project. + */ +public class Robot extends TimedRobot { + private RobotContainer robotContainer; + + /** + * This function is run when the robot is first started up and should be used for any + * initialization code. + */ + @Override + public void robotInit() { + // Instantiate our RobotContainer. This will perform all our button bindings, and put our + // autonomous chooser on the dashboard. + robotContainer = new RobotContainer(); + } + + /** + * This function is called every robot packet, no matter the mode. Use this for items like + * diagnostics that you want ran during disabled, autonomous, teleoperated and test. + * + *

This runs after the mode specific periodic functions, but before + * LiveWindow and SmartDashboard integrated updating. + */ + @Override + public void robotPeriodic() { + CommandScheduler.getInstance().run(); + } + + /** + * This function is called once each time the robot enters Disabled mode. + */ + @Override + public void disabledInit() { + } + + @Override + public void disabledPeriodic() { + } + + /** + * This autonomous runs the autonomous command selected by your {@link RobotContainer} class. + */ + @Override + public void autonomousInit() { + DriverStation.reportError("No Auto to run here!", false); + } + + /** + * This function is called periodically during autonomous. + */ + @Override + public void autonomousPeriodic() { + } + + @Override + public void teleopInit() { + } + + /** + * This function is called periodically during operator control. + */ + @Override + public void teleopPeriodic() { + } + + @Override + public void testInit() { + // Cancels all running commands at the start of test mode. + CommandScheduler.getInstance().cancelAll(); + } + + /** + * This function is called periodically during test mode. + */ + @Override + public void testPeriodic() { + } +} diff --git a/KiwiLight - Rio Code/KiwiLightSampleCode/src/main/java/frc/robot/RobotContainer.java b/KiwiLight - Rio Code/KiwiLightSampleCode/src/main/java/frc/robot/RobotContainer.java new file mode 100644 index 0000000..88f0c79 --- /dev/null +++ b/KiwiLight - Rio Code/KiwiLightSampleCode/src/main/java/frc/robot/RobotContainer.java @@ -0,0 +1,66 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) 2018-2019 FIRST. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in the root directory of */ +/* the project. */ +/*----------------------------------------------------------------------------*/ + +package frc.robot; + +import edu.wpi.first.wpilibj.GenericHID; +import edu.wpi.first.wpilibj.Joystick; +import edu.wpi.first.wpilibj.XboxController; +import edu.wpi.first.wpilibj2.command.Command; +import edu.wpi.first.wpilibj2.command.RunCommand; +import edu.wpi.first.wpilibj2.command.button.JoystickButton; +import frc.robot.commands.CyborgCommandAlign; +import frc.robot.subsystems.SubsystemDrive; +import frc.robot.subsystems.SubsystemReceiver; +import frc.robot.util.Xbox; + +/** + * This class is where the bulk of the robot should be declared. Since Command-based is a + * "declarative" paradigm, very little robot logic should actually be handled in the {@link Robot} + * periodic methods (other than the scheduler calls). Instead, the structure of the robot + * (including subsystems, commands, and button mappings) should be declared here. + */ +public class RobotContainer { + private final SubsystemDrive SUB_DRIVE = new SubsystemDrive(); + private final SubsystemReceiver SUB_KIWILIGHT = new SubsystemReceiver(Constants.KIWILIGHT_PORT); + + private final Joystick DRIVER = new Joystick(0); + + /** + * The container for the robot. Contains subsystems, OI devices, and commands. + */ + public RobotContainer() { + // Configure the button bindings + configureButtonBindings(); + } + + /** + * Use this method to define your button->command mappings. Buttons can be created by + * instantiating a {@link GenericHID} or one of its subclasses ({@link + * edu.wpi.first.wpilibj.Joystick} or {@link XboxController}), and then passing it to a + * {@link edu.wpi.first.wpilibj2.command.button.JoystickButton}. + */ + private void configureButtonBindings() { + SUB_DRIVE.setDefaultCommand( + new RunCommand(() -> SUB_DRIVE.DriveTankByController(DRIVER), SUB_DRIVE) + ); + + JoystickButton toggleAlign = new JoystickButton(DRIVER, Xbox.A); + toggleAlign.toggleWhenPressed(new CyborgCommandAlign(SUB_DRIVE, SUB_KIWILIGHT)); + } + + + /** + * Use this to pass the autonomous command to the main {@link Robot} class. + * + * @return the command to run in autonomous + */ + public Command getAutonomousCommand() { + // An ExampleCommand will run in autonomous + return null; + } +} diff --git a/KiwiLight - Rio Code/KiwiLightSampleCode/src/main/java/frc/robot/commands/CyborgCommandAlign.java b/KiwiLight - Rio Code/KiwiLightSampleCode/src/main/java/frc/robot/commands/CyborgCommandAlign.java new file mode 100644 index 0000000..52a2233 --- /dev/null +++ b/KiwiLight - Rio Code/KiwiLightSampleCode/src/main/java/frc/robot/commands/CyborgCommandAlign.java @@ -0,0 +1,61 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) 2019 FIRST. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in the root directory of */ +/* the project. */ +/*----------------------------------------------------------------------------*/ + +package frc.robot.commands; + +import edu.wpi.first.wpilibj.controller.PIDController; +import edu.wpi.first.wpilibj2.command.CommandBase; +import frc.robot.subsystems.SubsystemDrive; +import frc.robot.subsystems.SubsystemReceiver; +import frc.robot.util.Util; + +public class CyborgCommandAlign extends CommandBase { + private SubsystemDrive drivetrain; + private SubsystemReceiver kiwilight; + private PIDController pidcontroller; + + /** + * Creates a new CyborgCommandAlign. + */ + public CyborgCommandAlign(SubsystemDrive drivetrain, SubsystemReceiver kiwilight) { + this.drivetrain = drivetrain; + this.kiwilight = kiwilight; + addRequirements(drivetrain); + } + + // Called when the command is initially scheduled. + @Override + public void initialize() { + double kP = Util.getAndSetDouble("Align kP", 0); + double kI = Util.getAndSetDouble("Align kI", 0); + double kD = Util.getAndSetDouble("Align kD", 0); + + pidcontroller = new PIDController(kP, kI, kD); + } + + // Called every time the scheduler runs while the command is scheduled. + @Override + public void execute() { + double horizontalAngle = kiwilight.getHorizontalAngleToTarget(); + if(horizontalAngle < 180) { + double output = pidcontroller.calculate(horizontalAngle); + drivetrain.driveDirect(output, output * -1); + } + } + + // Called once the command ends or is interrupted. + @Override + public void end(boolean interrupted) { + drivetrain.driveDirect(0, 0); + } + + // Returns true when the command should end. + @Override + public boolean isFinished() { + return false; + } +} diff --git a/KiwiLight - Rio Code/KiwiLightSampleCode/src/main/java/frc/robot/subsystems/SubsystemDrive.java b/KiwiLight - Rio Code/KiwiLightSampleCode/src/main/java/frc/robot/subsystems/SubsystemDrive.java new file mode 100644 index 0000000..3e36f9b --- /dev/null +++ b/KiwiLight - Rio Code/KiwiLightSampleCode/src/main/java/frc/robot/subsystems/SubsystemDrive.java @@ -0,0 +1,91 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) 2019 FIRST. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in the root directory of */ +/* the project. */ +/*----------------------------------------------------------------------------*/ + +package frc.robot.subsystems; + +import com.revrobotics.CANSparkMax; +import com.revrobotics.CANSparkMax.IdleMode; +import com.revrobotics.CANSparkMaxLowLevel.MotorType; + +import edu.wpi.first.wpilibj.Joystick; +import edu.wpi.first.wpilibj2.command.SubsystemBase; +import frc.robot.Constants; +import frc.robot.util.Util; +import frc.robot.util.Xbox; + +public class SubsystemDrive extends SubsystemBase { + private CANSparkMax + rightMaster, + rightSlave, + leftMaster, + leftSlave; + + /** + * Creates a new SubsystemDrive. + */ + public SubsystemDrive() { + rightMaster = new CANSparkMax(Constants.DRIVE_RIGHT_MASTER_ID, MotorType.kBrushless); + rightSlave = new CANSparkMax(Constants.DRIVE_RIGHT_SLAVE_ID, MotorType.kBrushless); + leftMaster = new CANSparkMax(Constants.DRIVE_LEFT_MASTER_ID, MotorType.kBrushless); + leftSlave = new CANSparkMax(Constants.DRIVE_LEFT_SLAVE_ID, MotorType.kBrushless); + + setInverts(); + setBraking(); + } + + @Override + public void periodic() { + // This method will be called once per scheduler run + } + + /** + * Drives the drivetrain motors using the passed controller + * @param controller The controller to drive with + */ + public void DriveTankByController(Joystick controller) { + setInverts(); + + double throttle = Xbox.RT(controller) - Xbox.LT(controller); + double steering = Xbox.LEFT_X(controller); + + double driveRight = throttle + steering; + double driveLeft = throttle - steering; + + driveRight = (driveRight < -1 ? -1 : (driveRight > 1 ? 1 : driveRight)); + driveLeft = (driveLeft < -1 ? -1 : (driveLeft > 1 ? 1 : driveLeft)); + + double inhibitor = Util.getAndSetDouble("Drive Inhibitor", 1); + driveRight *= inhibitor; + driveLeft *= inhibitor; + + leftMaster.set(driveLeft); + leftSlave.set(driveLeft); + rightMaster.set(driveRight); + rightSlave.set(driveRight); + } + + public void driveDirect(double left, double right) { + rightMaster.set(right); + rightSlave.set(right); + leftMaster.set(left); + leftSlave.set(left); + } + + private void setInverts() { + rightMaster.setInverted(Constants.DRIVE_RIGHT_MASTER_INVERT); + rightSlave.setInverted(Constants.DRIVE_RIGHT_SLAVE_INVERT); + leftMaster.setInverted(Constants.DRIVE_LEFT_MASTER_INVERT); + leftSlave.setInverted(Constants.DRIVE_LEFT_SLAVE_INVERT); + } + + private void setBraking() { + rightMaster.setIdleMode(IdleMode.kBrake); + rightSlave.setIdleMode(IdleMode.kBrake); + leftMaster.setIdleMode(IdleMode.kBrake); + leftSlave.setIdleMode(IdleMode.kBrake); + } +} diff --git a/KiwiLight - Rio Code/KiwiLightSampleCode/src/main/java/frc/robot/subsystems/SubsystemReceiver.java b/KiwiLight - Rio Code/KiwiLightSampleCode/src/main/java/frc/robot/subsystems/SubsystemReceiver.java new file mode 100644 index 0000000..c592e70 --- /dev/null +++ b/KiwiLight - Rio Code/KiwiLightSampleCode/src/main/java/frc/robot/subsystems/SubsystemReceiver.java @@ -0,0 +1,210 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) 2019 FIRST. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in the root directory of */ +/* the project. */ +/*----------------------------------------------------------------------------*/ + +package frc.robot.subsystems; + +import java.io.IOException; +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import java.net.SocketException; + +import edu.wpi.first.wpilibj.DriverStation; +import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard; +import frc.robot.util.Util; + +import edu.wpi.first.wpilibj2.command.SubsystemBase; + +/** + * The thing that listens to the Pi. + */ +public class SubsystemReceiver extends SubsystemBase { + private String latestSegment; + private double[] latestData; + + private Boolean inRange; + + private DatagramSocket serverSocket; + private byte[] receiveData; + + private long latestTime; + + + /** + * Creates a new SubsystemReceiver. + */ + public SubsystemReceiver(int port) { + latestSegment = "-1,-1,-1,-1,-1,180,180"; + latestData = new double[] {-1, -1, -1, -1, -1, 180, 180}; + latestTime = System.currentTimeMillis(); + + SmartDashboard.putString("RPi Data", latestSegment); + SmartDashboard.putBoolean("Spotted", false); + SmartDashboard.putBoolean("Updated", false); + inRange = false; + + try { + serverSocket = new DatagramSocket(port); + receiveData = new byte[1024]; + } catch (SocketException e) { //thrown when a socket cannot be created + DriverStation.reportError("SOCKET EXCEPTION", true); + } + + // EXPECTED FORMAT OF INPUT STRING: + // :X,Y,W,H,D,HA,VA; + // X = X-coordinate + // Y = Y-coordinate + // W = Width of target in image space. + // H = Height of target in image space + // D = Distance from target + // HA = Horizontal Angle from center (positive = CW) + // VA = Vertical Angle from center (positive = up) + + Thread listener = new Thread(() -> { + while(!Thread.interrupted()) { + try { + DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length); //create a new packet for the receiving data + serverSocket.receive(receivePacket); //receive the packet from the Socket + String segment = new String(receivePacket.getData()).replaceAll("\\s+",""); //remove whitespace and place data in 'segment' + latestSegment = segment.substring(segment.indexOf(":") + 1, segment.indexOf(";")); // store segment without borders + latestTime = System.currentTimeMillis(); // add timestamp for stored segment + String formattedString = segment.substring(segment.indexOf(":") + 1, segment.indexOf(";")); + SmartDashboard.putString("RPi Data", formattedString); // put string on dashboard without borders + latestData = analyzeData(formattedString); + + } catch (IOException e) { //thrown when the socket cannot receive the packet + DriverStation.reportError("IO EXCEPTION", true); + } + } + }); + + listener.start(); + } + + @Override + public void periodic() { + SmartDashboard.putBoolean("Spotted", targetSpotted()); + SmartDashboard.putBoolean("Updated", getSecondsSinceUpdate() < 0.5); + } + + /** + * Prints dashboard indicators indicating whether the subsystem is ready for a match. + * Indicators are to be used for pre-match only. They do not provide an accurite indication + * of the state of a subsystem in mid match. + * @return true if the system is ready for a match, false otherwise. + */ + public boolean getSystemIsGo() { + return getSecondsSinceUpdate() < 0.5; + } + + /** + * Retrieves the last known pixel coordinates of the target + * @return [0] = X-coordinate (in pixels from left) + * [1] = Y-coordinate (in pixels from bottom) + * [2] = Distance (in inches) + * [3] = Angle from center (in degrees; positive = CW) + * {-1,-1,-1,-1} for no known location + */ + public double[] getLatestData() { + return latestData; + } + + /** + * Returns the width of the seen target in pixels, or -1 if no target is seen. + */ + public double getTargetWidthPixels() { + return latestData[2]; + } + + /** + * Returns the height of the seen target in pixels, or -1 if no target is seen. + */ + public double getTargetHeightPixels() { + return latestData[3]; + } + + /** + * Returns the distance of the camera to the target, or -1 if no target is seen. + */ + public double getDistanceToTarget() { + return latestData[4]; + } + + /** + * Returns the horizontal angle (degrees) to the target, or 180 if no target is seen. + */ + public double getHorizontalAngleToTarget() { + return latestData[5]; + } + + /** + * Returns the vertical angle (degrees) to the target, or 180 if no target is seen. + */ + public double getVerticalAngleToTarget() { + return latestData[6]; + } + + /** + * Returns true if a target is seen, false otherwise. + */ + public boolean targetSpotted() { + return latestData[2] > -1; + } + + /** + * Returns the miliseconds since the pi sent the LastKnownLocation + * @return ms since last received UDP packet + */ + public double getSecondsSinceUpdate() { + return Util.roundTo((double) ((System.currentTimeMillis() - latestTime) / 1000), 5); + } + + /** + * If data is being received, records whether or not its in "target lock" range + * If dats is not being received, the last known state is kept + */ + public void updateTargetLock(double[] data) { + if (data[2] != -1) { + inRange = data[2] < 0; + } + } + + /** + * Gets the state of target lock + * @return true if within range, false if out of range + */ + public Boolean getWithinRange() { + return inRange; + } + + /** + * Retrieves the last known pixel coordinates of the target + * @return [0] = X-coordinate (in pixels from left) + * [1] = Y-coordinate (in pixels from bottom) + * [2] = Distance (in inches) + * [3] = Angle from center (in degrees; positive = CW) + * {-1,-1,-1,-1} for no known location + */ + private double[] analyzeData(String input) { + double[] newData = {-1, -1, -1, -1, -1, 180, 180}; + String[] stringData = input.split(","); + + if(stringData.length != newData.length) { + DriverStation.reportWarning("INPUT STRING IMPROPERLY FORMATTED!", true); + return newData; + } + + try { + for(int i=0; iIf you change your main robot class, change the parameter type. - */ - public static void main(String... args) { - RobotBase.startRobot(Robot::new); - } -} diff --git a/KiwiLight - Rio Code/src/main/java/frc/robot/OI.java b/KiwiLight - Rio Code/src/main/java/frc/robot/OI.java deleted file mode 100644 index 1bdbd5f..0000000 --- a/KiwiLight - Rio Code/src/main/java/frc/robot/OI.java +++ /dev/null @@ -1,50 +0,0 @@ -/*----------------------------------------------------------------------------*/ -/* Copyright (c) 2018 FIRST. All Rights Reserved. */ -/* Open Source Software - may be modified and shared by FRC teams. The code */ -/* must be accompanied by the FIRST BSD license file in the root directory of */ -/* the project. */ -/*----------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------*/ -/* .d8888b. .d8888b. .d8888b. 888888888 */ -/* d88P Y88b d88P Y88b d88P Y88b 888 */ -/* .d88P 888 888 888 888 */ -/* 8888" 888d888b. Y88b. d888 8888888b. */ -/* "Y8b. 888P "Y88b "Y888P888 "Y88b */ -/* 888 888 888 888 888 888 */ -/* Y88b d88P Y88b d88P Y88b d88P Y88b d88P */ -/* "Y8888P" "Y8888P" "Y8888P" "Y8888P" */ -/* */ -/* This code was written by FRC3695 - Foximus Prime and stored */ -/* at github.com/wh1ter0se/KiwiLight. KiwiLight is published */ -/* under a GPL-3.0 license, permitting modification and */ -/* distribution under the condition that the source is */ -/* disclosed and distribution is accompanied by the same license */ -/*---------------------------------------------------------------*/ -package frc.robot; - -import edu.wpi.first.wpilibj.Joystick; -import edu.wpi.first.wpilibj.GenericHID.RumbleType; -import edu.wpi.first.wpilibj.buttons.Button; -import edu.wpi.first.wpilibj.buttons.JoystickButton; -import frc.robot.Util.Xbox; - -/** - * Config for the operator interface (control scheme) - */ -public class OI { - public static final Joystick DRIVER = new Joystick(0); - public static final Joystick OPERATOR = new Joystick(1); - - Button align = new JoystickButton(DRIVER, Xbox.RSTICK); - - public void setDriverRumble(double rumble) { - DRIVER.setRumble(RumbleType.kLeftRumble, rumble); - DRIVER.setRumble(RumbleType.kRightRumble, rumble); - } - - public void setOperatorRumble(double rumble) { - OPERATOR.setRumble(RumbleType.kLeftRumble, rumble); - OPERATOR.setRumble(RumbleType.kRightRumble, rumble); - } -} diff --git a/KiwiLight - Rio Code/src/main/java/frc/robot/Robot.java b/KiwiLight - Rio Code/src/main/java/frc/robot/Robot.java deleted file mode 100644 index 366b4b7..0000000 --- a/KiwiLight - Rio Code/src/main/java/frc/robot/Robot.java +++ /dev/null @@ -1,104 +0,0 @@ -/*----------------------------------------------------------------------------*/ -/* Copyright (c) 2017-2018 FIRST. All Rights Reserved. */ -/* Open Source Software - may be modified and shared by FRC teams. The code */ -/* must be accompanied by the FIRST BSD license file in the root directory of */ -/* the project. */ -/*----------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------*/ -/* .d8888b. .d8888b. .d8888b. 888888888 */ -/* d88P Y88b d88P Y88b d88P Y88b 888 */ -/* .d88P 888 888 888 888 */ -/* 8888" 888d888b. Y88b. d888 8888888b. */ -/* "Y8b. 888P "Y88b "Y888P888 "Y88b */ -/* 888 888 888 888 888 888 */ -/* Y88b d88P Y88b d88P Y88b d88P Y88b d88P */ -/* "Y8888P" "Y8888P" "Y8888P" "Y8888P" */ -/* */ -/* This code was written by FRC3695 - Foximus Prime and stored */ -/* at github.com/wh1ter0se/KiwiLight. KiwiLight is published */ -/* under a GPL-3.0 license, permitting modification and */ -/* distribution under the condition that the source is */ -/* disclosed and distribution is accompanied by the same license */ -/*---------------------------------------------------------------*/ -package frc.robot; - -import edu.wpi.first.wpilibj.TimedRobot; -import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard; -import frc.robot.Subsystems.SubsystemDrive; -import frc.robot.Subsystems.SubsystemReceiver; - -/** - * The VM is configured to automatically run this class, and to call the - * functions corresponding to each mode, as described in the TimedRobot - * documentation. If you change the name of this class or the package after - * creating this project, you must also update the build.gradle file in the - * project. - */ -public class Robot extends TimedRobot { - - public static OI oi; - public static SubsystemDrive SUB_DRIVE; - public static SubsystemReceiver SUB_RECEIVER; - - /** - * This function is run when the robot is first started up and should be - * used for any initialization code. - */ - @Override - public void robotInit() { - oi = new OI(); - SUB_DRIVE = new SubsystemDrive(); - SUB_RECEIVER = new SubsystemReceiver(); - } - - /** - * This function is called every robot packet, no matter the mode. Use - * this for items like diagnostics that you want ran during disabled, - * autonomous, teleoperated and test. - * - *

This runs after the mode specific periodic functions, but before - * LiveWindow and SmartDashboard integrated updating. - */ - @Override - public void robotPeriodic() { - SmartDashboard.putBoolean("Spotted", SUB_RECEIVER.targetSpotted()); - SmartDashboard.putBoolean("Updated", SUB_RECEIVER.getSecondsSinceUpdate() < 1); - } - - /** - * This autonomous (along with the chooser code above) shows how to select - * between different autonomous modes using the dashboard. The sendable - * chooser code works with the Java SmartDashboard. If you prefer the - * LabVIEW Dashboard, remove all of the chooser code and uncomment the - * getString line to get the auto name from the text box below the Gyro - * - *

You can add additional auto modes by adding additional comparisons to - * the switch structure below with additional strings. If using the - * SendableChooser make sure to add them to the chooser code above as well. - */ - @Override - public void autonomousInit() { - } - - /** - * This function is called periodically during autonomous. - */ - @Override - public void autonomousPeriodic() { - } - - /** - * This function is called periodically during operator control. - */ - @Override - public void teleopPeriodic() { - } - - /** - * This function is called periodically during test mode. - */ - @Override - public void testPeriodic() { - } -} diff --git a/KiwiLight - Rio Code/src/main/java/frc/robot/Subsystems/SubsystemDrive.java b/KiwiLight - Rio Code/src/main/java/frc/robot/Subsystems/SubsystemDrive.java deleted file mode 100644 index da0f657..0000000 --- a/KiwiLight - Rio Code/src/main/java/frc/robot/Subsystems/SubsystemDrive.java +++ /dev/null @@ -1,123 +0,0 @@ -/*----------------------------------------------------------------------------*/ -/* Copyright (c) 2018 FIRST. All Rights Reserved. */ -/* Open Source Software - may be modified and shared by FRC teams. The code */ -/* must be accompanied by the FIRST BSD license file in the root directory of */ -/* the project. */ -/*----------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------*/ -/* .d8888b. .d8888b. .d8888b. 888888888 */ -/* d88P Y88b d88P Y88b d88P Y88b 888 */ -/* .d88P 888 888 888 888 */ -/* 8888" 888d888b. Y88b. d888 8888888b. */ -/* "Y8b. 888P "Y88b "Y888P888 "Y88b */ -/* 888 888 888 888 888 888 */ -/* Y88b d88P Y88b d88P Y88b d88P Y88b d88P */ -/* "Y8888P" "Y8888P" "Y8888P" "Y8888P" */ -/* */ -/* This code was written by FRC3695 - Foximus Prime and stored */ -/* at github.com/wh1ter0se/KiwiLight. KiwiLight is published */ -/* under a GPL-3.0 license, permitting modification and */ -/* distribution under the condition that the source is */ -/* disclosed and distribution is accompanied by the same license */ -/*---------------------------------------------------------------*/ -package frc.robot.Subsystems; - -import com.revrobotics.CANSparkMax; -import com.revrobotics.CANSparkMax.IdleMode; -import com.revrobotics.CANSparkMaxLowLevel.MotorType; - -import edu.wpi.first.wpilibj.Joystick; -import edu.wpi.first.wpilibj.command.Subsystem; -import frc.robot.Constants; -import frc.robot.Commands.ManualCommandDrive; -import frc.robot.Util.Xbox; - -/** - * The vroom-vroom control room - */ -public class SubsystemDrive extends Subsystem { - - private static CANSparkMax leftMaster; - private static CANSparkMax leftSlave; - private static CANSparkMax rightMaster; - private static CANSparkMax rightSlave; // this code will work with any other motor controller as well - - @Override - public void initDefaultCommand() { - setDefaultCommand(new ManualCommandDrive()); - } - - public SubsystemDrive() { - leftMaster = new CANSparkMax(Constants.LEFT_MASTER_ID, MotorType.kBrushless); - leftSlave = new CANSparkMax(Constants.LEFT_SLAVE_ID, MotorType.kBrushless); - rightMaster = new CANSparkMax(Constants.RIGHT_MASTER_ID, MotorType.kBrushless); - rightSlave = new CANSparkMax(Constants.RIGHT_SLAVE_ID, MotorType.kBrushless); - - setInverts(); - setBraking(true); - } - - /** - * Sets the inverts of each motor controller - */ - private void setInverts() { - leftMaster.setInverted(Constants.LEFT_DRIVE_INVERT); - leftSlave.setInverted(Constants.LEFT_DRIVE_INVERT); - rightMaster.setInverted(Constants.RIGHT_DRIVE_INVERT); - rightSlave.setInverted(Constants.RIGHT_DRIVE_INVERT); - } - - /** - * Sets each motor to braking or coasting mode - * @param braking true if braking mode, false if coasting mode - */ - public void setBraking(Boolean braking) { - leftMaster.setIdleMode(braking ? IdleMode.kBrake : IdleMode.kCoast); - leftSlave.setIdleMode(braking ? IdleMode.kBrake : IdleMode.kCoast); - rightMaster.setIdleMode(braking ? IdleMode.kBrake : IdleMode.kCoast); - rightSlave.setIdleMode(braking ? IdleMode.kBrake : IdleMode.kCoast); - } - - /** - * Rocket League-style control for a tank drive bot - * Left and right triggers accelerate linearly and left stick rotates - * @param joy the joystick to be used - * @param ramp the ramprate to apply to the motors - * @param inhibitor a scalar applied to the final motor output to limit speed - */ - public void driveRocketLeague(Joystick joy, double ramp, double inhibitor, double turnInhibitor) { - double adder = Xbox.RT(joy) - Xbox.LT(joy); - double left = adder + (Xbox.LEFT_X(joy) * turnInhibitor); - double right = adder - (Xbox.LEFT_X(joy) * turnInhibitor); - - left = (left > 1.0 ? 1.0 : (left < -1.0 ? -1.0 : left)); - right = (right > 1.0 ? 1.0 : (right < -1.0 ? -1.0 : right)); - - left *= inhibitor; - right *= inhibitor; - - leftMaster.set(left); - leftSlave.follow(leftMaster); - rightMaster.set(right); - rightSlave.follow(rightMaster); - } - - public void driveDirect(double leftOutput, double rightOutput) { - leftMaster.set(leftOutput); - leftSlave.follow(leftMaster); - rightMaster.set(rightOutput); - rightSlave.follow(rightMaster); - } - - /** - * Sets all motor controller values to zero - */ - public void stopMotors() { - leftMaster.set(0); - leftSlave.follow(leftMaster); - rightMaster.set(0); - rightSlave.follow(rightMaster); - } - -} diff --git a/KiwiLight - Rio Code/src/main/java/frc/robot/Subsystems/SubsystemReceiver.java b/KiwiLight - Rio Code/src/main/java/frc/robot/Subsystems/SubsystemReceiver.java deleted file mode 100644 index 048e9af..0000000 --- a/KiwiLight - Rio Code/src/main/java/frc/robot/Subsystems/SubsystemReceiver.java +++ /dev/null @@ -1,143 +0,0 @@ -/*----------------------------------------------------------------------------*/ -/* Copyright (c) 2018 FIRST. All Rights Reserved. */ -/* Open Source Software - may be modified and shared by FRC teams. The code */ -/* must be accompanied by the FIRST BSD license file in the root directory of */ -/* the project. */ -/*----------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------*/ -/* .d8888b. .d8888b. .d8888b. 888888888 */ -/* d88P Y88b d88P Y88b d88P Y88b 888 */ -/* .d88P 888 888 888 888 */ -/* 8888" 888d888b. Y88b. d888 8888888b. */ -/* "Y8b. 888P "Y88b "Y888P888 "Y88b */ -/* 888 888 888 888 888 888 */ -/* Y88b d88P Y88b d88P Y88b d88P Y88b d88P */ -/* "Y8888P" "Y8888P" "Y8888P" "Y8888P" */ -/* */ -/* This code was written by FRC3695 - Foximus Prime and stored */ -/* at github.com/wh1ter0se/KiwiLight. KiwiLight is published */ -/* under a GPL-3.0 license, permitting modification and */ -/* distribution under the condition that the source is */ -/* disclosed and distribution is accompanied by the same license */ -/*---------------------------------------------------------------*/ -package frc.robot.Subsystems; - -import java.io.IOException; -import java.net.DatagramPacket; -import java.net.DatagramSocket; -import java.util.stream.IntStream; - -import edu.wpi.first.wpilibj.DriverStation; -import edu.wpi.first.wpilibj.command.Subsystem; -import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard; -import frc.robot.Constants; -import frc.robot.Robot; -import frc.robot.Util.Util; - -/** - * The receiver code that runs on the Rio to listen for UDP data - */ -public class SubsystemReceiver extends Subsystem { - - private static String latestSegment; - - private static DatagramSocket serverSocket; - private static byte[] receiveData; - - private static long latestTime; - - @Override - public void initDefaultCommand() { - } - - public SubsystemReceiver() { - latestSegment = "-1,-1,-1,-1"; - latestTime = System.currentTimeMillis(); - - SmartDashboard.putString("RPi Data", latestSegment); - - // EXPECTED FORMAT OF INPUT STRING: - // :X,Y,H,D,A; - // X = X-coordinate - // Y = Y-coordinate - // D = Distance from target - // A = Angle from center (positive = CW) - - Thread listener = new Thread(() -> { - while(!Thread.interrupted()) { - try { - DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length); //create a new packet for the receiving data - serverSocket.receive(receivePacket); //receive the packet from the Socket - String segment = new String(receivePacket.getData()).replaceAll("\\s+",""); //remove whitespace and place data in 'segment' - latestSegment = segment.substring(segment.indexOf(":") + 1, segment.indexOf(";")); // store segment without borders - latestTime = System.currentTimeMillis(); // add timestamp for stored segment - SmartDashboard.putString("RPi Data", segment.substring(segment.indexOf(":") + 1, segment.indexOf(";"))); // put string on dashboard without borders - } catch (IOException e) { //thrown when the socket cannot receive the packet - DriverStation.reportError("IO EXCEPTION", true); - } - } - }); - - listener.start(); - - } - - /** - * Retrieves the last known pixel coordinates of the target - * @return [0] = X-coordinate (in pixels from left) - * [1] = Y-coordinate (in pixels from bottom) - * [2] = Distance (in inches) - * [3] = Angle from center (in degrees; positive = CW) - * {-1,-1,-1, 180} for no known location - */ - public double[] getLastKnownData() { - double[] data = new double[]{-1,-1,-1,-1}; - int[] indices = new int[]{2,5,8}; - try { - indices = IntStream.range(0, latestSegment.length() - 1) - .filter(i -> latestSegment.charAt(i) == ',') - .toArray(); - data[0] = Integer.parseInt(latestSegment.substring(0, latestSegment.indexOf(",", indices[0]))); - data[1] = Integer.parseInt(latestSegment.substring(latestSegment.indexOf(",", indices[0]) + 1, latestSegment.indexOf(",", indices[1]))); - data[2] = Integer.parseInt(latestSegment.substring(latestSegment.indexOf(",", indices[1]) + 1, latestSegment.indexOf(",", indices[2]))); - data[3] = Integer.parseInt(latestSegment.substring(latestSegment.indexOf(",", indices[2]) + 1)); - } catch (NumberFormatException e) { - DriverStation.reportError("NUMBER FORMAT EXCEPTION", true); - DriverStation.reportError("latestSegment = " + latestSegment, false); - } catch (StringIndexOutOfBoundsException e) { - DriverStation.reportError("STRING INDEX OUT OF BOUNDS EXCEPTION", true); - DriverStation.reportError("latestSegment = " + latestSegment, false); - } catch (ArrayIndexOutOfBoundsException e) { - DriverStation.reportError("ARRAY INDEX OUT OF BOUNDS EXCEPTION", true); - DriverStation.reportError("latestSegment = " + latestSegment, false); - } - return data; - } - - /** - * Returns the miliseconds since the pi sent the LastKnownLocation - * @return ms since last received UDP packet - */ - public double getSecondsSinceUpdate() { - return Util.roundTo((double) ((System.currentTimeMillis() - latestTime) / 1000), 2); - } - - /** - * Checks if the JeVois is sending coordinates - * @return true if receiving a distance, false if distance is -1 - */ - public Boolean targetSpotted() { - return Robot.SUB_RECEIVER.getLastKnownData()[2] != -1; - } - - /** - * Checks if the current coordinate is outside of target lock IF within target lock range. - * This prevents the loop from getting confused if it spots another target in its periphery. - * Without this function, KiwiLight is usually unable to do the shuttle without getting confused. - * @return true if within target lock range and target is outside of the locked field of view, false otherwise - */ - public Boolean targetLost() { - return Math.abs(Robot.SUB_RECEIVER.getLastKnownData()[3]) > Constants.TARGET_LOCK_FOV && Robot.SUB_RECEIVER.getLastKnownData()[2] < Constants.TARGET_LOCK_RANGE; - } -} diff --git a/KiwiLight - Rio Code/src/main/java/frc/robot/Util/MiniPID.java b/KiwiLight - Rio Code/src/main/java/frc/robot/Util/MiniPID.java deleted file mode 100644 index 3b3845b..0000000 --- a/KiwiLight - Rio Code/src/main/java/frc/robot/Util/MiniPID.java +++ /dev/null @@ -1,481 +0,0 @@ -/*----------------------------------------------------------------------------*/ -/* Copyright (c) 2018 FIRST. All Rights Reserved. */ -/* Open Source Software - may be modified and shared by FRC teams. The code */ -/* must be accompanied by the FIRST BSD license file in the root directory of */ -/* the project. */ -/*----------------------------------------------------------------------------*/ - -/*-------------------------------------------------*/ -/* Full credit to FRC2811 Stormbots for this class */ -/* github.com/tekdemo/MiniPID-Java */ -/*-------------------------------------------------*/ -package frc.robot.Util; - -/** -* Small, easy to use PID implementation with advanced controller capability.
-* Minimal usage:
-* MiniPID pid = new MiniPID(p,i,d);
-* ...looping code...{
-* output= pid.getOutput(sensorvalue,target);
-* } -* -* @see http://brettbeauregard.com/blog/2011/04/improving-the-beginners-pid-direction/improving-the-beginners-pid-introduction -*/ -public class MiniPID{ - //********************************** - // Class private variables - //********************************** - - private double P=0; - private double I=0; - private double D=0; - private double F=0; - - private double maxIOutput=0; - private double maxError=0; - private double errorSum=0; - - private double maxOutput=0; - private double minOutput=0; - - private double setpoint=0; - - private double lastActual=0; - - private boolean firstRun=true; - private boolean reversed=false; - - private double outputRampRate=0; - private double lastOutput=0; - - private double outputFilter=0; - - private double setpointRange=0; - - //********************************** - // Constructor functions - //********************************** - - /** - * Create a MiniPID class object. - * See setP, setI, setD methods for more detailed parameters. - * @param p Proportional gain. Large if large difference between setpoint and target. - * @param i Integral gain. Becomes large if setpoint cannot reach target quickly. - * @param d Derivative gain. Responds quickly to large changes in error. Small values prevents P and I terms from causing overshoot. - */ - public MiniPID(double p, double i, double d){ - P=p; I=i; D=d; - checkSigns(); - } - - /** - * Create a MiniPID class object. - * See setP, setI, setD, setF methods for more detailed parameters. - * @param p Proportional gain. Large if large difference between setpoint and target. - * @param i Integral gain. Becomes large if setpoint cannot reach target quickly. - * @param d Derivative gain. Responds quickly to large changes in error. Small values prevents P and I terms from causing overshoot. - * @param f Feed-forward gain. Open loop "best guess" for the output should be. Only useful if setpoint represents a rate. - */ - public MiniPID(double p, double i, double d, double f){ - P=p; I=i; D=d; F=f; - checkSigns(); - } - - //********************************** - // Configuration functions - //********************************** - /** - * Configure the Proportional gain parameter.
- * This responds quickly to changes in setpoint, and provides most of the initial driving force - * to make corrections.
- * Some systems can be used with only a P gain, and many can be operated with only PI.
- * For position based controllers, this is the first parameter to tune, with I second.
- * For rate controlled systems, this is often the second after F. - * - * @param p Proportional gain. Affects output according to output+=P*(setpoint-current_value) - */ - public void setP(double p){ - P=p; - checkSigns(); - } - - /** - * Changes the I parameter
- * This is used for overcoming disturbances, and ensuring that the controller always gets to the control mode. - * Typically tuned second for "Position" based modes, and third for "Rate" or continuous based modes.
- * Affects output through output+=previous_errors*Igain ;previous_errors+=current_error - * - * @see {@link #setMaxIOutput(double) setMaxIOutput} for how to restrict - * - * @param i New gain value for the Integral term - */ - public void setI(double i){ - if(I!=0){ - errorSum=errorSum*I/i; - } - if(maxIOutput!=0){ - maxError=maxIOutput/i; - } - I=i; - checkSigns(); - // Implementation note: - // This Scales the accumulated error to avoid output errors. - // As an example doubling the I term cuts the accumulated error in half, which results in the - // output change due to the I term constant during the transition. - } - - /** - * Changes the D parameter
- * This has two primary effects: - * - *

  • Adds a "startup kick" and speeds up system response during setpoint changes - *
  • Adds "drag" and slows the system when moving toward the target - * - * A small D value can be useful for both improving response times, and preventing overshoot. - * However, in many systems a large D value will cause significant instability, particularly - * for large setpoint changes. - *
    - * Affects output through output += -D*(current_input_value - last_input_value) - * - * @param d New gain value for the Derivative term - */ - public void setD(double d){ - D=d; - checkSigns(); - } - - /** - * Configure the FeedForward parameter.
    - * This is excellent for velocity, rate, and other continuous control modes where you can - * expect a rough output value based solely on the setpoint.
    - * Should not be used in "position" based control modes.
    - * Affects output according to output+=F*Setpoint. Note, that a F-only system is actually open loop. - * - * @param f Feed forward gain. - */ - public void setF(double f){ - F=f; - checkSigns(); - } - - /** - * Configure the PID object. - * See setP, setI, setD methods for more detailed parameters. - * @param p Proportional gain. Large if large difference between setpoint and target. - * @param i Integral gain. Becomes large if setpoint cannot reach target quickly. - * @param d Derivative gain. Responds quickly to large changes in error. Small values prevents P and I terms from causing overshoot. - */ - public void setPID(double p, double i, double d){ - P=p;D=d; - //Note: the I term has additional calculations, so we need to use it's - //specific method for setting it. - setI(i); - checkSigns(); - } - - /** - * Configure the PID object. - * See setP, setI, setD, setF methods for more detailed parameters. - * @param p Proportional gain. Large if large difference between setpoint and target. - * @param i Integral gain. Becomes large if setpoint cannot reach target quickly. - * @param d Derivative gain. Responds quickly to large changes in error. Small values prevents P and I terms from causing overshoot. - * @param f Feed-forward gain. Open loop "best guess" for the output should be. Only useful if setpoint represents a rate. - */ - public void setPID(double p, double i, double d,double f){ - P=p;D=d;F=f; - //Note: the I term has additional calculations, so we need to use it's - //specific method for setting it. - setI(i); - checkSigns(); - } - - /** - * Set the maximum output value contributed by the I component of the system - * This can be used to prevent large windup issues and make tuning simpler - * @param maximum. Units are the same as the expected output value - */ - public void setMaxIOutput(double maximum){ - // Internally maxError and Izone are similar, but scaled for different purposes. - // The maxError is generated for simplifying math, since calculations against - // the max error are far more common than changing the I term or Izone. - maxIOutput=maximum; - if(I!=0){ - maxError=maxIOutput/I; - } - } - - /** - * Specify a maximum output range.
    - * When one input is specified, output range is configured to - * [-output, output] - * @param output - */ - public void setOutputLimits(double output){ - setOutputLimits(-output,output); - } - - /** - * Specify a maximum output. - * When two inputs specified, output range is configured to - * [minimum, maximum] - * @param minimum possible output value - * @param maximum possible output value - */ - public void setOutputLimits(double minimum,double maximum){ - if(maximum(maximum-minimum) ){ - setMaxIOutput(maximum-minimum); - } - } - - /** - * Set the operating direction of the PID controller - * @param reversed Set true to reverse PID output - */ - public void setDirection(boolean reversed){ - this.reversed=reversed; - } - - //********************************** - // Primary operating functions - //********************************** - - /** - * Configure setpoint for the PID calculations
    - * This represents the target for the PID system's, such as a - * position, velocity, or angle.
    - * @see MiniPID#getOutput(actual)
    - * @param setpoint - */ - public void setSetpoint(double setpoint){ - this.setpoint=setpoint; - } - - /** - * Calculate the output value for the current PID cycle.
    - * @param actual The monitored value, typically as a sensor input. - * @param setpoint The target value for the system - * @return calculated output value for driving the system - */ - public double getOutput(double actual, double setpoint){ - double output; - double Poutput; - double Ioutput; - double Doutput; - double Foutput; - - this.setpoint=setpoint; - - // Ramp the setpoint used for calculations if user has opted to do so - if(setpointRange!=0){ - setpoint=constrain(setpoint,actual-setpointRange,actual+setpointRange); - } - - // Do the simple parts of the calculations - double error=setpoint-actual; - - // Calculate F output. Notice, this depends only on the setpoint, and not the error. - Foutput=F*setpoint; - - // Calculate P term - Poutput=P*error; - - // If this is our first time running this, we don't actually _have_ a previous input or output. - // For sensor, sanely assume it was exactly where it is now. - // For last output, we can assume it's the current time-independent outputs. - if(firstRun){ - lastActual=actual; - lastOutput=Poutput+Foutput; - firstRun=false; - } - - // Calculate D Term - // Note, this is negative. This actually "slows" the system if it's doing - // the correct thing, and small values helps prevent output spikes and overshoot - Doutput= -D*(actual-lastActual); - lastActual=actual; - - // The Iterm is more complex. There's several things to factor in to make it easier to deal with. - // 1. maxIoutput restricts the amount of output contributed by the Iterm. - // 2. prevent windup by not increasing errorSum if we're already running against our max Ioutput - // 3. prevent windup by not increasing errorSum if output is output=maxOutput - Ioutput=I*errorSum; - if(maxIOutput!=0){ - Ioutput=constrain(Ioutput,-maxIOutput,maxIOutput); - } - - // And, finally, we can just add the terms up - output=Foutput + Poutput + Ioutput + Doutput; - - // Figure out what we're doing with the error. - if(minOutput!=maxOutput && !bounded(output, minOutput,maxOutput) ){ - errorSum=error; - // reset the error sum to a sane level - // Setting to current error ensures a smooth transition when the P term - // decreases enough for the I term to start acting upon the controller - // From that point the I term will build up as would be expected - } - else if(outputRampRate!=0 && !bounded(output, lastOutput-outputRampRate,lastOutput+outputRampRate) ){ - errorSum=error; - } - else if(maxIOutput!=0){ - errorSum=constrain(errorSum+error,-maxError,maxError); - // In addition to output limiting directly, we also want to prevent I term - // buildup, so restrict the error directly - } - else{ - errorSum+=error; - } - - // Restrict output to our specified output and ramp limits - if(outputRampRate!=0){ - output=constrain(output, lastOutput-outputRampRate,lastOutput+outputRampRate); - } - if(minOutput!=maxOutput){ - output=constrain(output, minOutput,maxOutput); - } - if(outputFilter!=0){ - output=lastOutput*outputFilter+output*(1-outputFilter); - } - - // Get a test printline with lots of details about the internal - // calculations. This can be useful for debugging. - // System.out.printf("Final output %5.2f [ %5.2f, %5.2f , %5.2f ], eSum %.2f\n",output,Poutput, Ioutput, Doutput,errorSum ); - // System.out.printf("%5.2f\t%5.2f\t%5.2f\t%5.2f\n",output,Poutput, Ioutput, Doutput ); - - lastOutput=output; - return output; - } - - /** - * Calculate the output value for the current PID cycle.
    - * In no-parameter mode, this uses the last sensor value, - * and last setpoint value.
    - * Not typically useful, and use of parameter modes is suggested.
    - * @return calculated output value for driving the system - */ - public double getOutput(){ - return getOutput(lastActual,setpoint); - } - - /** - * Calculate the output value for the current PID cycle.
    - * In one parameter mode, the last configured setpoint will be used.
    - * @see MiniPID#setSetpoint() - * @param actual The monitored value, typically as a sensor input. - * @param setpoint The target value for the system - * @return calculated output value for driving the system - */ - public double getOutput(double actual){ - return getOutput(actual,setpoint); - } - - /** - * Resets the controller. This erases the I term buildup, and removes - * D gain on the next loop.
    - * This should be used any time the PID is disabled or inactive for extended - * duration, and the controlled portion of the system may have changed due to - * external forces. - */ - public void reset(){ - firstRun=true; - errorSum=0; - } - - /** - * Set the maximum rate the output can increase per cycle.
    - * This can prevent sharp jumps in output when changing setpoints or - * enabling a PID system, which might cause stress on physical or electrical - * systems.
    - * Can be very useful for fast-reacting control loops, such as ones - * with large P or D values and feed-forward systems. - * - * @param rate, with units being the same as the output - */ - public void setOutputRampRate(double rate){ - outputRampRate=rate; - } - - /** - * Set a limit on how far the setpoint can be from the current position - *
    Can simplify tuning by helping tuning over a small range applies to a much larger range. - *
    This limits the reactivity of P term, and restricts impact of large D term - * during large setpoint adjustments. Increases lag and I term if range is too small. - * @param range, with units being the same as the expected sensor range. - */ - public void setSetpointRange(double range){ - setpointRange=range; - } - - /** - * Set a filter on the output to reduce sharp oscillations.
    - * 0.1 is likely a sane starting value. Larger values use historical data - * more heavily, with low values weigh newer data. 0 will disable, filtering, and use - * only the most recent value.
    - * Increasing the filter strength will P and D oscillations, but force larger I - * values and increase I term overshoot.
    - * Uses an exponential wieghted rolling sum filter, according to a simple
    - *
    output*(1-strength)*sum(0..n){output*strength^n}
    algorithm. - * @param output valid between [0..1), meaning [current output only.. historical output only) - */ - public void setOutputFilter(double strength){ - if(strength==0 || bounded(strength,0,1)){ - outputFilter=strength; - } - } - - //************************************** - // Helper functions - //************************************** - - /** - * Forces a value into a specific range - * @param value input value - * @param min maximum returned value - * @param max minimum value in range - * @return Value if it's within provided range, min or max otherwise - */ - private double constrain(double value, double min, double max){ - if(value > max){ return max;} - if(value < min){ return min;} - return value; - } - - /** - * Test if the value is within the min and max, inclusive - * @param value to test - * @param min Minimum value of range - * @param max Maximum value of range - * @return true if value is within range, false otherwise - */ - private boolean bounded(double value, double min, double max){ - // Note, this is an inclusive range. This is so tests like - // `bounded(constrain(0,0,1),0,1)` will return false. - // This is more helpful for determining edge-case behaviour - // than <= is. - return (min0) P*=-1; - if(I>0) I*=-1; - if(D>0) D*=-1; - if(F>0) F*=-1; - } - else{ // all values should be above zero - if(P<0) P*=-1; - if(I<0) I*=-1; - if(D<0) D*=-1; - if(F<0) F*=-1; - } - } -} diff --git a/KiwiLight - Vision Code/KiwiLight b/KiwiLight - Vision Code/KiwiLight deleted file mode 100755 index f5685ff..0000000 Binary files a/KiwiLight - Vision Code/KiwiLight and /dev/null differ diff --git a/KiwiLight - Vision Code/KiwiLight.cpp b/KiwiLight - Vision Code/KiwiLight.cpp index 7f99a40..fecdf44 100644 --- a/KiwiLight - Vision Code/KiwiLight.cpp +++ b/KiwiLight - Vision Code/KiwiLight.cpp @@ -10,9 +10,10 @@ using namespace KiwiLight; //define some static vars for KiwiLightApp. Vars will be defined for real on call to Create(); VideoCapture KiwiLightApp::camera; +UDP KiwiLightApp::udpSender; Runner KiwiLightApp::runner; ConfigEditor KiwiLightApp::configeditor; -GThread *KiwiLightApp::streamingThread; +GThread *KiwiLightApp::streamingThread; UIMode KiwiLightApp::mode = UIMode::UI_STREAM; bool KiwiLightApp::lastImageGrabSuccessful = false; bool KiwiLightApp::udpEnabled = false; @@ -35,6 +36,8 @@ void KiwiLightApp::Create(int argc, char *argv[]) { KiwiLightApp::mode = UIMode::UI_PAUSING; KiwiLightApp::cameraFailures = 0; KiwiLightApp:currentCameraIndex = 100; //just to define index. Camera will only open if currentCameraindex != 100 + + KiwiLightApp::udpSender = UDP("127.0.0.1", 3695, false); gtk_init(&argc, &argv); win = Window(GTK_WINDOW_TOPLEVEL); @@ -166,6 +169,9 @@ bool KiwiLightApp::LastImageCaptureSuccessful() { return KiwiLightApp::lastImageGrabSuccessful; } +UDP KiwiLightApp::GetUDP() { + return KiwiLightApp::udpSender; +} /** * Returns KiwiLight's menu bar @@ -299,6 +305,36 @@ void KiwiLightApp::OpenNewCameraOnIndex(int index) { } } +/** + * This method is ONLY to be used if KiwiLight is working headless (no UI)!!!!!!! + * Opens new camera without updating UI elements + */ +void KiwiLightApp::InitCameraOnly(int index) { + std::cout << "Configuring Auto Exposure setting on new camera" << std::endl; + Shell::ExecuteCommand( + std::string("v4l2-ctl -d ") + + std::to_string(index) + + std::string(" --set-ctrl=exposure_auto=1") + ); + + KiwiLightApp::camera = VideoCapture(index); +} + + +void KiwiLightApp::ReconnectUDP(std::string newAddress, int newPort) { + KiwiLightApp::udpSender = UDP(newAddress, newPort, false); +} + + +void KiwiLightApp::ReconnectUDP(std::string newAddress, int newPort, bool block) { + KiwiLightApp::udpSender = UDP(newAddress, newPort, block); +} + + +void KiwiLightApp::SendOverUDP(std::string message) { + KiwiLightApp::udpSender.Send(message); +} + /** * Causes the editor to apply all camera settings to the video stream. */ @@ -362,7 +398,7 @@ void KiwiLightApp::UpdateStreamsConstantly() { //now because some cameras like the jevois take a little longer for the stream to start, we will wait until it gives us a good frame //to avoid the VIDIOC_QBUF: Invalid Argument barage. bool retrieveSuccess = false; - while(!retrieveSuccess) { + while(!retrieveSuccess && KiwiLightApp::mode != UIMode::UI_PAUSING && streamThreadEnabled) { usleep(250000); //give camera some time to adjust and do things bool grabSuccess = KiwiLightApp::camera.grab(); if(grabSuccess) { @@ -397,7 +433,7 @@ void KiwiLightApp::UpdateStreams() { //if the udp is enabled, send the message if(KiwiLightApp::udpEnabled) { - KiwiLightApp::runner.SendOverUDP(output); + KiwiLightApp::udpSender.Send(output); } } break; @@ -409,7 +445,7 @@ void KiwiLightApp::UpdateStreams() { //send if udp enabled if(KiwiLightApp::udpEnabled) { - KiwiLightApp::configeditor.SendOverUDP(output); + KiwiLightApp::udpSender.Send(output); } } break; @@ -449,6 +485,11 @@ void KiwiLightApp::ToggleUDP() { //set the button text KiwiLightApp::toggleUDPButton.SetText((KiwiLightApp::udpEnabled ? "Disable UDP" : "Enable UDP")); + + //set the buttons in the config editor if necessary + if(KiwiLightApp::mode == UIMode::UI_EDITOR) { + KiwiLightApp::configeditor.SetUDPEnabledLabels(KiwiLightApp::udpEnabled); + } } /** @@ -465,28 +506,30 @@ void KiwiLightApp::NewConfiguration() { * @param currentMode The UIMode active when callback was triggered */ void KiwiLightApp::EditConfiguration() { - //since this is a callback, close streamer UIMode currentMode = KiwiLightApp::mode; - std::string pathToOpen = ""; - StopStreamingThread(); - - if(currentMode == UIMode::UI_STREAM) { - //find generic.xml (in /home/user/KiwiLightData/confs) - char *homedir = getenv("HOME"); - if(homedir == NULL) { - std::cout << "The HOME environment variable could not be found." << std::endl; - return; - } else { - pathToOpen = std::string(homedir) + "/KiwiLightData/confs/generic.xml"; + if(currentMode != UIMode::UI_EDITOR) { + //since this is a callback, close streamer + std::string pathToOpen = ""; + StopStreamingThread(); + + if(currentMode == UIMode::UI_STREAM) { + //find generic.xml (in /home/user/KiwiLightData/confs) + char *homedir = getenv("HOME"); + if(homedir == NULL) { + std::cout << "The HOME environment variable could not be found." << std::endl; + return; + } else { + pathToOpen = std::string(homedir) + "/KiwiLightData/confs/generic.xml"; + } + } else if(currentMode == UIMode::UI_RUNNER) { + std::cout << "taking runner path" << std::endl; + pathToOpen = KiwiLightApp::runner.GetFileName(); + } else if(currentMode == UIMode::UI_PAUSING) { + std::cout << "WARNING: UI mode unclear. Make sure EditConfiguration() is called before stream thread is terminated" << std::endl; } - } else if(currentMode == UIMode::UI_RUNNER) { - std::cout << "taking runner path" << std::endl; - pathToOpen = KiwiLightApp::runner.GetFileName(); - } else if(currentMode == UIMode::UI_PAUSING) { - std::cout << "WARNING: UI mode unclear. Make sure EditConfiguration() is called before stream thread is terminated" << std::endl; + KiwiLightApp::configeditor = ConfigEditor(pathToOpen); + LaunchStreamingThread(UIMode::UI_EDITOR); } - KiwiLightApp::configeditor = ConfigEditor(pathToOpen); - LaunchStreamingThread(UIMode::UI_EDITOR); } /** diff --git a/KiwiLight - Vision Code/KiwiLight.h b/KiwiLight - Vision Code/KiwiLight.h index 8537c8c..59a74e8 100644 --- a/KiwiLight - Vision Code/KiwiLight.h +++ b/KiwiLight - Vision Code/KiwiLight.h @@ -1,118 +1,124 @@ -#ifndef KiwiLight_H -#define KiwiLight_H - -#include -#include -#include -#include "ui/UI.h" -#include "util/Util.h" -#include "runner/Runner.h" - -/** - * the main header for the KiwiLight program and namespace - * Written by: Brach Knutson - */ - - -using namespace cv; - -namespace KiwiLight { - - enum UIMode { - UI_STREAM, - UI_RUNNER, - UI_EDITOR, - UI_PAUSING - }; - - /** - * Its KiwiLight! Handles everything from building, starting, calling and things in the UI. - */ - class KiwiLightApp { - public: - //UI building and starting - static void Create(int argc, char *argv[]); - static void Start(); - - //UI accessors - static Runner GetRunner(); - static ConfigEditor GetEditor(); - - //camera accessors - static Mat TakeImage(); - static double GetCameraProperty(int propId); - static bool CameraOpen(); - - //camera mutators - static void SetCameraProperty(int propId, double value); - - //general accessors - static bool LastImageCaptureSuccessful(); - static UIMode CurrentMode(); - - //misc. UI callbacks - static void CloseEditor(bool saveFirst); - static void StartEditorLearningTarget(); - static void StartEditorLearningDistance(); - static void EditorReconnectUDP(); - static void EditorSetImageResolutionFromOverview(); - static void EditorConnectUDPFromOverview(); - static void EditorApplyCameraSettings(); - static void EditorOpenNewCameraFromOverview(); - static void OpenNewCameraOnIndex(int index); - - //thread utilities - static void LaunchStreamingThread(UIMode newMode); - static void StopStreamingThread(); - - private: - //menu bar utility - static MenuBar CreateMenuBar(); - - //UI constant callbacks - static void UpdateApp(); - static void UpdateStreamsConstantly(); - static void UpdateStreams(); - - //UI button callbacks - static void OpenNewCameraFromMainIndex(); - static void ToggleUDP(); - static void NewConfiguration(); - static void EditConfiguration(); - static void OpenConfiguration(); - static void OpenConfigurationFromFile(std::string fileName); - static void CloseConfiguration(); - static void Quit(); - static void ShowAboutWindow(); - static void ShowHelpWindow(); - - //essential objects - static Runner runner; - static ConfigEditor configeditor; - static VideoCapture camera; - static GThread *streamingThread; - - //utilities - static UIMode mode; - static bool lastImageGrabSuccessful; - static bool udpEnabled; - static bool streamThreadEnabled; - static bool outImgInUse; - static Mat lastFrameGrabImage; - static int currentCameraIndex; - - //ui widgets - static Window win; - static ConfigPanel confInfo; - static NumberBox cameraIndexBox; - static Label cameraStatusLabel; - static Image outputImage; - static Button toggleUDPButton; - - //counters - static int cameraFailures; - }; - -} - -#endif +#ifndef KiwiLight_H +#define KiwiLight_H + +#include +#include +#include +#include "ui/UI.h" +#include "util/Util.h" +#include "runner/Runner.h" + +/** + * the main header for the KiwiLight program and namespace + * Written by: Brach Knutson + */ + + +using namespace cv; + +namespace KiwiLight { + + enum UIMode { + UI_STREAM, + UI_RUNNER, + UI_EDITOR, + UI_PAUSING + }; + + /** + * Its KiwiLight! Handles everything from building, starting, calling and things in the UI. + */ + class KiwiLightApp { + public: + //UI building and starting + static void Create(int argc, char *argv[]); + static void Start(); + + //UI accessors + static Runner GetRunner(); + static ConfigEditor GetEditor(); + + //camera accessors + static Mat TakeImage(); + static double GetCameraProperty(int propId); + static bool CameraOpen(); + + //camera mutators + static void SetCameraProperty(int propId, double value); + + //general accessors + static bool LastImageCaptureSuccessful(); + static UIMode CurrentMode(); + static UDP GetUDP(); + + //misc. UI callbacks + static void CloseEditor(bool saveFirst); + static void StartEditorLearningTarget(); + static void StartEditorLearningDistance(); + static void EditorReconnectUDP(); + static void ToggleUDP(); + static void EditorSetImageResolutionFromOverview(); + static void EditorConnectUDPFromOverview(); + static void EditorApplyCameraSettings(); + static void EditorOpenNewCameraFromOverview(); + static void OpenNewCameraOnIndex(int index); + static void InitCameraOnly(int index); + static void ReconnectUDP(std::string newAddress, int newPort); + static void ReconnectUDP(std::string newAddress, int newPort, bool block); + static void SendOverUDP(std::string message); + + //thread utilities + static void LaunchStreamingThread(UIMode newMode); + static void StopStreamingThread(); + + private: + //menu bar utility + static MenuBar CreateMenuBar(); + + //UI constant callbacks + static void UpdateApp(); + static void UpdateStreamsConstantly(); + static void UpdateStreams(); + + //UI button callbacks + static void OpenNewCameraFromMainIndex(); + static void NewConfiguration(); + static void EditConfiguration(); + static void OpenConfiguration(); + static void OpenConfigurationFromFile(std::string fileName); + static void CloseConfiguration(); + static void Quit(); + static void ShowAboutWindow(); + static void ShowHelpWindow(); + + //essential objects + static Runner runner; + static ConfigEditor configeditor; + static VideoCapture camera; + static UDP udpSender; + static GThread *streamingThread; + + //utilities + static UIMode mode; + static bool lastImageGrabSuccessful; + static bool udpEnabled; + static bool streamThreadEnabled; + static bool outImgInUse; + static Mat lastFrameGrabImage; + static int currentCameraIndex; + + //ui widgets + static Window win; + static ConfigPanel confInfo; + static NumberBox cameraIndexBox; + static Label cameraStatusLabel; + static Image outputImage; + static Button toggleUDPButton; + + //counters + static int cameraFailures; + }; + +} + +#endif diff --git a/KiwiLight - Vision Code/Main.cpp b/KiwiLight - Vision Code/Main.cpp index 8c19083..ae2b9df 100644 --- a/KiwiLight - Vision Code/Main.cpp +++ b/KiwiLight - Vision Code/Main.cpp @@ -1,28 +1,145 @@ -#include "KiwiLight.h" - -/** - * 3695 thing here - */ - -using namespace cv; -using namespace KiwiLight; - -int main(int argc, char *argv[]) { - if(argc == 1) { - KiwiLightApp::Create(argc, argv); - KiwiLightApp::Start(); - } else { - std::cout << "Command: \"" << argv[1] << "\"" << std::endl; - //special command, do something else - if(std::string(argv[1]) == "-c") { - std::string configPath = argv[2]; - std::cout << "Config Path: " << configPath << std::endl; - //create the KiwiLight runner and camera - KiwiLightApp::OpenNewCameraOnIndex(0); - Runner runner = Runner(configPath, true); - runner.Loop(); - } - } - - return 0; -} +#include "KiwiLight.h" + +/** + * 3695 thing here + */ + +using namespace cv; +using namespace KiwiLight; + +void ShowHelp() { + std::cout << "KIWILIGHT HELP\n"; + std::cout << "Usage: Kiwilight [options] [config files]\n"; + std::cout << "\n"; + std::cout << "KiwiLight is a smart vision solution for FRC applications developed by FRC Team 3695: Foximus Prime.\n"; + std::cout << "\n"; + std::cout << "Options:\n"; + std::cout << "-c: Runs a config file, or multiple config files.\n"; + std::cout << "-h: Displays this help window.\n"; + std::cout << std::endl; +} + + +void RunConfigs(std::vector filePaths) { + //init needed KiwiLight variables + KiwiLightApp::InitCameraOnly(0); + KiwiLightApp::ReconnectUDP("127.0.0.1", 3695, false); + + std::cout << "Command: Run Configs\n"; + std::cout << "Config files found: " << filePaths.size() << "\n"; + std::cout << "Ensure that all config files share the same UDP Address and Port." << std::endl; + + //initalize the runners + std::cout << "\nInitalizing Runners" << std::endl; + const int numTargets = (const int) filePaths.size(); + Runner runners[numTargets]; + int totalContours = 0; + for(int i=0; i confsToRun; + + for(int i=0; i 4) { + if(argument.substr(argument.length() - 4) == ".xml") { + confsToRun.push_back(argument); + } + } + } + + if(runningConfig) { + RunConfigs(confsToRun); + } + } + + return 0; +} diff --git a/KiwiLight - Vision Code/Makefile b/KiwiLight - Vision Code/Makefile index eafbc43..1cd6579 100644 --- a/KiwiLight - Vision Code/Makefile +++ b/KiwiLight - Vision Code/Makefile @@ -1,202 +1,202 @@ - - -# Makefile for the KiwiLight program. -# Written By: Brach Knutson - -CXX = g++ -CV = `pkg-config --cflags --libs opencv` -GTK = `pkg-config --cflags --libs gtk+-3.0` - -#UI -bin/ui/ConfirmationDialog.o: ui/ConfirmationDialog.cpp - $(CXX) -c -o bin/ui/ConfirmationDialog.o ui/ConfirmationDialog.cpp $(GTK) - -bin/ui/SubMenuItem.o: ui/SubMenuItem.cpp - $(CXX) -c -o bin/ui/SubMenuItem.o ui/SubMenuItem.cpp $(GTK) - -bin/ui/MenuItem.o: ui/MenuItem.cpp - $(CXX) -c -o bin/ui/MenuItem.o ui/MenuItem.cpp $(GTK) - -bin/ui/MenuBar.o: ui/MenuBar.cpp - $(CXX) -c -o bin/ui/MenuBar.o ui/MenuBar.cpp $(GTK) - -bin/ui/Button.o: ui/Button.cpp - $(CXX) -c -o bin/ui/Button.o ui/Button.cpp $(GTK) - -bin/ui/Label.o: ui/Label.cpp - $(CXX) -c -o bin/ui/Label.o ui/Label.cpp $(GTK) - -bin/ui/LabeledSlider.o: ui/LabeledSlider.cpp - $(CXX) -c -o bin/ui/LabeledSlider.o ui/LabeledSlider.cpp $(GTK) - -bin/ui/AboutWindow.o: ui/AboutWindow.cpp - $(CXX) -c -o bin/ui/AboutWindow.o ui/AboutWindow.cpp $(GTK) - -bin/ui/HelpWindow.o: ui/HelpWindow.cpp - $(CXX) -c -o bin/ui/HelpWindow.o ui/HelpWindow.cpp $(GTK) - -bin/ui/Panel.o: ui/Panel.cpp - $(CXX) -c -o bin/ui/Panel.o ui/Panel.cpp $(GTK) - -bin/ui/Scrollable.o: ui/Scrollable.cpp - $(CXX) -c -o bin/ui/Scrollable.o ui/Scrollable.cpp $(GTK) - -bin/ui/Frame.o: ui/Frame.cpp - $(CXX) -c -o bin/ui/Frame.o ui/Frame.cpp $(GTK) - -bin/ui/Separator.o: ui/Separator.cpp - $(CXX) -c -o bin/ui/Separator.o ui/Separator.cpp $(GTK) - -bin/ui/Slider.o: ui/Slider.cpp - $(CXX) -c -o bin/ui/Slider.o ui/Slider.cpp $(GTK) - -bin/ui/CheckBox.o: ui/CheckBox.cpp - $(CXX) -c -o bin/ui/CheckBox.o ui/CheckBox.cpp $(GTK) - -bin/ui/TextBox.o: ui/TextBox.cpp - $(CXX) -c -o bin/ui/TextBox.o ui/TextBox.cpp $(GTK) - -bin/ui/NumberBox.o: ui/NumberBox.cpp - $(CXX) -c -o bin/ui/NumberBox.o ui/NumberBox.cpp $(GTK) - -bin/ui/FileChooser.o: ui/FileChooser.cpp - $(CXX) -c -o bin/ui/FileChooser.o ui/FileChooser.cpp $(GTK) - -bin/ui/TabView.o: ui/TabView.cpp - $(CXX) -c -o bin/ui/TabView.o ui/TabView.cpp $(GTK) - -bin/ui/PopupTextBox.o: ui/PopupTextBox.cpp - $(CXX) -c -o bin/ui/PopupTextBox.o ui/PopupTextBox.cpp $(GTK) - -bin/ui/Image.o: ui/Image.cpp - $(CXX) -c -o bin/ui/Image.o ui/Image.cpp $(GTK) $(CV) - -bin/ui/Window.o: ui/Window.cpp - $(CXX) -c -o bin/ui/Window.o ui/Window.cpp $(GTK) - -bin/ui/ConfigPanel.o: ui/ConfigPanel.cpp - $(CXX) -c -o bin/ui/ConfigPanel.o ui/ConfigPanel.cpp $(GTK) - -bin/ui/OverviewPanel.o: ui/OverviewPanel.cpp - $(CXX) -c -o bin/ui/OverviewPanel.o ui/OverviewPanel.cpp $(GTK) $(CV) - -bin/ui/Settings.o: ui/Settings.cpp - $(CXX) -c -o bin/ui/Settings.o ui/Settings.cpp $(GTK) - -bin/ui/PreprocessorEditor.o: ui/PreprocessorEditor.cpp - $(CXX) -c -o bin/ui/PreprocessorEditor.o ui/PreprocessorEditor.cpp $(CV) $(GTK) - -bin/ui/PostprocessorEditor.o: ui/PostprocessorEditor.cpp - $(CXX) -c -o bin/ui/PostprocessorEditor.o ui/PostprocessorEditor.cpp $(CV) $(GTK) - -bin/ui/RunnerEditor.o: ui/RunnerEditor.cpp - $(CXX) -c -o bin/ui/RunnerEditor.o ui/RunnerEditor.cpp $(CV) $(GTK) - -bin/ui/ConfigEditor.o: ui/ConfigEditor.cpp - $(CXX) -c -o bin/ui/ConfigEditor.o ui/ConfigEditor.cpp $(CV) $(GTK) - -bin/ui/CameraSetting.o: ui/CameraSetting.cpp - $(CXX) -c -o bin/ui/CameraSetting.o ui/CameraSetting.cpp $(GTK) - -lib/UI.a: bin/ui/ConfirmationDialog.o bin/ui/SubMenuItem.o bin/ui/MenuItem.o bin/ui/MenuBar.o bin/ui/Button.o bin/ui/Label.o bin/ui/LabeledSlider.o bin/ui/AboutWindow.o bin/ui/HelpWindow.o bin/ui/Panel.o bin/ui/Scrollable.o bin/ui/Frame.o bin/ui/Separator.o bin/ui/Slider.o bin/ui/CheckBox.o bin/ui/TextBox.o bin/ui/NumberBox.o bin/ui/FileChooser.o bin/ui/TabView.o bin/ui/PopupTextBox.o bin/ui/Image.o bin/ui/Window.o bin/ui/ConfigPanel.o bin/ui/OverviewPanel.o bin/ui/Settings.o bin/ui/PreprocessorEditor.o bin/ui/PostprocessorEditor.o bin/ui/RunnerEditor.o bin/ui/ConfigEditor.o bin/ui/CameraSetting.o - ar rs lib/UI.a bin/ui/ConfirmationDialog.o bin/ui/SubMenuItem.o bin/ui/MenuItem.o bin/ui/MenuBar.o bin/ui/Button.o bin/ui/Label.o bin/ui/LabeledSlider.o bin/ui/AboutWindow.o bin/ui/HelpWindow.o bin/ui/Panel.o bin/ui/Scrollable.o bin/ui/Frame.o bin/ui/Separator.o bin/ui/Slider.o bin/ui/CheckBox.o bin/ui/TextBox.o bin/ui/NumberBox.o bin/ui/FileChooser.o bin/ui/TabView.o bin/ui/PopupTextBox.o bin/ui/Image.o bin/ui/Window.o bin/ui/ConfigPanel.o bin/ui/OverviewPanel.o bin/ui/Settings.o bin/ui/PreprocessorEditor.o bin/ui/PostprocessorEditor.o bin/ui/RunnerEditor.o bin/ui/ConfigEditor.o bin/ui/CameraSetting.o - -#UTIL -bin/util/Flags.o: util/Flags.cpp - $(CXX) -c -o bin/util/Flags.o util/Flags.cpp $(GTK) - -bin/util/Shell.o: util/Shell.cpp - $(CXX) -c -o bin/util/Shell.o util/Shell.cpp $(GTK) - -bin/util/Util.o: util/Util.cpp - $(CXX) -c -o bin/util/Util.o util/Util.cpp $(GTK) - -bin/util/StringUtils.o: util/StringUtils.cpp - $(CXX) -c -o bin/util/StringUtils.o util/StringUtils.cpp $(GTK) - -bin/util/DataUtils.o: util/DataUtils.cpp - $(CXX) -c -o bin/util/DataUtils.o util/DataUtils.cpp $(GTK) - -bin/util/UDP.o: util/UDP.cpp - $(CXX) -c -o bin/util/UDP.o util/UDP.cpp $(GTK) - -bin/util/XMLDocument.o: util/XMLDocument.cpp - $(CXX) -c -o bin/util/XMLDocument.o util/XMLDocument.cpp $(GTK) - -bin/util/XMLTag.o: util/XMLTag.cpp - $(CXX) -c -o bin/util/XMLTag.o util/XMLTag.cpp $(GTK) - -bin/util/XMLTagAttribute.o: util/XMLTagAttribute.cpp - $(CXX) -c -o bin/util/XMLTagAttribute.o util/XMLTagAttribute.cpp $(GTK) - -bin/util/SettingPair.o: util/SettingPair.cpp - $(CXX) -c -o bin/util/SettingPair.o util/SettingPair.cpp $(GTK) - -bin/util/Color.o: util/Color.cpp - $(CXX) -c -o bin/util/Color.o util/Color.cpp $(GTK) $(CV) - -lib/Util.a: bin/util/Flags.o bin/util/Shell.o bin/util/Util.o bin/util/StringUtils.o bin/util/DataUtils.o bin/util/UDP.o bin/util/XMLDocument.o bin/util/XMLTag.o bin/util/XMLTagAttribute.o bin/util/SettingPair.o bin/util/Color.o - ar rs lib/Util.a bin/util/Flags.o bin/util/Shell.o bin/util/Util.o bin/util/StringUtils.o bin/util/DataUtils.o bin/util/UDP.o bin/util/XMLDocument.o bin/util/XMLTag.o bin/util/XMLTagAttribute.o bin/util/SettingPair.o bin/util/Color.o - -#RUNNER -bin/runner/Contour.o: runner/Contour.cpp - $(CXX) -c -o bin/runner/Contour.o runner/Contour.cpp $(GTK) $(CV) - -bin/runner/ExampleContour.o: runner/ExampleContour.cpp - $(CXX) -c -o bin/runner/ExampleContour.o runner/ExampleContour.cpp $(GTK) $(CV) - -bin/runner/ExampleTarget.o: runner/ExampleTarget.cpp - $(CXX) -c -o bin/runner/ExampleTarget.o runner/ExampleTarget.cpp $(GTK) $(CV) - -bin/runner/PostProcessor.o: runner/PostProcessor.cpp - $(CXX) -c -o bin/runner/PostProcessor.o runner/PostProcessor.cpp $(GTK) $(CV) - -bin/runner/PreProcessor.o: runner/PreProcessor.cpp - $(CXX) -c -o bin/runner/PreProcessor.o runner/PreProcessor.cpp $(GTK) $(CV) - -bin/runner/CameraFrame.o: runner/CameraFrame.cpp - $(CXX) -c -o bin/runner/CameraFrame.o runner/CameraFrame.cpp $(GTK) $(CV) - -bin/runner/ConfigLearner.o: runner/ConfigLearner.cpp - $(CXX) -c -o bin/runner/ConfigLearner.o runner/ConfigLearner.cpp $(GTK) $(CV) - -bin/runner/Runner.o: runner/Runner.cpp - $(CXX) -c -o bin/runner/Runner.o runner/Runner.cpp $(GTK) $(CV) - -bin/runner/TargetDistanceLearner.o: runner/TargetDistanceLearner.cpp - $(CXX) -c -o bin/runner/TargetDistanceLearner.o runner/TargetDistanceLearner.cpp $(GTK) $(CV) - -bin/runner/Target.o: runner/Target.cpp - $(CXX) -c -o bin/runner/Target.o runner/Target.cpp $(GTK) $(CV) - -bin/runner/TargetTroubleshooter.o: runner/TargetTroubleshooter.cpp - $(CXX) -c -o bin/runner/TargetTroubleshooter.o runner/TargetTroubleshooter.cpp $(GTK) $(CV) - -bin/runner/RunnerSettings.o: runner/RunnerSettings.cpp - $(CXX) -c -o bin/runner/RunnerSettings.o runner/RunnerSettings.cpp - -lib/Runner.a: bin/runner/Contour.o bin/runner/ExampleContour.o bin/runner/ExampleTarget.o bin/runner/PostProcessor.o bin/runner/PreProcessor.o bin/runner/CameraFrame.o bin/runner/ConfigLearner.o bin/runner/Runner.o bin/runner/Target.o bin/runner/TargetDistanceLearner.o bin/runner/TargetTroubleshooter.o bin/runner/RunnerSettings.o - ar rs lib/Runner.a bin/runner/Runner.o bin/runner/ConfigLearner.o bin/runner/Contour.o bin/runner/ExampleContour.o bin/runner/ExampleTarget.o bin/runner/PostProcessor.o bin/runner/PreProcessor.o bin/runner/CameraFrame.o bin/runner/Target.o bin/runner/TargetDistanceLearner.o bin/runner/TargetTroubleshooter.o bin/runner/RunnerSettings.o - -#MAIN FILE -bin/KiwiLight.o: KiwiLight.cpp - $(CXX) -c -o bin/KiwiLight.o KiwiLight.cpp $(CV) $(GTK) - -KiwiLight: Main.cpp bin/KiwiLight.o lib/UI.a lib/Util.a lib/Runner.a - $(CXX) -o KiwiLight Main.cpp bin/KiwiLight.o lib/UI.a lib/Runner.a lib/Util.a $(CV) $(GTK) - -#SET UP THE FILES AND FOLDERS -setup: - mkdir lib - mkdir bin - mkdir bin/ui - mkdir bin/util - mkdir bin/runner - -#UNINSTALL -clean: - $(info Uninstalling KiwiLight Executables...) - rm -r bin - rm -r lib - make setup - rm KiwiLight + + +# Makefile for the KiwiLight program. +# Written By: Brach Knutson + +CXX = g++ +CV = `pkg-config --cflags --libs opencv` +GTK = `pkg-config --cflags --libs gtk+-3.0` + +#UI +bin/ui/ConfirmationDialog.o: ui/ConfirmationDialog.cpp + $(CXX) -c -o bin/ui/ConfirmationDialog.o ui/ConfirmationDialog.cpp $(GTK) + +bin/ui/SubMenuItem.o: ui/SubMenuItem.cpp + $(CXX) -c -o bin/ui/SubMenuItem.o ui/SubMenuItem.cpp $(GTK) + +bin/ui/MenuItem.o: ui/MenuItem.cpp + $(CXX) -c -o bin/ui/MenuItem.o ui/MenuItem.cpp $(GTK) + +bin/ui/MenuBar.o: ui/MenuBar.cpp + $(CXX) -c -o bin/ui/MenuBar.o ui/MenuBar.cpp $(GTK) + +bin/ui/Button.o: ui/Button.cpp + $(CXX) -c -o bin/ui/Button.o ui/Button.cpp $(GTK) + +bin/ui/Label.o: ui/Label.cpp + $(CXX) -c -o bin/ui/Label.o ui/Label.cpp $(GTK) + +bin/ui/LabeledSlider.o: ui/LabeledSlider.cpp + $(CXX) -c -o bin/ui/LabeledSlider.o ui/LabeledSlider.cpp $(GTK) + +bin/ui/AboutWindow.o: ui/AboutWindow.cpp + $(CXX) -c -o bin/ui/AboutWindow.o ui/AboutWindow.cpp $(GTK) + +bin/ui/HelpWindow.o: ui/HelpWindow.cpp + $(CXX) -c -o bin/ui/HelpWindow.o ui/HelpWindow.cpp $(GTK) + +bin/ui/Panel.o: ui/Panel.cpp + $(CXX) -c -o bin/ui/Panel.o ui/Panel.cpp $(GTK) + +bin/ui/Scrollable.o: ui/Scrollable.cpp + $(CXX) -c -o bin/ui/Scrollable.o ui/Scrollable.cpp $(GTK) + +bin/ui/Frame.o: ui/Frame.cpp + $(CXX) -c -o bin/ui/Frame.o ui/Frame.cpp $(GTK) + +bin/ui/Separator.o: ui/Separator.cpp + $(CXX) -c -o bin/ui/Separator.o ui/Separator.cpp $(GTK) + +bin/ui/Slider.o: ui/Slider.cpp + $(CXX) -c -o bin/ui/Slider.o ui/Slider.cpp $(GTK) + +bin/ui/CheckBox.o: ui/CheckBox.cpp + $(CXX) -c -o bin/ui/CheckBox.o ui/CheckBox.cpp $(GTK) + +bin/ui/TextBox.o: ui/TextBox.cpp + $(CXX) -c -o bin/ui/TextBox.o ui/TextBox.cpp $(GTK) + +bin/ui/NumberBox.o: ui/NumberBox.cpp + $(CXX) -c -o bin/ui/NumberBox.o ui/NumberBox.cpp $(GTK) + +bin/ui/FileChooser.o: ui/FileChooser.cpp + $(CXX) -c -o bin/ui/FileChooser.o ui/FileChooser.cpp $(GTK) + +bin/ui/TabView.o: ui/TabView.cpp + $(CXX) -c -o bin/ui/TabView.o ui/TabView.cpp $(GTK) + +bin/ui/PopupTextBox.o: ui/PopupTextBox.cpp + $(CXX) -c -o bin/ui/PopupTextBox.o ui/PopupTextBox.cpp $(GTK) + +bin/ui/Image.o: ui/Image.cpp + $(CXX) -c -o bin/ui/Image.o ui/Image.cpp $(GTK) $(CV) + +bin/ui/Window.o: ui/Window.cpp + $(CXX) -c -o bin/ui/Window.o ui/Window.cpp $(GTK) + +bin/ui/ConfigPanel.o: ui/ConfigPanel.cpp + $(CXX) -c -o bin/ui/ConfigPanel.o ui/ConfigPanel.cpp $(GTK) + +bin/ui/OverviewPanel.o: ui/OverviewPanel.cpp + $(CXX) -c -o bin/ui/OverviewPanel.o ui/OverviewPanel.cpp $(GTK) $(CV) + +bin/ui/Settings.o: ui/Settings.cpp + $(CXX) -c -o bin/ui/Settings.o ui/Settings.cpp $(GTK) + +bin/ui/PreprocessorEditor.o: ui/PreprocessorEditor.cpp + $(CXX) -c -o bin/ui/PreprocessorEditor.o ui/PreprocessorEditor.cpp $(CV) $(GTK) + +bin/ui/PostprocessorEditor.o: ui/PostprocessorEditor.cpp + $(CXX) -c -o bin/ui/PostprocessorEditor.o ui/PostprocessorEditor.cpp $(CV) $(GTK) + +bin/ui/RunnerEditor.o: ui/RunnerEditor.cpp + $(CXX) -c -o bin/ui/RunnerEditor.o ui/RunnerEditor.cpp $(CV) $(GTK) + +bin/ui/ConfigEditor.o: ui/ConfigEditor.cpp + $(CXX) -c -o bin/ui/ConfigEditor.o ui/ConfigEditor.cpp $(CV) $(GTK) + +bin/ui/CameraSetting.o: ui/CameraSetting.cpp + $(CXX) -c -o bin/ui/CameraSetting.o ui/CameraSetting.cpp $(GTK) + +lib/UI.a: bin/ui/ConfirmationDialog.o bin/ui/SubMenuItem.o bin/ui/MenuItem.o bin/ui/MenuBar.o bin/ui/Button.o bin/ui/Label.o bin/ui/LabeledSlider.o bin/ui/AboutWindow.o bin/ui/HelpWindow.o bin/ui/Panel.o bin/ui/Scrollable.o bin/ui/Frame.o bin/ui/Separator.o bin/ui/Slider.o bin/ui/CheckBox.o bin/ui/TextBox.o bin/ui/NumberBox.o bin/ui/FileChooser.o bin/ui/TabView.o bin/ui/PopupTextBox.o bin/ui/Image.o bin/ui/Window.o bin/ui/ConfigPanel.o bin/ui/OverviewPanel.o bin/ui/Settings.o bin/ui/PreprocessorEditor.o bin/ui/PostprocessorEditor.o bin/ui/RunnerEditor.o bin/ui/ConfigEditor.o bin/ui/CameraSetting.o + ar rs lib/UI.a bin/ui/ConfirmationDialog.o bin/ui/SubMenuItem.o bin/ui/MenuItem.o bin/ui/MenuBar.o bin/ui/Button.o bin/ui/Label.o bin/ui/LabeledSlider.o bin/ui/AboutWindow.o bin/ui/HelpWindow.o bin/ui/Panel.o bin/ui/Scrollable.o bin/ui/Frame.o bin/ui/Separator.o bin/ui/Slider.o bin/ui/CheckBox.o bin/ui/TextBox.o bin/ui/NumberBox.o bin/ui/FileChooser.o bin/ui/TabView.o bin/ui/PopupTextBox.o bin/ui/Image.o bin/ui/Window.o bin/ui/ConfigPanel.o bin/ui/OverviewPanel.o bin/ui/Settings.o bin/ui/PreprocessorEditor.o bin/ui/PostprocessorEditor.o bin/ui/RunnerEditor.o bin/ui/ConfigEditor.o bin/ui/CameraSetting.o + +#UTIL +bin/util/Flags.o: util/Flags.cpp + $(CXX) -c -o bin/util/Flags.o util/Flags.cpp $(GTK) + +bin/util/Shell.o: util/Shell.cpp + $(CXX) -c -o bin/util/Shell.o util/Shell.cpp $(GTK) + +bin/util/Util.o: util/Util.cpp + $(CXX) -c -o bin/util/Util.o util/Util.cpp $(GTK) + +bin/util/StringUtils.o: util/StringUtils.cpp + $(CXX) -c -o bin/util/StringUtils.o util/StringUtils.cpp $(GTK) + +bin/util/DataUtils.o: util/DataUtils.cpp + $(CXX) -c -o bin/util/DataUtils.o util/DataUtils.cpp $(GTK) + +bin/util/UDP.o: util/UDP.cpp + $(CXX) -c -o bin/util/UDP.o util/UDP.cpp $(GTK) + +bin/util/XMLDocument.o: util/XMLDocument.cpp + $(CXX) -c -o bin/util/XMLDocument.o util/XMLDocument.cpp $(GTK) + +bin/util/XMLTag.o: util/XMLTag.cpp + $(CXX) -c -o bin/util/XMLTag.o util/XMLTag.cpp $(GTK) + +bin/util/XMLTagAttribute.o: util/XMLTagAttribute.cpp + $(CXX) -c -o bin/util/XMLTagAttribute.o util/XMLTagAttribute.cpp $(GTK) + +bin/util/SettingPair.o: util/SettingPair.cpp + $(CXX) -c -o bin/util/SettingPair.o util/SettingPair.cpp $(GTK) + +bin/util/Color.o: util/Color.cpp + $(CXX) -c -o bin/util/Color.o util/Color.cpp $(GTK) $(CV) + +lib/Util.a: bin/util/Flags.o bin/util/Shell.o bin/util/Util.o bin/util/StringUtils.o bin/util/DataUtils.o bin/util/UDP.o bin/util/XMLDocument.o bin/util/XMLTag.o bin/util/XMLTagAttribute.o bin/util/SettingPair.o bin/util/Color.o + ar rs lib/Util.a bin/util/Flags.o bin/util/Shell.o bin/util/Util.o bin/util/StringUtils.o bin/util/DataUtils.o bin/util/UDP.o bin/util/XMLDocument.o bin/util/XMLTag.o bin/util/XMLTagAttribute.o bin/util/SettingPair.o bin/util/Color.o + +#RUNNER +bin/runner/Contour.o: runner/Contour.cpp + $(CXX) -c -o bin/runner/Contour.o runner/Contour.cpp $(GTK) $(CV) + +bin/runner/ExampleContour.o: runner/ExampleContour.cpp + $(CXX) -c -o bin/runner/ExampleContour.o runner/ExampleContour.cpp $(GTK) $(CV) + +bin/runner/ExampleTarget.o: runner/ExampleTarget.cpp + $(CXX) -c -o bin/runner/ExampleTarget.o runner/ExampleTarget.cpp $(GTK) $(CV) + +bin/runner/PostProcessor.o: runner/PostProcessor.cpp + $(CXX) -c -o bin/runner/PostProcessor.o runner/PostProcessor.cpp $(GTK) $(CV) + +bin/runner/PreProcessor.o: runner/PreProcessor.cpp + $(CXX) -c -o bin/runner/PreProcessor.o runner/PreProcessor.cpp $(GTK) $(CV) + +bin/runner/CameraFrame.o: runner/CameraFrame.cpp + $(CXX) -c -o bin/runner/CameraFrame.o runner/CameraFrame.cpp $(GTK) $(CV) + +bin/runner/ConfigLearner.o: runner/ConfigLearner.cpp + $(CXX) -c -o bin/runner/ConfigLearner.o runner/ConfigLearner.cpp $(GTK) $(CV) + +bin/runner/Runner.o: runner/Runner.cpp + $(CXX) -c -o bin/runner/Runner.o runner/Runner.cpp $(GTK) $(CV) + +bin/runner/TargetDistanceLearner.o: runner/TargetDistanceLearner.cpp + $(CXX) -c -o bin/runner/TargetDistanceLearner.o runner/TargetDistanceLearner.cpp $(GTK) $(CV) + +bin/runner/Target.o: runner/Target.cpp + $(CXX) -c -o bin/runner/Target.o runner/Target.cpp $(GTK) $(CV) + +bin/runner/TargetTroubleshooter.o: runner/TargetTroubleshooter.cpp + $(CXX) -c -o bin/runner/TargetTroubleshooter.o runner/TargetTroubleshooter.cpp $(GTK) $(CV) + +bin/runner/RunnerSettings.o: runner/RunnerSettings.cpp + $(CXX) -c -o bin/runner/RunnerSettings.o runner/RunnerSettings.cpp + +lib/Runner.a: bin/runner/Contour.o bin/runner/ExampleContour.o bin/runner/ExampleTarget.o bin/runner/PostProcessor.o bin/runner/PreProcessor.o bin/runner/CameraFrame.o bin/runner/ConfigLearner.o bin/runner/Runner.o bin/runner/Target.o bin/runner/TargetDistanceLearner.o bin/runner/TargetTroubleshooter.o bin/runner/RunnerSettings.o + ar rs lib/Runner.a bin/runner/Runner.o bin/runner/ConfigLearner.o bin/runner/Contour.o bin/runner/ExampleContour.o bin/runner/ExampleTarget.o bin/runner/PostProcessor.o bin/runner/PreProcessor.o bin/runner/CameraFrame.o bin/runner/Target.o bin/runner/TargetDistanceLearner.o bin/runner/TargetTroubleshooter.o bin/runner/RunnerSettings.o + +#MAIN FILE +bin/KiwiLight.o: KiwiLight.cpp + $(CXX) -c -o bin/KiwiLight.o KiwiLight.cpp $(CV) $(GTK) + +KiwiLight: Main.cpp bin/KiwiLight.o lib/UI.a lib/Util.a lib/Runner.a + $(CXX) -o KiwiLight Main.cpp bin/KiwiLight.o lib/UI.a lib/Runner.a lib/Util.a $(CV) $(GTK) + +#SET UP THE FILES AND FOLDERS +setup: + mkdir lib + mkdir bin + mkdir bin/ui + mkdir bin/util + mkdir bin/runner + +#UNINSTALL +clean: + $(info Uninstalling KiwiLight Executables...) + rm -r bin + rm -r lib + make setup + rm KiwiLight diff --git a/KiwiLight - Vision Code/confs/generic.xml b/KiwiLight - Vision Code/confs/generic.xml index 1f655e2..c3b2000 100644 --- a/KiwiLight - Vision Code/confs/generic.xml +++ b/KiwiLight - Vision Code/confs/generic.xml @@ -1,61 +1,61 @@ - - - 600 - 400 - - - 35 - 5 - 150 - -1 - 2 - 2800 - 25 - 0 - 3 - 5 - 0 - 0 - 0 - - - - - 0 - 0 - - - 250 - 145 - - - 75 - 3 - 5 - - 80 - 255 - 255 - - - - - - 0.000000 - 0.000000 - 0.000000 - 0.900000 - 1.000000 - 500.000000 - - 12 - 300 - 36 - -0.1 - - -
    127.0.0.1
    - 3695 -
    -
    -
    + + + 600 + 400 + + + 35 + 5 + 150 + -1 + 2 + 2800 + 25 + 0 + 3 + 5 + 0 + 0 + 0 + + + + + 0 + 0 + + + 250 + 145 + + + 75 + 3 + 5 + + 80 + 255 + 255 + + + + + + 0.000000 + 0.000000 + 0.000000 + 0.900000 + 1.000000 + 500.000000 + + 12 + 300 + 36 + -0.1 + + +
    127.0.0.1
    + 3695 +
    +
    +
    diff --git a/KiwiLight - Vision Code/generic.xml b/KiwiLight - Vision Code/generic.xml new file mode 100644 index 0000000..a655f41 --- /dev/null +++ b/KiwiLight - Vision Code/generic.xml @@ -0,0 +1,55 @@ + + + 600 + 400 + 1 + 512 + 1 + 512 + 1 + 512 + 512 + 512 + + + + + 0 + 0 + + + 250 + 145 + + + 75 + 3 + 5 + + 80 + 255 + 255 + + + + + + 0.000000 + 0.000000 + 0.000000 + 0.900000 + 1.000000 + 500.000000 + + 12 + 300 + 36 + -0.1 + true + + +
    127.0.0.1
    + 3695 +
    +
    +
    diff --git a/KiwiLight - Vision Code/install.sh b/KiwiLight - Vision Code/install.sh index 02c82e6..730db1a 100644 --- a/KiwiLight - Vision Code/install.sh +++ b/KiwiLight - Vision Code/install.sh @@ -1,66 +1,95 @@ -# ---------------------------------- # -# # -# UNIX INSTALLER FOR KIWILIGHT # -# # -# ---------------------------------- # +# +# UNIX INSTALLER FOR KIWILIGHT +# Written By: Brach Knutson +# -Install() { - echo "Downloading Packages" +echo "Welcome to the KiwiLight installer!" +echo +echo "Running this program will install/uninstall the following packages/dependencies:" +echo " - OpenCV" +echo " - Video4Linux" +echo " - GTK 3" +echo " - Cmake" +echo " - VNC" +echo "" +read -p "Do you want to continue? [y/n]:" confirm - sudo apt-get --assume-yes install pkg-config - sudo apt-get --assume-yes install cmake - sudo apt-get --assume-yes install libgtk-3-dev - sudo apt-get --assume-yes install libv4l-dev +if [ $confirm != "y" ]; +then +echo "Aborting." +return 0 +fi + +echo "What would you like to do?" +echo "1: Install" +echo "2: Uninstall" +read -p "Enter an action:" action + +if [ $action = "1" ]; +then + echo "Installing." + #install packages sudo apt-get --assume-yes install v4l-utils + sudo apt-get --assume-yes install libgtk-3-dev + sudo apt-get --assume-yes install cmake + sudo apt-get --assume-yes install realvnc-vnc-server - echo "Preparing to download OPENCV" + #install OpenCV + currentDir=$PWD + cd $HOME mkdir opencv cd opencv - - echo "downloading OPENCV" wget https://github.com/opencv/opencv/archive/3.4.5.zip - mkdir src - - echo "unzipping OPENCV" - unzip 3.4.5.zip -d src + unzip 3.4.5.zip mkdir build + cmake -S opencv-3.4.5 -B build \ + -DCMAKE_BUILD_TYPE=RELEASE \ + -DCMAKE_INSTALL_PREFIX=/usr/local \ + -DBUILD_TEST=FALSE \ + -DBUILD_JAVA=FALSE \ + -DWITH_GTK=TRUE + cd build - - echo "Preparing to compile OPENCV" - cmake -D CMAKE_BUILD_TYPE=RELEASE \ - -D CMAKE_INSTALL_PREFIX=/usr/local \ - -D WITH_GTK_2_X=FALSE \ - -D WITH_GTK=TRUE \ - -D BUILD_TESTS=FALSE \ - ../src/opencv-3.4.5 - - echo "Compiling OPENCV (this will take a while!)" - sudo make -j2 install + sudo make -j3 install sudo ldconfig - - #return back to normal directory - cd ../.. - - echo "Preparing to compile KIWILIGHT" - mkdir bin - mkdir lib - - echo "Compiling KIWILIGHT" - make -j2 KiwiLight - - echo "KIWILIGHT has been successfully installed." -} - - -echo "Welcome to the KiwiLight installer!" -echo "Installing KiwiLight will download many packages and may take a long time." -echo "Would you like to continue? [y/n]: " - -read -N1 confirm -echo - -if [ ${confirm} = 'y' ]; then - Install - else - echo "Aborting." + cd "$currentDir" + + #prepare KiwiLight + cd $HOME + mkdir KiwiLightData + mkdir KiwiLightData/confs + mkdir KiwiLightData/tmp + cp "$currentDir/generic.xml" KiwiLightData/confs + + cd "$currentDir" + + make setup + make -j4 KiwiLight + sudo ln KiwiLight /usr/bin/KiwiLight + +elif [ $action = "2" ]; +then + echo "Uninstalling" + #uninstall packages + sudo apt-get --assume-yes remove v4l-utils + sudo apt-get --assume-yes remove libgtk-3-dev + sudo apt-get --assume-yes remove cmake + sudo apt-get --assume-yes autoremove + + #uninstall OpenCV + currentDir=$PWD + cd $HOME + cd opencv/build + sudo make -j4 uninstall + sudo rm -r opencv + cd $currentDir + + #remove KiwiLight + rm -r $HOME/KiwiLightData + sudo rm /usr/bin/KiwiLight + +else +echo "That is not a valid option." fi + +echo "Finished!" diff --git a/KiwiLight - Vision Code/out.log b/KiwiLight - Vision Code/out.log deleted file mode 100644 index e69de29..0000000 diff --git a/KiwiLight - Vision Code/runner/CameraFrame.cpp b/KiwiLight - Vision Code/runner/CameraFrame.cpp index fb9ddb2..67acd25 100644 --- a/KiwiLight - Vision Code/runner/CameraFrame.cpp +++ b/KiwiLight - Vision Code/runner/CameraFrame.cpp @@ -29,7 +29,7 @@ CameraFrame::CameraFrame(Mat img, int minimumArea) { } } - this->seenTarget = Target(0, targetContours, 0.0, 0.0, 0.0, 0.0); + this->seenTarget = Target(0, targetContours, 0.0, 0.0, 0.0, 0.0, DistanceCalcMode::BY_WIDTH); } /** diff --git a/KiwiLight - Vision Code/runner/ConfigLearner.cpp b/KiwiLight - Vision Code/runner/ConfigLearner.cpp index 7bad4a6..5e04c13 100644 --- a/KiwiLight - Vision Code/runner/ConfigLearner.cpp +++ b/KiwiLight - Vision Code/runner/ConfigLearner.cpp @@ -60,7 +60,7 @@ void ConfigLearner::FeedImage(Mat img, int minimumContourArea) { contourObjects.push_back(newObject); } - Target targ = Target(0, contourObjects, 0.0, 0.0, 0.0, 0.0); + Target targ = Target(0, contourObjects, 0.0, 0.0, 0.0, 0.0, DistanceCalcMode::BY_WIDTH); rectangle(this->out, targ.Bounds(), Scalar(255, 0, 0), 3); circle(this->out, targ.Center(), 3, Scalar(0,255,0), 4); @@ -171,7 +171,7 @@ ExampleTarget ConfigLearner::StopLearning(int minimumContourArea) { double percentComplete = (((double) i / (double) regularNumberOfContours) * 10.0) + 90.0; } - ExampleTarget newTarget = ExampleTarget(0, finishedContours, 0.0, 0.0, 0.0, 0.0); + ExampleTarget newTarget = ExampleTarget(0, finishedContours, 0.0, 0.0, 0.0, 0.0, DistanceCalcMode::BY_WIDTH); //clear info from the last learn this->currentlyLearning = false; diff --git a/KiwiLight - Vision Code/runner/Contour.cpp b/KiwiLight - Vision Code/runner/Contour.cpp index 0cd6b46..827bdb9 100644 --- a/KiwiLight - Vision Code/runner/Contour.cpp +++ b/KiwiLight - Vision Code/runner/Contour.cpp @@ -1,34 +1,34 @@ -#include "Runner.h" - -/** - * Source file for the Contour class. - * Written By: Brach Knutson - */ - -using namespace cv; -using namespace KiwiLight; - -/** - * Creates a new contour object given the vector of points. - */ -Contour::Contour(std::vector points) { - this->points = points; - - //find out the basic information of the contour - cv::Rect boundingRect = cv::boundingRect(points); - this->x = boundingRect.x; - this->y = boundingRect.y; - this->width = boundingRect.width; - this->height = boundingRect.height; - - int centerX = (this->width / 2) + this->x; - int centerY = (this->height / 2) + this->y; - this->center = Point(centerX, centerY); - - cv::RotatedRect angleRect = cv::minAreaRect(points); - this->angle = (int) angleRect.angle; - this->angle = this->angle % 90; - - int trueArea = cv::contourArea(points); - this->solidity = trueArea / (double) this->Area(); +#include "Runner.h" + +/** + * Source file for the Contour class. + * Written By: Brach Knutson + */ + +using namespace cv; +using namespace KiwiLight; + +/** + * Creates a new contour object given the vector of points. + */ +Contour::Contour(std::vector points) { + this->points = points; + + //find out the basic information of the contour + cv::Rect boundingRect = cv::boundingRect(points); + this->x = boundingRect.x; + this->y = boundingRect.y; + this->width = boundingRect.width; + this->height = boundingRect.height; + + int centerX = (this->width / 2) + this->x; + int centerY = (this->height / 2) + this->y; + this->center = Point(centerX, centerY); + + cv::RotatedRect angleRect = cv::minAreaRect(points); + this->angle = (int) angleRect.angle; + this->angle = this->angle % 90; + + int trueArea = cv::contourArea(points); + this->solidity = trueArea / (double) this->Area(); } \ No newline at end of file diff --git a/KiwiLight - Vision Code/runner/ExampleContour.cpp b/KiwiLight - Vision Code/runner/ExampleContour.cpp index 31a9859..0947afa 100644 --- a/KiwiLight - Vision Code/runner/ExampleContour.cpp +++ b/KiwiLight - Vision Code/runner/ExampleContour.cpp @@ -1,98 +1,98 @@ -#include "Runner.h" - -/** - * Source file for the ExampleContour class. - * Written By: Brach Knutson - */ - -using namespace cv; -using namespace KiwiLight; - -/** - * Creates an instance of the default ExampleContour, a square. - */ -ExampleContour::ExampleContour(int id) { - this->id = id; - this->distX = SettingPair(0, 0.25); - this->distY = SettingPair(0, 0.25); - this->angle = SettingPair(0, 90); - this->aspectRatio = SettingPair(1, 0.25); - this->solidity = SettingPair(1, 0.125); - this->minimumArea = 500; -} - -/** - * Creates an ExampleContour to model a real contour using the given information. - */ -ExampleContour::ExampleContour(int id, SettingPair distX, SettingPair distY, SettingPair angle,SettingPair aspectRatio,SettingPair solidity,int minimumArea) { - this->id = id; - this->distX = distX; - this->distY = distY; - this->angle = angle; - this->aspectRatio = aspectRatio; - this->solidity = solidity; - this->minimumArea = minimumArea; -} - - -bool ExampleContour::IsContour(Contour contour) { - bool angleTest = false; - bool arTest = false; - bool solidTest = false; - bool areaTest = false; - - //conduct all five tests and return result of all five - - bool angleLower = (contour.Angle() > this->angle.LowerBound()); - bool angleUpper = (contour.Angle() < this->angle.UpperBound()); - angleTest = angleLower && angleUpper; - - bool arLower = (contour.AspectRatio() > this->aspectRatio.LowerBound()); - bool arUpper = (contour.AspectRatio() < this->aspectRatio.UpperBound()); - arTest = arLower && arUpper; - - bool solidLower = (contour.Solidity() > this->solidity.LowerBound()); - bool solidUpper = (contour.Solidity() < this->solidity.UpperBound()); - solidTest = solidLower && solidUpper; - - areaTest = (contour.Area() > this->minimumArea); - - return (angleTest && arTest && solidTest && areaTest); -} - -// void SetDistX(SettingPair distX); -// void SetDistY(SettingPair distY); -// void SetAngle(SettingPair angle); -// void SetAspectRatio(SettingPair aspectRatio); -// void SetSolidity(SettingPair solidity); -// void SetMinimumArea(int minimumArea); - - -void ExampleContour::SetDistX(SettingPair distX) { - this->distX = distX; -} - - -void ExampleContour::SetDistY(SettingPair distY) { - this->distY = distY; -} - - -void ExampleContour::SetAngle(SettingPair angle) { - this->angle = angle; -} - - -void ExampleContour::SetAspectRatio(SettingPair aspectRatio) { - this->aspectRatio = aspectRatio; -} - - -void ExampleContour::SetSolidity(SettingPair solidity) { - this->solidity = solidity; -} - - -void ExampleContour::SetMinimumArea(int minimumArea) { - this->minimumArea = minimumArea; +#include "Runner.h" + +/** + * Source file for the ExampleContour class. + * Written By: Brach Knutson + */ + +using namespace cv; +using namespace KiwiLight; + +/** + * Creates an instance of the default ExampleContour, a square. + */ +ExampleContour::ExampleContour(int id) { + this->id = id; + this->distX = SettingPair(0, 0.25); + this->distY = SettingPair(0, 0.25); + this->angle = SettingPair(0, 90); + this->aspectRatio = SettingPair(1, 0.25); + this->solidity = SettingPair(1, 0.125); + this->minimumArea = 500; +} + +/** + * Creates an ExampleContour to model a real contour using the given information. + */ +ExampleContour::ExampleContour(int id, SettingPair distX, SettingPair distY, SettingPair angle,SettingPair aspectRatio,SettingPair solidity,int minimumArea) { + this->id = id; + this->distX = distX; + this->distY = distY; + this->angle = angle; + this->aspectRatio = aspectRatio; + this->solidity = solidity; + this->minimumArea = minimumArea; +} + + +bool ExampleContour::IsContour(Contour contour) { + bool angleTest = false; + bool arTest = false; + bool solidTest = false; + bool areaTest = false; + + //conduct all five tests and return result of all five + + bool angleLower = (contour.Angle() > this->angle.LowerBound()); + bool angleUpper = (contour.Angle() < this->angle.UpperBound()); + angleTest = angleLower && angleUpper; + + bool arLower = (contour.AspectRatio() > this->aspectRatio.LowerBound()); + bool arUpper = (contour.AspectRatio() < this->aspectRatio.UpperBound()); + arTest = arLower && arUpper; + + bool solidLower = (contour.Solidity() > this->solidity.LowerBound()); + bool solidUpper = (contour.Solidity() < this->solidity.UpperBound()); + solidTest = solidLower && solidUpper; + + areaTest = (contour.Area() > this->minimumArea); + + return (angleTest && arTest && solidTest && areaTest); +} + +// void SetDistX(SettingPair distX); +// void SetDistY(SettingPair distY); +// void SetAngle(SettingPair angle); +// void SetAspectRatio(SettingPair aspectRatio); +// void SetSolidity(SettingPair solidity); +// void SetMinimumArea(int minimumArea); + + +void ExampleContour::SetDistX(SettingPair distX) { + this->distX = distX; +} + + +void ExampleContour::SetDistY(SettingPair distY) { + this->distY = distY; +} + + +void ExampleContour::SetAngle(SettingPair angle) { + this->angle = angle; +} + + +void ExampleContour::SetAspectRatio(SettingPair aspectRatio) { + this->aspectRatio = aspectRatio; +} + + +void ExampleContour::SetSolidity(SettingPair solidity) { + this->solidity = solidity; +} + + +void ExampleContour::SetMinimumArea(int minimumArea) { + this->minimumArea = minimumArea; } \ No newline at end of file diff --git a/KiwiLight - Vision Code/runner/ExampleTarget.cpp b/KiwiLight - Vision Code/runner/ExampleTarget.cpp index 8a89bf1..e5c5d9c 100644 --- a/KiwiLight - Vision Code/runner/ExampleTarget.cpp +++ b/KiwiLight - Vision Code/runner/ExampleTarget.cpp @@ -11,19 +11,29 @@ using namespace KiwiLight; /** * Creates a new ExampleTarget with given ExampleContours, to model a real target. */ -ExampleTarget::ExampleTarget(int id, std::vector contours, double knownHeight, double focalHeight, double distErrorCorrect, double calibratedDistance) { +ExampleTarget::ExampleTarget( + int id, + std::vector contours, + double knownHeight, + double focalHeight, + double distErrorCorrect, + double calibratedDistance, + DistanceCalcMode distMode +) { this->id = id; this->contours = contours; this->knownHeight = knownHeight; this->focalHeight = focalHeight; this->distErrorCorrect = distErrorCorrect; this->calibratedDistance = calibratedDistance; + this->distMode = distMode; } /** * returns a vector containing all targets found within the vector of contours. */ std::vector ExampleTarget::GetTargets(std::vector objects) { + std::vector foundTargets = std::vector(); std::vector validContours = std::vector(); @@ -37,7 +47,7 @@ std::vector ExampleTarget::GetTargets(std::vector objects) { std::vector potentialTarget = std::vector(); potentialTarget.push_back(validContours[i]); if(isTarget(potentialTarget)) { - Target newTarg = Target(this->id, potentialTarget, this->knownHeight, this->focalHeight, this->distErrorCorrect, this->calibratedDistance); + Target newTarg = Target(this->id, potentialTarget, this->knownHeight, this->focalHeight, this->distErrorCorrect, this->calibratedDistance, this->distMode); foundTargets.push_back(newTarg); } } @@ -73,7 +83,7 @@ std::vector ExampleTarget::GetTargets(std::vector objects) { //test new target if(isTarget(potentialTarget)) { - Target newTarget = Target(this->id, potentialTarget, this->knownHeight, this->focalHeight, this->distErrorCorrect, this->calibratedDistance); + Target newTarget = Target(this->id, potentialTarget, this->knownHeight, this->focalHeight, this->distErrorCorrect, this->calibratedDistance, this->distMode); foundTargets.push_back(newTarget); } } @@ -114,7 +124,7 @@ bool ExampleTarget::isTarget(std::vector objects) { int totalGood = 0; - Target potentialTarg = Target(0, imageContours, 0, 0, 0, 0); + Target potentialTarg = Target(0, imageContours, 0, 0, 0, 0, this->distMode); int centerX = potentialTarg.Center().x; int centerY = potentialTarg.Center().y; @@ -179,10 +189,7 @@ ExampleContour ExampleTarget::GetExampleContourByID(int id) { void ExampleTarget::SetContourProperty(int contour, TargetProperty prop, SettingPair values) { //get the index of the contour we want to change, that way we directly set the values instead of taking a reference - // //make sure we have a contour with the id "contour" - // while(contour >= this->contours.size()) { - // this->AddGenericContour(); - // } + //make sure we have a contour with the id "contour" if(contour > this->contours.size()) { return; } @@ -268,6 +275,9 @@ void ExampleTarget::SetTargetProperty(RunnerProperty prop, double value) { case RunnerProperty::ERROR_CORRECTION: this->distErrorCorrect = value; break; + case RunnerProperty::CALC_DIST_BY_HEIGHT: + this->distMode = (value == 1 ? DistanceCalcMode::BY_HEIGHT : DistanceCalcMode::BY_WIDTH); + break; } } @@ -288,6 +298,9 @@ double ExampleTarget::GetTargetProperty(RunnerProperty prop) { case RunnerProperty::ERROR_CORRECTION: value = this->distErrorCorrect; break; + case RunnerProperty::CALC_DIST_BY_HEIGHT: + value = (this->distMode == DistanceCalcMode::BY_HEIGHT ? 1 : 0); + break; } return value; diff --git a/KiwiLight - Vision Code/runner/PostProcessor.cpp b/KiwiLight - Vision Code/runner/PostProcessor.cpp index ee71234..d9d176b 100644 --- a/KiwiLight - Vision Code/runner/PostProcessor.cpp +++ b/KiwiLight - Vision Code/runner/PostProcessor.cpp @@ -1,111 +1,111 @@ -#include "Runner.h" - -/** - * Source file for the Runner class. - * Written By: Brach Knutson - */ - -using namespace cv; -using namespace KiwiLight; - -/** - * Creates a new PostProcessor with the given settings. - * Just give it all the runner settings, PostProcessor will pick out the ones it will use. - */ -PostProcessor::PostProcessor(std::vector targets, bool debugging) { - this->debugging = debugging; - this->targets = targets; - ExampleTarget targ = this->targets[0]; -} - -void PostProcessor::SetTarget(int id, ExampleTarget target) { - //find the id to replace - for(int i=0; itargets.size(); i++) { - if(this->targets[i].ID() == id) { - this->targets[i] = target; - return; - } - } -} - -int PostProcessor::NumberOfContours(int target) { - //find the target with the id, and return its contour count - for(int i=0; itargets[i].ID() == target) { - return this->targets[i].Contours().size(); - } - } - - return -1; -} - -/** - * Processes the given image (from the preprocessor) and returns a vector containing any - * targets it finds. - */ -std::vector PostProcessor::ProcessImage(cv::Mat img) { - std::vector foundTargets = std::vector(); - - //find contours with input image - std::vector< std::vector< Point > > contours; - cv::findContours(img, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); - - //create contour wrappers and prepare to compare with targets - std::vector objects = std::vector(); - for(int i=0; icontoursFromLastFrame = objects; - - for(int k=0; ktargets.size(); k++) { - std::vector targs = this->targets[k].GetTargets(objects); - - // add results to our found targets - for(int a=0; a PostProcessor::GetValidContoursForTarget(std::vector contours) { - return this->targets[0].GetValidContours(contours); -} - - -void PostProcessor::SetTargetContourProperty(int contour, TargetProperty prop, SettingPair values) { - if(this->debugging) { - this->targets[0].SetContourProperty(contour, prop, values); - } -} - - -SettingPair PostProcessor::GetTargetContourProperty(int contour, TargetProperty prop) { - return this->targets[0].GetContourProperty(contour, prop); -} - - -ExampleTarget PostProcessor::GetExampleTargetByID(int id) { - for(int i=0; itargets.size(); i++) { - if(this->targets[i].ID() == id) { - return this->targets[i]; - } - } - - std::cout << "WARNING: Target at ID " << id << " does not exist!" << std::endl; - return targets[0]; -} - - -void PostProcessor::SetRunnerProperty(RunnerProperty prop, double value) { - this->targets[0].SetTargetProperty(prop, value); -} - - -double PostProcessor::GetRunnerProperty(RunnerProperty prop) { - return this->targets[0].GetTargetProperty(prop); -} +#include "Runner.h" + +/** + * Source file for the Runner class. + * Written By: Brach Knutson + */ + +using namespace cv; +using namespace KiwiLight; + +/** + * Creates a new PostProcessor with the given settings. + * Just give it all the runner settings, PostProcessor will pick out the ones it will use. + */ +PostProcessor::PostProcessor(std::vector targets, bool debugging) { + this->debugging = debugging; + this->targets = targets; + ExampleTarget targ = this->targets[0]; +} + +void PostProcessor::SetTarget(int id, ExampleTarget target) { + //find the id to replace + for(int i=0; itargets.size(); i++) { + if(this->targets[i].ID() == id) { + this->targets[i] = target; + return; + } + } +} + +int PostProcessor::NumberOfContours(int target) { + //find the target with the id, and return its contour count + for(int i=0; itargets[i].ID() == target) { + return this->targets[i].Contours().size(); + } + } + + return -1; +} + +/** + * Processes the given image (from the preprocessor) and returns a vector containing any + * targets it finds. + */ +std::vector PostProcessor::ProcessImage(cv::Mat img) { + std::vector foundTargets = std::vector(); + + //find contours with input image + std::vector< std::vector< Point > > contours; + cv::findContours(img, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); + + //create contour wrappers and prepare to compare with targets + std::vector objects = std::vector(); + for(int i=0; icontoursFromLastFrame = objects; + + for(int k=0; ktargets.size(); k++) { + std::vector targs = this->targets[k].GetTargets(objects); + + // add results to our found targets + for(int a=0; a PostProcessor::GetValidContoursForTarget(std::vector contours) { + return this->targets[0].GetValidContours(contours); +} + + +void PostProcessor::SetTargetContourProperty(int contour, TargetProperty prop, SettingPair values) { + if(this->debugging) { + this->targets[0].SetContourProperty(contour, prop, values); + } +} + + +SettingPair PostProcessor::GetTargetContourProperty(int contour, TargetProperty prop) { + return this->targets[0].GetContourProperty(contour, prop); +} + + +ExampleTarget PostProcessor::GetExampleTargetByID(int id) { + for(int i=0; itargets.size(); i++) { + if(this->targets[i].ID() == id) { + return this->targets[i]; + } + } + + std::cout << "WARNING: Target at ID " << id << " does not exist!" << std::endl; + return targets[0]; +} + + +void PostProcessor::SetRunnerProperty(RunnerProperty prop, double value) { + this->targets[0].SetTargetProperty(prop, value); +} + + +double PostProcessor::GetRunnerProperty(RunnerProperty prop) { + return this->targets[0].GetTargetProperty(prop); +} diff --git a/KiwiLight - Vision Code/runner/PreProcessor.cpp b/KiwiLight - Vision Code/runner/PreProcessor.cpp index f1e3aa3..e3dfc02 100644 --- a/KiwiLight - Vision Code/runner/PreProcessor.cpp +++ b/KiwiLight - Vision Code/runner/PreProcessor.cpp @@ -1,148 +1,148 @@ -#include "Runner.h" - -/** - * Source file for the PreProcessor class. - * Written By: Brach Knutson - */ - -using namespace cv; -using namespace KiwiLight; - - -PreProcessor::PreProcessor(bool fullPreprocessor, Color targetColor, int threshold, int erosion, int dilation, bool debug) { - this->isFullPreprocessor = fullPreprocessor; - this->debugging = debug; - this->targetColor = targetColor; - this->threshold = threshold; - this->threshValue = 255; - this->threshtype = 0; - this->erode = erosion; - this->dilate = dilation; -} - - -/** - * Takes the given generic image and makes it usable for the PostProcessor. - */ -cv::Mat PreProcessor::ProcessImage(cv::Mat img) { - cv::Mat out; - - if(this->isFullPreprocessor) { - cv::threshold(img, img, this->threshold, this->threshValue, this->threshtype); - cv::Mat dilateKernel = cv::getStructuringElement(cv::MORPH_RECT, - cv::Size(this->dilate, this->dilate)); - - cv::Mat erodeKernel = cv::getStructuringElement(cv::MORPH_RECT, - cv::Size(this->erode, this->erode)); - - cv::erode(img, img, erodeKernel); - cv::dilate(img, img, dilateKernel); - cv::cvtColor(img, img, cv::COLOR_BGR2HSV); - cv::inRange(img, this->targetColor.GetLowerBound(), this->targetColor.GetUpperBound(), out); - } else { - cv::cvtColor(img, out, cv::COLOR_BGR2GRAY); - } - - return out; -} - - -void PreProcessor::SetProperty(PreProcessorProperty prop, double value) { - switch(prop) { - case PreProcessorProperty::IS_FULL: - this->isFullPreprocessor = (value == 1 ? true : false); - break; - case PreProcessorProperty::THRESHOLD: - this->threshold = value; - break; - case PreProcessorProperty::EROSION: - this->erode = value; - break; - case PreProcessorProperty::DILATION: - this->dilate = value; - break; - case PreProcessorProperty::COLOR_HUE: - { - Color newColor = Color((int) value, this->targetColor.GetS(), this->targetColor.GetV(), this->targetColor.GetHError(), this->targetColor.GetSError(), this->targetColor.GetVError()); - this->targetColor = newColor; - break; - } - case PreProcessorProperty::COLOR_SATURATION: - { - Color newColor = Color(this->targetColor.GetH(), (int) value, this->targetColor.GetV(), this->targetColor.GetHError(), this->targetColor. GetSError(), this->targetColor.GetVError()); - this->targetColor = newColor; - break; - } - case PreProcessorProperty::COLOR_VALUE: - { - Color newColor = Color(this->targetColor.GetH(), this->targetColor.GetS(), (int) value, this->targetColor.GetHError(), this->targetColor.GetSError(), this->targetColor.GetVError()); - this->targetColor = newColor; - break; - } - - case PreProcessorProperty::COLOR_ERROR: - { - Color newColor = Color(this->targetColor.GetH(), this->targetColor.GetS(), this->targetColor.GetV(), value, value, value); - this->targetColor = newColor; - break; - } - } -} - - -double PreProcessor::GetProperty(PreProcessorProperty prop) { - double finalValue = -1.0; - - switch(prop) { - case PreProcessorProperty::IS_FULL: - finalValue = (this->isFullPreprocessor ? 1 : 0); - break; - case PreProcessorProperty::THRESHOLD: - finalValue = this->threshold; - break; - case PreProcessorProperty::EROSION: - finalValue = this->erode; - break; - case PreProcessorProperty::DILATION: - finalValue = this->dilate; - break; - case PreProcessorProperty::COLOR_HUE: - finalValue = this->targetColor.GetH(); - break; - case PreProcessorProperty::COLOR_SATURATION: - finalValue = this->targetColor.GetS(); - break; - case PreProcessorProperty::COLOR_VALUE: - finalValue = this->targetColor.GetV(); - break; - case PreProcessorProperty::COLOR_ERROR: - finalValue = this->targetColor.GetHError(); - break; - default: - std::cout << "PROPERTY NOT FOUND" << std::endl; - break; - } - - return finalValue; -} - - -std::string PreProcessor::toString() { - std::string endline = "\n"; - std::string thisString = ""; - thisString += std::string("Debugging: ") + std::string((this->debugging ? "YES" : "NO")) + endline; - - if(this->isFullPreprocessor) { - std::string("Type: FULL\n") + - std::string("Threshold Value: ") + std::to_string(this->threshold) + endline + - std::string("Dilation: ") + std::to_string(this->dilate) + endline + - std::string("Color H: ") + std::to_string(this->targetColor.GetH()) + endline + - std::string("Color S: ") + std::to_string(this->targetColor.GetS()) + endline + - std::string("Color V: ") + std::to_string(this->targetColor.GetV()) + endline + - std::string("Color Error: ") + std::to_string(this->targetColor.GetHError()) + endline; - } else { - thisString += std::string("Type: PARTIAL") + endline; - } - - return thisString; -} +#include "Runner.h" + +/** + * Source file for the PreProcessor class. + * Written By: Brach Knutson + */ + +using namespace cv; +using namespace KiwiLight; + + +PreProcessor::PreProcessor(bool fullPreprocessor, Color targetColor, int threshold, int erosion, int dilation, bool debug) { + this->isFullPreprocessor = fullPreprocessor; + this->debugging = debug; + this->targetColor = targetColor; + this->threshold = threshold; + this->threshValue = 255; + this->threshtype = 0; + this->erode = erosion; + this->dilate = dilation; +} + + +/** + * Takes the given generic image and makes it usable for the PostProcessor. + */ +cv::Mat PreProcessor::ProcessImage(cv::Mat img) { + cv::Mat out; + + if(this->isFullPreprocessor) { + cv::threshold(img, img, this->threshold, this->threshValue, this->threshtype); + cv::Mat dilateKernel = cv::getStructuringElement(cv::MORPH_RECT, + cv::Size(this->dilate, this->dilate)); + + cv::Mat erodeKernel = cv::getStructuringElement(cv::MORPH_RECT, + cv::Size(this->erode, this->erode)); + + cv::erode(img, img, erodeKernel); + cv::dilate(img, img, dilateKernel); + cv::cvtColor(img, img, cv::COLOR_BGR2HSV); + cv::inRange(img, this->targetColor.GetLowerBound(), this->targetColor.GetUpperBound(), out); + } else { + cv::cvtColor(img, out, cv::COLOR_BGR2GRAY); + } + + return out; +} + + +void PreProcessor::SetProperty(PreProcessorProperty prop, double value) { + switch(prop) { + case PreProcessorProperty::IS_FULL: + this->isFullPreprocessor = (value == 1 ? true : false); + break; + case PreProcessorProperty::THRESHOLD: + this->threshold = value; + break; + case PreProcessorProperty::EROSION: + this->erode = value; + break; + case PreProcessorProperty::DILATION: + this->dilate = value; + break; + case PreProcessorProperty::COLOR_HUE: + { + Color newColor = Color((int) value, this->targetColor.GetS(), this->targetColor.GetV(), this->targetColor.GetHError(), this->targetColor.GetSError(), this->targetColor.GetVError()); + this->targetColor = newColor; + break; + } + case PreProcessorProperty::COLOR_SATURATION: + { + Color newColor = Color(this->targetColor.GetH(), (int) value, this->targetColor.GetV(), this->targetColor.GetHError(), this->targetColor. GetSError(), this->targetColor.GetVError()); + this->targetColor = newColor; + break; + } + case PreProcessorProperty::COLOR_VALUE: + { + Color newColor = Color(this->targetColor.GetH(), this->targetColor.GetS(), (int) value, this->targetColor.GetHError(), this->targetColor.GetSError(), this->targetColor.GetVError()); + this->targetColor = newColor; + break; + } + + case PreProcessorProperty::COLOR_ERROR: + { + Color newColor = Color(this->targetColor.GetH(), this->targetColor.GetS(), this->targetColor.GetV(), value, value, value); + this->targetColor = newColor; + break; + } + } +} + + +double PreProcessor::GetProperty(PreProcessorProperty prop) { + double finalValue = -1.0; + + switch(prop) { + case PreProcessorProperty::IS_FULL: + finalValue = (this->isFullPreprocessor ? 1 : 0); + break; + case PreProcessorProperty::THRESHOLD: + finalValue = this->threshold; + break; + case PreProcessorProperty::EROSION: + finalValue = this->erode; + break; + case PreProcessorProperty::DILATION: + finalValue = this->dilate; + break; + case PreProcessorProperty::COLOR_HUE: + finalValue = this->targetColor.GetH(); + break; + case PreProcessorProperty::COLOR_SATURATION: + finalValue = this->targetColor.GetS(); + break; + case PreProcessorProperty::COLOR_VALUE: + finalValue = this->targetColor.GetV(); + break; + case PreProcessorProperty::COLOR_ERROR: + finalValue = this->targetColor.GetHError(); + break; + default: + std::cout << "PROPERTY NOT FOUND" << std::endl; + break; + } + + return finalValue; +} + + +std::string PreProcessor::toString() { + std::string endline = "\n"; + std::string thisString = ""; + thisString += std::string("Debugging: ") + std::string((this->debugging ? "YES" : "NO")) + endline; + + if(this->isFullPreprocessor) { + std::string("Type: FULL\n") + + std::string("Threshold Value: ") + std::to_string(this->threshold) + endline + + std::string("Dilation: ") + std::to_string(this->dilate) + endline + + std::string("Color H: ") + std::to_string(this->targetColor.GetH()) + endline + + std::string("Color S: ") + std::to_string(this->targetColor.GetS()) + endline + + std::string("Color V: ") + std::to_string(this->targetColor.GetV()) + endline + + std::string("Color Error: ") + std::to_string(this->targetColor.GetHError()) + endline; + } else { + thisString += std::string("Type: PARTIAL") + endline; + } + + return thisString; +} diff --git a/KiwiLight - Vision Code/runner/Runner.cpp b/KiwiLight - Vision Code/runner/Runner.cpp index 494048d..e801ddf 100644 --- a/KiwiLight - Vision Code/runner/Runner.cpp +++ b/KiwiLight - Vision Code/runner/Runner.cpp @@ -1,416 +1,378 @@ -#include "../KiwiLight.h" - -/** - * Source file for the Runner class. - * Written By: Brach Knutson - */ - -using namespace cv; -using namespace KiwiLight; - -const std::string Runner::NULL_MESSAGE = ":-1,-1,-1,180,180;"; - -/** - * Creates a new runner which runs the configuration described by the given file - */ -Runner::Runner(std::string fileName, bool debugging) { - this->src = fileName; - this->debug = debugging; - this->postProcessorTargets = std::vector(); - this->lastIterationSuccessful = false; - XMLDocument file = XMLDocument(fileName); - if(file.HasContents()) { - this->parseDocument(file); - } else { - std::cout << "sorry! the file " << fileName << " could not be found. " << std::endl; - } - this->applySettings(file); - this->stop = false; -} - -void Runner::SetImageResize(Size sz) { - this->constantResize = sz; -} - -/** - * Puts the runner in a constant loop, and sends finished UDP messages. - * This method would be used in normal FRC situations - */ -void Runner::Loop() { - //give some information to stdout about the config - std::cout << std::endl; - std::cout << "------------------------------------" << std::endl; - std::cout << "KiwiLight Runner starting..." << std::endl; - std::cout << " Mode: " << (this->debug ? "Debug" : "Running") << std::endl; - std::cout << " Configuration Name: " << this->configName << std::endl; - std::cout << " Camera Index: " << this->cameraIndex << std::endl; - std::cout << " Preprocessor: " << (this->preprocessor.GetProperty(PreProcessorProperty::IS_FULL) == 1.0 ? "FULL" : "PARTIAL") << std::endl; - std::cout << " Postprocessor: FULL" << std::endl; - std::cout << " Number of Contours: " << this->postProcessorTargets[0].Contours().size() << std::endl; - std::cout << " UDP Destination Address: " << this->udp.GetAddress() << std::endl; - std::cout << " UDP Port: " << std::to_string(this->udp.GetPort()) << std::endl; - std::cout << "------------------------------------" << std::endl; - std::cout << std::endl; - - std::cout << "Waiting for UDP to connect" << std::endl; - while(true) { - bool connectSuccess = this->udp.AttemptToConnect(); - if(connectSuccess) { - std::cout << "UDP connected successfully." << std::endl; - break; - } - } - - //loops a lot until stopped - while(!stop) { - try { - //run algorithm and get the udp message to send to rio - std::string output = this->Iterate(); - this->udp.Send(output); - } catch(cv::Exception ex) { - std::cout << "An OpenCv Exception was encountered in the Loop!" << std::endl; - std::cout << "ex.what(): " << ex.what() << std::endl; - } - } -} - -/** - * Performs one iteration of the main loop, but does not send any file UDP messages. - */ -std::string Runner::Iterate() { - cv::Mat img; - cv::Mat out; //output image we draw on for debugging - if(RunnerSettings::USE_CAMERA) { - img = KiwiLightApp::TakeImage(); - - if(img.empty()) { - //oops we shall exit now because there be nothing in image - return NULL_MESSAGE; - } - } else { - this->lastIterationSuccessful = true; - img = cv::imread(RunnerSettings::IMAGE_TO_USE); - } - - resize(img, img, this->constantResize); - img.copyTo(this->originalImage); - img = this->preprocessor.ProcessImage(img); - img.copyTo(out); - std::vector targets = this->postprocessor.ProcessImage(img); - //find the percieved robot center using this->centerOffset - int trueCenterX = (this->constantResize.width / 2); - int robotCenterX = trueCenterX; - - int trueCenterY = (this->constantResize.height / 2); - int robotCenterY = trueCenterY; - - //find the target that is closest to the robot center - Target bestTarget; - int closestDist = 5000; // closest horizontal distance to the center - for(int i=0; icenterOffsetX; - double offestInchesY = centerInchesY - this->centerOffsetY; - - //convert back to pixels - double offsetPixelsX = offsetInchesX / inchesPerPixel; - double offsetPixelsY = offestInchesY / inchesPerPixel; - - //calculate the distance from the offset center - double distFromCenterX = offsetPixelsX - targ.Center().x; - double distFromCenterY = offsetPixelsY - targ.Center().y; - double trueDistance = sqrt(pow(distFromCenterX, 2) + pow(distFromCenterY, 2)); - - if(trueDistance < closestDist) { - closestDist = trueDistance; - bestTarget = targ; - robotCenterX = (int) offsetPixelsX; - robotCenterY = (int) offsetPixelsY; - } - } - - this->closestTarget = bestTarget; - - //figure out which target to send and then send the target - int coordX = -1, - coordY = -1, - distance = -1, - HAngle = 180, - VAngle = 180; - - std::string rioMessage = ""; - - if(targets.size() > 0) { - //use the best target to fill in the information to send to the rio - coordX = bestTarget.Center().x; - coordY = bestTarget.Center().y; - - distance = bestTarget.Distance(); - - HAngle = bestTarget.HorizontalAngle(distance, robotCenterX); - VAngle = bestTarget.VerticalAngle(distance, robotCenterY); - } - - this->lastFrameTargets = targets; - - std::string x = std::to_string(coordX), - y = std::to_string(coordY), - d = std::to_string(distance), - ax = std::to_string(HAngle), - ay = std::to_string(VAngle); - - rioMessage = ":" + x + "," + y + "," + d + "," + ax + "," + ay + ";"; - - //mark up the image with some stuff for the programmers to look at :) - if(this->debug) { - cv::cvtColor(out, out, cv::COLOR_GRAY2BGR); - - //write the out string onto the image - cv::putText(out, rioMessage, cv::Point(5, 15), cv::FONT_HERSHEY_PLAIN, 1.0, cv::Scalar(0,0,255), 2); - - //draw a line where the perceived horizontal robot center is - int camHeight = this->constantResize.height; - cv::Point HlineTopPoint = cv::Point(robotCenterX, 0); - cv::Point HlineBottomPoint = cv::Point(robotCenterX, camHeight); - cv::line(out, HlineTopPoint, HlineBottomPoint, cv::Scalar(255,0,255)); - - //draw another line where the vertical robot center is - int camWidth = this->constantResize.width; - cv::Point VlineTopPoint = cv::Point(0, robotCenterY); - cv::Point VlineBottomPoint = cv::Point(camWidth, robotCenterY); - cv::line(out, VlineTopPoint, VlineBottomPoint, cv::Scalar(255, 0, 255)); - - //draw a dot in the center of each valid contour - std::vector contoursFromFrame = this->postprocessor.GetContoursFromLastFrame(); - std::vector validContours = this->postprocessor.GetValidContoursForTarget(contoursFromFrame); - - Target targ = Target(0, validContours, 0, 0, 0, 0); - rectangle(out, targ.Bounds(), Scalar(0, 0, 255), 3); - - for(int i=0; ioutputImage); - } - - return rioMessage; -} - - -int Runner::GetNumberOfContours(int target) { - return this->postprocessor.NumberOfContours(target); -} - -/** - * Returns the example target at the given id. Returns the 0th exampletarget if id is out of bounds. - */ -ExampleTarget Runner::GetExampleTargetByID(int id) { - return this->postprocessor.GetExampleTargetByID(id); -} - -void Runner::SetExampleTarget(int contourID, ExampleTarget target) { - this->postprocessor.SetTarget(contourID, target); -} - -void Runner::ReconnectUDP(std::string udpAddr, int udpPort) { - this->udp = UDP(udpAddr, udpPort); -} - -void Runner::SendOverUDP(std::string message) { - this->udp.Send(message); -} - -void Runner::SetPreprocessorProperty(PreProcessorProperty prop, double value) { - if(this->debug) { - this->preprocessor.SetProperty(prop, value); - } -} - - -double Runner::GetPreprocessorProperty(PreProcessorProperty prop) { - return this->preprocessor.GetProperty(prop); -} - - -void Runner::SetPostProcessorContourProperty(int contour, TargetProperty prop, SettingPair values) { - if(this->debug) { - this->postprocessor.SetTargetContourProperty(contour, prop, values); - } -} - - -SettingPair Runner::GetPostProcessorContourProperty(int contour, TargetProperty prop) { - return this->postprocessor.GetTargetContourProperty(contour, prop); -} - - -void Runner::SetRunnerProperty(RunnerProperty prop, double value) { - switch(prop) { - case RunnerProperty::OFFSET_X: - this->centerOffsetX = value; - break; - case RunnerProperty::OFFSET_Y: - this->centerOffsetY = value; - break; - case RunnerProperty::IMAGE_WIDTH: - this->constantResize.width = (int) value; - break; - case RunnerProperty::IMAGE_HEIGHT: - this->constantResize.height = (int) value; - break; - default: - this->postprocessor.SetRunnerProperty(prop, value); - break; - } -} - - -double Runner::GetRunnerProperty(RunnerProperty prop) { - switch(prop) { - case RunnerProperty::OFFSET_X: - return this->centerOffsetX; - case RunnerProperty::OFFSET_Y: - return this->centerOffsetY; - case RunnerProperty::IMAGE_WIDTH: - return this->constantResize.width; - case RunnerProperty::IMAGE_HEIGHT: - return this->constantResize.height; - } - - return this->postprocessor.GetRunnerProperty(prop); -} - -/** - * Parses the XMLdocument doc and initalizes all runner settings and variables. - */ -void Runner::parseDocument(XMLDocument doc) { - XMLTag camera = doc.GetTagsByName("camera")[0]; - this->cameraIndex = std::stoi(camera.GetAttributesByName("index")[0].Value()); - - std::vector camSettings = - camera.GetTagsByName("settings")[0] - .GetTagsByName("setting"); - - XMLTag config = doc.GetTagsByName("configuration")[0]; - this->configName = doc.GetTagsByName("configuration")[0].GetAttributesByName("name")[0].Value(); - - XMLTag cameraOffset = config.GetTagsByName("cameraOffset")[0]; - this->centerOffsetX = std::stod(cameraOffset.GetTagsByName("horizontal")[0].Content()); - this->centerOffsetY = std::stod(cameraOffset.GetTagsByName("vertical")[0].Content()); - - XMLTag constResize = config.GetTagsByName("constantResize")[0]; - int resizeX = std::stoi(constResize.GetTagsByName("width")[0].Content()); - int resizeY = std::stoi(constResize.GetTagsByName("height")[0].Content()); - this->constantResize = Size(resizeX, resizeY); - - XMLTag preprocess = config.GetTagsByName("preprocessor")[0]; - bool preprocessorTypeIsFull = (preprocess.GetAttributesByName("type")[0].Value() == "full" ? true : false); - - int preprocessorThreshold = std::stoi(preprocess.GetTagsByName("threshold")[0].Content()); - int preprocessorErosion = std::stoi(preprocess.GetTagsByName("erosion")[0].Content()); - int preprocessorDilation = std::stoi(preprocess.GetTagsByName("dilation")[0].Content()); - XMLTag color = preprocess.GetTagsByName("targetColor")[0]; - int error = std::stoi(color.GetAttributesByName("error")[0].Value()); - int h = std::stoi(color.GetTagsByName("h")[0].Content()); - int s = std::stoi(color.GetTagsByName("s")[0].Content()); - int v = std::stoi(color.GetTagsByName("v")[0].Content()); - Color preprocessorColor = Color(h, s, v, error, error, error); - - XMLTag postprocess = config.GetTagsByName("postprocessor")[0]; - XMLTag udp = postprocess.GetTagsByName("UDP")[0]; - std::string udpAddr = udp.GetTagsByName("address")[0].Content(); - int udpPort = std::stoi(udp.GetTagsByName("port")[0].Content()); - - std::vector targets = postprocess.GetTagsByName("target"); - for(int i=0; i targContours = targetTag.GetTagsByName("contour"); - - int targetId = std::stoi(targetTag.GetAttributesByName("id")[0].Value()); - std::vector contours; - - //find all contours and populate the vector - for(int k=0; kpostProcessorTargets.push_back(newTarget); - } - - //init the preprocessor and postprocessor here - this->preprocessor = PreProcessor(preprocessorTypeIsFull, preprocessorColor, preprocessorThreshold, preprocessorErosion, preprocessorDilation, this->debug); - this->postprocessor = PostProcessor(this->postProcessorTargets, this->debug); - this->udp = UDP(udpAddr, udpPort); -} - -/** - * Applies the camera settings via shell. - */ -void Runner::applySettings(XMLDocument document) { - std::vector camSettings = - document.GetTagsByName("camera")[0] - .GetTagsByName("settings")[0] - .GetTagsByName("setting"); - - int camIndex = std::stoi(document.GetTagsByName("camera")[0].GetAttributesByName("index")[0].Value()); - KiwiLightApp::OpenNewCameraOnIndex(camIndex); - - for(int i=0; isrc = fileName; + this->debug = debugging; + this->postProcessorTargets = std::vector(); + this->lastIterationSuccessful = false; + XMLDocument file = XMLDocument(fileName); + if(file.HasContents()) { + this->parseDocument(file); + } else { + std::cout << "sorry! the file " << fileName << " could not be found. " << std::endl; + } + this->applySettings(file); + this->stop = false; +} + +void Runner::SetImageResize(Size sz) { + this->constantResize = sz; +} + +/** + * Performs one iteration of the main loop, but does not send any file UDP messages. + */ +std::string Runner::Iterate() { + cv::Mat img; + cv::Mat out; //output image we draw on for debugging + if(RunnerSettings::USE_CAMERA) { + img = KiwiLightApp::TakeImage(); + + if(img.empty()) { + //oops we shall exit now because there be nothing in image + return NULL_MESSAGE; + } + } else { + this->lastIterationSuccessful = true; + img = cv::imread(RunnerSettings::IMAGE_TO_USE); + } + + resize(img, img, this->constantResize); + img.copyTo(this->originalImage); + img = this->preprocessor.ProcessImage(img); + img.copyTo(out); + std::vector targets = this->postprocessor.ProcessImage(img); + //find the percieved robot center using this->centerOffset + int trueCenterX = (this->constantResize.width / 2); + int robotCenterX = trueCenterX; + + int trueCenterY = (this->constantResize.height / 2); + int robotCenterY = trueCenterY; + + //find the target that is closest to the robot center + Target bestTarget; + int closestDist = 5000; // closest horizontal distance to the center + for(int i=0; icenterOffsetX; + double offestInchesY = centerInchesY - this->centerOffsetY; + + //convert back to pixels + double offsetPixelsX = offsetInchesX / inchesPerPixel; + double offsetPixelsY = offestInchesY / inchesPerPixel; + + //calculate the distance from the offset center + double distFromCenterX = offsetPixelsX - targ.Center().x; + double distFromCenterY = offsetPixelsY - targ.Center().y; + double trueDistance = sqrt(pow(distFromCenterX, 2) + pow(distFromCenterY, 2)); + + if(trueDistance < closestDist) { + closestDist = trueDistance; + bestTarget = targ; + robotCenterX = (int) offsetPixelsX; + robotCenterY = (int) offsetPixelsY; + } + } + + this->closestTarget = bestTarget; + this->lastFrameCenterPoint = Point(robotCenterX, robotCenterY); + + //figure out which target to send and then send the target + int coordX = -1, + coordY = -1, + width = -1, + height = -1, + distance = -1, + HAngle = 180, + VAngle = 180; + + std::string rioMessage = ""; + + if(targets.size() > 0) { + //use the best target to fill in the information to send to the rio + coordX = bestTarget.Center().x; + coordY = bestTarget.Center().y; + + width = bestTarget.Bounds().width; + height = bestTarget.Bounds().height; + + distance = bestTarget.Distance(); + + HAngle = bestTarget.HorizontalAngle(distance, robotCenterX); + VAngle = bestTarget.VerticalAngle(distance, robotCenterY); + } + + this->lastFrameTargets = targets; + + std::string x = std::to_string(coordX), + y = std::to_string(coordY), + w = std::to_string(width), + h = std::to_string(height), + d = std::to_string(distance), + ax = std::to_string(HAngle), + ay = std::to_string(VAngle); + + rioMessage = ":" + x + "," + y + "," + w + "," + h +"," + d + "," + ax + "," + ay + ";"; + + //mark up the image with some stuff for the programmers to look at :) + if(this->debug) { + cv::cvtColor(out, out, cv::COLOR_GRAY2BGR); + + //write the out string onto the image + cv::putText(out, rioMessage, cv::Point(5, 15), cv::FONT_HERSHEY_PLAIN, 1.0, cv::Scalar(0,0,255), 2); + + //draw a line where the perceived horizontal robot center is + int camHeight = this->constantResize.height; + cv::Point HlineTopPoint = cv::Point(robotCenterX, 0); + cv::Point HlineBottomPoint = cv::Point(robotCenterX, camHeight); + cv::line(out, HlineTopPoint, HlineBottomPoint, cv::Scalar(255,0,255)); + + //draw another line where the vertical robot center is + int camWidth = this->constantResize.width; + cv::Point VlineTopPoint = cv::Point(0, robotCenterY); + cv::Point VlineBottomPoint = cv::Point(camWidth, robotCenterY); + cv::line(out, VlineTopPoint, VlineBottomPoint, cv::Scalar(255, 0, 255)); + + //draw a dot in the center of each valid contour + std::vector contoursFromFrame = this->postprocessor.GetContoursFromLastFrame(); + std::vector validContours = this->postprocessor.GetValidContoursForTarget(contoursFromFrame); + + Target targ = Target(0, validContours, 0, 0, 0, 0, DistanceCalcMode::BY_WIDTH); + rectangle(out, targ.Bounds(), Scalar(0, 0, 255), 3); + + for(int i=0; ioutputImage); + } + + return rioMessage; +} + + +int Runner::GetNumberOfContours(int target) { + return this->postprocessor.NumberOfContours(target); +} + +/** + * Returns the example target at the given id. Returns the 0th exampletarget if id is out of bounds. + */ +ExampleTarget Runner::GetExampleTargetByID(int id) { + return this->postprocessor.GetExampleTargetByID(id); +} + +void Runner::SetExampleTarget(int contourID, ExampleTarget target) { + this->postprocessor.SetTarget(contourID, target); +} + + +void Runner::SetPreprocessorProperty(PreProcessorProperty prop, double value) { + if(this->debug) { + this->preprocessor.SetProperty(prop, value); + } +} + + +double Runner::GetPreprocessorProperty(PreProcessorProperty prop) { + return this->preprocessor.GetProperty(prop); +} + + +void Runner::SetPostProcessorContourProperty(int contour, TargetProperty prop, SettingPair values) { + if(this->debug) { + this->postprocessor.SetTargetContourProperty(contour, prop, values); + } +} + + +SettingPair Runner::GetPostProcessorContourProperty(int contour, TargetProperty prop) { + return this->postprocessor.GetTargetContourProperty(contour, prop); +} + + +void Runner::SetRunnerProperty(RunnerProperty prop, double value) { + switch(prop) { + case RunnerProperty::OFFSET_X: + this->centerOffsetX = value; + break; + case RunnerProperty::OFFSET_Y: + this->centerOffsetY = value; + break; + case RunnerProperty::IMAGE_WIDTH: + this->constantResize.width = (int) value; + break; + case RunnerProperty::IMAGE_HEIGHT: + this->constantResize.height = (int) value; + break; + default: + this->postprocessor.SetRunnerProperty(prop, value); + break; + } +} + + +double Runner::GetRunnerProperty(RunnerProperty prop) { + switch(prop) { + case RunnerProperty::OFFSET_X: + return this->centerOffsetX; + case RunnerProperty::OFFSET_Y: + return this->centerOffsetY; + case RunnerProperty::IMAGE_WIDTH: + return this->constantResize.width; + case RunnerProperty::IMAGE_HEIGHT: + return this->constantResize.height; + } + + return this->postprocessor.GetRunnerProperty(prop); +} + +/** + * Parses the XMLdocument doc and initalizes all runner settings and variables. + */ +void Runner::parseDocument(XMLDocument doc) { + XMLTag camera = doc.GetTagsByName("camera")[0]; + this->cameraIndex = std::stoi(camera.GetAttributesByName("index")[0].Value()); + + std::vector camSettings = + camera.GetTagsByName("settings")[0] + .GetTagsByName("setting"); + + XMLTag config = doc.GetTagsByName("configuration")[0]; + this->configName = doc.GetTagsByName("configuration")[0].GetAttributesByName("name")[0].Value(); + + XMLTag cameraOffset = config.GetTagsByName("cameraOffset")[0]; + this->centerOffsetX = std::stod(cameraOffset.GetTagsByName("horizontal")[0].Content()); + this->centerOffsetY = std::stod(cameraOffset.GetTagsByName("vertical")[0].Content()); + + XMLTag constResize = config.GetTagsByName("constantResize")[0]; + int resizeX = std::stoi(constResize.GetTagsByName("width")[0].Content()); + int resizeY = std::stoi(constResize.GetTagsByName("height")[0].Content()); + this->constantResize = Size(resizeX, resizeY); + + XMLTag preprocess = config.GetTagsByName("preprocessor")[0]; + bool preprocessorTypeIsFull = (preprocess.GetAttributesByName("type")[0].Value() == "full" ? true : false); + + int preprocessorThreshold = std::stoi(preprocess.GetTagsByName("threshold")[0].Content()); + int preprocessorErosion = std::stoi(preprocess.GetTagsByName("erosion")[0].Content()); + int preprocessorDilation = std::stoi(preprocess.GetTagsByName("dilation")[0].Content()); + XMLTag color = preprocess.GetTagsByName("targetColor")[0]; + int error = std::stoi(color.GetAttributesByName("error")[0].Value()); + int h = std::stoi(color.GetTagsByName("h")[0].Content()); + int s = std::stoi(color.GetTagsByName("s")[0].Content()); + int v = std::stoi(color.GetTagsByName("v")[0].Content()); + Color preprocessorColor = Color(h, s, v, error, error, error); + + XMLTag postprocess = config.GetTagsByName("postprocessor")[0]; + XMLTag udp = postprocess.GetTagsByName("UDP")[0]; + std::string udpAddr = udp.GetTagsByName("address")[0].Content(); + int udpPort = std::stoi(udp.GetTagsByName("port")[0].Content()); + + std::vector targets = postprocess.GetTagsByName("target"); + for(int i=0; i targContours = targetTag.GetTagsByName("contour"); + + int targetId = std::stoi(targetTag.GetAttributesByName("id")[0].Value()); + std::vector contours; + + //find all contours and populate the vector + for(int k=0; kpostProcessorTargets.push_back(newTarget); + } + + //init the preprocessor and postprocessor here + this->preprocessor = PreProcessor(preprocessorTypeIsFull, preprocessorColor, preprocessorThreshold, preprocessorErosion, preprocessorDilation, this->debug); + this->postprocessor = PostProcessor(this->postProcessorTargets, this->debug); + KiwiLightApp::ReconnectUDP(udpAddr, udpPort); +} + +/** + * Applies the camera settings via shell. + */ +void Runner::applySettings(XMLDocument document) { + std::vector camSettings = + document.GetTagsByName("camera")[0] + .GetTagsByName("settings")[0] + .GetTagsByName("setting"); + + int camIndex = std::stoi(document.GetTagsByName("camera")[0].GetAttributesByName("index")[0].Value()); + KiwiLightApp::OpenNewCameraOnIndex(camIndex); + + for(int i=0; i contours, double knownHeight, double focalHeight, double distErrorCorrect, double calibratedDistance); + Target(int id, std::vector contours, double knownHeight, double focalHeight, double distErrorCorrect, double calibratedDistance, DistanceCalcMode distMode); int ID() { return this->id; }; std::vector Contours() { return this->contours; }; double Distance(); + double Distance(DistanceCalcMode mode); int HorizontalAngle(int imageCenterX); int HorizontalAngle(double distanceToTarget, int imageCenterX); int VerticalAngle(int imageCenterY); int VerticalAngle(double distanceToTarget, int imageCenterY); + int ObliqueAngle(int imageCenterX, int imageCenterY); double KnownWidth() { return this->knownHeight; }; double FocalWidth() { return this->focalHeight; }; double DistanceErrorCorrection() { return this->distErrorCorrect; }; @@ -178,13 +188,15 @@ namespace KiwiLight { focalHeight, distErrorCorrect, calibratedDistance; + + DistanceCalcMode distMode; }; class ExampleTarget { public: ExampleTarget() {}; - ExampleTarget(int id, std::vector contours, double knownHeight, double focalHeight, double distErrorCorrect, double calibratedDistance); + ExampleTarget(int id, std::vector contours, double knownHeight, double focalHeight, double distErrorCorrect, double calibratedDistance, DistanceCalcMode mode); std::vector GetTargets(std::vector contours); bool isTarget(std::vector contours); std::vector GetValidContours(std::vector contours); @@ -208,6 +220,8 @@ namespace KiwiLight { focalHeight, distErrorCorrect, calibratedDistance; + + DistanceCalcMode distMode; }; /** @@ -265,7 +279,6 @@ namespace KiwiLight { std::vector contoursFromLastFrame; }; - class CameraFrame { public: CameraFrame() {}; @@ -287,7 +300,6 @@ namespace KiwiLight { */ class Runner { public: - static const std::string NULL_MESSAGE; Runner() {}; @@ -296,21 +308,18 @@ namespace KiwiLight { PostProcessor GetPostProcessor() { return this->postprocessor; }; int GetCameraIndex() { return this->cameraIndex; }; void SetImageResize(Size sz); - void Loop(); - void ReconnectUDP(std::string udpAddr, int udpPort); - void SendOverUDP(std::string message); std::string Iterate(); int GetNumberOfTargets() { return this->postprocessor.NumberOfTargets(); }; int GetNumberOfContours(int target); bool GetLastFrameSuccessful() { return this->lastIterationSuccessful; }; std::vector GetLastFrameTargets() { return this->lastFrameTargets; }; Target GetClosestTargetToCenter() { return this->closestTarget; }; + Point GetLastFrameCenterPoint() { return this->lastFrameCenterPoint; }; std::string GetFileName() { return this->src; }; cv::Mat GetOriginalImage() { return this->originalImage; }; cv::Mat GetOutputImage() { return this->outputImage; }; Size GetConstantSize() { return this->constantResize; }; ExampleTarget GetExampleTargetByID(int id); - UDP GetUDP() { return this->udp; }; void SetExampleTarget(int targetID, ExampleTarget target); void SetPreprocessorProperty(PreProcessorProperty prop, double value); double GetPreprocessorProperty(PreProcessorProperty prop); @@ -339,14 +348,13 @@ namespace KiwiLight { std::vector postProcessorTargets; std::vector lastFrameTargets; + Point lastFrameCenterPoint; bool lastIterationSuccessful; bool stop, debug; double centerOffsetX, centerOffsetY; - - UDP udp; }; /** @@ -377,6 +385,7 @@ namespace KiwiLight { original; }; + /** * A tool that calculates the constants needed for accurate distance calculation */ diff --git a/KiwiLight - Vision Code/runner/RunnerSettings.cpp b/KiwiLight - Vision Code/runner/RunnerSettings.cpp index acb04bc..0cd6e41 100644 --- a/KiwiLight - Vision Code/runner/RunnerSettings.cpp +++ b/KiwiLight - Vision Code/runner/RunnerSettings.cpp @@ -6,4 +6,4 @@ */ const bool KiwiLight::RunnerSettings::USE_CAMERA = true; -const std::string KiwiLight::RunnerSettings::IMAGE_TO_USE = "sized.png"; \ No newline at end of file +const std::string KiwiLight::RunnerSettings::IMAGE_TO_USE = "widthheightest.png"; diff --git a/KiwiLight - Vision Code/runner/Settings.h b/KiwiLight - Vision Code/runner/Settings.h index 7f7ff63..d4e48a2 100644 --- a/KiwiLight - Vision Code/runner/Settings.h +++ b/KiwiLight - Vision Code/runner/Settings.h @@ -1,19 +1,19 @@ -#ifndef SETTINGS_H -#define SETTINGS_H - -#include - -/** - * Settings file for runner. Defines general rules for runner to follow. Used for debugging - * Written By: Brach Knutson - */ - -namespace KiwiLight { - class RunnerSettings { - public: - static const bool USE_CAMERA; - static const std::string IMAGE_TO_USE; - }; -} - -#endif +#ifndef SETTINGS_H +#define SETTINGS_H + +#include + +/** + * Settings file for runner. Defines general rules for runner to follow. Used for debugging + * Written By: Brach Knutson + */ + +namespace KiwiLight { + class RunnerSettings { + public: + static const bool USE_CAMERA; + static const std::string IMAGE_TO_USE; + }; +} + +#endif diff --git a/KiwiLight - Vision Code/runner/Target.cpp b/KiwiLight - Vision Code/runner/Target.cpp index 40564b9..0a13c19 100644 --- a/KiwiLight - Vision Code/runner/Target.cpp +++ b/KiwiLight - Vision Code/runner/Target.cpp @@ -28,13 +28,14 @@ Target::Target() { * generated by the ExampleTarget class. Use an ExampleTarget * to find targets!!! */ -Target::Target(int id, std::vector contours, double knownHeight, double focalHeight, double distErrorCorrect, double calibratedDistance) { +Target::Target(int id, std::vector contours, double knownHeight, double focalHeight, double distErrorCorrect, double calibratedDistance, DistanceCalcMode distMode) { this->id = id; this->contours = contours; this->knownHeight = knownHeight; this->focalHeight = focalHeight; this->distErrorCorrect = distErrorCorrect; this->calibratedDistance = calibratedDistance; + this->distMode = distMode; if(contours.size() == 1) { this->width = contours[0].Width(); @@ -72,20 +73,23 @@ Target::Target(int id, std::vector contours, double knownHeight, double this->height = (biggestY - smallestY) + biggestYHeight; this->x = (this->width / 2) + smallestX; this->y = (this->height / 2) + smallestY; - - // std::cout << "biggest x: " << biggestX << std::endl; - // std::cout << "biggest x width: " << biggestXWidth << std::endl; - // std::cout << "smallest x: " << smallestX << std::endl; - // std::cout << "total width: " << this->width << std::endl; } } /** - * Returns the distance from the camera to the target in inches. + * Returns the distance from the camera to the target in inches. Uses width for calculations by default. */ double Target::Distance() { + return Distance(distMode); +} + +/** + * Returns the distance from the camera to the target in inches. Uses specified mode (width or height) + */ +double Target::Distance(DistanceCalcMode mode) { //calculate distance (formula: known(in) * focal(in) / real(px)) - double dist = this->knownHeight * this->focalHeight / (double) this->Bounds().width; + double referenceLength = (double) (mode == DistanceCalcMode::BY_WIDTH ? this->Bounds().width : this->Bounds().height); + double dist = this->knownHeight * this->focalHeight / referenceLength; double err = this->calibratedDistance - dist; err *= this->distErrorCorrect; @@ -129,6 +133,26 @@ int Target::VerticalAngle(int imageCenterY) { return this->VerticalAngle(this->Distance(), imageCenterY); } + +int Target::ObliqueAngle(int imageCenterX, int imageCenterY) { + double horizontalAngle = this->HorizontalAngle(imageCenterX) * (M_PI / 180); //convert angle from degrees to radians + double verticalAngle = this->VerticalAngle(imageCenterY) * (M_PI / 180); + double targetDistance = this->Distance(); + + double horizontalOffset = targetDistance * tan(horizontalAngle); + double verticalOffset = targetDistance * tan(verticalAngle); + double obliqueOffset = sqrt ( + pow(horizontalOffset, 2) + + pow(verticalOffset, 2) + ); + + double obliqueAngle = atan(obliqueOffset / targetDistance); + + //convert the angle back to degrees + obliqueAngle *= (180 / M_PI); + return obliqueAngle; +} + /** * Returns a rectangle that represents the bounds of the target. */ diff --git a/KiwiLight - Vision Code/runner/TargetDistanceLearner.cpp b/KiwiLight - Vision Code/runner/TargetDistanceLearner.cpp index 42bf20f..d855cf4 100644 --- a/KiwiLight - Vision Code/runner/TargetDistanceLearner.cpp +++ b/KiwiLight - Vision Code/runner/TargetDistanceLearner.cpp @@ -1,58 +1,58 @@ -#include "Runner.h" - -/** - * Source file for the TargetDistanceLearner class. - * Written By: Brach Knutson - */ - -using namespace cv; -using namespace KiwiLight; - - -TargetDistanceLearner::TargetDistanceLearner(PreProcessor preprocessor, PostProcessor postprocessor) { - this->preprocessor = preprocessor; - this->postprocessor = postprocessor; - this->frames = 0; -} - - -void TargetDistanceLearner::FeedImage(Mat image) { - if(image.empty()) { - failedFrames++; - return; - } - - Mat img(image); - img = this->preprocessor.ProcessImage(img); - std::vector frameTargs = this->postprocessor.ProcessImage(img); - if(frameTargs.size() == 1) { - Target targ = frameTargs[0]; - this->targetWidths.push_back((double) targ.Bounds().width); - this->frames++; - } -} - - -void TargetDistanceLearner::FeedTarget(Target targ) { - this->targetWidths.push_back((double) targ.Bounds().width); - this->frames++; -} - - -double TargetDistanceLearner::GetFocalWidth(double trueDistance, double trueWidth) { - int sizeBeforeRemove = targetWidths.size(); - this->targetWidths = DataUtils::SortLeastGreatestDouble(this->targetWidths); - this->targetWidths = DataUtils::RemoveOutliers(this->targetWidths, 30); - - double avgWidth = DataUtils::Average(targetWidths); - - double focalWidth = avgWidth * trueDistance / trueWidth; - this->targetWidths = std::vector(); //reset the vector so it can learn again - this->frames = 0; //reset the frames counter so it can learn again - return focalWidth; -} - - -int TargetDistanceLearner::GetFramesLearned() { - return this->frames; -} +#include "Runner.h" + +/** + * Source file for the TargetDistanceLearner class. + * Written By: Brach Knutson + */ + +using namespace cv; +using namespace KiwiLight; + + +TargetDistanceLearner::TargetDistanceLearner(PreProcessor preprocessor, PostProcessor postprocessor) { + this->preprocessor = preprocessor; + this->postprocessor = postprocessor; + this->frames = 0; +} + + +void TargetDistanceLearner::FeedImage(Mat image) { + if(image.empty()) { + failedFrames++; + return; + } + + Mat img(image); + img = this->preprocessor.ProcessImage(img); + std::vector frameTargs = this->postprocessor.ProcessImage(img); + if(frameTargs.size() == 1) { + Target targ = frameTargs[0]; + this->targetWidths.push_back((double) targ.Bounds().width); + this->frames++; + } +} + + +void TargetDistanceLearner::FeedTarget(Target targ) { + this->targetWidths.push_back((double) targ.Bounds().width); + this->frames++; +} + + +double TargetDistanceLearner::GetFocalWidth(double trueDistance, double trueWidth) { + int sizeBeforeRemove = targetWidths.size(); + this->targetWidths = DataUtils::SortLeastGreatestDouble(this->targetWidths); + this->targetWidths = DataUtils::RemoveOutliers(this->targetWidths, 30); + + double avgWidth = DataUtils::Average(targetWidths); + + double focalWidth = avgWidth * trueDistance / trueWidth; + this->targetWidths = std::vector(); //reset the vector so it can learn again + this->frames = 0; //reset the frames counter so it can learn again + return focalWidth; +} + + +int TargetDistanceLearner::GetFramesLearned() { + return this->frames; +} diff --git a/KiwiLight - Vision Code/runner/TargetTroubleshooter.cpp b/KiwiLight - Vision Code/runner/TargetTroubleshooter.cpp index 09ced60..f6ea656 100644 --- a/KiwiLight - Vision Code/runner/TargetTroubleshooter.cpp +++ b/KiwiLight - Vision Code/runner/TargetTroubleshooter.cpp @@ -1,225 +1,225 @@ -#include "Runner.h" - -/** - * Source file for the TargetTroubleshooter class. - * Written By: Brach Knutson - */ - -using namespace KiwiLight; - -static const int TROUBLESHOOT_FRAMES = 50; - -/** - * Creates a new TargetTroubleshooter. The "target" parameter is the target that needs to be troubleshot. - */ -TargetTroubleshooter::TargetTroubleshooter(VideoCapture cap, PreProcessor preprocessor, ExampleTarget target) { - this->cap = cap; - this->preprocessor = preprocessor; - this->target = target; -} - -/** - * Troubleshoots the target. - * @param allowableMissedTests how many tests a contour is allowed to miss before it cannot be part of the target. - * @param dataOut an array of TroubleshootingData that test results and values will be dumped in by the method. - * Precondition: dataOut is the same size as target.Contours.size() - */ -bool TargetTroubleshooter::Troubleshoot(TroubleshootingData dataOut[]) { - CameraFrame frames[TROUBLESHOOT_FRAMES]; - int minimumArea = 50000; - - //figure out the minimum area - for(int i=0; itarget.Contours().size(); i++) { - if(this->target.Contours()[i].MinimumArea() < minimumArea) { - minimumArea = this->target.Contours()[i].MinimumArea(); - } - } - - //capture the frames - for(int i=0; icap.read(img); - } else { - success = true; - img = imread(RunnerSettings::IMAGE_TO_USE); - } - img = this->preprocessor.ProcessImage(img); - - if(success) { - CameraFrame newFrame = CameraFrame(img, minimumArea); - frames[i] = newFrame; - } else { - i--; - std::cout << "CAMERA GRAB FAILED! "; - } - - double percentDone = i / (double) TROUBLESHOOT_FRAMES; - percentDone *= 100; - - this->outString = "Collecting and processing images (" + std::to_string((int) percentDone) + "%)"; - } - - //figure out the average number of contours per frame - std::vector avgContours; - for(int i=0; i > groupedContours = std::vector< std::vector >(this->target.Contours().size()); - - int discardedFrames = 0; - for(int i=0; i grouped = frames[i].GetContoursGrouped(); - - for(int a=0; a > matchedContours = std::vector >(this->target.Contours().size()); //index 0 of matchedContours will correspond with exampleContour with id 0, 1 with 1, 2 with 2, etc - std::cout << "matched contours size: " << matchedContours.size() << std::endl; - std::vector targetContours = this->target.Contours(); - - for(int i=0; i group = groupedContours[i]; - std::vector horizontalDistances; - std::vector verticalDistances; - - std::cout << "group size: " << group.size() << std::endl; - - for(int a=0; atarget.Contours().size()]; - - //run tests on the contours and build the data in TroubleshootingData - for(int i=0; i HorizontalDistances; - std::vector VerticalDistances; - std::vector Angles; - std::vector Solidities; - std::vector AspectRatios; - - std::cout << "matched group " << i << " size: " << matchedContours[i].size() << std::endl; - for(int a=0; atarget.Contours()[i]; - Contour contourToTest = matchedContours[i][a]; - - //test contour - Distance dist = frames[a].GetContourDistance(contourToTest); - bool distXTest = (dist.x < testingContour.DistX().UpperBound()) && (dist.x > testingContour.DistX().LowerBound()); - bool distYTest = (dist.y < testingContour.DistY().UpperBound()) && (dist.y > testingContour.DistY().LowerBound()); - bool angleTest = (contourToTest.Angle() < testingContour.Angle().UpperBound()) && (contourToTest.Angle() > testingContour.Angle().LowerBound()); - bool solidityTest = (contourToTest.Solidity() < testingContour.Solidity().UpperBound()) && (contourToTest.Solidity() > testingContour.Solidity().LowerBound()); - bool aspectTest = (contourToTest.AspectRatio() < testingContour.AspectRatio().UpperBound()) && (contourToTest.AspectRatio() > testingContour.AspectRatio().LowerBound()); - - HorizontalDistances.push_back(dist.x); - VerticalDistances.push_back(dist.y); - Angles.push_back(contourToTest.Angle()); - Solidities.push_back(contourToTest.Solidity()); - AspectRatios.push_back(contourToTest.AspectRatio()); - - if(!distXTest) data[i].missedHorizontalDistances++; - if(!distYTest) data[i].missedVerticalDistances++; - if(!angleTest) data[i].missedAngles++; - if(!solidityTest) data[i].missedSolidities++; - if(!aspectTest) data[i].missedAspectRatios++; - } - - std::cout << "horizontal distances: " << DataUtils::VectorToString(HorizontalDistances) << std::endl; - std::cout << "vertical distances: " << DataUtils::VectorToString(VerticalDistances) << std::endl; - std::cout << "angles: " << DataUtils::VectorToString(Angles) << std::endl; - std::cout << "solidities: " << DataUtils::VectorToString(Solidities) << std::endl; - std::cout << "aspect ratios: " << DataUtils::VectorToString(AspectRatios) << std::endl; - - data[i].averageHorizontalDistance = DataUtils::Average(HorizontalDistances); - data[i].averageVerticalDistance = DataUtils::Average(VerticalDistances); - data[i].averageAngle = DataUtils::Average(Angles); - data[i].averageSolidity = DataUtils::Average(Solidities); - data[i].averageAspectRatio = DataUtils::Average(AspectRatios); - } - - std::cout << "TROUBLESHOOTING RESULTS:" << std::endl; - std::cout << std::endl; - - for(int i=0; icap = cap; + this->preprocessor = preprocessor; + this->target = target; +} + +/** + * Troubleshoots the target. + * @param allowableMissedTests how many tests a contour is allowed to miss before it cannot be part of the target. + * @param dataOut an array of TroubleshootingData that test results and values will be dumped in by the method. + * Precondition: dataOut is the same size as target.Contours.size() + */ +bool TargetTroubleshooter::Troubleshoot(TroubleshootingData dataOut[]) { + CameraFrame frames[TROUBLESHOOT_FRAMES]; + int minimumArea = 50000; + + //figure out the minimum area + for(int i=0; itarget.Contours().size(); i++) { + if(this->target.Contours()[i].MinimumArea() < minimumArea) { + minimumArea = this->target.Contours()[i].MinimumArea(); + } + } + + //capture the frames + for(int i=0; icap.read(img); + } else { + success = true; + img = imread(RunnerSettings::IMAGE_TO_USE); + } + img = this->preprocessor.ProcessImage(img); + + if(success) { + CameraFrame newFrame = CameraFrame(img, minimumArea); + frames[i] = newFrame; + } else { + i--; + std::cout << "CAMERA GRAB FAILED! "; + } + + double percentDone = i / (double) TROUBLESHOOT_FRAMES; + percentDone *= 100; + + this->outString = "Collecting and processing images (" + std::to_string((int) percentDone) + "%)"; + } + + //figure out the average number of contours per frame + std::vector avgContours; + for(int i=0; i > groupedContours = std::vector< std::vector >(this->target.Contours().size()); + + int discardedFrames = 0; + for(int i=0; i grouped = frames[i].GetContoursGrouped(); + + for(int a=0; a > matchedContours = std::vector >(this->target.Contours().size()); //index 0 of matchedContours will correspond with exampleContour with id 0, 1 with 1, 2 with 2, etc + std::cout << "matched contours size: " << matchedContours.size() << std::endl; + std::vector targetContours = this->target.Contours(); + + for(int i=0; i group = groupedContours[i]; + std::vector horizontalDistances; + std::vector verticalDistances; + + std::cout << "group size: " << group.size() << std::endl; + + for(int a=0; atarget.Contours().size()]; + + //run tests on the contours and build the data in TroubleshootingData + for(int i=0; i HorizontalDistances; + std::vector VerticalDistances; + std::vector Angles; + std::vector Solidities; + std::vector AspectRatios; + + std::cout << "matched group " << i << " size: " << matchedContours[i].size() << std::endl; + for(int a=0; atarget.Contours()[i]; + Contour contourToTest = matchedContours[i][a]; + + //test contour + Distance dist = frames[a].GetContourDistance(contourToTest); + bool distXTest = (dist.x < testingContour.DistX().UpperBound()) && (dist.x > testingContour.DistX().LowerBound()); + bool distYTest = (dist.y < testingContour.DistY().UpperBound()) && (dist.y > testingContour.DistY().LowerBound()); + bool angleTest = (contourToTest.Angle() < testingContour.Angle().UpperBound()) && (contourToTest.Angle() > testingContour.Angle().LowerBound()); + bool solidityTest = (contourToTest.Solidity() < testingContour.Solidity().UpperBound()) && (contourToTest.Solidity() > testingContour.Solidity().LowerBound()); + bool aspectTest = (contourToTest.AspectRatio() < testingContour.AspectRatio().UpperBound()) && (contourToTest.AspectRatio() > testingContour.AspectRatio().LowerBound()); + + HorizontalDistances.push_back(dist.x); + VerticalDistances.push_back(dist.y); + Angles.push_back(contourToTest.Angle()); + Solidities.push_back(contourToTest.Solidity()); + AspectRatios.push_back(contourToTest.AspectRatio()); + + if(!distXTest) data[i].missedHorizontalDistances++; + if(!distYTest) data[i].missedVerticalDistances++; + if(!angleTest) data[i].missedAngles++; + if(!solidityTest) data[i].missedSolidities++; + if(!aspectTest) data[i].missedAspectRatios++; + } + + std::cout << "horizontal distances: " << DataUtils::VectorToString(HorizontalDistances) << std::endl; + std::cout << "vertical distances: " << DataUtils::VectorToString(VerticalDistances) << std::endl; + std::cout << "angles: " << DataUtils::VectorToString(Angles) << std::endl; + std::cout << "solidities: " << DataUtils::VectorToString(Solidities) << std::endl; + std::cout << "aspect ratios: " << DataUtils::VectorToString(AspectRatios) << std::endl; + + data[i].averageHorizontalDistance = DataUtils::Average(HorizontalDistances); + data[i].averageVerticalDistance = DataUtils::Average(VerticalDistances); + data[i].averageAngle = DataUtils::Average(Angles); + data[i].averageSolidity = DataUtils::Average(Solidities); + data[i].averageAspectRatio = DataUtils::Average(AspectRatios); + } + + std::cout << "TROUBLESHOOTING RESULTS:" << std::endl; + std::cout << std::endl; + + for(int i=0; iwindow = Window(type, false); - this->window.SetSize(550,200); - - Panel main = Panel(true, 0); - Panel banners = Panel(false, 0); - Image kiwiLightBanner = Image("banner_small.png"); - banners.Pack_start(kiwiLightBanner.GetWidget(), false, false, 0); - - Image foximusBanner = Image("foximus_small.png"); - banners.Pack_start(foximusBanner.GetWidget(), false, false, 0); - - main.Pack_start(banners.GetWidget(), false, false, 0); - - Panel descriptions = Panel(false, 0); - Label header = Label("About KiwiLight"); - header.SetName("header"); - descriptions.Pack_start(header.GetWidget(), false, false, 0); - - Label description = Label( - std::string("KiwiLight was written by Brach Knutson and Colton Kreischer ") + - std::string("of FRC 3695 Foximus Prime for use by any FRC team ") + - std::string("for any vision purpose.\n\nKiwiLight is stored at ") + - std::string("github.com/wh1ter0se/KiwiLight. \n\nKiwiLight is published ") + - std::string("under a GPL-3.0 license, permitting modification ") + - std::string("and distribution under the condition that the source is ") + - std::string("disclosed and distribution is accompanied by the same license.") - ); - description.SetLineWrap(true); - descriptions.Pack_start(description.GetWidget(), false, false, 0); - - main.Pack_start(descriptions.GetWidget(), false, false, 0); - - this->window.SetPane(main); - - this->aboutwindow = window.GetWidget(); -} - -/** - * Shows the about window. - */ -void AboutWindow::Show() { - this->window.Show(); -} - - -void AboutWindow::SetName(std::string name) { - gtk_widget_set_name(this->aboutwindow, name.c_str()); +#include "UI.h" + +/** + * Source file for the AboutWindow class. + * Written By: Brach Knutson + */ + +using namespace KiwiLight; + +/** + * Creates a new AboutWindow with the given window type. + */ +AboutWindow::AboutWindow(GtkWindowType type) { + + //put together an about window + this->window = Window(type, false); + this->window.SetSize(550,200); + + Panel main = Panel(true, 0); + Panel banners = Panel(false, 0); + Image kiwiLightBanner = Image("banner_small.png"); + banners.Pack_start(kiwiLightBanner.GetWidget(), false, false, 0); + + Image foximusBanner = Image("foximus_small.png"); + banners.Pack_start(foximusBanner.GetWidget(), false, false, 0); + + main.Pack_start(banners.GetWidget(), false, false, 0); + + Panel descriptions = Panel(false, 0); + Label header = Label("About KiwiLight"); + header.SetName("header"); + descriptions.Pack_start(header.GetWidget(), false, false, 0); + + Label description = Label( + std::string("KiwiLight was written by Brach Knutson and Colton Kreischer ") + + std::string("of FRC 3695 Foximus Prime for use by any FRC team ") + + std::string("for any vision purpose.\n\nKiwiLight is stored at ") + + std::string("github.com/wh1ter0se/KiwiLight. \n\nKiwiLight is published ") + + std::string("under a GPL-3.0 license, permitting modification ") + + std::string("and distribution under the condition that the source is ") + + std::string("disclosed and distribution is accompanied by the same license.") + ); + description.SetLineWrap(true); + descriptions.Pack_start(description.GetWidget(), false, false, 0); + + main.Pack_start(descriptions.GetWidget(), false, false, 0); + + this->window.SetPane(main); + + this->aboutwindow = window.GetWidget(); +} + +/** + * Shows the about window. + */ +void AboutWindow::Show() { + this->window.Show(); +} + + +void AboutWindow::SetName(std::string name) { + gtk_widget_set_name(this->aboutwindow, name.c_str()); } \ No newline at end of file diff --git a/KiwiLight - Vision Code/ui/Button.cpp b/KiwiLight - Vision Code/ui/Button.cpp index 3fcd6e2..d258312 100644 --- a/KiwiLight - Vision Code/ui/Button.cpp +++ b/KiwiLight - Vision Code/ui/Button.cpp @@ -1,33 +1,33 @@ -#include "UI.h" - -/** - * Source file for the UI Button class. - * Written By: Brach Knutson - */ - - -using namespace KiwiLight; - -/** - * Creates a new button object given the label text text and the callback callback - */ -Button::Button(std::string text, void(*callback)()) { - this->text = text; - - this->button = gtk_button_new_with_label(text.c_str()); - g_signal_connect(this->button, "clicked", G_CALLBACK(callback), NULL); -} - -void Button::SetText(std::string text) { - gtk_button_set_label(GTK_BUTTON(this->button), text.c_str()); -} - - -void Button::SetCallback( void(*callback)() ) { - -} - - -void Button::SetName(std::string name) { - gtk_widget_set_name(this->button, name.c_str()); +#include "UI.h" + +/** + * Source file for the UI Button class. + * Written By: Brach Knutson + */ + + +using namespace KiwiLight; + +/** + * Creates a new button object given the label text text and the callback callback + */ +Button::Button(std::string text, void(*callback)()) { + this->text = text; + + this->button = gtk_button_new_with_label(text.c_str()); + g_signal_connect(this->button, "clicked", G_CALLBACK(callback), NULL); +} + +void Button::SetText(std::string text) { + gtk_button_set_label(GTK_BUTTON(this->button), text.c_str()); +} + + +void Button::SetCallback( void(*callback)() ) { + +} + + +void Button::SetName(std::string name) { + gtk_widget_set_name(this->button, name.c_str()); } \ No newline at end of file diff --git a/KiwiLight - Vision Code/ui/CameraSetting.cpp b/KiwiLight - Vision Code/ui/CameraSetting.cpp index 84a3b4c..b7dce16 100644 --- a/KiwiLight - Vision Code/ui/CameraSetting.cpp +++ b/KiwiLight - Vision Code/ui/CameraSetting.cpp @@ -1,64 +1,64 @@ -#include "UI.h" - -/** - * Source file for the CameraSetting class. - * Written By: Brach Knutson - */ - - -using namespace KiwiLight; - -/** - * Creates a new CameraSetting widget, using the given std::string from V4L - */ -CameraSetting::CameraSetting(std::string name, int valueName, double min, double max, double value) { - this->name = name; - this->valueName = valueName; - this->min = min; - this->max = max; - this->value = value; - - - //create the widget - std::string boundString = - "Min: " + std::to_string(min) + - ", Max: " + std::to_string(max) + - ", ID: " + std::to_string(valueName); - - std::string nameString = this->name + " (" + boundString + ")"; - - Panel main = Panel(true, 0); - this->nameLabel = Label(nameString); - main.Pack_start(nameLabel.GetWidget(), true, true, 0); - this->input = NumberBox(min, max, 0.01, value); - main.Pack_start(this->input.GetWidget(), true, true, 0); - - this->camerasetting = main.GetWidget(); -} - -/** - * Gets and returns the value of the widget. - */ -double CameraSetting::GetValue() { - return this->input.GetValue(); -} - -/** - * Returns an integer describing the name of the setting that this widget embodies - */ -int CameraSetting::GetValueName() { - return this->valueName; -} - -/** - * Sets the value of the setting to newValue. - */ -void CameraSetting::SetValue(double newValue) { - this->value = newValue; - this->input.SetValue(value); -} - - -void CameraSetting::SetName(std::string name) { - gtk_widget_set_name(this->camerasetting, name.c_str()); -} +#include "UI.h" + +/** + * Source file for the CameraSetting class. + * Written By: Brach Knutson + */ + + +using namespace KiwiLight; + +/** + * Creates a new CameraSetting widget, using the given std::string from V4L + */ +CameraSetting::CameraSetting(std::string name, int valueName, double min, double max, double value) { + this->name = name; + this->valueName = valueName; + this->min = min; + this->max = max; + this->value = value; + + + //create the widget + std::string boundString = + "Min: " + std::to_string(min) + + ", Max: " + std::to_string(max) + + ", ID: " + std::to_string(valueName); + + std::string nameString = this->name + " (" + boundString + ")"; + + Panel main = Panel(true, 0); + this->nameLabel = Label(nameString); + main.Pack_start(nameLabel.GetWidget(), true, true, 0); + this->input = NumberBox(min, max, 0.01, value); + main.Pack_start(this->input.GetWidget(), true, true, 0); + + this->camerasetting = main.GetWidget(); +} + +/** + * Gets and returns the value of the widget. + */ +double CameraSetting::GetValue() { + return this->input.GetValue(); +} + +/** + * Returns an integer describing the name of the setting that this widget embodies + */ +int CameraSetting::GetValueName() { + return this->valueName; +} + +/** + * Sets the value of the setting to newValue. + */ +void CameraSetting::SetValue(double newValue) { + this->value = newValue; + this->input.SetValue(value); +} + + +void CameraSetting::SetName(std::string name) { + gtk_widget_set_name(this->camerasetting, name.c_str()); +} diff --git a/KiwiLight - Vision Code/ui/CheckBox.cpp b/KiwiLight - Vision Code/ui/CheckBox.cpp index 29e5e3b..e55f4d6 100644 --- a/KiwiLight - Vision Code/ui/CheckBox.cpp +++ b/KiwiLight - Vision Code/ui/CheckBox.cpp @@ -1,36 +1,36 @@ -#include "UI.h" - -/** - * Source file for the CheckBox class. - * Written By: Brach Knutson - */ - - -using namespace KiwiLight; - -/** - * Creates a new CheckBox instance. the state will default to value of checked. - */ -CheckBox::CheckBox(std::string name, bool checked) { - this->checkbox = gtk_check_button_new_with_label(name.c_str()); - SetState(checked); -} - -/** - * Sets the state of the checkbox to the value of checked. - */ -void CheckBox::SetState(bool checked) { - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(this->checkbox), checked); -} - -/** - * Returns the state of the checkbox. True for checked, false for not. - */ -bool CheckBox::GetState() { - return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(this->checkbox)); -} - - -void CheckBox::SetName(std::string name) { - gtk_widget_set_name(this->checkbox, name.c_str()); +#include "UI.h" + +/** + * Source file for the CheckBox class. + * Written By: Brach Knutson + */ + + +using namespace KiwiLight; + +/** + * Creates a new CheckBox instance. the state will default to value of checked. + */ +CheckBox::CheckBox(std::string name, bool checked) { + this->checkbox = gtk_check_button_new_with_label(name.c_str()); + SetState(checked); +} + +/** + * Sets the state of the checkbox to the value of checked. + */ +void CheckBox::SetState(bool checked) { + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(this->checkbox), checked); +} + +/** + * Returns the state of the checkbox. True for checked, false for not. + */ +bool CheckBox::GetState() { + return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(this->checkbox)); +} + + +void CheckBox::SetName(std::string name) { + gtk_widget_set_name(this->checkbox, name.c_str()); } \ No newline at end of file diff --git a/KiwiLight - Vision Code/ui/ConfigEditor.cpp b/KiwiLight - Vision Code/ui/ConfigEditor.cpp index 1b10bc7..7f4e8be 100644 --- a/KiwiLight - Vision Code/ui/ConfigEditor.cpp +++ b/KiwiLight - Vision Code/ui/ConfigEditor.cpp @@ -71,6 +71,7 @@ ConfigEditor::ConfigEditor(std::string fileName) { Label cameraSettingsHeader = Label("Camera Settings"); cameraSettingsHeader.SetName("header"); cameraSettingsPanel.Pack_start(cameraSettingsHeader.GetWidget(), true, true, 0); + this->cameraSettings = Settings(this->currentDoc); cameraSettingsPanel.Pack_start(this->cameraSettings.GetWidget(), true, false, 0); @@ -119,7 +120,7 @@ ConfigEditor::ConfigEditor(std::string fileName) { this->window.SetPane(this->content); - this->window.SetOnWindowClosed(ConfigEditor::Closed); + this->window.SetOnWindowClosed(JustCloseButtonPressed); this->window.SetCSS("ui/Style.css"); this->window.Show(); @@ -163,7 +164,7 @@ void ConfigEditor::Update() { ExampleContour newContour = ExampleContour(i); newContours.push_back(newContour); } - ExampleTarget newTarget = ExampleTarget(0, newContours, 0.0, 0.0, 0.0, 0.0); + ExampleTarget newTarget = ExampleTarget(0, newContours, 0.0, 0.0, 0.0, 0.0, DistanceCalcMode::BY_WIDTH); this->runner.SetExampleTarget(0, newTarget); } @@ -185,6 +186,7 @@ void ConfigEditor::Update() { this->runner.SetRunnerProperty(RunnerProperty::PERCEIVED_WIDTH, this->runnerSettings.GetProperty(RunnerProperty::PERCEIVED_WIDTH)); this->runner.SetRunnerProperty(RunnerProperty::CALIBRATED_DISTANCE, this->runnerSettings.GetProperty(RunnerProperty::CALIBRATED_DISTANCE)); this->runner.SetRunnerProperty(RunnerProperty::ERROR_CORRECTION, this->runnerSettings.GetProperty(RunnerProperty::ERROR_CORRECTION)); + this->runner.SetRunnerProperty(RunnerProperty::CALC_DIST_BY_HEIGHT, this->runnerSettings.GetProperty(RunnerProperty::CALC_DIST_BY_HEIGHT)); //set service labels if(this->learnerActivated && this->learner.GetLearning()) { @@ -475,6 +477,10 @@ void ConfigEditor::Save() { XMLTag distErrorCorrect = XMLTag("distErrorCorrect", std::to_string((double) this->runnerSettings.GetProperty(RunnerProperty::ERROR_CORRECTION))); target.AddTag(distErrorCorrect); + // + XMLTag calcByHeight = XMLTag("calcByHeight", (this->runnerSettings.GetProperty(RunnerProperty::CALC_DIST_BY_HEIGHT) == 1 ? "true" : "false")); + target.AddTag(calcByHeight); + postprocessor.AddTag(target); /** @@ -601,15 +607,17 @@ void ConfigEditor::StartLearningDistance() { void ConfigEditor::ReconnectUDPFromEditor() { std::string newUDPAddr = this->runnerSettings.GetUDPAddr(); int newUDPPort = this->runnerSettings.GetUDPPort(); - this->runner.ReconnectUDP(newUDPAddr, newUDPPort); + KiwiLightApp::ReconnectUDP(newUDPAddr, newUDPPort); //set the things in the overview panel this->configOverview.SetUDPAddr(newUDPAddr); this->configOverview.SetUDPPort(newUDPPort); } -void ConfigEditor::SendOverUDP(std::string message) { - this->runner.SendOverUDP(message); + +void ConfigEditor::SetUDPEnabledLabels(bool UDPEnabled) { + this->configOverview.SetUDPEnabledLabels(UDPEnabled); + this->runnerSettings.SetUDPEnabledLabels(UDPEnabled); } /** @@ -647,7 +655,7 @@ void ConfigEditor::SetCameraIndexBoxes(int index) { void ConfigEditor::ReconnectUDPFromOverview() { std::string newAddr = this->configOverview.GetUDPAddr(); int newPort = this->configOverview.GetUDPPort(); - this->runner.ReconnectUDP(newAddr, newPort); + KiwiLightApp::ReconnectUDP(newAddr, newPort); //set the properties in the actual editor this->runnerSettings.SetUDPAddr(newAddr); @@ -668,13 +676,6 @@ void ConfigEditor::SetName(std::string name) { gtk_widget_set_name(this->configeditor, name.c_str()); } -/** - * Called when the X in the corner is pressed - */ -void ConfigEditor::Closed() { - KiwiLightApp::CloseEditor(false); -} - void ConfigEditor::UpdateImage() { this->runner.Iterate(); @@ -684,6 +685,6 @@ void ConfigEditor::UpdateImage() { vconcat(this->original, this->out, displayable); this->outputImage.Update(displayable); } catch(cv::Exception ex) { - std::cout << "cv exception in ce" << std::endl; + std::cout << "cv exception in config editor" << std::endl; } } diff --git a/KiwiLight - Vision Code/ui/ConfigPanel.cpp b/KiwiLight - Vision Code/ui/ConfigPanel.cpp index dd6afa8..17bb75e 100644 --- a/KiwiLight - Vision Code/ui/ConfigPanel.cpp +++ b/KiwiLight - Vision Code/ui/ConfigPanel.cpp @@ -1,145 +1,145 @@ -#include "UI.h" - -/** - * Source file for the ConfigPanel class - * Written By: Brach Knutson - */ - -using namespace KiwiLight; - -extern void EditSelected(); //from Main.cpp -extern void ToggleUDP(); //from Main.cpp - - -ConfigPanel::ConfigPanel(XMLDocument file) { - this->panel = Panel(false, 5); - - this->configFile = "(none)"; - std::string configName = "(none)"; - std::string preprocessorType = "(none)"; - std::string numContours = "(none)"; - std::string udpAddr = "(none)"; - std::string udpPort = "(none)"; - - if(file.HasContents()) { - this->configFile = file.FileName(); - - XMLTag confTag = file.GetTagsByName("configuration")[0]; - configName = confTag.GetAttributesByName("name")[0].Value(); - - XMLTag preprocessorTag = confTag.GetTagsByName("preprocessor")[0]; - preprocessorType = preprocessorTag.GetAttributesByName("type")[0].Value(); - - XMLTag postprocessorTag = confTag.GetTagsByName("postprocessor")[0]; - XMLTag targetTag = postprocessorTag.GetTagsByName("target")[0]; - numContours = std::to_string(targetTag.GetTagsByName("contour").size()); - - XMLTag udpTag = postprocessorTag.GetTagsByName("UDP")[0]; - udpAddr = udpTag.GetTagsByName("address")[0].Content(); - udpPort = udpTag.GetTagsByName("port")[0].Content(); - } - - this->configNameString = configName; - - this->header = Label("Configuration: " + configName); - this->header.SetName("header"); - this->panel.Pack_start(this->header.GetWidget(), false, false, 0); - - Panel filePanel = Panel(true, 0); - Label filePanelHeader = Label("File: "); - filePanelHeader.SetName("gray"); - filePanel.Pack_start(filePanelHeader.GetWidget(), false, false, 0); - - this->fileLabel = Label(this->configFile); - filePanel.Pack_start(this->fileLabel.GetWidget(), false, false, 0); - - this->panel.Pack_start(filePanel.GetWidget(), false, false, 0); - - Panel preprocessorPanel = Panel(true, 0); - Label preprocessorPanelHeader = Label("Preprocessor: "); - preprocessorPanelHeader.SetName("gray"); - preprocessorPanel.Pack_start(preprocessorPanelHeader.GetWidget(), false, false, 0); - - this->PreProcessorLabel = Label(preprocessorType); - preprocessorPanel.Pack_start(this->PreProcessorLabel.GetWidget(), false, false, 0); - - this->panel.Pack_start(preprocessorPanel.GetWidget(), false, false, 0); - - Panel targetPanel = Panel(true, 0); - Label targetPanelHeader = Label("Contours: "); - targetPanelHeader.SetName("gray"); - targetPanel.Pack_start(targetPanelHeader.GetWidget(), false, false, 0); - - this->TargetLabel = Label(numContours); - targetPanel.Pack_start(this->TargetLabel.GetWidget(), false, false, 0); - - this->panel.Pack_start(targetPanel.GetWidget(), false, false, 0); - - Panel udpAddrPanel = Panel(true, 0); - Label udpAddrPanelHeader = Label("UDP Address: "); - udpAddrPanelHeader.SetName("gray"); - udpAddrPanel.Pack_start(udpAddrPanelHeader.GetWidget(), false, false, 0); - - this->UDPAddressLabel = Label(udpAddr); - udpAddrPanel.Pack_start(this->UDPAddressLabel.GetWidget(), false, false, 0); - - this->panel.Pack_start(udpAddrPanel.GetWidget(), false, false, 0); - - Panel udpPortPanel = Panel(true, 0); - Label udpPortPanelHeader = Label("UDP Port: "); - udpPortPanelHeader.SetName("gray"); - udpPortPanel.Pack_start(udpPortPanelHeader.GetWidget(), false, false, 0); - - this->UDPPortLabel = Label(udpPort); - udpPortPanel.Pack_start(this->UDPPortLabel.GetWidget(), false, false, 0); - - this->panel.Pack_start(udpPortPanel.GetWidget(), false, false, 0); - - this->configPanel = this->panel.GetWidget(); -} - - -void ConfigPanel::LoadConfig(std::string fileName) { - this->LoadConfig(XMLDocument(fileName)); -} - -/** - * Loads the config described the the file at fileName. - */ -void ConfigPanel::LoadConfig(XMLDocument file) { - //create an xmldocument to parse and then find all information needed to fill out the label - - XMLTag config = file.GetTagsByName("configuration")[0]; - std::string name = config.GetAttributesByName("name")[0].Value(); - std::string preProcessorType = config.GetTagsByName("preprocessor")[0].GetAttributesByName("type")[0].Value(); - std::string postProcessorType = "full"; - std::string numContours = std::to_string(config.GetTagsByName("postprocessor")[0].GetTagsByName("target")[0].GetTagsByName("contour").size()); - - XMLTag UDPTag = config.GetTagsByName("postprocessor")[0].GetTagsByName("UDP")[0]; - std::string udpAddress = UDPTag.GetTagsByName("address")[0].Content(); - std::string udpPort = UDPTag.GetTagsByName("port")[0].Content(); - - //set the label texts for the informational panel with the found information - this->header.SetText("Configuration: " + name); - this->fileLabel.SetText(file.FileName()); - this->PreProcessorLabel.SetText(preProcessorType); - this->TargetLabel.SetText(numContours); - this->UDPAddressLabel.SetText(udpAddress); - this->UDPPortLabel.SetText(udpPort); - - this->configNameString = name; -} - - -void ConfigPanel::Clear() { - this->header.SetText("Configuration: (none loaded)"); - this->fileLabel.SetText("(none)"); - this->PreProcessorLabel.SetText("(none)"); - this->TargetLabel.SetText("(none)"); - this->UDPAddressLabel.SetText("(none)"); - this->UDPPortLabel.SetText("(none)"); -} - -void ConfigPanel::SetName(std::string name) { - gtk_widget_set_name(this->configPanel, name.c_str()); -} +#include "UI.h" + +/** + * Source file for the ConfigPanel class + * Written By: Brach Knutson + */ + +using namespace KiwiLight; + +extern void EditSelected(); //from Main.cpp +extern void ToggleUDP(); //from Main.cpp + + +ConfigPanel::ConfigPanel(XMLDocument file) { + this->panel = Panel(false, 5); + + this->configFile = "(none)"; + std::string configName = "(none)"; + std::string preprocessorType = "(none)"; + std::string numContours = "(none)"; + std::string udpAddr = "(none)"; + std::string udpPort = "(none)"; + + if(file.HasContents()) { + this->configFile = file.FileName(); + + XMLTag confTag = file.GetTagsByName("configuration")[0]; + configName = confTag.GetAttributesByName("name")[0].Value(); + + XMLTag preprocessorTag = confTag.GetTagsByName("preprocessor")[0]; + preprocessorType = preprocessorTag.GetAttributesByName("type")[0].Value(); + + XMLTag postprocessorTag = confTag.GetTagsByName("postprocessor")[0]; + XMLTag targetTag = postprocessorTag.GetTagsByName("target")[0]; + numContours = std::to_string(targetTag.GetTagsByName("contour").size()); + + XMLTag udpTag = postprocessorTag.GetTagsByName("UDP")[0]; + udpAddr = udpTag.GetTagsByName("address")[0].Content(); + udpPort = udpTag.GetTagsByName("port")[0].Content(); + } + + this->configNameString = configName; + + this->header = Label("Configuration: " + configName); + this->header.SetName("header"); + this->panel.Pack_start(this->header.GetWidget(), false, false, 0); + + Panel filePanel = Panel(true, 0); + Label filePanelHeader = Label("File: "); + filePanelHeader.SetName("gray"); + filePanel.Pack_start(filePanelHeader.GetWidget(), false, false, 0); + + this->fileLabel = Label(this->configFile); + filePanel.Pack_start(this->fileLabel.GetWidget(), false, false, 0); + + this->panel.Pack_start(filePanel.GetWidget(), false, false, 0); + + Panel preprocessorPanel = Panel(true, 0); + Label preprocessorPanelHeader = Label("Preprocessor: "); + preprocessorPanelHeader.SetName("gray"); + preprocessorPanel.Pack_start(preprocessorPanelHeader.GetWidget(), false, false, 0); + + this->PreProcessorLabel = Label(preprocessorType); + preprocessorPanel.Pack_start(this->PreProcessorLabel.GetWidget(), false, false, 0); + + this->panel.Pack_start(preprocessorPanel.GetWidget(), false, false, 0); + + Panel targetPanel = Panel(true, 0); + Label targetPanelHeader = Label("Contours: "); + targetPanelHeader.SetName("gray"); + targetPanel.Pack_start(targetPanelHeader.GetWidget(), false, false, 0); + + this->TargetLabel = Label(numContours); + targetPanel.Pack_start(this->TargetLabel.GetWidget(), false, false, 0); + + this->panel.Pack_start(targetPanel.GetWidget(), false, false, 0); + + Panel udpAddrPanel = Panel(true, 0); + Label udpAddrPanelHeader = Label("UDP Address: "); + udpAddrPanelHeader.SetName("gray"); + udpAddrPanel.Pack_start(udpAddrPanelHeader.GetWidget(), false, false, 0); + + this->UDPAddressLabel = Label(udpAddr); + udpAddrPanel.Pack_start(this->UDPAddressLabel.GetWidget(), false, false, 0); + + this->panel.Pack_start(udpAddrPanel.GetWidget(), false, false, 0); + + Panel udpPortPanel = Panel(true, 0); + Label udpPortPanelHeader = Label("UDP Port: "); + udpPortPanelHeader.SetName("gray"); + udpPortPanel.Pack_start(udpPortPanelHeader.GetWidget(), false, false, 0); + + this->UDPPortLabel = Label(udpPort); + udpPortPanel.Pack_start(this->UDPPortLabel.GetWidget(), false, false, 0); + + this->panel.Pack_start(udpPortPanel.GetWidget(), false, false, 0); + + this->configPanel = this->panel.GetWidget(); +} + + +void ConfigPanel::LoadConfig(std::string fileName) { + this->LoadConfig(XMLDocument(fileName)); +} + +/** + * Loads the config described the the file at fileName. + */ +void ConfigPanel::LoadConfig(XMLDocument file) { + //create an xmldocument to parse and then find all information needed to fill out the label + + XMLTag config = file.GetTagsByName("configuration")[0]; + std::string name = config.GetAttributesByName("name")[0].Value(); + std::string preProcessorType = config.GetTagsByName("preprocessor")[0].GetAttributesByName("type")[0].Value(); + std::string postProcessorType = "full"; + std::string numContours = std::to_string(config.GetTagsByName("postprocessor")[0].GetTagsByName("target")[0].GetTagsByName("contour").size()); + + XMLTag UDPTag = config.GetTagsByName("postprocessor")[0].GetTagsByName("UDP")[0]; + std::string udpAddress = UDPTag.GetTagsByName("address")[0].Content(); + std::string udpPort = UDPTag.GetTagsByName("port")[0].Content(); + + //set the label texts for the informational panel with the found information + this->header.SetText("Configuration: " + name); + this->fileLabel.SetText(file.FileName()); + this->PreProcessorLabel.SetText(preProcessorType); + this->TargetLabel.SetText(numContours); + this->UDPAddressLabel.SetText(udpAddress); + this->UDPPortLabel.SetText(udpPort); + + this->configNameString = name; +} + + +void ConfigPanel::Clear() { + this->header.SetText("Configuration: (none loaded)"); + this->fileLabel.SetText("(none)"); + this->PreProcessorLabel.SetText("(none)"); + this->TargetLabel.SetText("(none)"); + this->UDPAddressLabel.SetText("(none)"); + this->UDPPortLabel.SetText("(none)"); +} + +void ConfigPanel::SetName(std::string name) { + gtk_widget_set_name(this->configPanel, name.c_str()); +} diff --git a/KiwiLight - Vision Code/ui/ConfirmationDialog.cpp b/KiwiLight - Vision Code/ui/ConfirmationDialog.cpp index 361d473..f9cbebb 100644 --- a/KiwiLight - Vision Code/ui/ConfirmationDialog.cpp +++ b/KiwiLight - Vision Code/ui/ConfirmationDialog.cpp @@ -1,56 +1,56 @@ -#include "UI.h" - -/** - * Source file for the ConfirmationDialog class. - * Written By: Brach Knutson - */ - -using namespace KiwiLight; - - -ConfirmationDialog::ConfirmationDialog(std::string message) { - GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL); - this->dialog = gtk_dialog_new_with_buttons("Confirmation", GTK_WINDOW(window), GTK_DIALOG_MODAL, "OK", GTK_RESPONSE_ACCEPT, "Cancel", GTK_RESPONSE_REJECT, NULL); - GtkWidget *dialogContent = gtk_dialog_get_content_area(GTK_DIALOG(this->dialog)); - this->content = Panel(false, 0); - Label lbl = Label(message); - this->content.Pack_start(lbl.GetWidget(), false, false, 0); - - gtk_container_add(GTK_CONTAINER(dialogContent), this->content.GetWidget()); - -} - - -void ConfirmationDialog::SetBody(Panel pnl) { - this->content.Pack_start(pnl.GetWidget(), true, true, 0); -} - - -bool ConfirmationDialog::ShowButDontClose() { - gtk_widget_show_all(this->dialog); - gint response = gtk_dialog_run(GTK_DIALOG(this->dialog)); - return response == GTK_RESPONSE_ACCEPT; -} - - -void ConfirmationDialog::ShowWithoutRunning() { - gtk_widget_show_all(this->dialog); -} - - -bool ConfirmationDialog::ShowAndGetResponse() { - gtk_widget_show_all(this->dialog); - gint response = gtk_dialog_run(GTK_DIALOG(this->dialog)); - gtk_widget_destroy(this->dialog); - return response == GTK_RESPONSE_ACCEPT; -} - - -void ConfirmationDialog::Destroy() { - gtk_widget_destroy(this->dialog); -} - - -void ConfirmationDialog::SetName(std::string name) { - gtk_widget_set_name(this->dialog, name.c_str()); +#include "UI.h" + +/** + * Source file for the ConfirmationDialog class. + * Written By: Brach Knutson + */ + +using namespace KiwiLight; + + +ConfirmationDialog::ConfirmationDialog(std::string message) { + GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + this->dialog = gtk_dialog_new_with_buttons("Confirmation", GTK_WINDOW(window), GTK_DIALOG_MODAL, "OK", GTK_RESPONSE_ACCEPT, "Cancel", GTK_RESPONSE_REJECT, NULL); + GtkWidget *dialogContent = gtk_dialog_get_content_area(GTK_DIALOG(this->dialog)); + this->content = Panel(false, 0); + Label lbl = Label(message); + this->content.Pack_start(lbl.GetWidget(), false, false, 0); + + gtk_container_add(GTK_CONTAINER(dialogContent), this->content.GetWidget()); + +} + + +void ConfirmationDialog::SetBody(Panel pnl) { + this->content.Pack_start(pnl.GetWidget(), true, true, 0); +} + + +bool ConfirmationDialog::ShowButDontClose() { + gtk_widget_show_all(this->dialog); + gint response = gtk_dialog_run(GTK_DIALOG(this->dialog)); + return response == GTK_RESPONSE_ACCEPT; +} + + +void ConfirmationDialog::ShowWithoutRunning() { + gtk_widget_show_all(this->dialog); +} + + +bool ConfirmationDialog::ShowAndGetResponse() { + gtk_widget_show_all(this->dialog); + gint response = gtk_dialog_run(GTK_DIALOG(this->dialog)); + gtk_widget_destroy(this->dialog); + return response == GTK_RESPONSE_ACCEPT; +} + + +void ConfirmationDialog::Destroy() { + gtk_widget_destroy(this->dialog); +} + + +void ConfirmationDialog::SetName(std::string name) { + gtk_widget_set_name(this->dialog, name.c_str()); } \ No newline at end of file diff --git a/KiwiLight - Vision Code/ui/FileChooser.cpp b/KiwiLight - Vision Code/ui/FileChooser.cpp index 7e2f6ce..9669334 100644 --- a/KiwiLight - Vision Code/ui/FileChooser.cpp +++ b/KiwiLight - Vision Code/ui/FileChooser.cpp @@ -1,60 +1,60 @@ -#include "UI.h" - -/** - * Source file for the FileChooser class. - * Written By: Brach Knutson - */ - -using namespace KiwiLight; - -/** - * Creates a new FileChooser. - * @param writing Should be true if you intend this filechooser to choose a file to save to, false if choosing to read from. - * @param defaultFileName Only used if writing is true, the default name of the file to save to. - */ -FileChooser::FileChooser(bool writing, std::string defaultFileName) { - GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL); - - if(writing) { - this->filechooser = gtk_file_chooser_dialog_new("Save File", - GTK_WINDOW(window), - GTK_FILE_CHOOSER_ACTION_SAVE, - "Cancel", - GTK_RESPONSE_CANCEL, - "Save", - GTK_RESPONSE_ACCEPT, - NULL - ); - - // gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(this->filechooser), defaultFileName.c_str()); - gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(this->filechooser), defaultFileName.c_str()); - } else { - this->filechooser = gtk_file_chooser_dialog_new ("Open File", - GTK_WINDOW(window), - GTK_FILE_CHOOSER_ACTION_OPEN, - "Cancel", - GTK_RESPONSE_CANCEL, - "Open", - GTK_RESPONSE_ACCEPT, - NULL - ); - } - - gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(this->filechooser), getenv("HOME")); -} - - -std::string FileChooser::Show() { - gint result = gtk_dialog_run(GTK_DIALOG(this->filechooser)); - std::string file = ""; - if(result == GTK_RESPONSE_ACCEPT) { - file = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(this->filechooser)); - } - - gtk_widget_destroy(this->filechooser); - return file; -} - -void FileChooser::SetName(std::string name) { - gtk_widget_set_name(this->filechooser, name.c_str()); +#include "UI.h" + +/** + * Source file for the FileChooser class. + * Written By: Brach Knutson + */ + +using namespace KiwiLight; + +/** + * Creates a new FileChooser. + * @param writing Should be true if you intend this filechooser to choose a file to save to, false if choosing to read from. + * @param defaultFileName Only used if writing is true, the default name of the file to save to. + */ +FileChooser::FileChooser(bool writing, std::string defaultFileName) { + GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + + if(writing) { + this->filechooser = gtk_file_chooser_dialog_new("Save File", + GTK_WINDOW(window), + GTK_FILE_CHOOSER_ACTION_SAVE, + "Cancel", + GTK_RESPONSE_CANCEL, + "Save", + GTK_RESPONSE_ACCEPT, + NULL + ); + + // gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(this->filechooser), defaultFileName.c_str()); + gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(this->filechooser), defaultFileName.c_str()); + } else { + this->filechooser = gtk_file_chooser_dialog_new ("Open File", + GTK_WINDOW(window), + GTK_FILE_CHOOSER_ACTION_OPEN, + "Cancel", + GTK_RESPONSE_CANCEL, + "Open", + GTK_RESPONSE_ACCEPT, + NULL + ); + } + + gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(this->filechooser), getenv("HOME")); +} + + +std::string FileChooser::Show() { + gint result = gtk_dialog_run(GTK_DIALOG(this->filechooser)); + std::string file = ""; + if(result == GTK_RESPONSE_ACCEPT) { + file = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(this->filechooser)); + } + + gtk_widget_destroy(this->filechooser); + return file; +} + +void FileChooser::SetName(std::string name) { + gtk_widget_set_name(this->filechooser, name.c_str()); } \ No newline at end of file diff --git a/KiwiLight - Vision Code/ui/Frame.cpp b/KiwiLight - Vision Code/ui/Frame.cpp index d3d774d..4042b4c 100644 --- a/KiwiLight - Vision Code/ui/Frame.cpp +++ b/KiwiLight - Vision Code/ui/Frame.cpp @@ -1,35 +1,35 @@ -#include "UI.h" - -/** - * Source file for the Frame class. - * Written By: Brach Knutson - */ - - -using namespace KiwiLight; - -/** - * Creates a new frame with the given text in the label. - */ -Frame::Frame(std::string label) { - this->frame = gtk_frame_new(label.c_str()); - g_object_ref_sink(this->frame); - gtk_frame_set_shadow_type(GTK_FRAME(this->frame), GTK_SHADOW_ETCHED_IN); -} - -/** - * Pack the given widget into the frame (is it vertical or horizontal? idk!!!) - */ -void Frame::Pack(GtkWidget *widget) { - gtk_container_add(GTK_CONTAINER(this->frame), widget); -} - - -void Frame::Unpack(GtkWidget *widget) { - gtk_container_remove(GTK_CONTAINER(this->frame), widget); -} - - -void Frame::SetName(std::string name) { - gtk_widget_set_name(this->frame, name.c_str()); +#include "UI.h" + +/** + * Source file for the Frame class. + * Written By: Brach Knutson + */ + + +using namespace KiwiLight; + +/** + * Creates a new frame with the given text in the label. + */ +Frame::Frame(std::string label) { + this->frame = gtk_frame_new(label.c_str()); + g_object_ref_sink(this->frame); + gtk_frame_set_shadow_type(GTK_FRAME(this->frame), GTK_SHADOW_ETCHED_IN); +} + +/** + * Pack the given widget into the frame (is it vertical or horizontal? idk!!!) + */ +void Frame::Pack(GtkWidget *widget) { + gtk_container_add(GTK_CONTAINER(this->frame), widget); +} + + +void Frame::Unpack(GtkWidget *widget) { + gtk_container_remove(GTK_CONTAINER(this->frame), widget); +} + + +void Frame::SetName(std::string name) { + gtk_widget_set_name(this->frame, name.c_str()); } \ No newline at end of file diff --git a/KiwiLight - Vision Code/ui/HelpWindow.cpp b/KiwiLight - Vision Code/ui/HelpWindow.cpp index 8c1699b..576da95 100644 --- a/KiwiLight - Vision Code/ui/HelpWindow.cpp +++ b/KiwiLight - Vision Code/ui/HelpWindow.cpp @@ -1,54 +1,54 @@ -#include "UI.h" - -/** - * Source file for the HelpWindow class. - * Written By: Brach Knutson - */ - - -using namespace KiwiLight; - - -HelpWindow::HelpWindow(GtkWindowType type) { - this->window = Window(type, false); - this->window.SetSize(550, 200); - Panel main = Panel(true, 0); - Panel banners = Panel(false, 0); - - Image kiwiLogo = Image("banner_small.png"); - banners.Pack_start(kiwiLogo.GetWidget(), false, false, 0); - - Image foximusLogo = Image("foximus_small.png"); - banners.Pack_start(foximusLogo.GetWidget(), false, false, 0); - - main.Pack_start(banners.GetWidget(), false, false, 0); - - Panel labels = Panel(false, 0); - - Label header = Label("KiwiLight Help"); - header.SetName("header"); - labels.Pack_start(header.GetWidget(), false, false, 0); - - Label content = Label( - std::string("For KiwiLight help, check out the tutorial at \n\n") + - std::string("You can also email brach2003@gmail.com with any questions, comments, concerns, etc.") - ); - content.SetLineWrap(true); - labels.Pack_start(content.GetWidget(), false, false, 0); - - main.Pack_start(labels.GetWidget(), false, false, 0); - - this->window.SetPane(main); - - this->helpwindow = this->window.GetWidget(); -} - - -void HelpWindow::Show() { - this->window.Show(); -} - - -void HelpWindow::SetName(std::string name) { - gtk_widget_set_name(this->helpwindow, name.c_str()); +#include "UI.h" + +/** + * Source file for the HelpWindow class. + * Written By: Brach Knutson + */ + + +using namespace KiwiLight; + + +HelpWindow::HelpWindow(GtkWindowType type) { + this->window = Window(type, false); + this->window.SetSize(550, 200); + Panel main = Panel(true, 0); + Panel banners = Panel(false, 0); + + Image kiwiLogo = Image("banner_small.png"); + banners.Pack_start(kiwiLogo.GetWidget(), false, false, 0); + + Image foximusLogo = Image("foximus_small.png"); + banners.Pack_start(foximusLogo.GetWidget(), false, false, 0); + + main.Pack_start(banners.GetWidget(), false, false, 0); + + Panel labels = Panel(false, 0); + + Label header = Label("KiwiLight Help"); + header.SetName("header"); + labels.Pack_start(header.GetWidget(), false, false, 0); + + Label content = Label( + std::string("For KiwiLight help, check out the tutorial at \n\n") + + std::string("You can also email brach2003@gmail.com with any questions, comments, concerns, etc.") + ); + content.SetLineWrap(true); + labels.Pack_start(content.GetWidget(), false, false, 0); + + main.Pack_start(labels.GetWidget(), false, false, 0); + + this->window.SetPane(main); + + this->helpwindow = this->window.GetWidget(); +} + + +void HelpWindow::Show() { + this->window.Show(); +} + + +void HelpWindow::SetName(std::string name) { + gtk_widget_set_name(this->helpwindow, name.c_str()); } \ No newline at end of file diff --git a/KiwiLight - Vision Code/ui/Image.cpp b/KiwiLight - Vision Code/ui/Image.cpp index e55ff1c..78f0b16 100644 --- a/KiwiLight - Vision Code/ui/Image.cpp +++ b/KiwiLight - Vision Code/ui/Image.cpp @@ -1,84 +1,84 @@ -#include "UI.h" - -/** - * Source file for the Image class. - * Written By: Brach Knutson - */ - -using namespace cv; -using namespace KiwiLight; - - -Image::Image(std::string fileName) { - this->image = gtk_image_new_from_file(fileName.c_str()); - this->colorspace = ImageColorspace::RGB; - this->declaredAsStaticImage = true; - this->declared = true; -} - - -Image::Image(ImageColorspace colorspace) { - this->image = gtk_drawing_area_new(); - this->colorspace = colorspace; - this->declaredAsStaticImage = false; - this->declared = true; -} - -/** - * Updates and redraws the widget with newImage. - */ -void Image::Update(cv::Mat newImage) { - if(!this->declaredAsStaticImage) { - //convert the newImage to RGB colorspace - cv::Mat newImageCopy; //copy the image so that changes arent made to the argument image - newImage.copyTo(newImageCopy); - cvtColor(newImageCopy, newImageCopy, COLOR_BGR2RGB); - - //create the cairo renderer and initalize it - cairo_region_t *region = cairo_region_create(); - GdkWindow *win = gtk_widget_get_window(this->image); - - if(win != NULL) { - GdkDrawingContext *drawingContext = gdk_window_begin_draw_frame(win, region); - cairo_t *cairo = gdk_drawing_context_get_cairo_context(drawingContext); - - cairo_save(cairo); - cairo_translate(cairo, 0, 0); - - //create the pixbuf from the mat data - guchar *imageData = (guchar*) newImageCopy.data; - GdkPixbuf *imgData = gdk_pixbuf_new_from_data(imageData, - GDK_COLORSPACE_RGB, - FALSE, - 8, - newImageCopy.cols, - newImageCopy.rows, - newImageCopy.step, - NULL, - NULL); - - //create a surface from the pixbuf and render it - cairo_surface_t *surface = gdk_cairo_surface_create_from_pixbuf(imgData, 1, win); - cairo_set_source_surface(cairo, surface, 0, 0); - cairo_rectangle(cairo, 0, 0, newImageCopy.cols, newImageCopy.rows); - cairo_paint(cairo); - cairo_fill(cairo); - cairo_restore(cairo); - gdk_window_end_draw_frame(win, drawingContext); - - //request a new widget size so the entire image is visible - gtk_widget_set_size_request(this->image, newImageCopy.cols, newImageCopy.rows); - - //clean up memory so leaks don't happen - cairo_surface_destroy(surface); - cairo_region_destroy(region); - g_object_unref(G_OBJECT(imgData)); - } - } else { - std::cout << "CANNOT UPDATE A STATIC IMAGE!" << std::endl; - } -} - -void Image::SetName(std::string name) { - gtk_widget_set_name(this->image, name.c_str()); -} +#include "UI.h" + +/** + * Source file for the Image class. + * Written By: Brach Knutson + */ + +using namespace cv; +using namespace KiwiLight; + + +Image::Image(std::string fileName) { + this->image = gtk_image_new_from_file(fileName.c_str()); + this->colorspace = ImageColorspace::RGB; + this->declaredAsStaticImage = true; + this->declared = true; +} + + +Image::Image(ImageColorspace colorspace) { + this->image = gtk_drawing_area_new(); + this->colorspace = colorspace; + this->declaredAsStaticImage = false; + this->declared = true; +} + +/** + * Updates and redraws the widget with newImage. + */ +void Image::Update(cv::Mat newImage) { + if(!this->declaredAsStaticImage) { + //convert the newImage to RGB colorspace + cv::Mat newImageCopy; //copy the image so that changes arent made to the argument image + newImage.copyTo(newImageCopy); + cvtColor(newImageCopy, newImageCopy, COLOR_BGR2RGB); + + //create the cairo renderer and initalize it + cairo_region_t *region = cairo_region_create(); + GdkWindow *win = gtk_widget_get_window(this->image); + + if(win != NULL) { + GdkDrawingContext *drawingContext = gdk_window_begin_draw_frame(win, region); + cairo_t *cairo = gdk_drawing_context_get_cairo_context(drawingContext); + + cairo_save(cairo); + cairo_translate(cairo, 0, 0); + + //create the pixbuf from the mat data + guchar *imageData = (guchar*) newImageCopy.data; + GdkPixbuf *imgData = gdk_pixbuf_new_from_data(imageData, + GDK_COLORSPACE_RGB, + FALSE, + 8, + newImageCopy.cols, + newImageCopy.rows, + newImageCopy.step, + NULL, + NULL); + + //create a surface from the pixbuf and render it + cairo_surface_t *surface = gdk_cairo_surface_create_from_pixbuf(imgData, 1, win); + cairo_set_source_surface(cairo, surface, 0, 0); + cairo_rectangle(cairo, 0, 0, newImageCopy.cols, newImageCopy.rows); + cairo_paint(cairo); + cairo_fill(cairo); + cairo_restore(cairo); + gdk_window_end_draw_frame(win, drawingContext); + + //request a new widget size so the entire image is visible + gtk_widget_set_size_request(this->image, newImageCopy.cols, newImageCopy.rows); + + //clean up memory so leaks don't happen + cairo_surface_destroy(surface); + cairo_region_destroy(region); + g_object_unref(G_OBJECT(imgData)); + } + } else { + std::cout << "CANNOT UPDATE A STATIC IMAGE!" << std::endl; + } +} + +void Image::SetName(std::string name) { + gtk_widget_set_name(this->image, name.c_str()); +} diff --git a/KiwiLight - Vision Code/ui/Label.cpp b/KiwiLight - Vision Code/ui/Label.cpp index 9d21f75..cbf2164 100644 --- a/KiwiLight - Vision Code/ui/Label.cpp +++ b/KiwiLight - Vision Code/ui/Label.cpp @@ -1,52 +1,52 @@ -#include "UI.h" - -/** - * Source file for the Label class. - * Written By: Brach Knutson - */ - - -using namespace KiwiLight; - -/** - * Creates a new label. - */ -Label::Label(std::string text) { - this->label = gtk_label_new(text.c_str()); -} - -/** - * Sets the text of the label to the given std::string. - */ -void Label::SetText(std::string text) { - gtk_label_set_text(GTK_LABEL(this->label), text.c_str()); - this->text = text; -} - - -void Label::SetName(std::string name) { - gtk_widget_set_name(this->label, name.c_str()); -} - - -void Label::SetLineWrap(bool enabled) { - gtk_label_set_line_wrap(GTK_LABEL(this->label), enabled); -} - -void Label::SetJustify(int justify) { - GtkJustification justification; - switch(justify) { - case 0: - justification = GTK_JUSTIFY_LEFT; - break; - - case 1: - justification = GTK_JUSTIFY_RIGHT; - break; - - default: - justification = GTK_JUSTIFY_CENTER; - } - - gtk_label_set_justify(GTK_LABEL(this->label), justification); +#include "UI.h" + +/** + * Source file for the Label class. + * Written By: Brach Knutson + */ + + +using namespace KiwiLight; + +/** + * Creates a new label. + */ +Label::Label(std::string text) { + this->label = gtk_label_new(text.c_str()); +} + +/** + * Sets the text of the label to the given std::string. + */ +void Label::SetText(std::string text) { + gtk_label_set_text(GTK_LABEL(this->label), text.c_str()); + this->text = text; +} + + +void Label::SetName(std::string name) { + gtk_widget_set_name(this->label, name.c_str()); +} + + +void Label::SetLineWrap(bool enabled) { + gtk_label_set_line_wrap(GTK_LABEL(this->label), enabled); +} + +void Label::SetJustify(int justify) { + GtkJustification justification; + switch(justify) { + case 0: + justification = GTK_JUSTIFY_LEFT; + break; + + case 1: + justification = GTK_JUSTIFY_RIGHT; + break; + + default: + justification = GTK_JUSTIFY_CENTER; + } + + gtk_label_set_justify(GTK_LABEL(this->label), justification); } \ No newline at end of file diff --git a/KiwiLight - Vision Code/ui/LabeledSlider.cpp b/KiwiLight - Vision Code/ui/LabeledSlider.cpp index 7e2a48c..5b6140d 100644 --- a/KiwiLight - Vision Code/ui/LabeledSlider.cpp +++ b/KiwiLight - Vision Code/ui/LabeledSlider.cpp @@ -1,50 +1,50 @@ -#include "UI.h" - -/** - * Source file for the LabeledSlider class. - * Written By: Brach Knutson - */ - -using namespace KiwiLight; - - -LabeledSlider::LabeledSlider(std::string label, double min, double max, double step, double value) { - this->panel = Panel(false, 0); - this->label = Label(label.c_str()); - this->panel.Pack_start(this->label.GetWidget(), false, false, 0); - this->slider = Slider(min, max, step, value); - this->panel.Pack_start(this->slider.GetWidget(), false, false, 0); - - this->labeledslider = this->panel.GetWidget(); -} - - -LabeledSlider::LabeledSlider(bool horizontal, std::string label, double min, double max, double step, double value) { - this->panel = Panel(false, 0); - this->label = Label(label.c_str()); - this->panel.Pack_start(this->label.GetWidget(), false, false, 0); - this->slider = Slider(horizontal, min, max, step, value); - this->panel.Pack_start(this->slider.GetWidget(), false, false, 0); - - this->labeledslider = this->panel.GetWidget(); -} - - -double LabeledSlider::GetValue() { - return (double) this->slider.GetValue(); -} - - -void LabeledSlider::SetValue(double value) { - this->slider.SetValue(value); -} - - -void LabeledSlider::SetLabel(std::string text) { - this->label.SetText(text); -} - - -void LabeledSlider::SetName(std::string name) { - gtk_widget_set_name(this->labeledslider, name.c_str()); +#include "UI.h" + +/** + * Source file for the LabeledSlider class. + * Written By: Brach Knutson + */ + +using namespace KiwiLight; + + +LabeledSlider::LabeledSlider(std::string label, double min, double max, double step, double value) { + this->panel = Panel(false, 0); + this->label = Label(label.c_str()); + this->panel.Pack_start(this->label.GetWidget(), false, false, 0); + this->slider = Slider(min, max, step, value); + this->panel.Pack_start(this->slider.GetWidget(), false, false, 0); + + this->labeledslider = this->panel.GetWidget(); +} + + +LabeledSlider::LabeledSlider(bool horizontal, std::string label, double min, double max, double step, double value) { + this->panel = Panel(false, 0); + this->label = Label(label.c_str()); + this->panel.Pack_start(this->label.GetWidget(), false, false, 0); + this->slider = Slider(horizontal, min, max, step, value); + this->panel.Pack_start(this->slider.GetWidget(), false, false, 0); + + this->labeledslider = this->panel.GetWidget(); +} + + +double LabeledSlider::GetValue() { + return (double) this->slider.GetValue(); +} + + +void LabeledSlider::SetValue(double value) { + this->slider.SetValue(value); +} + + +void LabeledSlider::SetLabel(std::string text) { + this->label.SetText(text); +} + + +void LabeledSlider::SetName(std::string name) { + gtk_widget_set_name(this->labeledslider, name.c_str()); } \ No newline at end of file diff --git a/KiwiLight - Vision Code/ui/MenuBar.cpp b/KiwiLight - Vision Code/ui/MenuBar.cpp index e63bb56..f1484cd 100644 --- a/KiwiLight - Vision Code/ui/MenuBar.cpp +++ b/KiwiLight - Vision Code/ui/MenuBar.cpp @@ -1,28 +1,28 @@ -#include "UI.h" - -/** - * Source file for the MenuBar class. - * Written By: Brach Knutson - */ - - -using namespace KiwiLight; - -/** - * Creates a new MenuBar. - */ -MenuBar::MenuBar() { - this->menubar = gtk_menu_bar_new(); -} - -/** - * Add the given menu item to the bar. - */ -void MenuBar::AddItem(MenuItem item) { - gtk_menu_shell_append(GTK_MENU_SHELL(this->menubar), item.GetWidget()); -} - - -void MenuBar::SetName(std::string name) { - gtk_widget_set_name(this->menubar, name.c_str()); +#include "UI.h" + +/** + * Source file for the MenuBar class. + * Written By: Brach Knutson + */ + + +using namespace KiwiLight; + +/** + * Creates a new MenuBar. + */ +MenuBar::MenuBar() { + this->menubar = gtk_menu_bar_new(); +} + +/** + * Add the given menu item to the bar. + */ +void MenuBar::AddItem(MenuItem item) { + gtk_menu_shell_append(GTK_MENU_SHELL(this->menubar), item.GetWidget()); +} + + +void MenuBar::SetName(std::string name) { + gtk_widget_set_name(this->menubar, name.c_str()); } \ No newline at end of file diff --git a/KiwiLight - Vision Code/ui/MenuItem.cpp b/KiwiLight - Vision Code/ui/MenuItem.cpp index ed9e70f..6cc4cfb 100644 --- a/KiwiLight - Vision Code/ui/MenuItem.cpp +++ b/KiwiLight - Vision Code/ui/MenuItem.cpp @@ -1,27 +1,27 @@ -#include "UI.h" - -/** - * Source file for the MenuItem class. - * Written By: Brach Knutson - */ - - -using namespace KiwiLight; - -/** - * Create a new MenuItem with the given name and action when clicked. - */ -MenuItem::MenuItem(std::string name) { - this->menuitem = gtk_menu_item_new_with_label(name.c_str()); - this->menu = gtk_menu_new(); - gtk_menu_item_set_submenu(GTK_MENU_ITEM(this->menuitem), this->menu); -} - -void MenuItem::AddSubmenuItem(SubMenuItem item) { - gtk_menu_shell_append(GTK_MENU_SHELL(this->menu), item.GetWidget()); -} - - -void MenuItem::SetName(std::string name) { - gtk_widget_set_name(this->menu, name.c_str()); +#include "UI.h" + +/** + * Source file for the MenuItem class. + * Written By: Brach Knutson + */ + + +using namespace KiwiLight; + +/** + * Create a new MenuItem with the given name and action when clicked. + */ +MenuItem::MenuItem(std::string name) { + this->menuitem = gtk_menu_item_new_with_label(name.c_str()); + this->menu = gtk_menu_new(); + gtk_menu_item_set_submenu(GTK_MENU_ITEM(this->menuitem), this->menu); +} + +void MenuItem::AddSubmenuItem(SubMenuItem item) { + gtk_menu_shell_append(GTK_MENU_SHELL(this->menu), item.GetWidget()); +} + + +void MenuItem::SetName(std::string name) { + gtk_widget_set_name(this->menu, name.c_str()); } \ No newline at end of file diff --git a/KiwiLight - Vision Code/ui/NumberBox.cpp b/KiwiLight - Vision Code/ui/NumberBox.cpp index a55257e..073e200 100644 --- a/KiwiLight - Vision Code/ui/NumberBox.cpp +++ b/KiwiLight - Vision Code/ui/NumberBox.cpp @@ -1,39 +1,39 @@ -#include "UI.h" - -/** - * Source file for the NumberBox class. - * Written By: Brach Knutson - */ - -using namespace KiwiLight; - -NumberBox::NumberBox(double min, double max, double value) { - this->min = min; - this->max = max; - - this->numberBox = gtk_spin_button_new_with_range(min, max, 1.0); - gtk_spin_button_set_value(GTK_SPIN_BUTTON(this->numberBox), value); -} - - -NumberBox::NumberBox(double min, double max, double step, double value) { - this->min = min; - this->max = max; - this->numberBox = gtk_spin_button_new_with_range(min, max, step); - gtk_spin_button_set_value(GTK_SPIN_BUTTON(this->numberBox), value); -} - - -void NumberBox::SetValue(double value) { - gtk_spin_button_set_value(GTK_SPIN_BUTTON(this->numberBox), value); -} - - -double NumberBox::GetValue() { - return gtk_spin_button_get_value(GTK_SPIN_BUTTON(this->numberBox)); -} - - -void NumberBox::SetName(std::string name) { - gtk_widget_set_name(this->numberBox, name.c_str()); +#include "UI.h" + +/** + * Source file for the NumberBox class. + * Written By: Brach Knutson + */ + +using namespace KiwiLight; + +NumberBox::NumberBox(double min, double max, double value) { + this->min = min; + this->max = max; + + this->numberBox = gtk_spin_button_new_with_range(min, max, 1.0); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(this->numberBox), value); +} + + +NumberBox::NumberBox(double min, double max, double step, double value) { + this->min = min; + this->max = max; + this->numberBox = gtk_spin_button_new_with_range(min, max, step); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(this->numberBox), value); +} + + +void NumberBox::SetValue(double value) { + gtk_spin_button_set_value(GTK_SPIN_BUTTON(this->numberBox), value); +} + + +double NumberBox::GetValue() { + return gtk_spin_button_get_value(GTK_SPIN_BUTTON(this->numberBox)); +} + + +void NumberBox::SetName(std::string name) { + gtk_widget_set_name(this->numberBox, name.c_str()); } \ No newline at end of file diff --git a/KiwiLight - Vision Code/ui/OverviewPanel.cpp b/KiwiLight - Vision Code/ui/OverviewPanel.cpp index 579ce45..83b2932 100644 --- a/KiwiLight - Vision Code/ui/OverviewPanel.cpp +++ b/KiwiLight - Vision Code/ui/OverviewPanel.cpp @@ -1,195 +1,204 @@ -#include "../KiwiLight.h" - -/** - * Source file for the OverviewPanel class. - * Written By: Brach Knutson - */ - -using namespace cv; -using namespace KiwiLight; - - -OverviewPanel::OverviewPanel(XMLDocument doc) { - XMLTag configTag = doc.GetTagsByName("configuration")[0]; - Panel editor = Panel(false, 0); - Panel namePanel = Panel(true, 0); - Label confNameHeader = Label("Configuration: "); - confNameHeader.SetName("header"); - namePanel.Pack_start(confNameHeader.GetWidget(), false, false, 0); - - std::string realConfigName = configTag.GetAttributesByName("name")[0].Value(); - this->configName = TextBox(realConfigName); - namePanel.Pack_start(this->configName.GetWidget(), false, false, 0); - - editor.Pack_start(namePanel.GetWidget(), false, false, 0); - - Label targetInformationHeader = Label("Target Information:"); - targetInformationHeader.SetName("subHeader"); - editor.Pack_start(targetInformationHeader.GetWidget(), true, true, 0); - - //the real time target information panel - Panel targetInformationPanel = Panel(false, 0); - this->targetSpotted = Label("Target Spotted: NO"); - this->targetSpotted.SetName("gray"); - targetInformationPanel.Pack_start(this->targetSpotted.GetWidget(), false, false, 0); - - this->targetImageLocation = Label("Target Location: N/A"); - targetInformationPanel.Pack_start(this->targetImageLocation.GetWidget(), false, false, 0); - - this->targetDist = Label("Target Distance: N/A"); - targetInformationPanel.Pack_start(this->targetDist.GetWidget(), false, false, 0); - - this->targetHAngle = Label("Target Horizontal Angle: N/A"); - targetInformationPanel.Pack_start(this->targetHAngle.GetWidget(), false, false, 0); - - this->targetVAngle = Label("Target Vertical Angle: N/A"); - targetInformationPanel.Pack_start(this->targetVAngle.GetWidget(), false, false, 0); - - editor.Pack_start(targetInformationPanel.GetWidget(), true, true, 0); - - Label cameraHeader = Label("Camera"); - cameraHeader.SetName("subHeader"); - editor.Pack_start(cameraHeader.GetWidget(), true, true, 0); - - Panel cameraPanel = Panel(true, 0); - Label cameraIndexHeader = Label("Camera Index:"); - cameraPanel.Pack_start(cameraIndexHeader.GetWidget(), true, true, 0); - - int realCameraIndex = std::stoi(doc.GetTagsByName("camera")[0].GetAttributesByName("index")[0].Value()); - this->cameraIndex = NumberBox(0, 100, 1, realCameraIndex); - cameraPanel.Pack_start(this->cameraIndex.GetWidget(), true, true, 0); - - Button applyIndexButton = Button("Open", KiwiLightApp::EditorOpenNewCameraFromOverview); - cameraPanel.Pack_start(applyIndexButton.GetWidget(), true, true, 0); - editor.Pack_start(cameraPanel.GetWidget(), true, true, 0); - - Label udpHeader = Label("UDP"); - udpHeader.SetName("subHeader"); - editor.Pack_start(udpHeader.GetWidget(), true, true, 0); - - XMLTag udpTag = doc.GetTagsByName("configuration")[0].GetTagsByName("postprocessor")[0].GetTagsByName("UDP")[0]; - Panel udpPanel = Panel(true, 0); - Panel udpEditorContents = Panel(false, 0); - Panel udpAddrPanel = Panel(true, 0); - Label udpAddrPanelHeader = Label("IPv4 Address: "); - udpAddrPanel.Pack_start(udpAddrPanelHeader.GetWidget(), true, true, 0); - - std::string realUDP = udpTag.GetTagsByName("address")[0].Content(); - this->udpAddr = TextBox(realUDP); - udpAddrPanel.Pack_start(this->udpAddr.GetWidget(), true, true, 0); - - udpEditorContents.Pack_start(udpAddrPanel.GetWidget(), true, true, 0); - - Panel udpPortPanel = Panel(true, 0); - Label udpPortPanelHeader = Label("Port: "); - udpPortPanel.Pack_start(udpPortPanelHeader.GetWidget(), true, true, 0); - - int realUDPPort = std::stoi(udpTag.GetTagsByName("port")[0].Content()); - this->udpPort = NumberBox(1, 9999, 1, realUDPPort); - udpPortPanel.Pack_start(this->udpPort.GetWidget(), true, true, 0); - - udpEditorContents.Pack_start(udpPortPanel.GetWidget(), true, true, 0); - - udpPanel.Pack_start(udpEditorContents.GetWidget(), true, true, 0); - - Button reconnectUDP = Button("Reconnect", KiwiLightApp::EditorConnectUDPFromOverview); - udpPanel.Pack_start(reconnectUDP.GetWidget(), true, true, 0); - - editor.Pack_start(udpPanel.GetWidget(), true, true, 0); - - this->overviewpanel = editor.GetWidget(); -} - -/** - * Updates the overview panel. - */ -void OverviewPanel::Update() { - -} - -void OverviewPanel::SetConfigName(std::string name) { - this->configName.SetText(name); -} - -std::string OverviewPanel::GetConfigName() { - return this->configName.GetText(); -} - - -void OverviewPanel::SetTargetInformationLabels(bool targetSpotted, int targetImgX, int targetImgY, double targetDist, double targetHAngle, double targetVAngle) { - this->targetSpotted.SetText(std::string("Target Spotted: ") + (targetSpotted ? std::string("YES") : std::string("NO"))); - - std::string - targetLocationString = "N/A", - targetDistString = "N/A", - targetHAngleString = "N/A", - targetVAngleString = "N/A"; - - if(targetSpotted) { - targetLocationString = "( " + std::to_string(targetImgX) + ", " + std::to_string(targetImgY) + ")"; - targetDistString = std::to_string(targetDist); - targetHAngleString = std::to_string(targetHAngle); - targetVAngleString = std::to_string(targetVAngle); - } - - this->targetImageLocation.SetText("Target Location " + targetLocationString); - this->targetDist.SetText("Target Distance: " + targetDistString); - this->targetHAngle.SetText("Target Horizontal Angle: " + targetHAngleString); - this->targetVAngle.SetText("Target Vertical Angle: " + targetVAngleString); -} - - -void OverviewPanel::SetCameraIndex(int index) { - this->cameraIndex.SetValue((double) index); -} - - -int OverviewPanel::GetCameraIndex() { - return this->cameraIndex.GetValue(); -} - - -void OverviewPanel::SetUDPAddr(std::string addr) { - this->udpAddr.SetText(addr); -} - -std::string OverviewPanel::GetUDPAddr() { - return this->udpAddr.GetText(); -} - -void OverviewPanel::SetUDPPort(int port) { - this->udpPort.SetValue(port); -} - -int OverviewPanel::GetUDPPort() { - return (int) this->udpPort.GetValue(); -} - - -void OverviewPanel::SetTargetInformationLabelsFromString(std::string iterOutput) { - if(iterOutput.length() < 3) { //improperly formatted string - return; - } - - std::string trimmedOutput = iterOutput.substr(1, iterOutput.length() - 2); //sub off the ':' and ';' at beginning and end - std::vector splitOutput = StringUtils::SplitString(trimmedOutput, ','); - - //there must be 5 nums in string, no more, no less - if(splitOutput.size() == 5) { - int targetX = std::stoi(splitOutput[0]); - int targetY = std::stoi(splitOutput[1]); - double targetDist = std::stod(splitOutput[2]); - double targetAngleHorizontal = std::stod(splitOutput[3]); - double targetAngleVertical = std::stod(splitOutput[4]); - bool targetSpotted = (targetX > -1); - - SetTargetInformationLabels(targetSpotted, targetX, targetY, targetDist, targetAngleHorizontal, targetAngleVertical); - } else { - std::cout << "WARNING: Could not update overview panel information labels. Input string was wrongly formatted." << std::endl; - } -} - - -void OverviewPanel::SetName(std::string name) { - gtk_widget_set_name(this->overviewpanel, name.c_str()); +#include "../KiwiLight.h" + +/** + * Source file for the OverviewPanel class. + * Written By: Brach Knutson + */ + +using namespace cv; +using namespace KiwiLight; + + +OverviewPanel::OverviewPanel(XMLDocument doc) { + XMLTag configTag = doc.GetTagsByName("configuration")[0]; + Panel editor = Panel(false, 0); + Panel namePanel = Panel(true, 0); + Label confNameHeader = Label("Configuration: "); + confNameHeader.SetName("header"); + namePanel.Pack_start(confNameHeader.GetWidget(), false, false, 0); + + std::string realConfigName = configTag.GetAttributesByName("name")[0].Value(); + this->configName = TextBox(realConfigName); + namePanel.Pack_start(this->configName.GetWidget(), false, false, 0); + + editor.Pack_start(namePanel.GetWidget(), false, false, 0); + + Label targetInformationHeader = Label("Target Information:"); + targetInformationHeader.SetName("subHeader"); + editor.Pack_start(targetInformationHeader.GetWidget(), true, true, 0); + + //the real time target information panel + Panel targetInformationPanel = Panel(false, 0); + this->targetSpotted = Label("Target Spotted: NO"); + this->targetSpotted.SetName("gray"); + targetInformationPanel.Pack_start(this->targetSpotted.GetWidget(), false, false, 0); + + this->targetImageLocation = Label("Target Location: N/A"); + targetInformationPanel.Pack_start(this->targetImageLocation.GetWidget(), false, false, 0); + + this->targetDist = Label("Target Distance: N/A"); + targetInformationPanel.Pack_start(this->targetDist.GetWidget(), false, false, 0); + + this->targetHAngle = Label("Target Horizontal Angle: N/A"); + targetInformationPanel.Pack_start(this->targetHAngle.GetWidget(), false, false, 0); + + this->targetVAngle = Label("Target Vertical Angle: N/A"); + targetInformationPanel.Pack_start(this->targetVAngle.GetWidget(), false, false, 0); + + editor.Pack_start(targetInformationPanel.GetWidget(), true, true, 0); + + Label cameraHeader = Label("Camera"); + cameraHeader.SetName("subHeader"); + editor.Pack_start(cameraHeader.GetWidget(), true, true, 0); + + Panel cameraPanel = Panel(true, 0); + Label cameraIndexHeader = Label("Camera Index:"); + cameraPanel.Pack_start(cameraIndexHeader.GetWidget(), true, true, 0); + + int realCameraIndex = std::stoi(doc.GetTagsByName("camera")[0].GetAttributesByName("index")[0].Value()); + this->cameraIndex = NumberBox(0, 100, 1, realCameraIndex); + cameraPanel.Pack_start(this->cameraIndex.GetWidget(), true, true, 0); + + Button applyIndexButton = Button("Open", KiwiLightApp::EditorOpenNewCameraFromOverview); + cameraPanel.Pack_start(applyIndexButton.GetWidget(), true, true, 0); + editor.Pack_start(cameraPanel.GetWidget(), true, true, 0); + + Label udpHeader = Label("UDP"); + udpHeader.SetName("subHeader"); + editor.Pack_start(udpHeader.GetWidget(), true, true, 0); + + XMLTag udpTag = doc.GetTagsByName("configuration")[0].GetTagsByName("postprocessor")[0].GetTagsByName("UDP")[0]; + Panel udpPanel = Panel(true, 0); + Panel udpEditorContents = Panel(false, 0); + Panel udpAddrPanel = Panel(true, 0); + Label udpAddrPanelHeader = Label("IPv4 Address: "); + udpAddrPanel.Pack_start(udpAddrPanelHeader.GetWidget(), true, true, 0); + + std::string realUDP = udpTag.GetTagsByName("address")[0].Content(); + this->udpAddr = TextBox(realUDP); + udpAddrPanel.Pack_start(this->udpAddr.GetWidget(), true, true, 0); + + udpEditorContents.Pack_start(udpAddrPanel.GetWidget(), true, true, 0); + + Panel udpPortPanel = Panel(true, 0); + Label udpPortPanelHeader = Label("Port: "); + udpPortPanel.Pack_start(udpPortPanelHeader.GetWidget(), true, true, 0); + + int realUDPPort = std::stoi(udpTag.GetTagsByName("port")[0].Content()); + this->udpPort = NumberBox(1, 9999, 1, realUDPPort); + udpPortPanel.Pack_start(this->udpPort.GetWidget(), true, true, 0); + + udpEditorContents.Pack_start(udpPortPanel.GetWidget(), true, true, 0); + + udpPanel.Pack_start(udpEditorContents.GetWidget(), true, true, 0); + + Button reconnectUDP = Button("Reconnect", KiwiLightApp::EditorConnectUDPFromOverview); + udpPanel.Pack_start(reconnectUDP.GetWidget(), true, true, 0); + + this->enableUDP = Button("Enable", KiwiLightApp::ToggleUDP); + udpPanel.Pack_start(this->enableUDP.GetWidget(), true, true, 0); + + editor.Pack_start(udpPanel.GetWidget(), true, true, 0); + + this->overviewpanel = editor.GetWidget(); +} + +/** + * Updates the overview panel. + */ +void OverviewPanel::Update() { + +} + +void OverviewPanel::SetConfigName(std::string name) { + this->configName.SetText(name); +} + +std::string OverviewPanel::GetConfigName() { + return this->configName.GetText(); +} + + +void OverviewPanel::SetTargetInformationLabels(bool targetSpotted, int targetImgX, int targetImgY, double targetDist, double targetHAngle, double targetVAngle) { + this->targetSpotted.SetText(std::string("Target Spotted: ") + (targetSpotted ? std::string("YES") : std::string("NO"))); + + std::string + targetLocationString = "N/A", + targetDistString = "N/A", + targetHAngleString = "N/A", + targetVAngleString = "N/A"; + + if(targetSpotted) { + targetLocationString = "( " + std::to_string(targetImgX) + ", " + std::to_string(targetImgY) + ")"; + targetDistString = std::to_string(targetDist); + targetHAngleString = std::to_string(targetHAngle); + targetVAngleString = std::to_string(targetVAngle); + } + + this->targetImageLocation.SetText("Target Location " + targetLocationString); + this->targetDist.SetText("Target Distance: " + targetDistString); + this->targetHAngle.SetText("Target Horizontal Angle: " + targetHAngleString); + this->targetVAngle.SetText("Target Vertical Angle: " + targetVAngleString); +} + + +void OverviewPanel::SetCameraIndex(int index) { + this->cameraIndex.SetValue((double) index); +} + + +int OverviewPanel::GetCameraIndex() { + return this->cameraIndex.GetValue(); +} + + +void OverviewPanel::SetUDPAddr(std::string addr) { + this->udpAddr.SetText(addr); +} + +std::string OverviewPanel::GetUDPAddr() { + return this->udpAddr.GetText(); +} + +void OverviewPanel::SetUDPPort(int port) { + this->udpPort.SetValue(port); +} + +int OverviewPanel::GetUDPPort() { + return (int) this->udpPort.GetValue(); +} + +void OverviewPanel::SetUDPEnabledLabels(bool UDPEnabled) { + this->enableUDP.SetText((UDPEnabled ? "Disable" : "Enable")); +} + + +void OverviewPanel::SetTargetInformationLabelsFromString(std::string iterOutput) { + if(iterOutput.length() < 3) { //improperly formatted string + return; + } + + std::string trimmedOutput = iterOutput.substr(1, iterOutput.length() - 2); //sub off the ':' and ';' at beginning and end + std::vector splitOutput = StringUtils::SplitString(trimmedOutput, ','); + + //there must be 5 nums in string, no more, no less + if(splitOutput.size() == 7) { + int targetX = std::stoi(splitOutput[0]); + int targetY = std::stoi(splitOutput[1]); + int targetWidth = std::stoi(splitOutput[2]); + int targetHeight = std::stoi(splitOutput[3]); + double targetDist = std::stod(splitOutput[4]); + double targetAngleHorizontal = std::stod(splitOutput[5]); + double targetAngleVertical = std::stod(splitOutput[6]); + bool targetSpotted = (targetX > -1); + + SetTargetInformationLabels(targetSpotted, targetX, targetY, targetDist, targetAngleHorizontal, targetAngleVertical); + } else { + std::cout << "WARNING: Could not update overview panel information labels. Input string was wrongly formatted." << std::endl; + } +} + + +void OverviewPanel::SetName(std::string name) { + gtk_widget_set_name(this->overviewpanel, name.c_str()); } \ No newline at end of file diff --git a/KiwiLight - Vision Code/ui/Panel.cpp b/KiwiLight - Vision Code/ui/Panel.cpp index e18cb5b..faddfdf 100644 --- a/KiwiLight - Vision Code/ui/Panel.cpp +++ b/KiwiLight - Vision Code/ui/Panel.cpp @@ -1,36 +1,36 @@ -#include "UI.h" - -/** - * Source file for the Panel class. - * Written By: Brach Knutson - */ - - -using namespace KiwiLight; - -/** - * Creates a new panel. - */ -Panel::Panel(bool horizontal, int spacing) { - //using depreciated gtk_hbox_new() until gtk_box_new() is implemented in current version of gtk. - this->panel = gtk_box_new((horizontal ? GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL), spacing); -} - -/** - * Packs the given widget into the start of the container. - */ -void Panel::Pack_start(GtkWidget *widget, bool expand, bool fill, int pad) { - gtk_box_pack_start(GTK_BOX(this->panel), widget, gboolean(expand), gboolean(fill), pad); -} - -/** - * Packs the given widget into the end of the container. - */ -void Panel::Pack_end(GtkWidget *widget, bool expand, bool fill, int pad) { - gtk_box_pack_end(GTK_BOX(this->panel), widget, gboolean(expand), gboolean(fill), pad); -} - - -void Panel::SetName(std::string name) { - gtk_widget_set_name(this->panel, name.c_str()); +#include "UI.h" + +/** + * Source file for the Panel class. + * Written By: Brach Knutson + */ + + +using namespace KiwiLight; + +/** + * Creates a new panel. + */ +Panel::Panel(bool horizontal, int spacing) { + //using depreciated gtk_hbox_new() until gtk_box_new() is implemented in current version of gtk. + this->panel = gtk_box_new((horizontal ? GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL), spacing); +} + +/** + * Packs the given widget into the start of the container. + */ +void Panel::Pack_start(GtkWidget *widget, bool expand, bool fill, int pad) { + gtk_box_pack_start(GTK_BOX(this->panel), widget, gboolean(expand), gboolean(fill), pad); +} + +/** + * Packs the given widget into the end of the container. + */ +void Panel::Pack_end(GtkWidget *widget, bool expand, bool fill, int pad) { + gtk_box_pack_end(GTK_BOX(this->panel), widget, gboolean(expand), gboolean(fill), pad); +} + + +void Panel::SetName(std::string name) { + gtk_widget_set_name(this->panel, name.c_str()); } \ No newline at end of file diff --git a/KiwiLight - Vision Code/ui/PopupTextBox.cpp b/KiwiLight - Vision Code/ui/PopupTextBox.cpp index 1d9d536..7b4ba0a 100644 --- a/KiwiLight - Vision Code/ui/PopupTextBox.cpp +++ b/KiwiLight - Vision Code/ui/PopupTextBox.cpp @@ -1,38 +1,38 @@ -#include "UI.h" - -/** - * Source file for the PopupTextBox class. - * Written By: Brach Knutson - */ - -using namespace KiwiLight; - - -PopupTextBox::PopupTextBox(std::string name, std::string prompt, std::string initValue) { - GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL); - this->popuptextbox = gtk_dialog_new_with_buttons(name.c_str(), GTK_WINDOW(window), GTK_DIALOG_MODAL, "OK", GTK_RESPONSE_ACCEPT, NULL); - GtkWidget *dialogContent = gtk_dialog_get_content_area(GTK_DIALOG(this->popuptextbox)); - Panel pnl = Panel(false, 0); - Label promptLabel = Label(prompt); - pnl.Pack_start(promptLabel.GetWidget(), false, false, 0); - - this->textbox = TextBox(initValue); - pnl.Pack_start(this->textbox.GetWidget(), false, false, 0); - - gtk_container_add(GTK_CONTAINER(dialogContent), pnl.GetWidget()); - -} - - -std::string PopupTextBox::Show() { - gtk_widget_show_all(this->popuptextbox); - gtk_dialog_run(GTK_DIALOG(this->popuptextbox)); - std::string response = this->textbox.GetText(); - gtk_widget_destroy(this->popuptextbox); - return response; -} - - -void PopupTextBox::SetName(std::string name) { - gtk_widget_set_name(this->popuptextbox, name.c_str()); +#include "UI.h" + +/** + * Source file for the PopupTextBox class. + * Written By: Brach Knutson + */ + +using namespace KiwiLight; + + +PopupTextBox::PopupTextBox(std::string name, std::string prompt, std::string initValue) { + GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + this->popuptextbox = gtk_dialog_new_with_buttons(name.c_str(), GTK_WINDOW(window), GTK_DIALOG_MODAL, "OK", GTK_RESPONSE_ACCEPT, NULL); + GtkWidget *dialogContent = gtk_dialog_get_content_area(GTK_DIALOG(this->popuptextbox)); + Panel pnl = Panel(false, 0); + Label promptLabel = Label(prompt); + pnl.Pack_start(promptLabel.GetWidget(), false, false, 0); + + this->textbox = TextBox(initValue); + pnl.Pack_start(this->textbox.GetWidget(), false, false, 0); + + gtk_container_add(GTK_CONTAINER(dialogContent), pnl.GetWidget()); + +} + + +std::string PopupTextBox::Show() { + gtk_widget_show_all(this->popuptextbox); + gtk_dialog_run(GTK_DIALOG(this->popuptextbox)); + std::string response = this->textbox.GetText(); + gtk_widget_destroy(this->popuptextbox); + return response; +} + + +void PopupTextBox::SetName(std::string name) { + gtk_widget_set_name(this->popuptextbox, name.c_str()); } \ No newline at end of file diff --git a/KiwiLight - Vision Code/ui/PostprocessorEditor.cpp b/KiwiLight - Vision Code/ui/PostprocessorEditor.cpp index f372b01..45b4890 100644 --- a/KiwiLight - Vision Code/ui/PostprocessorEditor.cpp +++ b/KiwiLight - Vision Code/ui/PostprocessorEditor.cpp @@ -27,7 +27,7 @@ PostprocessorEditor::PostprocessorEditor(PostProcessor postprocessor) { ExampleContour newContour = ExampleContour(i); newContours.push_back(newContour); } - ExampleTarget newTarget = ExampleTarget(0, newContours, 0, 0, 0, 0); + ExampleTarget newTarget = ExampleTarget(0, newContours, 0, 0, 0, 0, DistanceCalcMode::BY_WIDTH); this->storageRunner.SetExampleTarget(0, newTarget); //init the values in the storage runner because they are all generic right now @@ -148,7 +148,7 @@ void PostprocessorEditor::SetNumContours(int contours) { newContours.push_back(newContour); } - ExampleTarget newTarg = ExampleTarget(0, newContours, 0.0, 0.0, 0.0, 0.0); + ExampleTarget newTarg = ExampleTarget(0, newContours, 0.0, 0.0, 0.0, 0.0, DistanceCalcMode::BY_WIDTH); std::cout << "ppe: setting target. " << newTarg.Contours().size() << " Contours." << std::endl; this->storageRunner.SetExampleTarget(0, newTarg); } diff --git a/KiwiLight - Vision Code/ui/PreprocessorEditor.cpp b/KiwiLight - Vision Code/ui/PreprocessorEditor.cpp index 3e90baa..59505fd 100644 --- a/KiwiLight - Vision Code/ui/PreprocessorEditor.cpp +++ b/KiwiLight - Vision Code/ui/PreprocessorEditor.cpp @@ -1,184 +1,184 @@ -#include "UI.h" - -/** - * Source file for the PreprocessorEditor class. - * Written By: Brach Knuston - */ - -using namespace KiwiLight; - - -PreprocessorEditor::PreprocessorEditor(PreProcessor preprocessor) { - this->lastIsFull = preprocessor.GetProperty(PreProcessorProperty::IS_FULL) == 1.0; - Panel editor = Panel(false, 0); - - Panel preprocessorTypePanel = Panel(false, 0); - double processorIsFullDouble = preprocessor.GetProperty(PreProcessorProperty::IS_FULL); - bool processorIsFullBool = (processorIsFullDouble == 1.0 ? true : false); - - Label preprocessorTypePanelHeader = Label("Type"); - preprocessorTypePanelHeader.SetName("subHeader"); - preprocessorTypePanel.Pack_start(preprocessorTypePanelHeader.GetWidget(), true, true, 0); - - Panel preprocessorPanelContents = Panel(true, 0); - this->isFull = CheckBox("Full", processorIsFullBool); - preprocessorPanelContents.Pack_start(this->isFull.GetWidget(), false, false, 0); - - this->isPartial = CheckBox("Partial", !processorIsFullBool); - preprocessorPanelContents.Pack_start(this->isPartial.GetWidget(), false, false, 0); - - preprocessorTypePanel.Pack_start(preprocessorPanelContents.GetWidget(), true, true, 0); - - editor.Pack_start(preprocessorTypePanel.GetWidget(), true, true, 0); - - Panel targetColorPanel = Panel(false, 0); - Label targetColorPanelHeader = Label("Target Color (HSV)"); - targetColorPanelHeader.SetName("subHeader"); - targetColorPanel.Pack_start(targetColorPanelHeader.GetWidget(), true, true, 0); - - Panel targetColorPanelContents = Panel(true, 0); - double realColorH = preprocessor.GetProperty(PreProcessorProperty::COLOR_HUE); - this->colorH = NumberBox(0, 100, realColorH); - targetColorPanelContents.Pack_start(this->colorH.GetWidget(), true, true, 0); - - double realColorS = preprocessor.GetProperty(PreProcessorProperty::COLOR_SATURATION); - this->colorS = NumberBox(0, 255, realColorS); - targetColorPanelContents.Pack_start(this->colorS.GetWidget(), true, true, 0); - - double realColorV = preprocessor.GetProperty(PreProcessorProperty::COLOR_VALUE); - this->colorV = NumberBox(0, 255, realColorV); - targetColorPanelContents.Pack_start(this->colorV.GetWidget(), true, true, 0); - - this->colorPreview = Image(ImageColorspace::RGB); - targetColorPanelContents.Pack_start(this->colorPreview.GetWidget(), false, false, 0); - - targetColorPanel.Pack_start(targetColorPanelContents.GetWidget(), true, true, 0); - - editor.Pack_start(targetColorPanel.GetWidget(), true, true, 0); - - Label imageProcLabel = Label("Image Processing"); - imageProcLabel.SetName("subHeader"); - editor.Pack_start(imageProcLabel.GetWidget(), true, true, 0); - - double realColorError = preprocessor.GetProperty(PreProcessorProperty::COLOR_ERROR); - this->colorError = LabeledSlider("Color Range", 0.0, 255.0, 1.0, realColorError); - editor.Pack_start(this->colorError.GetWidget(), true, true, 0); - - double realThreshonld = preprocessor.GetProperty(PreProcessorProperty::THRESHOLD); - this->threshold = LabeledSlider("Threshold", 1.0, 100.0, 1.0, realThreshonld); - editor.Pack_start(this->threshold.GetWidget(), true, true, 0); - - double realErosion = preprocessor.GetProperty(PreProcessorProperty::EROSION); - this->erosion = LabeledSlider("Erosion", 1.0, 25.0, 1.0, realErosion); - editor.Pack_start(this->erosion.GetWidget(), true, true, 0); - - double realDilation = preprocessor.GetProperty(PreProcessorProperty::DILATION); - this->dilation = LabeledSlider("Dilation", 1.0, 25.0, 1.0, realDilation); - editor.Pack_start(this->dilation.GetWidget(), true, true, 0); - - this->preprocessoreditor = editor.GetWidget(); -} - -/** - * Updates the UI of the editor. - */ -void PreprocessorEditor::Update() { - //set checkboxes to appropriate states based on which mode is selected. - if(this->isFull.GetState() && this->isPartial.GetState()) { - //both checkboxes checked, toggle intended - bool intendedStateIsFull = !this->lastIsFull; - - if(intendedStateIsFull) { - this->isFull.SetState(true); - this->isPartial.SetState(false); - } else { - this->isFull.SetState(false); - this->isPartial.SetState(true); - } - - this->lastIsFull = intendedStateIsFull; - } - - if(!this->isFull.GetState() && !this->isPartial.GetState()) { - //if no checkboxes are checked just revert back to whatever the last state was - if(this->lastIsFull) { - this->isFull.SetState(true); - this->isPartial.SetState(false); - } else { - this->isFull.SetState(false); - this->isPartial.SetState(true); - } - } - - //update the color in the box to the desired color - int hue = (int) this->colorH.GetValue(); - int saturation = (int) this->colorS.GetValue(); - int value = (int) this->colorV.GetValue(); - - Mat previewImage = Mat(Size(30, 30), CV_8UC3, Scalar(hue, saturation, value)); - cvtColor(previewImage, previewImage, COLOR_HSV2BGR_FULL); - this->colorPreview.Update(previewImage); -} - -/** - * Returns the value of the editor property - */ -double PreprocessorEditor::GetProperty(PreProcessorProperty prop) { - switch(prop) { - case PreProcessorProperty::IS_FULL: - return (this->isFull.GetState() ? 1.0 : 0.0); - case PreProcessorProperty::THRESHOLD: - return this->threshold.GetValue(); - case PreProcessorProperty::EROSION: - return this->erosion.GetValue(); - case PreProcessorProperty::DILATION: - return this->dilation.GetValue(); - case PreProcessorProperty::COLOR_HUE: - return this->colorH.GetValue(); - case PreProcessorProperty::COLOR_SATURATION: - return this->colorS.GetValue(); - case PreProcessorProperty::COLOR_VALUE: - return this->colorV.GetValue(); - case PreProcessorProperty::COLOR_ERROR: - return this->colorError.GetValue(); - } -} - -/** - * Sets the editor property to the value "value" - */ -void PreprocessorEditor::SetProperty(PreProcessorProperty prop, double value) { - switch(prop) { - case PreProcessorProperty::IS_FULL: - this->isFull.SetState(value == 1.0); - break; - case PreProcessorProperty::THRESHOLD: - this->threshold.SetValue(value); - break; - case PreProcessorProperty::EROSION: - this->erosion.SetValue(value); - break; - case PreProcessorProperty::DILATION: - this->dilation.SetValue(value); - break; - case PreProcessorProperty::COLOR_HUE: - this->colorH.SetValue(value); - break; - case PreProcessorProperty::COLOR_SATURATION: - this->colorS.SetValue(value); - break; - case PreProcessorProperty::COLOR_VALUE: - this->colorV.SetValue(value); - break; - case PreProcessorProperty::COLOR_ERROR: - this->colorError.SetValue(value); - break; - } -} - -/** - * Sets the name of the editor. - */ -void PreprocessorEditor::SetName(std::string name) { - gtk_widget_set_name(this->preprocessoreditor, name.c_str()); -} +#include "UI.h" + +/** + * Source file for the PreprocessorEditor class. + * Written By: Brach Knuston + */ + +using namespace KiwiLight; + + +PreprocessorEditor::PreprocessorEditor(PreProcessor preprocessor) { + this->lastIsFull = preprocessor.GetProperty(PreProcessorProperty::IS_FULL) == 1.0; + Panel editor = Panel(false, 0); + + Panel preprocessorTypePanel = Panel(false, 0); + double processorIsFullDouble = preprocessor.GetProperty(PreProcessorProperty::IS_FULL); + bool processorIsFullBool = (processorIsFullDouble == 1.0 ? true : false); + + Label preprocessorTypePanelHeader = Label("Type"); + preprocessorTypePanelHeader.SetName("subHeader"); + preprocessorTypePanel.Pack_start(preprocessorTypePanelHeader.GetWidget(), true, true, 0); + + Panel preprocessorPanelContents = Panel(true, 0); + this->isFull = CheckBox("Full", processorIsFullBool); + preprocessorPanelContents.Pack_start(this->isFull.GetWidget(), false, false, 0); + + this->isPartial = CheckBox("Partial", !processorIsFullBool); + preprocessorPanelContents.Pack_start(this->isPartial.GetWidget(), false, false, 0); + + preprocessorTypePanel.Pack_start(preprocessorPanelContents.GetWidget(), true, true, 0); + + editor.Pack_start(preprocessorTypePanel.GetWidget(), true, true, 0); + + Panel targetColorPanel = Panel(false, 0); + Label targetColorPanelHeader = Label("Target Color (HSV)"); + targetColorPanelHeader.SetName("subHeader"); + targetColorPanel.Pack_start(targetColorPanelHeader.GetWidget(), true, true, 0); + + Panel targetColorPanelContents = Panel(true, 0); + double realColorH = preprocessor.GetProperty(PreProcessorProperty::COLOR_HUE); + this->colorH = NumberBox(0, 100, realColorH); + targetColorPanelContents.Pack_start(this->colorH.GetWidget(), true, true, 0); + + double realColorS = preprocessor.GetProperty(PreProcessorProperty::COLOR_SATURATION); + this->colorS = NumberBox(0, 255, realColorS); + targetColorPanelContents.Pack_start(this->colorS.GetWidget(), true, true, 0); + + double realColorV = preprocessor.GetProperty(PreProcessorProperty::COLOR_VALUE); + this->colorV = NumberBox(0, 255, realColorV); + targetColorPanelContents.Pack_start(this->colorV.GetWidget(), true, true, 0); + + this->colorPreview = Image(ImageColorspace::RGB); + targetColorPanelContents.Pack_start(this->colorPreview.GetWidget(), false, false, 0); + + targetColorPanel.Pack_start(targetColorPanelContents.GetWidget(), true, true, 0); + + editor.Pack_start(targetColorPanel.GetWidget(), true, true, 0); + + Label imageProcLabel = Label("Image Processing"); + imageProcLabel.SetName("subHeader"); + editor.Pack_start(imageProcLabel.GetWidget(), true, true, 0); + + double realColorError = preprocessor.GetProperty(PreProcessorProperty::COLOR_ERROR); + this->colorError = LabeledSlider("Color Range", 0.0, 255.0, 1.0, realColorError); + editor.Pack_start(this->colorError.GetWidget(), true, true, 0); + + double realThreshonld = preprocessor.GetProperty(PreProcessorProperty::THRESHOLD); + this->threshold = LabeledSlider("Threshold", 1.0, 100.0, 1.0, realThreshonld); + editor.Pack_start(this->threshold.GetWidget(), true, true, 0); + + double realErosion = preprocessor.GetProperty(PreProcessorProperty::EROSION); + this->erosion = LabeledSlider("Erosion", 1.0, 25.0, 1.0, realErosion); + editor.Pack_start(this->erosion.GetWidget(), true, true, 0); + + double realDilation = preprocessor.GetProperty(PreProcessorProperty::DILATION); + this->dilation = LabeledSlider("Dilation", 1.0, 25.0, 1.0, realDilation); + editor.Pack_start(this->dilation.GetWidget(), true, true, 0); + + this->preprocessoreditor = editor.GetWidget(); +} + +/** + * Updates the UI of the editor. + */ +void PreprocessorEditor::Update() { + //set checkboxes to appropriate states based on which mode is selected. + if(this->isFull.GetState() && this->isPartial.GetState()) { + //both checkboxes checked, toggle intended + bool intendedStateIsFull = !this->lastIsFull; + + if(intendedStateIsFull) { + this->isFull.SetState(true); + this->isPartial.SetState(false); + } else { + this->isFull.SetState(false); + this->isPartial.SetState(true); + } + + this->lastIsFull = intendedStateIsFull; + } + + if(!this->isFull.GetState() && !this->isPartial.GetState()) { + //if no checkboxes are checked just revert back to whatever the last state was + if(this->lastIsFull) { + this->isFull.SetState(true); + this->isPartial.SetState(false); + } else { + this->isFull.SetState(false); + this->isPartial.SetState(true); + } + } + + //update the color in the box to the desired color + int hue = (int) this->colorH.GetValue(); + int saturation = (int) this->colorS.GetValue(); + int value = (int) this->colorV.GetValue(); + + Mat previewImage = Mat(Size(30, 30), CV_8UC3, Scalar(hue, saturation, value)); + cvtColor(previewImage, previewImage, COLOR_HSV2BGR_FULL); + this->colorPreview.Update(previewImage); +} + +/** + * Returns the value of the editor property + */ +double PreprocessorEditor::GetProperty(PreProcessorProperty prop) { + switch(prop) { + case PreProcessorProperty::IS_FULL: + return (this->isFull.GetState() ? 1.0 : 0.0); + case PreProcessorProperty::THRESHOLD: + return this->threshold.GetValue(); + case PreProcessorProperty::EROSION: + return this->erosion.GetValue(); + case PreProcessorProperty::DILATION: + return this->dilation.GetValue(); + case PreProcessorProperty::COLOR_HUE: + return this->colorH.GetValue(); + case PreProcessorProperty::COLOR_SATURATION: + return this->colorS.GetValue(); + case PreProcessorProperty::COLOR_VALUE: + return this->colorV.GetValue(); + case PreProcessorProperty::COLOR_ERROR: + return this->colorError.GetValue(); + } +} + +/** + * Sets the editor property to the value "value" + */ +void PreprocessorEditor::SetProperty(PreProcessorProperty prop, double value) { + switch(prop) { + case PreProcessorProperty::IS_FULL: + this->isFull.SetState(value == 1.0); + break; + case PreProcessorProperty::THRESHOLD: + this->threshold.SetValue(value); + break; + case PreProcessorProperty::EROSION: + this->erosion.SetValue(value); + break; + case PreProcessorProperty::DILATION: + this->dilation.SetValue(value); + break; + case PreProcessorProperty::COLOR_HUE: + this->colorH.SetValue(value); + break; + case PreProcessorProperty::COLOR_SATURATION: + this->colorS.SetValue(value); + break; + case PreProcessorProperty::COLOR_VALUE: + this->colorV.SetValue(value); + break; + case PreProcessorProperty::COLOR_ERROR: + this->colorError.SetValue(value); + break; + } +} + +/** + * Sets the name of the editor. + */ +void PreprocessorEditor::SetName(std::string name) { + gtk_widget_set_name(this->preprocessoreditor, name.c_str()); +} diff --git a/KiwiLight - Vision Code/ui/RunnerEditor.cpp b/KiwiLight - Vision Code/ui/RunnerEditor.cpp index 985c75c..d12a2ad 100644 --- a/KiwiLight - Vision Code/ui/RunnerEditor.cpp +++ b/KiwiLight - Vision Code/ui/RunnerEditor.cpp @@ -13,14 +13,6 @@ static void ReconnectUDP() { RunnerEditor::RunnerEditor(Runner runner) { Panel editor = Panel(false, 0); - // OFFSET_X, - // OFFSET_Y, - // IMAGE_WIDTH, - // IMAGE_HEIGHT, - // TRUE_WIDTH, - // PERCEIVED_WIDTH, - // CALIBRATED_DISTANCE, - // ERROR_CORRECTION Panel udpPanel = Panel(true, 0); Panel udpInputPanel = Panel(false, 0); @@ -28,7 +20,7 @@ RunnerEditor::RunnerEditor(Runner runner) { Label udpAddressPanelHeader = Label("IPv4 Address: "); udpAddressPanel.Pack_start(udpAddressPanelHeader.GetWidget(), true, true, 0); - std::string realUDPAddress = runner.GetUDP().GetAddress(); + std::string realUDPAddress = KiwiLightApp::GetUDP().GetAddress(); this->udpAddress = TextBox(realUDPAddress); udpAddressPanel.Pack_start(this->udpAddress.GetWidget(), true, true, 0); @@ -38,7 +30,7 @@ RunnerEditor::RunnerEditor(Runner runner) { Label udpPortPanelHeader = Label("Port: "); udpPortPanel.Pack_start(udpPortPanelHeader.GetWidget(), true, true, 0); - int realUDPPort = runner.GetUDP().GetPort(); + int realUDPPort = KiwiLightApp::GetUDP().GetPort(); this->udpPort = NumberBox(0.0, 9999.0, 1.0, (double) realUDPPort); udpPortPanel.Pack_start(this->udpPort.GetWidget(), true, true, 0); udpInputPanel.Pack_start(udpPortPanel.GetWidget(), true, true, 0); @@ -46,6 +38,9 @@ RunnerEditor::RunnerEditor(Runner runner) { Button reconnectUDP = Button("Reconnect", ReconnectUDP); udpPanel.Pack_start(reconnectUDP.GetWidget(), true, true, 0); + this->enableUDP = Button("Enable", KiwiLightApp::ToggleUDP); + udpPanel.Pack_start(this->enableUDP.GetWidget(), true, true, 0); + editor.Pack_start(udpPanel.GetWidget(), true, true, 0); @@ -91,6 +86,11 @@ RunnerEditor::RunnerEditor(Runner runner) { this->distanceLabel = Label("Calculated Distance: (no target!)"); this->distanceLabel.SetName("gray"); distancePanel.Pack_start(this->distanceLabel.GetWidget(), true, true, 0); + + this->useHeight = CheckBox("Use Height to calculate distance", true); + bool realUseHeight = runner.GetRunnerProperty(RunnerProperty::CALC_DIST_BY_HEIGHT) == 1; + this->useHeight.SetState(realUseHeight); + distancePanel.Pack_start(this->useHeight.GetWidget(), true, true, 0); Panel imageConstantsPanel = Panel(true, 0); double realTargetWidth = runner.GetRunnerProperty(RunnerProperty::TRUE_WIDTH); @@ -147,6 +147,8 @@ double RunnerEditor::GetProperty(RunnerProperty prop) { return this->targetCalibratedDistance.GetValue(); case RunnerProperty::ERROR_CORRECTION: return this->targetErrorCorrection.GetValue(); + case RunnerProperty::CALC_DIST_BY_HEIGHT: + return (this->useHeight.GetState() ? 1 : 0); } } @@ -179,6 +181,9 @@ void RunnerEditor::SetProperty(RunnerProperty prop, double value) { case RunnerProperty::ERROR_CORRECTION: this->targetErrorCorrection.SetValue(value); break; + case RunnerProperty::CALC_DIST_BY_HEIGHT: + this->useHeight.SetState(value == 1); + break; } } @@ -203,6 +208,10 @@ void RunnerEditor::SetUDPPort(int newPort) { } +void RunnerEditor::SetUDPEnabledLabels(bool UDPEnabled) { + this->enableUDP.SetText((UDPEnabled ? "Disable" : "Enable")); +} + void RunnerEditor::SetName(std::string name) { gtk_widget_set_name(this->runnereditor, name.c_str()); } diff --git a/KiwiLight - Vision Code/ui/Scrollable.cpp b/KiwiLight - Vision Code/ui/Scrollable.cpp index 6f6a25f..237123c 100644 --- a/KiwiLight - Vision Code/ui/Scrollable.cpp +++ b/KiwiLight - Vision Code/ui/Scrollable.cpp @@ -1,28 +1,28 @@ -#include "UI.h" - -/** - * Source file for the Scrollable class. - * Written By: Brach Knutson - */ - -using namespace KiwiLight; - - -Scrollable::Scrollable(bool horizontal, bool vertical) { - this->scrollable = gtk_scrolled_window_new(NULL, NULL); - gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(this->scrollable), - (horizontal ? GTK_POLICY_AUTOMATIC : GTK_POLICY_NEVER), - (vertical? GTK_POLICY_AUTOMATIC : GTK_POLICY_NEVER)); - - gtk_container_set_border_width(GTK_CONTAINER(this->scrollable), 5); -} - - -void Scrollable::PackWidget(GtkWidget *wid) { - gtk_container_add(GTK_CONTAINER(this->scrollable), wid); -} - - -void Scrollable::SetName(std::string name) { - gtk_widget_set_name(this->scrollable, name.c_str()); +#include "UI.h" + +/** + * Source file for the Scrollable class. + * Written By: Brach Knutson + */ + +using namespace KiwiLight; + + +Scrollable::Scrollable(bool horizontal, bool vertical) { + this->scrollable = gtk_scrolled_window_new(NULL, NULL); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(this->scrollable), + (horizontal ? GTK_POLICY_AUTOMATIC : GTK_POLICY_NEVER), + (vertical? GTK_POLICY_AUTOMATIC : GTK_POLICY_NEVER)); + + gtk_container_set_border_width(GTK_CONTAINER(this->scrollable), 5); +} + + +void Scrollable::PackWidget(GtkWidget *wid) { + gtk_container_add(GTK_CONTAINER(this->scrollable), wid); +} + + +void Scrollable::SetName(std::string name) { + gtk_widget_set_name(this->scrollable, name.c_str()); } \ No newline at end of file diff --git a/KiwiLight - Vision Code/ui/Separator.cpp b/KiwiLight - Vision Code/ui/Separator.cpp index 8e4b3f6..dd7148b 100644 --- a/KiwiLight - Vision Code/ui/Separator.cpp +++ b/KiwiLight - Vision Code/ui/Separator.cpp @@ -1,24 +1,24 @@ -#include "UI.h" - -/** - * Source file for the UI Separator class. - * Written By: Brach Knutson - */ - - -using namespace KiwiLight; - -/** - * Creates a new Separator. - */ -Separator::Separator(bool horizontal) { - if(horizontal) - this->separator = gtk_separator_new(GTK_ORIENTATION_HORIZONTAL); - else - this->separator = gtk_separator_new(GTK_ORIENTATION_VERTICAL); -} - - -void Separator::SetName(std::string name) { - gtk_widget_set_name(this->separator, name.c_str()); +#include "UI.h" + +/** + * Source file for the UI Separator class. + * Written By: Brach Knutson + */ + + +using namespace KiwiLight; + +/** + * Creates a new Separator. + */ +Separator::Separator(bool horizontal) { + if(horizontal) + this->separator = gtk_separator_new(GTK_ORIENTATION_HORIZONTAL); + else + this->separator = gtk_separator_new(GTK_ORIENTATION_VERTICAL); +} + + +void Separator::SetName(std::string name) { + gtk_widget_set_name(this->separator, name.c_str()); } \ No newline at end of file diff --git a/KiwiLight - Vision Code/ui/Settings.cpp b/KiwiLight - Vision Code/ui/Settings.cpp index c4fee2c..519acad 100644 --- a/KiwiLight - Vision Code/ui/Settings.cpp +++ b/KiwiLight - Vision Code/ui/Settings.cpp @@ -1,168 +1,168 @@ -#include "../KiwiLight.h" - -/** - * Source file for the Settings class - * Written By: Brach Knutson - */ - - -using namespace KiwiLight; - -/** - * Create a new Settings menu. - */ -Settings::Settings(XMLDocument doc) { - - std::vector docSettings = - doc.GetTagsByName("camera")[0] - .GetTagsByName("settings")[0] - .GetTagsByName("setting"); - - Panel editor = Panel(false, 0); - - //camera index - Panel cameraIndexPanel = Panel(true, 0); - Label cameraIndexHeader = Label("Camera Index: "); - cameraIndexPanel.Pack_start(cameraIndexHeader.GetWidget(), true, true, 0); - - int realCameraIndex = std::stoi(doc.GetTagsByName("camera")[0].GetAttributesByName("index")[0].Value()); - this->cameraIndex = NumberBox(0.0, 10.0, 1.0, realCameraIndex); - cameraIndexPanel.Pack_start(this->cameraIndex.GetWidget(), true, true, 0); - editor.Pack_start(cameraIndexPanel.GetWidget(), true, true, 0); - - //resolution area - Label resolutionHeader = Label("Resolution"); - resolutionHeader.SetName("subHeader"); - editor.Pack_start(resolutionHeader.GetWidget(), true, true, 0); - - //frame width - int realFrameWidth = std::stoi(Util::SearchCameraSettingsByID(docSettings, CAP_PROP_FRAME_WIDTH).Content()); - CameraSetting frameWidth = CameraSetting("Width: ", CAP_PROP_FRAME_WIDTH, 100, 2000, realFrameWidth); - this->settings.push_back(frameWidth); - editor.Pack_start(frameWidth.GetWidget(), true, true, 0); - - //frame height - int realFrameHeight = std::stoi(Util::SearchCameraSettingsByID(docSettings, CAP_PROP_FRAME_HEIGHT).Content()); - CameraSetting frameHeight = CameraSetting("Height: ", CAP_PROP_FRAME_HEIGHT, 100, 2000, realFrameHeight); - this->settings.push_back(frameHeight); - editor.Pack_start(frameHeight.GetWidget(), true, true, 0); - - Label resolutionNote = Label( - "NOTE: Some resolutions may not be supported by your camera!" - ); - editor.Pack_start(resolutionNote.GetWidget(), true, true, 0); - - Separator hsep = Separator(true); - editor.Pack_start(hsep.GetWidget(), true, true, 0); - - Label settingsHeader = Label("Other Settings"); - editor.Pack_start(settingsHeader.GetWidget(), true, true, 0); - - //exposure auto - double realExposureAuto = std::stod(Util::SearchCameraSettingsByID(docSettings, CAP_PROP_AUTO_EXPOSURE).Content()); - CameraSetting autoExposure = CameraSetting("Auto Exposure: ", CAP_PROP_AUTO_EXPOSURE, 0, 1, realExposureAuto); - this->settings.push_back(autoExposure); - editor.Pack_start(autoExposure.GetWidget(), true, true, 0); - - //exposure - double realExposure = std::stod(Util::SearchCameraSettingsByID(docSettings, CAP_PROP_EXPOSURE).Content()); - CameraSetting exposure = CameraSetting("Exposure: ", CAP_PROP_EXPOSURE, -1, 1, realExposure); - this->settings.push_back(exposure); - editor.Pack_start(exposure.GetWidget(), true, true, 0); - - //white balance auto - double realWhiteBalanceAuto = std::stod(Util::SearchCameraSettingsByID(docSettings, CAP_PROP_AUTO_WB).Content()); - CameraSetting autoWB = CameraSetting("Auto White Balance: ", CAP_PROP_AUTO_WB, 0, 1, realWhiteBalanceAuto); - this->settings.push_back(autoWB); - editor.Pack_start(autoWB.GetWidget(), true, true, 0); - - //white balance - double realWhiteBalance = std::stod(Util::SearchCameraSettingsByID(docSettings, CAP_PROP_WB_TEMPERATURE).Content()); - CameraSetting WB = CameraSetting("White Balance: ", CAP_PROP_WB_TEMPERATURE, -1, 1, realWhiteBalance); - this->settings.push_back(WB); - editor.Pack_start(WB.GetWidget(), true, true, 0); - - //brightness - double realBrightness = std::stod(Util::SearchCameraSettingsByID(docSettings, CAP_PROP_BRIGHTNESS).Content()); - CameraSetting brightness = CameraSetting("Brightness: ", CAP_PROP_BRIGHTNESS, -1, 1, realBrightness); - this->settings.push_back(brightness); - editor.Pack_start(brightness.GetWidget(), true, true, 0); - - //the apply button - Button apply = Button("Apply", KiwiLightApp::EditorApplyCameraSettings); - editor.Pack_start(apply.GetWidget(), true, true, 0); - - this->settingsWidget = editor.GetWidget(); -} - -void Settings::Update() { - -} - - -/** - * Returns an XMLTag containing information describing the settings' values. - */ -XMLTag Settings::GetFinishedTag() { - XMLTag settingsTag = XMLTag("settings"); - for(int i=0; isettings.size(); i++) { - XMLTag newSetting = XMLTag("setting", std::to_string(this->settings[i].GetValue())); - //add the name attribute - XMLTagAttribute settingAttr = XMLTagAttribute("id", std::to_string(this->settings[i].GetValueName())); - newSetting.AddAttribute(settingAttr); - - settingsTag.AddTag(newSetting); - } - - return settingsTag; -} - -/** - * Finds the setting with the given ID and sets its value. - */ -void Settings::SetSettingValueFromID(int id, double value) { - for(int i=0; isettings.size(); i++) { - if(this->settings[i].GetValueName() == id) { - this->settings[i].SetValue(value); - } - } -} - - -/** - * Finds the setting with the given ID and returns it's value, or -1.0 if none found. - */ -double Settings::GetSettingValueFromID(int id) { - for(int i=0; isettings.size(); i++) { - if(this->settings[i].GetValueName() == id) { - return this->settings[i].GetValue(); - } - } - - return -1; -} - - -void Settings::SetCameraIndex(int index) { - this->cameraIndex.SetValue((double) index); -} - - -int Settings::GetCameraIndex() { - return this->cameraIndex.GetValue(); -} - - -std::vector Settings::GetSettingIDs() { - std::vector ids; - for(int i=0; isettings.size(); i++) { - ids.push_back(this->settings[i].GetValueName()); - } - - return ids; -} - - -void Settings::SetName(std::string name) { - gtk_widget_set_name(this->settingsWidget, name.c_str()); -} +#include "../KiwiLight.h" + +/** + * Source file for the Settings class + * Written By: Brach Knutson + */ + + +using namespace KiwiLight; + +/** + * Create a new Settings menu. + */ +Settings::Settings(XMLDocument doc) { + + std::vector docSettings = + doc.GetTagsByName("camera")[0] + .GetTagsByName("settings")[0] + .GetTagsByName("setting"); + + Panel editor = Panel(false, 0); + + //camera index + Panel cameraIndexPanel = Panel(true, 0); + Label cameraIndexHeader = Label("Camera Index: "); + cameraIndexPanel.Pack_start(cameraIndexHeader.GetWidget(), true, true, 0); + + int realCameraIndex = std::stoi(doc.GetTagsByName("camera")[0].GetAttributesByName("index")[0].Value()); + this->cameraIndex = NumberBox(0.0, 10.0, 1.0, realCameraIndex); + cameraIndexPanel.Pack_start(this->cameraIndex.GetWidget(), true, true, 0); + editor.Pack_start(cameraIndexPanel.GetWidget(), true, true, 0); + + //resolution area + Label resolutionHeader = Label("Resolution"); + resolutionHeader.SetName("subHeader"); + editor.Pack_start(resolutionHeader.GetWidget(), true, true, 0); + + //frame width + int realFrameWidth = std::stoi(Util::SearchCameraSettingsByID(docSettings, CAP_PROP_FRAME_WIDTH).Content()); + CameraSetting frameWidth = CameraSetting("Width: ", CAP_PROP_FRAME_WIDTH, 100, 2000, realFrameWidth); + this->settings.push_back(frameWidth); + editor.Pack_start(frameWidth.GetWidget(), true, true, 0); + + //frame height + int realFrameHeight = std::stoi(Util::SearchCameraSettingsByID(docSettings, CAP_PROP_FRAME_HEIGHT).Content()); + CameraSetting frameHeight = CameraSetting("Height: ", CAP_PROP_FRAME_HEIGHT, 100, 2000, realFrameHeight); + this->settings.push_back(frameHeight); + editor.Pack_start(frameHeight.GetWidget(), true, true, 0); + + Label resolutionNote = Label( + "NOTE: Some resolutions may not be supported by your camera!" + ); + editor.Pack_start(resolutionNote.GetWidget(), true, true, 0); + + Separator hsep = Separator(true); + editor.Pack_start(hsep.GetWidget(), true, true, 0); + + Label settingsHeader = Label("Other Settings"); + editor.Pack_start(settingsHeader.GetWidget(), true, true, 0); + + //exposure auto + double realExposureAuto = std::stod(Util::SearchCameraSettingsByID(docSettings, CAP_PROP_AUTO_EXPOSURE).Content()); + CameraSetting autoExposure = CameraSetting("Auto Exposure: ", CAP_PROP_AUTO_EXPOSURE, 0, 1, realExposureAuto); + this->settings.push_back(autoExposure); + editor.Pack_start(autoExposure.GetWidget(), true, true, 0); + + //exposure + double realExposure = std::stod(Util::SearchCameraSettingsByID(docSettings, CAP_PROP_EXPOSURE).Content()); + CameraSetting exposure = CameraSetting("Exposure: ", CAP_PROP_EXPOSURE, -1, 1, realExposure); + this->settings.push_back(exposure); + editor.Pack_start(exposure.GetWidget(), true, true, 0); + + //white balance auto + double realWhiteBalanceAuto = std::stod(Util::SearchCameraSettingsByID(docSettings, CAP_PROP_AUTO_WB).Content()); + CameraSetting autoWB = CameraSetting("Auto White Balance: ", CAP_PROP_AUTO_WB, 0, 1, realWhiteBalanceAuto); + this->settings.push_back(autoWB); + editor.Pack_start(autoWB.GetWidget(), true, true, 0); + + //white balance + double realWhiteBalance = std::stod(Util::SearchCameraSettingsByID(docSettings, CAP_PROP_WB_TEMPERATURE).Content()); + CameraSetting WB = CameraSetting("White Balance: ", CAP_PROP_WB_TEMPERATURE, -1, 1, realWhiteBalance); + this->settings.push_back(WB); + editor.Pack_start(WB.GetWidget(), true, true, 0); + + //brightness + double realBrightness = std::stod(Util::SearchCameraSettingsByID(docSettings, CAP_PROP_BRIGHTNESS).Content()); + CameraSetting brightness = CameraSetting("Brightness: ", CAP_PROP_BRIGHTNESS, -1, 1, realBrightness); + this->settings.push_back(brightness); + editor.Pack_start(brightness.GetWidget(), true, true, 0); + + //the apply button + Button apply = Button("Apply", KiwiLightApp::EditorApplyCameraSettings); + editor.Pack_start(apply.GetWidget(), true, true, 0); + + this->settingsWidget = editor.GetWidget(); +} + +void Settings::Update() { + +} + + +/** + * Returns an XMLTag containing information describing the settings' values. + */ +XMLTag Settings::GetFinishedTag() { + XMLTag settingsTag = XMLTag("settings"); + for(int i=0; isettings.size(); i++) { + XMLTag newSetting = XMLTag("setting", std::to_string(this->settings[i].GetValue())); + //add the name attribute + XMLTagAttribute settingAttr = XMLTagAttribute("id", std::to_string(this->settings[i].GetValueName())); + newSetting.AddAttribute(settingAttr); + + settingsTag.AddTag(newSetting); + } + + return settingsTag; +} + +/** + * Finds the setting with the given ID and sets its value. + */ +void Settings::SetSettingValueFromID(int id, double value) { + for(int i=0; isettings.size(); i++) { + if(this->settings[i].GetValueName() == id) { + this->settings[i].SetValue(value); + } + } +} + + +/** + * Finds the setting with the given ID and returns it's value, or -1.0 if none found. + */ +double Settings::GetSettingValueFromID(int id) { + for(int i=0; isettings.size(); i++) { + if(this->settings[i].GetValueName() == id) { + return this->settings[i].GetValue(); + } + } + + return -1; +} + + +void Settings::SetCameraIndex(int index) { + this->cameraIndex.SetValue((double) index); +} + + +int Settings::GetCameraIndex() { + return this->cameraIndex.GetValue(); +} + + +std::vector Settings::GetSettingIDs() { + std::vector ids; + for(int i=0; isettings.size(); i++) { + ids.push_back(this->settings[i].GetValueName()); + } + + return ids; +} + + +void Settings::SetName(std::string name) { + gtk_widget_set_name(this->settingsWidget, name.c_str()); +} diff --git a/KiwiLight - Vision Code/ui/Slider.cpp b/KiwiLight - Vision Code/ui/Slider.cpp index f70faa6..d907a6f 100644 --- a/KiwiLight - Vision Code/ui/Slider.cpp +++ b/KiwiLight - Vision Code/ui/Slider.cpp @@ -1,36 +1,36 @@ -#include "UI.h" - -/** - * Source file for the Slider class. - * Written By: Brach Knutson - */ - - -using namespace KiwiLight; - -Slider::Slider(double min, double max, double step, double value) { - this->slider = gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL, min, max, step); - gtk_range_set_value(GTK_RANGE(this->slider), gdouble(value)); -} - - -Slider::Slider(bool horizontal, double min, double max, double step, double value) { - // this->slider = gtk_scale_new_with_range((horizontal ? GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL), min, max, step); - this->slider = gtk_scale_new_with_range(GTK_ORIENTATION_VERTICAL, min, max, step); - gtk_range_set_value(GTK_RANGE(this->slider), gdouble(value)); -} - - -void Slider::SetValue(double value) { - gtk_range_set_value(GTK_RANGE(this->slider), value); -} - - -double Slider::GetValue() { - return gtk_range_get_value(GTK_RANGE(this->slider)); -} - - -void Slider::SetName(std::string name) { - gtk_widget_set_name(this->slider, name.c_str()); +#include "UI.h" + +/** + * Source file for the Slider class. + * Written By: Brach Knutson + */ + + +using namespace KiwiLight; + +Slider::Slider(double min, double max, double step, double value) { + this->slider = gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL, min, max, step); + gtk_range_set_value(GTK_RANGE(this->slider), gdouble(value)); +} + + +Slider::Slider(bool horizontal, double min, double max, double step, double value) { + // this->slider = gtk_scale_new_with_range((horizontal ? GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL), min, max, step); + this->slider = gtk_scale_new_with_range(GTK_ORIENTATION_VERTICAL, min, max, step); + gtk_range_set_value(GTK_RANGE(this->slider), gdouble(value)); +} + + +void Slider::SetValue(double value) { + gtk_range_set_value(GTK_RANGE(this->slider), value); +} + + +double Slider::GetValue() { + return gtk_range_get_value(GTK_RANGE(this->slider)); +} + + +void Slider::SetName(std::string name) { + gtk_widget_set_name(this->slider, name.c_str()); } \ No newline at end of file diff --git a/KiwiLight - Vision Code/ui/Style.css b/KiwiLight - Vision Code/ui/Style.css index 3efff05..3d46a37 100644 --- a/KiwiLight - Vision Code/ui/Style.css +++ b/KiwiLight - Vision Code/ui/Style.css @@ -1,85 +1,85 @@ - -/** - * Stylesheet written for the KiwiLight UI. - * Written By: Brach Knutson - */ - -window, window * { - background-color: rgb(24, 24, 24); - color: rgb(52, 117, 22); -} - -menubar, -menubar * { - background-color: rgb(50, 50, 50); -} - -menubar label { - background-color:transparent; - color:white; -} - -window:not(dialog) button, -window:not(dialog) button * { - background-color:black; - border-radius: 0px; - border-style:solid; - border-width:5px; - border-color:black; - padding:0px; -} - -window:not(dialog) button:hover, -window:not(dialog) button:hover * { - transition: 150ms ease-out; - background-color:rgb(39, 39, 39); -} - -window:not(dialog) button:active, -window:not(dialog) button:active * { - transition: 150ms ease-out; - background-color:rgb(17, 53, 3); -} - -window:not(dialog) button:disabled { - color:rgb(7, 22, 1); -} - -scrolledwindow * { - background-color: transparent; -} - -scrollbar { - background-color: white; -} - -scale * { - background-color: rgb(39, 39, 39); - color: rgb(52, 117, 22); -} - -#mainHeader { - background-color:rgb(40, 40, 40); -} - -#mainHeader > label { - background-color:transparent; -} - -#white { - color:rgb(212, 212, 212); -} - -#header { - color:rgb(175, 175, 175); - font-size:30px; -} - -#subHeader { - color:rgb(143, 143, 143); - font-size:18px; -} - -#gray { - color:rgb(143, 143, 143); + +/** + * Stylesheet written for the KiwiLight UI. + * Written By: Brach Knutson + */ + +window, window * { + background-color: rgb(24, 24, 24); + color: rgb(52, 117, 22); +} + +menubar, +menubar * { + background-color: rgb(50, 50, 50); +} + +menubar label { + background-color:transparent; + color:white; +} + +window:not(dialog) button, +window:not(dialog) button * { + background-color:black; + border-radius: 0px; + border-style:solid; + border-width:5px; + border-color:black; + padding:0px; +} + +window:not(dialog) button:hover, +window:not(dialog) button:hover * { + transition: 150ms ease-out; + background-color:rgb(39, 39, 39); +} + +window:not(dialog) button:active, +window:not(dialog) button:active * { + transition: 150ms ease-out; + background-color:rgb(17, 53, 3); +} + +window:not(dialog) button:disabled { + color:rgb(7, 22, 1); +} + +scrolledwindow * { + background-color: transparent; +} + +scrollbar { + background-color: white; +} + +scale * { + background-color: rgb(39, 39, 39); + color: rgb(52, 117, 22); +} + +#mainHeader { + background-color:rgb(40, 40, 40); +} + +#mainHeader > label { + background-color:transparent; +} + +#white { + color:rgb(212, 212, 212); +} + +#header { + color:rgb(175, 175, 175); + font-size:30px; +} + +#subHeader { + color:rgb(143, 143, 143); + font-size:18px; +} + +#gray { + color:rgb(143, 143, 143); } \ No newline at end of file diff --git a/KiwiLight - Vision Code/ui/SubMenuItem.cpp b/KiwiLight - Vision Code/ui/SubMenuItem.cpp index 2b54ec8..70969a9 100644 --- a/KiwiLight - Vision Code/ui/SubMenuItem.cpp +++ b/KiwiLight - Vision Code/ui/SubMenuItem.cpp @@ -1,21 +1,21 @@ -#include "UI.h" - -/** - * Source file for the SubMenuItem class. - * Written By: Brach Knutson - */ - - -using namespace KiwiLight; - -/** - * Create a submenu item with the given name, when clicked, the item will call callback. - */ -SubMenuItem::SubMenuItem(std::string name, void(* callback)()) { - this->submenuitem = gtk_menu_item_new_with_label(name.c_str()); - g_signal_connect(this->submenuitem, "activate", G_CALLBACK(callback), NULL); // connect the callback to the menu item. -} - -void SubMenuItem::SetName(std::string name) { - gtk_widget_set_name(this->submenuitem, name.c_str()); +#include "UI.h" + +/** + * Source file for the SubMenuItem class. + * Written By: Brach Knutson + */ + + +using namespace KiwiLight; + +/** + * Create a submenu item with the given name, when clicked, the item will call callback. + */ +SubMenuItem::SubMenuItem(std::string name, void(* callback)()) { + this->submenuitem = gtk_menu_item_new_with_label(name.c_str()); + g_signal_connect(this->submenuitem, "activate", G_CALLBACK(callback), NULL); // connect the callback to the menu item. +} + +void SubMenuItem::SetName(std::string name) { + gtk_widget_set_name(this->submenuitem, name.c_str()); } \ No newline at end of file diff --git a/KiwiLight - Vision Code/ui/TabView.cpp b/KiwiLight - Vision Code/ui/TabView.cpp index 4888fca..212d6b1 100644 --- a/KiwiLight - Vision Code/ui/TabView.cpp +++ b/KiwiLight - Vision Code/ui/TabView.cpp @@ -1,26 +1,26 @@ -#include "UI.h" - -/** - * Source file for the TabView class. - * Written By: Brach Knutson - */ - -using namespace KiwiLight; - - -TabView::TabView(std::string tab1Name, GtkWidget *tab1Content) { - this->tabview = gtk_notebook_new(); - Label tabLabel = Label(tab1Name); - gtk_notebook_append_page(GTK_NOTEBOOK(this->tabview), tab1Content, tabLabel.GetWidget()); -} - - -void TabView::AddTab(std::string tabName, GtkWidget *tabContent) { - Label tabLabel = Label(tabName); - gtk_notebook_append_page(GTK_NOTEBOOK(this->tabview), tabContent, tabLabel.GetWidget()); -} - - -void TabView::SetName(std::string name) { - gtk_widget_set_name(this->tabview, name.c_str()); +#include "UI.h" + +/** + * Source file for the TabView class. + * Written By: Brach Knutson + */ + +using namespace KiwiLight; + + +TabView::TabView(std::string tab1Name, GtkWidget *tab1Content) { + this->tabview = gtk_notebook_new(); + Label tabLabel = Label(tab1Name); + gtk_notebook_append_page(GTK_NOTEBOOK(this->tabview), tab1Content, tabLabel.GetWidget()); +} + + +void TabView::AddTab(std::string tabName, GtkWidget *tabContent) { + Label tabLabel = Label(tabName); + gtk_notebook_append_page(GTK_NOTEBOOK(this->tabview), tabContent, tabLabel.GetWidget()); +} + + +void TabView::SetName(std::string name) { + gtk_widget_set_name(this->tabview, name.c_str()); } \ No newline at end of file diff --git a/KiwiLight - Vision Code/ui/TextBox.cpp b/KiwiLight - Vision Code/ui/TextBox.cpp index 402dc47..1b3c2fb 100644 --- a/KiwiLight - Vision Code/ui/TextBox.cpp +++ b/KiwiLight - Vision Code/ui/TextBox.cpp @@ -1,43 +1,43 @@ -#include "UI.h" - -/** - * Source file for the TextBox class. - * Written By: Brach Knutson - */ - - -using namespace KiwiLight; - -/** - * Creates a new textbox with the given text. - */ -TextBox::TextBox(std::string text) { - this->textbox = gtk_entry_new(); - gtk_entry_set_text(GTK_ENTRY(this->textbox), text.c_str()); -} - -/** - * Sets the textbox text to the given std::string. - */ -void TextBox::SetText(std::string text) { - gtk_entry_set_text(GTK_ENTRY(this->textbox), text.c_str()); -} - -/** - * Sets the alignment of the entry. 0=left, 1=right - */ -void TextBox::SetAlignment(double align) { - gtk_entry_set_alignment(GTK_ENTRY(this->textbox), gfloat(align)); -} - -/** - * Returns the text inside the textbox. - */ -std::string TextBox::GetText() { - return gtk_entry_get_text(GTK_ENTRY(this->textbox)); -} - - -void TextBox::SetName(std::string name) { - gtk_widget_set_name(this->textbox, name.c_str()); +#include "UI.h" + +/** + * Source file for the TextBox class. + * Written By: Brach Knutson + */ + + +using namespace KiwiLight; + +/** + * Creates a new textbox with the given text. + */ +TextBox::TextBox(std::string text) { + this->textbox = gtk_entry_new(); + gtk_entry_set_text(GTK_ENTRY(this->textbox), text.c_str()); +} + +/** + * Sets the textbox text to the given std::string. + */ +void TextBox::SetText(std::string text) { + gtk_entry_set_text(GTK_ENTRY(this->textbox), text.c_str()); +} + +/** + * Sets the alignment of the entry. 0=left, 1=right + */ +void TextBox::SetAlignment(double align) { + gtk_entry_set_alignment(GTK_ENTRY(this->textbox), gfloat(align)); +} + +/** + * Returns the text inside the textbox. + */ +std::string TextBox::GetText() { + return gtk_entry_get_text(GTK_ENTRY(this->textbox)); +} + + +void TextBox::SetName(std::string name) { + gtk_widget_set_name(this->textbox, name.c_str()); } \ No newline at end of file diff --git a/KiwiLight - Vision Code/ui/TroubleshootingWindow.cpp b/KiwiLight - Vision Code/ui/TroubleshootingWindow.cpp index edbb745..2c50596 100644 --- a/KiwiLight - Vision Code/ui/TroubleshootingWindow.cpp +++ b/KiwiLight - Vision Code/ui/TroubleshootingWindow.cpp @@ -1,40 +1,40 @@ -#include "Runner.h" - -/** - * Source file for the TroubleshootingWindow class. - * Written By: Brach Knutson - */ - -using namespace KiwiLight; - - -TroubleshootingWindow::TroubleshootingWindow(TroubleshootingData data[], int dataLen) { - this->window = Window(GTK_WINDOW_TOPLEVEL); - Panel content = Panel(false, 0); - Label title = Label("Troubleshoot Results"); - title.SetName("header"); - content.Pack_start(title.GetWidget(), false, false, 0); - - for(int i=0; iwindow.SetContentPane(content); - - this->troubleshootingwindow = this->window.GetWidget(); -} - - -void TroubleshootingWindow::Show() { - this->window.Show(); -} - - -void TroubleshootingWindow::SetName(std::string name) { - gtk_widget_set_name(this->troubleshootingwindow, name.c_str()); +#include "Runner.h" + +/** + * Source file for the TroubleshootingWindow class. + * Written By: Brach Knutson + */ + +using namespace KiwiLight; + + +TroubleshootingWindow::TroubleshootingWindow(TroubleshootingData data[], int dataLen) { + this->window = Window(GTK_WINDOW_TOPLEVEL); + Panel content = Panel(false, 0); + Label title = Label("Troubleshoot Results"); + title.SetName("header"); + content.Pack_start(title.GetWidget(), false, false, 0); + + for(int i=0; iwindow.SetContentPane(content); + + this->troubleshootingwindow = this->window.GetWidget(); +} + + +void TroubleshootingWindow::Show() { + this->window.Show(); +} + + +void TroubleshootingWindow::SetName(std::string name) { + gtk_widget_set_name(this->troubleshootingwindow, name.c_str()); } \ No newline at end of file diff --git a/KiwiLight - Vision Code/ui/UI.h b/KiwiLight - Vision Code/ui/UI.h index 9e25e6c..905f325 100644 --- a/KiwiLight - Vision Code/ui/UI.h +++ b/KiwiLight - Vision Code/ui/UI.h @@ -495,6 +495,7 @@ namespace KiwiLight { std::string GetUDPAddr(); void SetUDPPort(int port); int GetUDPPort(); + void SetUDPEnabledLabels(bool UDPEnabled); void SetTargetInformationLabelsFromString(std::string iterOutput); GtkWidget *GetWidget() { return overviewpanel; }; void SetName(std::string name); @@ -504,6 +505,7 @@ namespace KiwiLight { TextBox udpAddr; NumberBox udpPort; NumberBox cameraIndex; + Button enableUDP; Label targetSpotted, @@ -624,6 +626,7 @@ namespace KiwiLight { int GetUDPPort(); void SetUDPAddr(std::string newAddr); void SetUDPPort(int newPort); + void SetUDPEnabledLabels(bool UDPEnabled); GtkWidget *GetWidget() { return this->runnereditor; }; void SetName(std::string name); @@ -633,6 +636,10 @@ namespace KiwiLight { TextBox udpAddress; NumberBox udpPort; + Button enableUDP; + + CheckBox useHeight; + LabeledSlider offsetX, offsetY, @@ -658,7 +665,7 @@ namespace KiwiLight { void StartLearningTarget(); void StartLearningDistance(); void ReconnectUDPFromEditor(); - void SendOverUDP(std::string message); + void SetUDPEnabledLabels(bool UDPEnabled); void ApplyCameraSettings(); void SetCameraIndexBoxes(int index); void ReconnectUDPFromOverview(); @@ -669,7 +676,6 @@ namespace KiwiLight { void SetName(std::string name); private: - static void Closed(); void UpdateImage(); //universal config learning utility diff --git a/KiwiLight - Vision Code/ui/Window.cpp b/KiwiLight - Vision Code/ui/Window.cpp index 62c519c..70eb016 100644 --- a/KiwiLight - Vision Code/ui/Window.cpp +++ b/KiwiLight - Vision Code/ui/Window.cpp @@ -1,110 +1,110 @@ -#include "UI.h" - -/** - * Source file for the Window class. - * Written By: Brach Knutson - */ - - -using namespace KiwiLight; - -void(*Window::onAppClosed)() = 0; -void(*Window::timeoutMethod)() = 0; - -gboolean Window::delete_event(GtkWidget *widget, GdkEvent *event, gpointer pointer) { - Window::onAppClosed(); - return FALSE; -} - -void Window::Destroy() { - gtk_main_quit(); -} - -void Window::SetOnAppClosed(void(*onAppClosed)()) { - Window::onAppClosed = onAppClosed; -} - -void Window::SetOnWindowClosed(void(*onWindowClosed)()) { - g_signal_connect(this->window, "delete-event", G_CALLBACK(onWindowClosed), NULL); - g_signal_connect(this->window, "destroy", G_CALLBACK(onWindowClosed), NULL); -} - -/** - * Creates a new window. - */ -Window::Window(GtkWindowType type) { - this->window = gtk_window_new(type); - g_signal_connect(this->window, "delete-event", G_CALLBACK(delete_event), NULL); - g_signal_connect(this->window, "destroy", G_CALLBACK(Destroy), NULL); - gtk_container_set_border_width(GTK_CONTAINER(this->window), 0); -} - - -Window::Window(GtkWindowType type, bool terminateOnClose) { - this->window = gtk_window_new(type); - gtk_container_set_border_width(GTK_CONTAINER(this->window), 0); - - if(terminateOnClose) { - g_signal_connect(this->window, "delete-event", G_CALLBACK(delete_event), NULL); - g_signal_connect(this->window, "destroy", G_CALLBACK(Destroy), NULL); - } -} - -/** - * Sets the main content pane to the given panel. A - * content pane must be set for a window or else no - * content will be shown. - */ -void Window::SetPane(Panel pane) { - gtk_container_add(GTK_CONTAINER(this->window), pane.GetWidget()); -} - -/** - * Set the size of the window to the width w and - * height h. - */ -void Window::SetSize(int w, int h) { - gtk_window_set_default_size(GTK_WINDOW(this->window), w, h); -} - -/** - * Run a method on a timed interval. - */ -int Window::SetInterval(int interval, void(*method)()) { - timeoutMethod = method; - return g_timeout_add(interval, GSourceFunc(timeoutCallMethod), NULL); -} - -/** - * Cancel an existing interval by given id - */ -void Window::RemoveInterval(int id) { - g_source_remove(id); -} - -/** - * Shows the window and all widgets within it. - */ -void Window::Show() { - gtk_widget_show_all(this->window); -} - - -void Window::SetCSS(std::string fileName) { - GtkCssProvider *css = gtk_css_provider_new(); - GdkDisplay *disp = gdk_display_get_default(); - GdkScreen *screen = gdk_screen_get_default(); - gtk_css_provider_load_from_path(css, fileName.c_str(), NULL); - gtk_style_context_add_provider_for_screen(screen, GTK_STYLE_PROVIDER(css), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); -} - - -gboolean Window::timeoutCallMethod() { - timeoutMethod(); - return TRUE; -} - - -void Window::SetName(std::string name) { - gtk_widget_set_name(this->window, name.c_str()); +#include "UI.h" + +/** + * Source file for the Window class. + * Written By: Brach Knutson + */ + + +using namespace KiwiLight; + +void(*Window::onAppClosed)() = 0; +void(*Window::timeoutMethod)() = 0; + +gboolean Window::delete_event(GtkWidget *widget, GdkEvent *event, gpointer pointer) { + Window::onAppClosed(); + return FALSE; +} + +void Window::Destroy() { + gtk_main_quit(); +} + +void Window::SetOnAppClosed(void(*onAppClosed)()) { + Window::onAppClosed = onAppClosed; +} + +void Window::SetOnWindowClosed(void(*onWindowClosed)()) { + g_signal_connect(this->window, "delete-event", G_CALLBACK(onWindowClosed), NULL); + g_signal_connect(this->window, "destroy", G_CALLBACK(onWindowClosed), NULL); +} + +/** + * Creates a new window. + */ +Window::Window(GtkWindowType type) { + this->window = gtk_window_new(type); + g_signal_connect(this->window, "delete-event", G_CALLBACK(delete_event), NULL); + g_signal_connect(this->window, "destroy", G_CALLBACK(Destroy), NULL); + gtk_container_set_border_width(GTK_CONTAINER(this->window), 0); +} + + +Window::Window(GtkWindowType type, bool terminateOnClose) { + this->window = gtk_window_new(type); + gtk_container_set_border_width(GTK_CONTAINER(this->window), 0); + + if(terminateOnClose) { + g_signal_connect(this->window, "delete-event", G_CALLBACK(delete_event), NULL); + g_signal_connect(this->window, "destroy", G_CALLBACK(Destroy), NULL); + } +} + +/** + * Sets the main content pane to the given panel. A + * content pane must be set for a window or else no + * content will be shown. + */ +void Window::SetPane(Panel pane) { + gtk_container_add(GTK_CONTAINER(this->window), pane.GetWidget()); +} + +/** + * Set the size of the window to the width w and + * height h. + */ +void Window::SetSize(int w, int h) { + gtk_window_set_default_size(GTK_WINDOW(this->window), w, h); +} + +/** + * Run a method on a timed interval. + */ +int Window::SetInterval(int interval, void(*method)()) { + timeoutMethod = method; + return g_timeout_add(interval, GSourceFunc(timeoutCallMethod), NULL); +} + +/** + * Cancel an existing interval by given id + */ +void Window::RemoveInterval(int id) { + g_source_remove(id); +} + +/** + * Shows the window and all widgets within it. + */ +void Window::Show() { + gtk_widget_show_all(this->window); +} + + +void Window::SetCSS(std::string fileName) { + GtkCssProvider *css = gtk_css_provider_new(); + GdkDisplay *disp = gdk_display_get_default(); + GdkScreen *screen = gdk_screen_get_default(); + gtk_css_provider_load_from_path(css, fileName.c_str(), NULL); + gtk_style_context_add_provider_for_screen(screen, GTK_STYLE_PROVIDER(css), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); +} + + +gboolean Window::timeoutCallMethod() { + timeoutMethod(); + return TRUE; +} + + +void Window::SetName(std::string name) { + gtk_widget_set_name(this->window, name.c_str()); } \ No newline at end of file diff --git a/KiwiLight - Vision Code/util/Color.cpp b/KiwiLight - Vision Code/util/Color.cpp index cb38019..dac82b2 100644 --- a/KiwiLight - Vision Code/util/Color.cpp +++ b/KiwiLight - Vision Code/util/Color.cpp @@ -1,51 +1,51 @@ -#include "Util.h" - -/** - * Source file for the Color class. - * Written By: Brach Knutson - */ - -using namespace cv; -using namespace KiwiLight; - -/** - * Creates a new color with the given values and errors. - * NOTE: all color values are in the HSV colorspace (hue - saturation - value). - */ -Color::Color(int h, int s, int v, int hError, int sError, int vError) { - this->h = h; - this->s = s; - this->v = v; - this->hError = hError; - this->sError = sError; - this->vError = vError; -} - -/** - * Returns a representation of the color in a cv::Scalar for use in the inRange or whatever - */ -cv::Scalar Color::ReturnScalar() { - return cv::Scalar(this->h, this->s, this->v); -} - -/** - * Returns a cv::Scalar representation of the upper bound of the color range. - * (that is, all values have had their corrisponding error values added to them) - */ -cv::Scalar Color::GetUpperBound() { - int newH = this->h + this->hError; - int newS = this->s + this->sError; - int newV = this->v + this->vError; - return cv::Scalar(newH, newS, newV); -} - -/** - * Returns a cv::Scalar representation of the lower bound of the color range. - * (all values had errors subtracted from them) - */ -cv::Scalar Color::GetLowerBound() { - int newH = this->h - this->hError; - int newS = this->s - this->sError; - int newV = this->v - this->vError; - return cv::Scalar(newH, newS, newV); +#include "Util.h" + +/** + * Source file for the Color class. + * Written By: Brach Knutson + */ + +using namespace cv; +using namespace KiwiLight; + +/** + * Creates a new color with the given values and errors. + * NOTE: all color values are in the HSV colorspace (hue - saturation - value). + */ +Color::Color(int h, int s, int v, int hError, int sError, int vError) { + this->h = h; + this->s = s; + this->v = v; + this->hError = hError; + this->sError = sError; + this->vError = vError; +} + +/** + * Returns a representation of the color in a cv::Scalar for use in the inRange or whatever + */ +cv::Scalar Color::ReturnScalar() { + return cv::Scalar(this->h, this->s, this->v); +} + +/** + * Returns a cv::Scalar representation of the upper bound of the color range. + * (that is, all values have had their corrisponding error values added to them) + */ +cv::Scalar Color::GetUpperBound() { + int newH = this->h + this->hError; + int newS = this->s + this->sError; + int newV = this->v + this->vError; + return cv::Scalar(newH, newS, newV); +} + +/** + * Returns a cv::Scalar representation of the lower bound of the color range. + * (all values had errors subtracted from them) + */ +cv::Scalar Color::GetLowerBound() { + int newH = this->h - this->hError; + int newS = this->s - this->sError; + int newV = this->v - this->vError; + return cv::Scalar(newH, newS, newV); } \ No newline at end of file diff --git a/KiwiLight - Vision Code/util/DataUtils.cpp b/KiwiLight - Vision Code/util/DataUtils.cpp index 13bc86b..ce3ee29 100644 --- a/KiwiLight - Vision Code/util/DataUtils.cpp +++ b/KiwiLight - Vision Code/util/DataUtils.cpp @@ -1,211 +1,211 @@ -#include "Util.h" - -/** - * Source file for the DataUtils class. - * Written By: Brach Knutson - */ - -using namespace KiwiLight; - -/** - * Sorts "data" in order from least to greatest. Sorts using insertion sort. - */ -std::vector DataUtils::SortLeastGreatestDouble(std::vector data) { - std::vector result; - - for(int i=0; i= valueToInsert) { - result.emplace(result.begin(), valueToInsert); - } else { - //look for a position to insert the value in - bool placeToInsertFound = false; - for(int k=1; k valueBeforeI && valueToInsert <= valueAtI) { - result.emplace(result.begin() + k, valueToInsert); - placeToInsertFound = true; - break; - } - } - - //value is greater than everything in the list - if(!placeToInsertFound) { - result.emplace(result.end(), valueToInsert); - } - } - } - - return result; -} - - -double DataUtils::Total(std::vector data) { - double total = 0.0; - - for(int i=0; i data) { - double avg = 0.0; - - for(int i=0; i data) { - int middle = data.size() / 2; - return data[middle]; -} - - -double DataUtils::Greatest(std::vector data) { - double greatest = -1000000000.0; - - for(int i=0; i greatest) { - greatest = value; - } - } - - return greatest; -} - - -double DataUtils::Least(std::vector data) { - double least = 1000000000.0; - - for(int i=0; i data) { - double avgDiff = 0.0; - int totalDifferences = 0; - - for(int i=0; i data, double value) { - int occurrances = 0; - - for(int i=0; i data) { - int indexWithMostOccurrances = 0; - int numberOfOccurrances = -1; - - for(int i=0; i numberOfOccurrances) { - numberOfOccurrances = occurrances; - indexWithMostOccurrances = i; - } - } - - return data[indexWithMostOccurrances]; -} - - -bool DataUtils::IsOutlier(std::vector data, int indexOfValue, double allowableError) { - double average = DataUtils::Average(data); - double upperBound = average + allowableError; - double lowerBound = average - allowableError; - - return !(data[indexOfValue] > lowerBound && data[indexOfValue] < upperBound); -} - - -std::vector DataUtils::RemoveOutliers(std::vector data, double allowableError) { - std::vector newSet = std::vector(); - - for(int i=0; i DataUtils::VectorDoubleToInt(std::vector data) { - std::vector result; - for(int i=0; i DataUtils::VectorIntToDouble(std::vector data) { - std::vector result; - for(int i=0; i data) { - std::string vectorString = "["; - - for(int i=0; i DataUtils::SortLeastGreatestDouble(std::vector data) { + std::vector result; + + for(int i=0; i= valueToInsert) { + result.emplace(result.begin(), valueToInsert); + } else { + //look for a position to insert the value in + bool placeToInsertFound = false; + for(int k=1; k valueBeforeI && valueToInsert <= valueAtI) { + result.emplace(result.begin() + k, valueToInsert); + placeToInsertFound = true; + break; + } + } + + //value is greater than everything in the list + if(!placeToInsertFound) { + result.emplace(result.end(), valueToInsert); + } + } + } + + return result; +} + + +double DataUtils::Total(std::vector data) { + double total = 0.0; + + for(int i=0; i data) { + double avg = 0.0; + + for(int i=0; i data) { + int middle = data.size() / 2; + return data[middle]; +} + + +double DataUtils::Greatest(std::vector data) { + double greatest = -1000000000.0; + + for(int i=0; i greatest) { + greatest = value; + } + } + + return greatest; +} + + +double DataUtils::Least(std::vector data) { + double least = 1000000000.0; + + for(int i=0; i data) { + double avgDiff = 0.0; + int totalDifferences = 0; + + for(int i=0; i data, double value) { + int occurrances = 0; + + for(int i=0; i data) { + int indexWithMostOccurrances = 0; + int numberOfOccurrances = -1; + + for(int i=0; i numberOfOccurrances) { + numberOfOccurrances = occurrances; + indexWithMostOccurrances = i; + } + } + + return data[indexWithMostOccurrances]; +} + + +bool DataUtils::IsOutlier(std::vector data, int indexOfValue, double allowableError) { + double average = DataUtils::Average(data); + double upperBound = average + allowableError; + double lowerBound = average - allowableError; + + return !(data[indexOfValue] > lowerBound && data[indexOfValue] < upperBound); +} + + +std::vector DataUtils::RemoveOutliers(std::vector data, double allowableError) { + std::vector newSet = std::vector(); + + for(int i=0; i DataUtils::VectorDoubleToInt(std::vector data) { + std::vector result; + for(int i=0; i DataUtils::VectorIntToDouble(std::vector data) { + std::vector result; + for(int i=0; i data) { + std::string vectorString = "["; + + for(int i=0; i Flags::flagNames = std::vector(); - -/** - * Raises a flag with the passed name. - */ -void Flags::RaiseFlag(std::string flagName) { - if(!Flags::GetFlag(flagName)) { //flag not there, raise it - Flags::flagNames.push_back(flagName); - } -} - -/** - * Removes any flag with the given name. - */ -void Flags::LowerFlag(std::string flagName) { - //repopulate the flag std::vector without the given flag - std::vector newFlags = std::vector(); - for(int i=0; i Flags::flagNames = std::vector(); + +/** + * Raises a flag with the passed name. + */ +void Flags::RaiseFlag(std::string flagName) { + if(!Flags::GetFlag(flagName)) { //flag not there, raise it + Flags::flagNames.push_back(flagName); + } +} + +/** + * Removes any flag with the given name. + */ +void Flags::LowerFlag(std::string flagName) { + //repopulate the flag std::vector without the given flag + std::vector newFlags = std::vector(); + for(int i=0; ivalue = value; - this->error = error; -} - - -double SettingPair::LowerBound() { - return this->value - this->error; -} - - -double SettingPair::UpperBound() { - return this->value + this->error; +#include "Util.h" + +/** + * Source file for the SettingPair class. + * Written By: Brach Knutson + */ + +using namespace KiwiLight; + + +SettingPair::SettingPair(double value, double error) { + this->value = value; + this->error = error; +} + + +double SettingPair::LowerBound() { + return this->value - this->error; +} + + +double SettingPair::UpperBound() { + return this->value + this->error; } \ No newline at end of file diff --git a/KiwiLight - Vision Code/util/Shell.cpp b/KiwiLight - Vision Code/util/Shell.cpp index 516639b..f8113ed 100644 --- a/KiwiLight - Vision Code/util/Shell.cpp +++ b/KiwiLight - Vision Code/util/Shell.cpp @@ -1,40 +1,40 @@ -#include "Util.h" - -/** - * Source file for the Shell class. - * Written By: Brach Knutson - */ - -using namespace KiwiLight; - -std::string Shell::ExecuteCommand(std::string command) { - //to create the out file for the command, find HOME to place it in KiwiLightData - std::string outLocation = ""; - char *home = getenv("HOME"); - if(home != NULL) { - outLocation = std::string(home) + "/KiwiLightData/tmp/shell_out.log"; - } else { - std::cout << "The Shell utility was unable to find HOME" << std::endl; - } - - std::string execute = command + " >> " + outLocation; - system(execute.c_str()); - - //create a file stream to view the log - std::fstream log = std::fstream(outLocation); - std::string logString = ""; - - //loop through and read every line, formatting into std::string separated by newline characters - std::string line; - while(getline(log, line)) { - logString += line + "\n"; - } - - log.close(); - - //clear the file text for the next time - std::ofstream file = std::ofstream(outLocation, std::ofstream::out | std::ofstream::trunc); - file.close(); - - return logString; +#include "Util.h" + +/** + * Source file for the Shell class. + * Written By: Brach Knutson + */ + +using namespace KiwiLight; + +std::string Shell::ExecuteCommand(std::string command) { + //to create the out file for the command, find HOME to place it in KiwiLightData + std::string outLocation = ""; + char *home = getenv("HOME"); + if(home != NULL) { + outLocation = std::string(home) + "/KiwiLightData/tmp/shell_out.log"; + } else { + std::cout << "The Shell utility was unable to find HOME" << std::endl; + } + + std::string execute = command + " >> " + outLocation; + system(execute.c_str()); + + //create a file stream to view the log + std::fstream log = std::fstream(outLocation); + std::string logString = ""; + + //loop through and read every line, formatting into std::string separated by newline characters + std::string line; + while(getline(log, line)) { + logString += line + "\n"; + } + + log.close(); + + //clear the file text for the next time + std::ofstream file = std::ofstream(outLocation, std::ofstream::out | std::ofstream::trunc); + file.close(); + + return logString; } \ No newline at end of file diff --git a/KiwiLight - Vision Code/util/StringUtils.cpp b/KiwiLight - Vision Code/util/StringUtils.cpp index 673a7f9..926f1c9 100644 --- a/KiwiLight - Vision Code/util/StringUtils.cpp +++ b/KiwiLight - Vision Code/util/StringUtils.cpp @@ -1,70 +1,70 @@ -#include "Util.h" - -/** - * Source file for the StringUtils class. - * Written By: Brach Knutson - */ - - -using namespace KiwiLight; - -/** - * Splits the given std::string str by the char character. - */ -std::vector StringUtils::SplitString(std::string str, char character) { - std::vector substrings; - std::string current = ""; - - for(int i=0; i 0) { - substrings.push_back(current); - } - - return substrings; -} - - -std::string StringUtils::Substring(std::string str, int begin, int end) { - std::string substr = ""; - - if(begin == end || - begin > end || - begin > str.length() || - end > str.length()) { - return ""; - } - - for(int i=begin; i StringUtils::SplitString(std::string str, char character) { + std::vector substrings; + std::string current = ""; + + for(int i=0; i 0) { + substrings.push_back(current); + } + + return substrings; +} + + +std::string StringUtils::Substring(std::string str, int begin, int end) { + std::string substr = ""; + + if(begin == end || + begin > end || + begin > str.length() || + end > str.length()) { + return ""; + } + + for(int i=begin; iaddress = dest_ip; - this->port = port; - - std::cout << "Setting up UDP..." << std::endl; - - this->sock = socket(AF_INET, SOCK_DGRAM, 0); //"0" for wildcard of what protocol is best - if(this->sock < 0) //socket creation didnt be like that tho - err("SOCKET FAILED"); - - memset(&this->client_address, 0, sizeof(this->client_address)); - this->client_address.sin_family = AF_INET; - this->client_address.sin_port = htons(port); - - //do inet_pton() - int pton_result = inet_pton(AF_INET, dest_ip.c_str(), &this->client_address.sin_addr); - if(pton_result <= 0) - err("PTON FAILED"); - - //wait for the connect to succeed before we go - std::cout << "Waiting to connect..." << std::endl; - while(true) { - //now connect - int connect_result = connect(this->sock, (sockaddr*) &this->client_address, sizeof(this->client_address)); - if(connect_result > -1) //the connection was the big good - break; - } - - std::cout << "Connection set up." << std::endl; -} - - -UDP::UDP(std::string dest_ip, int port, bool blockUntilConnected) { - this->address = dest_ip; - this->port = port; - - std::cout << "Setting up UDP..." << std::endl; - - this->sock = socket(AF_INET, SOCK_DGRAM, 0); //"0" for wildcard of what protocol is best - if(this->sock < 0) //socket creation didnt be like that tho - err("SOCKET FAILED"); - - memset(&this->client_address, 0, sizeof(this->client_address)); - this->client_address.sin_family = AF_INET; - this->client_address.sin_port = htons(port); - - //do inet_pton() - int pton_result = inet_pton(AF_INET, dest_ip.c_str(), &this->client_address.sin_addr); - if(pton_result <= 0) - err("PTON FAILED"); - - //wait for the connect to succeed before we go - std::cout << "Waiting to connect..." << std::endl; - while(true) { - //now connect - int connect_result = connect(this->sock, (sockaddr*) &this->client_address, sizeof(this->client_address)); - if(connect_result > -1 || !blockUntilConnected) //the connection was the big good - break; - } - - std::cout << "Connection set up." << std::endl; -} - - -UDP::UDP(std::string this_ip, std::string dest_ip, int port, bool blockUntilConnected) { - this->address = dest_ip; - this->port = port; - - std::cout << "Setting up UDP..." << std::endl; - - - this->sock = socket(AF_INET, SOCK_DGRAM, 0); //"0" for wildcard of what protocol is best - if(this->sock < 0) //socket creation didnt be like that tho - err("SOCKET FAILED"); - - //define destination address - memset(&this->client_address, 0, sizeof(this->client_address)); - this->client_address.sin_family = AF_INET; - this->client_address.sin_port = htons(port); - - //define our address - sockaddr_in server_address; - memset(&server_address, 0, sizeof(server_address)); - server_address.sin_family = AF_INET; - server_address.sin_port = htons(port); - - //convert "this_ip" to a usable address struct - int pton_result_1 = inet_pton(AF_INET, this_ip.c_str(), &this->client_address.sin_addr); - if(pton_result_1 <= 0) - err("THIS PTON FAILED"); - - //convert "dest_ip" to a usable address struct - int pton_result_2 = inet_pton(AF_INET, dest_ip.c_str(), &this->client_address.sin_addr); - if(pton_result_2 <= 0) - err("DEST PTON FAILED"); - - - //"bind" our address to the socket - int bind_result = bind(this->sock, (sockaddr*) &server_address, sizeof(server_address)); - if(bind_result < 0) - err("BIND FAILED"); - - //wait for the connect to succeed before we go - std::cout << "Waiting to connect..." << std::endl; - while(true) { - //now connect - int connect_result = connect(this->sock, (sockaddr*) &this->client_address, sizeof(this->client_address)); - if(connect_result > -1 || !blockUntilConnected) //the connection was the big good - break; - } - - std::cout << "Connection set up." << std::endl; -} - -/** - * Attempts to connect to the router. - * @return true if the connection was successful, or the UDP was already connected, false otherwise. - */ -bool UDP::AttemptToConnect() { - if(!this->connected) { - int connect_result = connect(this->sock, (sockaddr*) &this->client_address, sizeof(this->client_address)); - - if(connect_result < 0) { - std::cout << "CONNECT FAILED" << std::endl; - } - return (connect_result > -1); - } - - return true; -} - -/** - * Sends the given message to the destination - * @param msg a string containing the message to send - */ -void UDP::Send(std::string msg) { - const char *buffer = msg.c_str(); - //std::cout << msg << std::endl; - int send_result = send(this->sock, buffer, strlen(buffer), 0); //the big send -} - -/** - * Reads the buffer and returns whats there - * @return a string containing the contents of the buffer - */ -std::string UDP::Recieve() { - char buffer[1024] = {0}; - int read_result = recv(this->sock, buffer, 1024, MSG_DONTWAIT); - std::string bufferStr = std::string(buffer); - return bufferStr; -} - -/** - * closes the UDP socket - */ -void UDP::Close() { - close(this->sock); -} +#include "Util.h" + +/** + * source file for UDP class + * Written By: Brach Knutson + */ + +using namespace KiwiLight; + + +/** + * literally kills everything + */ +void err(const char *msg) { + perror(msg); + exit(1); +} + + +UDP::UDP(std::string dest_ip, int port, bool blockUntilConnected) { + this->address = dest_ip; + this->port = port; + this->connected = false; + + this->sock = socket(AF_INET, SOCK_DGRAM, 0); //"0" for wildcard of what protocol is best + if(this->sock < 0) //socket creation didnt be like that tho + err("SOCKET FAILED"); + + memset(&this->client_address, 0, sizeof(this->client_address)); + this->client_address.sin_family = AF_INET; + this->client_address.sin_port = htons(port); + + //do inet_pton(), translating information from our stringed ip address into the address object + int pton_result = inet_pton(AF_INET, dest_ip.c_str(), &this->client_address.sin_addr); + if(pton_result <= 0) + err("PTON FAILED"); + + //wait for the connect to succeed before we go + while(true) { + if(AttemptToConnect() || !blockUntilConnected) { + break; + } + } +} + + +UDP::UDP(std::string this_ip, std::string dest_ip, int port, bool blockUntilConnected) { + this->address = dest_ip; + this->port = port; + this->connected = false; + + this->sock = socket(AF_INET, SOCK_DGRAM, 0); //"0" for wildcard of what protocol is best + if(this->sock < 0) //socket creation didnt be like that tho + err("SOCKET FAILED"); + + //define destination address + memset(&this->client_address, 0, sizeof(this->client_address)); + this->client_address.sin_family = AF_INET; + this->client_address.sin_port = htons(port); + + //define our address + sockaddr_in server_address; + memset(&server_address, 0, sizeof(server_address)); + server_address.sin_family = AF_INET; + server_address.sin_port = htons(port); + + //convert "this_ip" to a usable address struct + int pton_result_1 = inet_pton(AF_INET, this_ip.c_str(), &this->client_address.sin_addr); + if(pton_result_1 <= 0) + err("THIS PTON FAILED"); + + //convert "dest_ip" to a usable address struct + int pton_result_2 = inet_pton(AF_INET, dest_ip.c_str(), &this->client_address.sin_addr); + if(pton_result_2 <= 0) + err("DEST PTON FAILED"); + + + //"bind" our address to the socket + int bind_result = bind(this->sock, (sockaddr*) &server_address, sizeof(server_address)); + if(bind_result < 0) + err("BIND FAILED"); + + //wait for the connect to succeed before we go + std::cout << "Waiting to connect..." << std::endl; + while(true) { + if(AttemptToConnect() || !blockUntilConnected) { + break; + } + } + + std::cout << "Connection set up." << std::endl; +} + +/** + * Attempts to connect to the router. + * @return true if the connection was successful, or the UDP was already connected, false otherwise. + */ +bool UDP::AttemptToConnect() { + int connect_result = connect(this->sock, (sockaddr*) &this->client_address, sizeof(this->client_address)); + + if(connect_result < 0) { + std::cout << "CONNECT FAILED" << std::endl; + return false; + } + + this->connected = true; + return true; +} + +/** + * Sends the given message to the destination + * @param msg a string containing the message to send + */ +void UDP::Send(std::string msg) { + const char *buffer = msg.c_str(); + int send_result = send(this->sock, buffer, strlen(buffer), 0); //the big send +} + +/** + * Reads the buffer and returns whats there + * @return a string containing the contents of the buffer + */ +std::string UDP::Recieve() { + char buffer[1024] = {0}; + int read_result = recv(this->sock, buffer, 1024, MSG_DONTWAIT); + std::string bufferStr = std::string(buffer); + return bufferStr; +} + +/** + * closes the UDP socket + */ +void UDP::Close() { + close(this->sock); +} diff --git a/KiwiLight - Vision Code/util/Util.cpp b/KiwiLight - Vision Code/util/Util.cpp index 19240c4..14f3f97 100644 --- a/KiwiLight - Vision Code/util/Util.cpp +++ b/KiwiLight - Vision Code/util/Util.cpp @@ -1,30 +1,30 @@ -#include "Util.h" - -/** - * Source file for the Util class. - * Written By: Brach Knutson - */ - -using namespace cv; -using namespace KiwiLight; - -/** - * Searches the vector of camera setting XMLTags and returns the one with the correct ID. - * @param settings The list of camera settings to search through. See precondition for more details. - * @param id The Camera property ID to search for. - * @return The first XMLTag with the matching ID, or NULL if none found. - * Precondition: The XMLTags in settings MUST be formatted as follows: - * [content] - */ -XMLTag Util::SearchCameraSettingsByID(std::vector settings, int id) { - for(int i=0; i[content] + */ +XMLTag Util::SearchCameraSettingsByID(std::vector settings, int id) { + for(int i=0; i #include #include -#include "gtk-3.0/gtk/gtk.h" #include "opencv2/opencv.hpp" #include "netdb.h" #include "unistd.h" @@ -83,7 +82,6 @@ namespace KiwiLight { class UDP { public: UDP(){}; - UDP(std::string dest_ip, int port); UDP(std::string dest_ip, int port, bool blockUntilConnected); UDP(std::string this_ip, std::string dest_ip, int port, bool blockUntilConnected); bool AttemptToConnect(); diff --git a/KiwiLight - Vision Code/util/XMLDocument.cpp b/KiwiLight - Vision Code/util/XMLDocument.cpp index 3286a20..0cbf3bc 100644 --- a/KiwiLight - Vision Code/util/XMLDocument.cpp +++ b/KiwiLight - Vision Code/util/XMLDocument.cpp @@ -156,6 +156,8 @@ std::vector XMLDocument::GetTagsByName(std::string name) { if(results.size() == 0) { std::cout << "There were no XML Tag results for \"" << name << "\"" << std::endl; + XMLTag placeholder = XMLTag(name, "0"); + results.push_back(placeholder); } return results; diff --git a/KiwiLight - Vision Code/util/XMLTag.cpp b/KiwiLight - Vision Code/util/XMLTag.cpp index 1c446ac..d73d876 100644 --- a/KiwiLight - Vision Code/util/XMLTag.cpp +++ b/KiwiLight - Vision Code/util/XMLTag.cpp @@ -79,6 +79,8 @@ std::vector XMLTag::GetTagsByName(std::string name) { if(results.size() == 0) { std::cout << "There were no XML Tag results for \"" << name << "\"" << std::endl; + XMLTag placeholder = XMLTag(name, "0"); + results.push_back(placeholder); } return results; @@ -96,6 +98,8 @@ std::vector XMLTag::GetAttributesByName(std::string name) { if(results.size() == 0) { std::cout << "There were no XML Attribute results for \"" << name << "\"" << std::endl; + XMLTagAttribute placeholder = XMLTagAttribute(name, "0"); + results.push_back(placeholder); } return results; diff --git a/KiwiLight - Vision Code/util/XMLTagAttribute.cpp b/KiwiLight - Vision Code/util/XMLTagAttribute.cpp index 2a9e29d..2afdba9 100644 --- a/KiwiLight - Vision Code/util/XMLTagAttribute.cpp +++ b/KiwiLight - Vision Code/util/XMLTagAttribute.cpp @@ -1,18 +1,18 @@ -#include "Util.h" - -/** - * Source file for the XMLTagAttribute class. - */ - -using namespace KiwiLight; - - -XMLTagAttribute::XMLTagAttribute(std::string name, std::string value) { - this->name = name; - this->value = value; -} - - -std::string XMLTagAttribute::ReturnString() { - return name + "=\"" + value + "\""; +#include "Util.h" + +/** + * Source file for the XMLTagAttribute class. + */ + +using namespace KiwiLight; + + +XMLTagAttribute::XMLTagAttribute(std::string name, std::string value) { + this->name = name; + this->value = value; +} + + +std::string XMLTagAttribute::ReturnString() { + return name + "=\"" + value + "\""; } \ No newline at end of file diff --git a/Manual.pdf b/Manual.pdf new file mode 100644 index 0000000..5ae7af2 Binary files /dev/null and b/Manual.pdf differ