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

Project: Autonomous Ski Lift Simulation for Safety & Efficiency (C example) #118

Open
wants to merge 10 commits into
base: main
Choose a base branch
from

Conversation

Max851010
Copy link

@Max851010 Max851010 commented Feb 2, 2025

Project Description

This project simulates the behavior of ski lifts with a focus on improving safety and reducing labor costs through automation using Lingua Franca. The simulation models key aspects of ski lift operations, including:

  1. Passenger Flow & Lift Capacity
    • Ensuring smooth and efficient boarding/unboarding.
  2. Safety Mechanisms
    • Detecting potential dangers and automating responses to prevent accidents.
  3. Autonomous Control
    • Optimizing lift operations with minimal human intervention.

The goal is to explore how automation can enhance safety while reducing operational costs, making ski lifts more efficient and reliable.

About me

Hello everyone! I'm Cheng Yen, Tsai, a current M.S. Computer Science student at Arizona State University. In Fall 2024, I took CSE 522: Real-Time Embedded Systems, where I had my first experience programming for embedded systems and working with Lingua Franca. It's amazing because embedded system is so different than any system I built before (I was a full-stack web developer before return to school).

Now I'm developing this applied project under the guidance of Professor @hokeun for my graduate requirement. Because I'm a snowboarder, it's really excited to have this opportunity to combine my passion with my technical skills while contributing to the Lingua Franca community. I'm sure I will have fun here! Nice to meet you all.

More detail about my experience: https://www.linkedin.com/in/cheng-yen-tsai-3690a2201/

Updates in this PR

The current implementation now is only the animation of lift motion, the ability to open/close entry gate, the stop/move behavior of the lift.

Sensors (Reactors) – Planned for Future Implementation

  1. EntrySensor
    • Detects the number of people passing through the entry gate (not used yet, but planned for future use).
  2. LiftSensor
    • Tracks the position of the ski lift chairs and determines when to open/close the entry gate (not used yet, but planned for future use).
  3. ObjectDetector
    • Detects passengers in both the ready and exit areas (not used yet, but planned for future use).
  4. ScreenPrinter
    • Aims to encapsulate the ski lift motion display logic in a C file and expose it as a reactor. Implementation is currently blocked due to difficulties passing parameters using the method described here.

Modal Models

  1. EntryGate
    • Controls the opening and closing behavior of the entry gate.
  2. LiftMotion
    • Manages the movement and stopping behavior of the ski lift.

Main Reactor

  1. Lift
    • The central starting point of the system, currently handling printing behavior as well.

Demo Video

Screen.Recording.2025-02-02.at.11.08.26.AM.mov

…lift and the status of it's motion. Moreover, the status of the entry gate is printed too.Other functionalities are not fully implemented.
Copy link
Member

@hokeun hokeun left a comment

Choose a reason for hiding this comment

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

Looks like a great start! I left some comments to clean up the code and finish the implementation of an empty reactor.

examples/C/src/SkiLift/lib/ScreenPrinter.lf Show resolved Hide resolved
examples/C/src/SkiLift/Lift.lf Outdated Show resolved Hide resolved
examples/C/src/SkiLift/Lift.lf Outdated Show resolved Hide resolved
examples/C/src/SkiLift/EntryGate.lf Outdated Show resolved Hide resolved
examples/C/src/SkiLift/Lift.lf Outdated Show resolved Hide resolved
@lhstrh
Copy link
Member

lhstrh commented Feb 4, 2025

This is pretty cool! I approved a CI run for this.

@Max851010
Copy link
Author

@lhstrh Thank you! So glad you like the idea!

@Max851010
Copy link
Author

@hokeun I cleaned up comments, reformatted the code using VS code formatter, and implemented the ScreenPrinter reactor!

Copy link
Member

@hokeun hokeun left a comment

Choose a reason for hiding this comment

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

Thanks for addressing my previous comments! I left some additional minor comments. I tested this example out on my local machine, and confirmed that it works fine.

Also, could you add a README for this example?

Here are some sample READMEs for other examples in the playground:

Also, when you write your README, please feel free to re-use the content you already have in the PR description.

self->offset = (self->offset + 1) % self->screen_wideth; // Update the offset for the next frame
=}

// TODO: Behaviors on the start of the lift
Copy link
Member

Choose a reason for hiding this comment

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

Is this a TODO that you want to do after merging this PR? Can you elaborate on what TODOs are left?

}
=}

// TODO: Behavior on the end of the lift
Copy link
Member

Choose a reason for hiding this comment

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

Same comment here.

@Max851010
Copy link
Author

@hokeun Thank you for reviewing professor! I pushed three new changes.

  1. Adjust the file structure and move the LiftMotion Modal Model from Lift.lf to lib/LiftMotion.lf
  2. Remove TODO comments because they will be implemented in the future PRs.
  3. Readme file

@hokeun hokeun marked this pull request as ready for review February 7, 2025 17:16
Copy link
Member

@hokeun hokeun left a comment

Choose a reason for hiding this comment

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

Looks great to me! Thanks, Cheng Yen.

@Max851010 I suggest we wait for a few more days in case other reviewers want to take a look before merging.

@hokeun hokeun requested review from lhstrh and edwardalee February 7, 2025 17:17
Copy link
Member

@lhstrh lhstrh left a comment

Choose a reason for hiding this comment

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

Looks great! Any reflections on the experience of building this? How did LF make it easier?

Copy link
Contributor

@edwardalee edwardalee left a comment

Choose a reason for hiding this comment

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

Looks great! Can you elaborate on what the problem is with passing parameters with bodiless reactions? Maybe open an issue?

@Max851010
Copy link
Author

@hokeun @lhstrh @edwardalee Thank you all for reviewing the project! I'll keep adding new features!

@lhstrh The best part of Lingua Franca is the reactor diagrams in VS Code! The logic and data flow of embedded systems can be quite complex sometimes in my opinion. It's much easier to design the system with the diagram feature. On the other hand, the difficult part of LF might be the documentation doesn't cover enough use cases. Sometime it's hard to find guidance for specific scenarios. For example, it took me several hours to figure out how to implement self loop in my LiftMotion modal reactors (which I'm not sure if I did it correctly). If cases like this were documented, it would help a lot!

@edwardalee For example, I tried to put all the preamble functions in a C file and call one of the function with a parameter as it's input. However, I couldn't find a similar example in other projects or in the LF documentation.
I wanted to do something like this:

#include <stdio.h>
#include "../include/HelloDecl/HelloDecl.h"

void hello(hellodecl_self_t* self, int x) {
    printf("x: %d\n", x);
}
target C {
    cmake-include: ["hello.cmake"],
    files: ["hello.c"]
}

main reactor HelloDecl {
    reaction hello(startup, 100)
}

Moreover, can I call the function without using the startup event? Like using timer event or none?

@edwardalee
Copy link
Contributor

Good questions. You are right that we need more examples. That has been one of the goals of the playground!

One option would be this, I think:

main reactor HelloDecl {
    reaction(startup) {=
        hello(self, 100);
    =}
}

IMHO, this would be even cleaner, so you wouldn't have to expose the (internal) hellodecl_self_t type:

#include <stdio.h>
#include "../include/HelloDecl/HelloDecl.h"

void hello(int x) {
    printf("x: %d\n", x);
}

and then

main reactor HelloDecl {
    reaction(startup) {=
        hello(100);
    =}
}

or better

main reactor HelloDecl(x: int = 100) {
    reaction(startup) {=
        hello(self->x);
    =}
}

On the question about whether to use the startup event, a reaction has to have a trigger. The startup event is equivalent to a timer declared as follows:

   timer s(0)

@Max851010
Copy link
Author

Max851010 commented Feb 8, 2025

@edwardalee Thank you so much!!! That's exactly what I need. I just tried it and it worked!
Also I found out that I need to declare the function in the preamble inside the reactor to prevent the error like undeclared function 'skiLiftInit'; ISO C99 and later do not support implicit function declarations:

main reactor HelloDecl {
   preamble{=
       hello(int x);
   =}
    reaction(startup) {=
        hello(100);
    =}
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants