MarginallyClever / Robot-Overlord-App

Simulation and control software for robots
https://www.marginallyclever.com/
GNU General Public License v2.0
157 stars 48 forks source link

Refactor RobotComponents #157

Closed Jackymancs4 closed 11 months ago

Jackymancs4 commented 1 year ago

I have little Arduino robot with wheels, so I decided to try and begin the endevoir to control it with Robot Overlord.

Since in the Discord Server there have been some mild interest in Hexapod robots, I think it is the perfect time to discuss how to make it easier to add and manage different categories of robots.

The proposed hierarchy:

Each category of robots has its own system and helpers. There is alot of clean up to to, but this branch loads all the demos. To use Edit Arm, one needs to replace the RobotComponent with ArmRobotComponent.

For what consern the three wheeled robot the intented steps are:

This PR is maily for discussion, and it should really be split into more, assuming of couse there is interest.

i-make-robots commented 1 year ago

For now your way is the easiest way to get something up and running aka minimum viable product.

Thinking about the gripper question posted elsewhere, I wonder if it would be better to have a MotorComponent controlled by a RobotComponent. Every motor can have a name (taken from the entity name?) and that name is then used by the system that generate gcode.

What do you think?

Jackymancs4 commented 1 year ago

I enjoy a variable level of abstraction. A gripper could be implemented as a RobotComponent where you indicate all joint, motors and kinematics, or as GripperComponent where I only indicate the claws, their relation and status.

I'm thinking like I could build a RobotArm joint by joint, but the abstraction gives me the Arm Edit panel. BTW I really need your help on separating the scrictly arm logic from the generic robot one, in order to deduplicate the relative code. I think for example every robot could go to home (by defining a default status), but I'm unsure about linear velocity.

WheeledRobotComponent is meant to be just any robot with wheels attached to it. Like a circle of wood that has 6 wheel attached tangently to it that just spin arround its center. For the ThreeWheeled kind of robot I indented the specific configuration of two parallel driving wheels and a free spinning one. It is a very common and well studied model with specific kinematic. Other kind could be the Rover (with N indipendent steering ang driving wheels) and Car with linked driving wheels and specific kinematic for the steering.

Others configurations could be implement composing WheeledRobotComponent by hand.

if a motor is mounted to a wheel backwards it would be flagged in MotorComponent.

Every motor should just indicate its "forward" direction relative to its axis

the gcode scanner wouldn't know it's looking at a gripper, all it would "see" is motor names and motor positions, same as all other robot joints. Any other tool added to the system would also use motor and the system (hopefully) doesn't need to be rewritten.

I think every Component should declare to the presenter how to translate him and it's children.

I have not studied your implementation of the motorComponent.

i-make-robots commented 1 year ago

The Robot interface was a good idea in the past and is quickly becoming a problem.
The RobotComponent name is a problem, because it covers all robots when the implementation only handles some kinds of arms. Tech debt is a real problem.

Jackymancs4 commented 1 year ago

The RobotComponent name is a problem, because it covers all robots when the implementation only handles some kinds of arms.

Indeed I'm trying to move much of that handling into the ArmRobotComponent. If a "Project Schema Version" could be embeded ito new save files, a migration path (or a simple message) could be devised for older projects.

i-make-robots commented 1 year ago

I think every Component should declare to the presenter how to translate him and it's children.

Components don't know about "presenters" so how would it do this? and do it once for every presenter, for every component? Exponentially more difficult.

created https://github.com/MarginallyClever/Robot-Overlord-App/issues/158 for schema version.

Jackymancs4 commented 1 year ago

Components don't know about "presenters" so how would it do this? and do it once for every presenter, for every component? Exponentially more difficult.

Every component has a similar system for saving (with toJSON and parseJSON). My idea idea is a method with like

    public Something toPresenter(Presenter presenter) {
        if presenter isinstanceof Marlin
        return Something;
    }

You override for those who need it, otherwise use default in Component. The details should be discussed in its own issue.

Exponentially more difficult.

Also much more versatile.

the gcode scanner wouldn't know it's looking at a gripper, all it would "see" is motor names and motor positions, same as all other robot joints. Any other tool added to the system would also use motor and the system (hopefully) doesn't need to be rewritten.

Implenting toPresenter only on MotorComponents would achieve this.

