Program Listing for File move_absolute_command.cpp

Return to documentation for file (src/tap/control/setpoint/commands/move_absolute_command.cpp)

/*
 * Copyright (c) 2020-2021 Advanced Robotics at the University of Washington <robomstr@uw.edu>
 *
 * This file is part of Taproot.
 *
 * Taproot is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Taproot is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Taproot.  If not, see <https://www.gnu.org/licenses/>.
 */

#include "move_absolute_command.hpp"

#include "tap/algorithms/math_user_utils.hpp"
#include "tap/architecture/clock.hpp"

namespace tap
{
namespace control
{
namespace setpoint
{
MoveAbsoluteCommand::MoveAbsoluteCommand(
    SetpointSubsystem* setpointSubsystem,
    float setpoint,
    float speed,
    float setpointTolerance,
    bool automaticallyClearJam,
    bool setSetpointToTargetOnEnd)
    : setpointSubsystem(setpointSubsystem),
      setpoint(setpoint),
      speed(speed),
      setpointTolerance(setpointTolerance),
      automaticallyClearJam(automaticallyClearJam),
      setSetpointToTargetOnEnd(setSetpointToTargetOnEnd)
{
    this->addSubsystemRequirement(setpointSubsystem);
}

bool MoveAbsoluteCommand::isReady()
{
    return !setpointSubsystem->isJammed() && setpointSubsystem->isOnline();
}

void MoveAbsoluteCommand::initialize()
{
    rampToSetpoint.setTarget(setpoint);
    rampToSetpoint.setValue(setpointSubsystem->getCurrentValue());
    prevMoveTime = tap::arch::clock::getTimeMilliseconds();
}

void MoveAbsoluteCommand::execute()
{
    // If the subsystem is jammed, set the setpoint to the current value. Necessary since
    // derived classes may choose to overwrite the `isFinished` function and so for motor safety
    // we do this. Also if subsystem is offline we delay our execution so that setpoint doesn't
    // run away while subsystem offline.
    if (setpointSubsystem->isJammed() || !setpointSubsystem->isOnline())
    {
        // Set prevMoveTime to now so that delta time doesn't become ridiculous while
        // subsystem is stuck in non-functional state.
        prevMoveTime = tap::arch::clock::getTimeMilliseconds();
        setpointSubsystem->setSetpoint(setpointSubsystem->getCurrentValue());
        return;
    }

    // We can assume that subsystem is connected, otherwise end will be called.
    uint32_t currTime = tap::arch::clock::getTimeMilliseconds();
    // Divide by 1'000 to get setpoint-units because speed is in setpoint-units/second
    // and time interval is in milliseconds. (milliseconds * 1/1000 (second/millisecond) *
    // (setpoint-units/second))  = 1/1000 setpoint-units as our conversion
    rampToSetpoint.update((static_cast<float>(currTime - prevMoveTime) * speed) / 1000.0f);
    prevMoveTime = currTime;

    setpointSubsystem->setSetpoint(rampToSetpoint.getValue());
}

void MoveAbsoluteCommand::end(bool)
{
    // Either set setpoint to ideal target or current value based on option
    // used to construct command.
    if (!setpointSubsystem->isJammed() && setSetpointToTargetOnEnd)
    {
        setpointSubsystem->setSetpoint(setpoint);
    }
    else
    {
        setpointSubsystem->setSetpoint(setpointSubsystem->getCurrentValue());
    }

    if (automaticallyClearJam)
    {
        setpointSubsystem->clearJam();
    }
}

bool MoveAbsoluteCommand::isFinished() const
{
    // Command is finished if we've reached target or if our subsystem is jammed
    // or offline
    return setpointSubsystem->isJammed() || !setpointSubsystem->isOnline() ||
           (rampToSetpoint.isTargetReached() && algorithms::compareFloatClose(
                                                    setpointSubsystem->getCurrentValue(),
                                                    rampToSetpoint.getTarget(),
                                                    setpointTolerance));
}

}  // namespace setpoint

}  // namespace control

}  // namespace tap