ClemensElflein / open_mower_ros

Other
500 stars 124 forks source link

Create hardware dependent launch configurations #5

Closed ClemensElflein closed 1 year ago

ClemensElflein commented 2 years ago

Basically what was discussed in #3

jkaflik commented 2 years ago

XML explained (please see section #3): http://wiki.ros.org/roslaunch/XML

mnh-jansson commented 1 year ago

Unfortunately i don't think the current solution in development branch is flexible enough to support hardware variations such as Mowgli as it requires rosserial. Would it be a good idea to move over to a one liner include instead of params?

ClemensElflein commented 1 year ago

I also don't want mowgli and open mower to drift apart too far, I have fetched the important changes (again with some adaptations) from mowgli this week, but with time this will be hard due to small changes here and there.

Current Approach

It can be used like that. We could have hardware dependent include directories and move all the serial interface mappings out of the mower_config.sh and have just some high level config there (how wide is my mower, how far should it undock etc).

For example: open_mower.launch currently includes "_comms.launch" which connects to everything on the hardware (+ntrip, that should be moved out of there).

We could have

and so on, then we can include the right one using the OM_MOWER switch.

The only downside is that all dependencies of all platforms are part of the dependency tree (i.e. rosserial will be installed even when not using mowgli and xESC stuff will be installed when using mowgli)

Another Approach

So we also could do this as an alternative: We move everything that is shared between all hardware platforms (i.e. the high level stuff) into one repo called open_mower_core or something (or move the hardware dependent stuff out of this one, probably even better) and then create a repo for each hardware platform that includes the core as a dependency (similar to what mowgli is doing right now).

So in the end the user running mowgli will get the mowgli repo which then gets the current compatible open mower core and I could have like open_mower_yardforce, open_mower_husqvarna etc.

Also pinging @cloudn1ne - what do you think?

cloudn1ne commented 1 year ago

assuming you want to switch to BT also for OpenMower:

Im not fully there yet, but im positive that in a few more days i have the BT++ working in the same state as it is now with the slightly enhanced mower_logic (stop, resume) behaviors. From then on it should be really easy to add additional behaviors by creating new BT nodes.

The BT code is already written in a way that it is independent from the hardware as much as possible and where possible (so excluding map service calls) even independent from a "mower usercase", as there might be other uses for the robot platform ;-)

Very similar to mower_logic the following topics/services are subbed/published by mowgli_bt atm:

   // Subscribers
    subMowgliStatus = n.subscribe("mowgli/status", 50, MowgliStatusCB);
    subOdom = n.subscribe("odom", 50, OdomCB);

    // Publishers
    pubCurrentState = n.advertise<std_msgs::String>("mower_logic/current_state", 10, true);
    pubCommandVelocity = n.advertise<geometry_msgs::Twist>("/logic_vel", 1, true);

    // Service servers
    ros::ServiceServer srvHighLevelCommand = n.advertiseService("mower_service/high_level_control", highLevelCommandCB);

    // Service clients
    svcMowClient =  n.serviceClient<mower_msgs::MowerControlSrv>("mower_service/mow_enabled");
    svcDockingPointClient = n.serviceClient<mower_map::GetDockingPointSrv>("mower_map_service/get_docking_point");
    svcMapClient = n.serviceClient<mower_map::GetMowingAreaSrv>("mower_map_service/get_mowing_area");
    svcPlanPathClient = n.serviceClient<slic3r_coverage_planner::PlanPath>("slic3r_coverage_planner/plan_path");
    svcPlannerGetProgressClient = n.serviceClient<ftc_local_planner::PlannerGetProgress>("move_base_flex/FTCPlanner/planner_get_progress");

    // Action clients
    srvMbfExePathClient = new actionlib::SimpleActionClient<mbf_msgs::ExePathAction>("move_base_flex/exe_path", true);
    srvMbfMoveBaseClient = new actionlib::SimpleActionClient<mbf_msgs::MoveBaseAction>("move_base_flex/move_base", true);

Hardware -> BT++ Flow

BT++ -> Hardware Flow

Repo layout

Not sure:

Config

i think the config.sh approach is fine, i already prefixed my custom config variables with MOWGLI_ - however some stuff moved to the XML file for the BT (docking/undocking distances for example). Maybe a custom node that fetches ENV variables would need to be written to keep the current config schema.

ClemensElflein commented 1 year ago

Thank you for the detailed answer!

I almost agree with your layout, I think we should split that at a different point, though. For example having dead reckoning implemented in the "common" part of the software might be a good idea, because if we improve on that, we improve it for all platforms.

I think we should separate as low as possible and only implement the hardware drivers differently (+ obviously stuff like PID params / min max battery voltages, ...)

Having a single packet with the messages for implementing the low level interface is a good idea. Then anyone can implement that and can theoretically run the open mower stack.

cloudn1ne commented 1 year ago

Im making a drawing atm - i'll post when finished - as a basis for further discussion. For DR i agree, but as u noted yourself the stopping /odom approach is a bit hacking, but i dont understand enough atm about the nav stack and all the transform to come up with a better way - at least we should make a dedicated node that outputs /odom then (tbd what that actually will do)

cloudn1ne commented 1 year ago

MowgliArch_v1.0.2

.drawio file is here

ClemensElflein commented 1 year ago

That looks like I imagined it, thank you for drawing that out. The only thing I'd change is the odometry / dead reckoning solution. I don't like the two parallel sensor fusions (why are these different anyways, don't they have the same output with the same input?) and having DR implemented in robot_localization and in openmower_odometry.

ClemensElflein commented 1 year ago

(btw rviz currently already fetches the map from the remote map server, it's not the local copy)

cloudn1ne commented 1 year ago

added OM to the drawing, at least as i understand it.

cloudn1ne commented 1 year ago

i had the sensor fusion working with robot_localization before i started with integrating any OM parts - config is still somewhere in the mowglirover repo afaik - but the problem was, that you have two run two instances - one for the "jumping" gps coordinates, and one that then loops back the first ekf into the second one which fuses the wheel odometry and imu - it was "somehow" working but not stable for me, but i really dont get the whole TF stuff yet. So maybe you can get that to work ?

What my approach is atm - and what i mean with DR in openmower_odometry is basically a switch between /odom_gps (rel GPS coords + IMU heading) and /odom_dr (EKF output, which is wheel sensors and IMU heading). priority is on /odom_gps, but if that goes away for up to n seconds /odom_dr is emitted before it (for now) stops.

Another option would be to put the decision of what odom topic to use into openmower_bt - you are undocking/docking, then odom_dr is good enough. You need a recovery behavior because you are stuck for 10mins already waiting for GPS, same use a custom odom topic as configured ... just emit proper status information from XXXX_odometry that allows BT to make the proper choice

Damme commented 1 year ago

I would like to see this implemented somehow, worx branch needs a way to select between communication module (mower_comms and worx_comms). I see a hardware specific launch folder structure could work.

ClemensElflein commented 1 year ago

With the docker deployment I think the smartest solution for custom comms packages to do the following:

if you run local without the docker you can clone open_mower_ros and your ros workspace, source both and do the same as above.

I want to avoid having code in the open_mower_ros that has lots of hardware dependencies I cannot test

ClemensElflein commented 1 year ago

for wheel ticks, serial ports and so on you can already overwrite it using config files. set OM_MOWER to "CUSTOM" and put your files into ~/mower_params