i-make-robots commented 1 year ago
public void toPresenter(Presenter p) {
    p.doSomething(this.state);
}
...
toPresenter(MarlinPresenter);
toPresenter(BLDCPresenter);
toPresenter(ROSPresenter);

The presenter implementation decides what to do with the information. Components don't need to know where the data is going.

Jackymancs4 commented 1 year ago

continuing from Discord:

i-make-robots commented 1 year ago

Go home should stay in RobotComponent

Why? What does "go home" even mean to a wheeled robot?

i-make-robots commented 1 year ago

Root Pose should stay in RobotComponent

FWIW get(Robot.POSE) is a short form of getEntity().getComponent(PoseComponent.class).getWorld(), it's only there as a convenience.

Jackymancs4 commented 1 year ago

Why? What does "go home" even mean to a wheeled robot?

In this context, "Go home" is a reset state. If the wheeled robot (or any robot) has a servo for steering (like a RC car, or a rover), "Go home" could mean "get all the wheels aligned".

FWIW get(Robot.POSE) is a short form of getEntity().getComponent(PoseComponent.class).getWorld(), it's only there as a convenience.

Yes, both getPoseWorld and setPoseWorld seem convienient in all robots.

i-make-robots commented 1 year ago

CrabRobotComponent CrabDemoRobotComponent DogRobotComponent DogDemoRobotComponent WheeledRobotComponent ThreeWheeledRobotComponent

mm... I think the demos should be downloadables, same as the arms that already exist. the system does all the work, the component holds the data, and each demo is a different set of data.
example,

Jackymancs4 commented 1 year ago

Yes, demos are just TypeRobotComponents with meshes populated. They should have no extra logic.

2,3,4,6 wheeled robots should all use WheeledRobotComponent, the only difference is the number of wheels.

I think special cases for specific configurations are warrented. Like a GrabberComponent that could be implemented as a RobotComponent. Special types could enable dedicated builders/helpers. Then the user can use it or not.

For the ThreeWheeled kind of robot I indented the specific configuration of two parallel driving wheels and a free spinning one. It is a very common and well studied model with specific kinematic.

For this kind of robot, specific logic that handle the speed ratios could be implemented, but not available for all wheeled robots.

i-make-robots commented 1 year ago

For the ThreeWheeled kind of robot

the center of rotation is between the two wheels, right? so how is that different from a 4 wheeled tank-steer robot? technically it's not even a 3 wheel robot. a 3 wheel would probably be an omni-drive. I'm starting to think there's a motor component and a WheelComponent that has option for normal/omni/mecanum, then the WheelRobotSystem uses motor+wheel+orientation to figure out body movement.

i-make-robots commented 1 year ago

if GrabberComponent is implemented as a RobotComponent then the PARENT RobotComponent might see one robot inside another and get confused. I know I would be! đŸ˜…

Jackymancs4 commented 1 year ago

I think you are focusing too much on the number of wheels. I'm talking about specific configurations that allows specific helpers or builders for simulation or control.

If I tape 3 wheeled motors to a plank, it's not a 3 wheeled robot, it's a generic wheeled robot.

so how is that different from a 4 wheeled tank-steer robot?

E.g. Tank steering does not require a pivoting free-spinning wheels.

the center of rotation is between the two wheels, right?

https://www.xarg.org/image/article/ackerman-steering.png

No, e.g. the image if we consider in only the central idealized wheel, the center falls out of the vehicle.

Jackymancs4 commented 1 year ago

if GrabberComponent is implemented as a RobotComponent then the PARENT RobotComponent might see one robot inside another and get confused.

I don't see how. If I want to put a robot arm on top of a wheeled robot, I should be able to (With the RobotArmComponent child of the WheeledRobotComponent). Composability is the coolest feature of the EntitySystem.

Jackymancs4 commented 1 year ago

Moving discussion about wheeled robots to #159 . Do you have other feedback on this https://github.com/MarginallyClever/Robot-Overlord-App/pull/157#issuecomment-1575638479 ?

Also related https://github.com/MarginallyClever/Robot-Overlord-App/issues/158

i-make-robots commented 1 year ago

160 should give you everything you need to simulate your car. A new Component that reads the motor values and sends them to the real robot should be the only missing part. What do you think?

github-actions[bot] commented 11 months ago

Stale pull request message