Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Develop #76

Draft
wants to merge 130 commits into
base: main
Choose a base branch
from
Draft

Develop #76

wants to merge 130 commits into from

Conversation

aaronchongth
Copy link
Member

@aaronchongth aaronchongth commented Mar 3, 2021

This PR introduces a complete overhaul and redesign of free_fleet. This attempts to create multiple layers of abstractions that would accommodate different software configurations, mobile platforms and UIs, in order to be more widely used as a generic fleet management system.

The objective of this PR while development is still underway, is to have the API reviewed and modified if needed, such that further developments that use these new abstractions can be adapted without too many breaking changes.

Inspired and modeled after the fleet adapters from the RMF project, we have added these abstractions,

  • Middleware - Split between ClientMiddleware and ServerMiddleware, allows communication between the fleet manager and the mobile platform client. With this in place, users can implement and use their preferred middleware, for example ROS, ROS 2, different implementations of DDS, REST, MQTT or other web APIs.

  • Command Handle - This is used by the client to control the mobile platform, users will be able to implement this to interact with their preferred navigation stack or robot controlling API.

  • Status Handle - This is used by the client to gather information in order to update the fleet management system. The implementation will also be dependent on the mobile platform's API.

Other features:

Also fixes:

  1. Reactive message subscriptions - Message subscriptions to be made reactive instead of polling #88
  2. Messages are generated during build - Generate message source files from IDL during build #90
  3. Code style linting - Add style linting #100

@aaronchongth aaronchongth changed the base branch from master to main March 16, 2021 06:14
Copy link
Collaborator

@mxgrey mxgrey left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this PR is taking the free_fleet in a really great direction.

Based on ongoing discussions about "What is Free Fleet?", I anticipate we'll want another very significant round of redesign on top of this one, so let's keep the version number in alpha/beta range at 0.1.0 or 0.2.0 so we're not over-committing to the current API.

In addition to the in-line feedback, I wonder if we should reconsider the use of namespaces. I'm not sure agv is actually a very meaningful namespace for this library. We might want to instead group classes into namespace based on which component in the pipeline they are used by, e.g. free_fleet::server:: and free_fleet::client.

free_fleet/include/free_fleet/agv/Client.hpp Outdated Show resolved Hide resolved
free_fleet/include/free_fleet/agv/Client.hpp Outdated Show resolved Hide resolved
free_fleet/include/free_fleet/Manager.hpp Outdated Show resolved Hide resolved
free_fleet/CMakeLists.txt Outdated Show resolved Hide resolved
free_fleet/include/free_fleet/Manager.hpp Outdated Show resolved Hide resolved
free_fleet/include/free_fleet/CoordinateTransformer.hpp Outdated Show resolved Hide resolved
free_fleet/include/free_fleet/Manager.hpp Outdated Show resolved Hide resolved
free_fleet/include/free_fleet/messages/ModeRequest.hpp Outdated Show resolved Hide resolved
free_fleet/include/free_fleet/Manager.hpp Outdated Show resolved Hide resolved
free_fleet/include/free_fleet/transport/Middleware.hpp Outdated Show resolved Hide resolved
@aaronchongth
Copy link
Member Author

@mxgrey, thanks for the review so far! I have a much better understanding of how a reactive system can be useful in this scenario now, as well as how working towards a feature-based system would be great.

I haven't given much thought about the use of namespaces, other than using them as a way to keep things within categories or subsets (i.e. agv, transport, requests), I'll look into getting them towards component pipeline based as you mentioned. I'll develop these locally for now.

I've addressed most of the design concerns and got to implement what we have discussed previously regarding requests, I'd be keen to get your review again before any new commits. Let me know what you think.

Copy link
Collaborator

@mxgrey mxgrey left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The architecture is generally looking really good!

I'm leaving a final round of pedantic suggestions to tidy up the implementation before merging, but they'll mostly be minor changes.

free_fleet/include/free_fleet/Manager.hpp Outdated Show resolved Hide resolved
free_fleet/include/free_fleet/messages/DockRequest.hpp Outdated Show resolved Hide resolved
free_fleet/src/Manager.cpp Outdated Show resolved Hide resolved
free_fleet/src/Manager.cpp Outdated Show resolved Hide resolved
free_fleet/src/Manager.cpp Outdated Show resolved Hide resolved
free_fleet/src/internal_Manager.hpp Outdated Show resolved Hide resolved
free_fleet/src/utilities/utilities.cpp Outdated Show resolved Hide resolved
free_fleet/src/utilities/utilities.hpp Outdated Show resolved Hide resolved
free_fleet_cyclonedds/src/CycloneDDSMiddleware.cpp Outdated Show resolved Hide resolved
free_fleet_cyclonedds/src/messages/MiddlewareMessages.h Outdated Show resolved Hide resolved
Signed-off-by: Aaron Chong <aaronchongth@gmail.com>
Signed-off-by: Aaron Chong <aaronchongth@gmail.com>
Signed-off-by: Aaron Chong <aaronchongth@gmail.com>
… abstraction

Signed-off-by: Aaron Chong <aaronchongth@gmail.com>
Signed-off-by: Aaron Chong <aaronchongth@gmail.com>
Signed-off-by: Aaron Chong <aaronchongth@gmail.com>
Signed-off-by: Aaron Chong <aaronchongth@gmail.com>
Signed-off-by: Aaron Chong <aaronchongth@gmail.com>
Signed-off-by: Aaron Chong <aaronchongth@gmail.com>
Signed-off-by: Aaron Chong <aaronchongth@gmail.com>
Signed-off-by: Aaron Chong <aaronchongth@gmail.com>
Signed-off-by: Aaron <aaronchongth@gmail.com>
Signed-off-by: Aaron Chong <aaronchongth@gmail.com>
Signed-off-by: Aaron Chong <aaronchongth@gmail.com>
Signed-off-by: Aaron Chong <aaronchongth@gmail.com>
Signed-off-by: Aaron Chong <aaronchongth@gmail.com>
Signed-off-by: Aaron Chong <aaronchongth@gmail.com>
Signed-off-by: Aaron Chong <aaronchongth@gmail.com>
Signed-off-by: Aaron Chong <aaronchongth@gmail.com>
Signed-off-by: Aaron Chong <aaronchongth@gmail.com>
… during navigation requests

Signed-off-by: Aaron Chong <aaronchongth@gmail.com>
Copy link
Collaborator

@mxgrey mxgrey left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm about halfway through reviewing the code, and this new design is looking really great.

Most of my comments so far are pretty minor nitpicks, although the issues I've raised about capturing this are important to avoid race conditions and/or use-after-free bugs.

free_fleet/include/free_fleet/Console.hpp Outdated Show resolved Hide resolved
virtual void resume(RequestCompleted resumed_callback) = 0;

/// Have the robot begin a pre-defined docking procedure. Implement this
/// function as a no-op if your robots do not perform docking procedures.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's change the documentation to say "If you robot has no docking abilities, implement this by simply triggering docking_finished_callback() immediately". If the function is implemented as a no-op, then the fleet manager could get stuck forever waiting for the docking command to finish.

On the other hand, for error handling it might be good if there's a way to indicate whether the docking procedure is recognized by the client. Maybe we should rework this function so that it returns a boolean: true if the docking command is recognized, and false if it's not recognized. If the function returns true, then the fleet manager will wait for the docking_finished_callback to be triggered; if it returns false, then the fleet manager should log an error/warning and not bother waiting for the docking_finished_callback to be triggered.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes sense, thanks! e58cc91

public:

/// Forward transformation, from frame A to frame B.
virtual messages::Location forward_transform(const messages::Location& input)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure it's obvious what "Forward" or "Backward" mean in this context. Since this interface is specific to free_fleet, why don't we say from_fleet_to_robot(~) and from_robot_to_fleet(~)?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Follow-up: I see that later on we give names like to_robot to the CoordinateTransformer object. That does help alleviate my concern above. I'm just a little bit worried that encoding the direction of the transformation in the variable name could allow the meaning to get accidentally lost, e.g. when passing the CoordinateTransformer to a function. For example, the compiler wouldn't stop this from happening:

void do_some_transformation(const CoordinateTransformer& to_fleet)
{
  ...
}

void some_other_function(const CoordinateTransformer& to_robot)
{
  do_some_transformation(to_robot);
  ...
}

I'm not sure if this is worth being concerned about, so I'll leave it up to however you feel about the points I've raised to decide whether we should (1) keep things the way they are, or (2) encode the meaning of the transformation directions into the class definition.


/// Robot has diverged from the navigation graph, with no valid goal
/// information.
Lost
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When the TrackingState value is Lost the std::size_t component of the tracking estimation doesn't have any meaning, right?

In that case, I'd recommend the following:

enum class TrackingMode : uint8_t
{
  OnWaypoint,
  OnLane
};

struct TrackingState
{
  TrackingMode mode;
  std::size_t waypoint;
};

std::optional<TrackingState> tracking_estimation() const;

When the robot is lost, tracking_estimation would return a std::nullopt.

task_id = request.task_id();
task_ids.insert(task_id.value());
command_handle->stop(
[this]() {complete_task();});
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar to the previous comment, capturing this in a lambda that will be run in some other scope at an arbitrary time is unsafe, because you can't be sure that this will still be alive when the lambda is triggered. This should also be refactored to use a std::shared_ptr or std::weak_ptr of the shared data structure.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved fields into a separate data structure, and passed shared pointers to lambdas, e8bec64

free_fleet/src/manager/Manager.cpp Outdated Show resolved Hide resolved
[this]() {return _pimpl->time_now_fn();}));

_pimpl->tasks[request_task_id] = request_info;
_pimpl->unacknowledged_tasks[request_task_id] = request_info;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For each robot, any new new task (really, command) should supersede previous tasks (really, commands). But in the current implementation, the robot will be forced to acknowledge every single request that gets sent.

As an alternative approach, I might recommend mapping unacknowledged tasks/commands with the robot ID as the key, and only keeping up to one unacknowledged task at a time (the one with the highest task ID value) per robot. I'd also recommend wrapping that check-and-overwrite into a simple member function that each of these request_... functions can easily call.

free_fleet/include/free_fleet/messages/RobotState.hpp Outdated Show resolved Hide resolved
free_fleet/src/manager/RobotInfo.cpp Outdated Show resolved Hide resolved
free_fleet/src/manager/SimpleCoordinateTransformer.cpp Outdated Show resolved Hide resolved
Copy link
Collaborator

@mxgrey mxgrey left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've finished the review now and only have a few very small nitpicks to add. It's looking really great; thanks for all the massive iterating you've done 👍

free_fleet/src/manager/internal_RobotInfo.hpp Outdated Show resolved Hide resolved
free_fleet/test/unit/make_Client.cpp Outdated Show resolved Hide resolved
free_fleet_cyclonedds/src/Subscriber.hpp Show resolved Hide resolved
free_fleet_cyclonedds/src/messages/convert.cpp Outdated Show resolved Hide resolved
free_fleet_cyclonedds/test/unit/test_pubsub.cpp Outdated Show resolved Hide resolved
Signed-off-by: Aaron Chong <aaronchongth@gmail.com>
Signed-off-by: Aaron Chong <aaronchongth@gmail.com>
Signed-off-by: Aaron Chong <aaronchongth@gmail.com>
Signed-off-by: Aaron Chong <aaronchongth@gmail.com>
Signed-off-by: Aaron Chong <aaronchongth@gmail.com>
Signed-off-by: Aaron Chong <aaronchongth@gmail.com>
…iddleware in client and server

Signed-off-by: Aaron Chong <aaronchongth@gmail.com>
Signed-off-by: Aaron Chong <aaronchongth@gmail.com>
Signed-off-by: Aaron Chong <aaronchongth@gmail.com>
Signed-off-by: Aaron Chong <aaronchongth@gmail.com>
…dleware implementations

Signed-off-by: Aaron Chong <aaronchongth@gmail.com>
* fix bugs

Signed-off-by: chianfern <chianfern@gmail.com>

* uncrustify

Signed-off-by: chianfern <chianfern@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants